| 2026-08-06 |

Stage 5 dc0: RETIRE + archive dc-ha-scaleup.yaml (operator-ruled; R6 superseded) [DOCFIX-211]
...
Operator ruling 2026-08-06, exact utterance "Retire the redundancy and archive." The
overlay was wholly redundant -- BUNDLEFIX-053 folded its entire content into bundle.yaml,
so applying it was an all-keys no-op deep-merge (Task-#1 post-wave review, measured).
- Archived: git mv overlays/dc-ha-scaleup.yaml -> docs/archive/dc-ha-scaleup-RETIRED-20260806.yaml
+ a do-not-deploy banner. docs/archive/ chosen explicitly (no prior overlay-archive precedent).
- design-decisions.md: GA-R5 SUPERSESSION note on D-121's R6 (original 2026-07-27 record retained
as history); fixed :503 and :4563 "overlay encodes v-a" refs -> bundle.yaml/BUNDLEFIX-053.
- Harness (tests/provider-bundle-check): T17 REMOVED (== T18 once vault-hacluster is in base);
T17b/T32/T33/T34 RE-POINTED onto good.yaml (base HA chain). T33/T34 now use the deterministic
mutate() helper, not sed-on-overlay (no silent no-op fixture; a wrong key path KeyErrors). Each
FAIL case proven to fire against the real checker message. 58->57 cases; provider-bundle-check 57/0.
- Runbook dc-dc-phase4 Step-4 note + Step-12.3(a) gate: the two-phase "base at cluster_count:1 then
apply the overlay to reach 3" model RETIRED -- base deploys 3-unit HA directly, so cluster_count:3
is the expected post-Step-4 value.
- Rendered vips overlays: edited the render SOURCE (render/values/vr1-dc{0,1}-vips.yaml, D-136) and
re-rendered (not hand-edited); overlay diff = the two comment lines only; render-drift 4/0.
Hand-maintained vr1-dc{0,1}-machines.yaml deploy-command comments + provider-bundle-check.py +
cloud-assert.sh comments + dc-dc-deployment-workflow.md item 22 reconciled.
- CURRENT-STATE: no edit needed -- active status already omits the HA overlay from the deploy input;
remaining mentions are dated historical narrative (retained as history, GA-R1).
- Also finalizes Item 3/5 changelog notes (F9 approved+staged; Task #1 recommendation ruled).
Gauntlet ALL GREEN (99 harnesses); repo-lint 0 fail (1 pre-existing legacy L1 warn).
Staging: dc0 rack vr1-dc0-vips.yaml now stale-by-one-comment vs the re-render (functionally
identical); re-syncs + sha-verifies at the next deploy per D-138 (logged, no rack write for a comment).
Revert: git mv the overlay back (strip banner) + git revert this commit + re-render vips from
reverted values.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fg98z7QyzwYUs8fsWCn728
|

Task #2: commit D-020 vault-metal-only amendment; teach renderer + gates; harnesses green
...
The RULED-but-uncommitted D-020 amendment (vault METAL-ONLY, 2026-08-05) is now
committed and enforced end-to-end. Discovered mid-task that the overlays are RENDERED
from render/values/*.yaml (D-136) and hand-editing them is forbidden by the render-drift
gate -- which was ALREADY red at the part-2 close (undocumented) from that session's dc0
overlay hand-edit. Resolved by teaching the renderer, not by hand-editing (advisor-reviewed;
the amendment is ruled, so this is OPS implementation).
Vault VIP shape is now the metal PAIR (metal-admin + metal-internal, no provider-public,
no v6) across all four consumers, each with a failing-direction fixture:
- provider-bundle-check.py: per-DC/family-aware vault exception; STILL band- and
octet-uniqueness-checked (advisor caught the first draft's early `continue` disarming
octet_owner for .61 -- proven rc=0 draft / rc=1 fixed). T54/T55/T56.
- render-dc-overlays.py: name-keyed metal-only render branch (drops provider + v6);
overlays re-rendered (diff vs HEAD = exactly the one vault line each). T15b.
- pre-flight-checks.sh CHECK 1: awk name-tracking + vault metal-pair branch. T28b.
- render/values/*.yaml: vault comment (part of rendered bytes).
D-121 status 12/14 -> 14/14 in CURRENT-STATE, with the missing juju-status capture
DECLARED as an owed gap (GA-R1 rule 2) rather than papered over.
Verify: gauntlet ALL GREEN (99); repo-lint 0 fail; provider-bundle-check 58/0,
render-dc-overlays 24/0, render-drift 4/0, pre-flight-checks 32/0.
Body: docs/changelog-20260805-task2-vault-metal-only-commit.md
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fg98z7QyzwYUs8fsWCn728
|
| 2026-07-31 |

Build the (b) ruling: prefer-ipv6 emitted for NO application; 9b re-pointed
...
Renderer: the emission condition is DISABLED, not deleted -- when the v6
completion work lands (allocatable ranges on the six v6 plane subnets, rack-side
v6 legs, a v6 default route, v6-reachable services) that one line turns it back
on, and PREFER_IPV6_CHARMS is still the correct set to gate it by.
Both overlays re-rendered: exactly 7 lines removed per DC and nothing else --
all 13 apps keep 6-leg dual-family vips at both DCs.
INVARIANT 9b RE-POINTED, not deleted: it required the option and the v6 legs to
travel together on a declaring charm (the L3-9 defect), which would now fail on
the ruled artifact. The rule is the option must be ABSENT everywhere. L3-9 cannot
recur while it is absent -- there is nothing to keep while legs are dropped. It
returns to the coupling form when v6 is operational.
HARNESS re-pointed rather than deleted, and three stale fixtures fixed:
- T20 was 'option without v6 legs FAILS'; now 'option on a DECLARING charm FAILS'
- T21 was the inverse; now the POSITIVE CONTROL -- v6 legs WITHOUT the option
must PASS, so 9b cannot be satisfied by rejecting everything
- T22/T23/T30 each set prefer-ipv6 because the OLD coupling required it
alongside v6 legs. Under the absence rule 9b fires FIRST and short-circuits,
so their v6-band assertions would never have been reached and they would have
passed for the wrong reason. The option is removed from those fixtures.
Mutation-proven: disabling the 9b absence check kills T20; re-enabling renderer
emission kills render-drift. Source restored byte-identical after each.
Gauntlet ALL GREEN (93); repo-lint 0 fail; harness 55/55.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

Build the 2026-07-31 ruling: renderer + invariant 9 replaced, overlays re-rendered
...
Three parts, all mutation-proven.
(i) provider-bundle-check.py gains PREFER_IPV6_CHARMS -- the measured authority,
keyed by CHARM name, carrying the revisions and a re-measure warning -- and
invariant 9 is REPLACED, never deleted:
9a prefer-ipv6 on a charm that does NOT declare it FAILS. Asserted on
PRESENCE, not truthiness: 'prefer-ipv6: false' is the same fatal
'unknown option' to juju as true.
9b on a DECLARING charm it still travels with the v6 legs -- the L3-9
protection is retained unchanged for those seven.
9c arity.
The old text's mechanism claim ("prefer-ipv6 makes HAProxy bind :::port") is
refuted by this session's measurement and is recorded as such in-file.
(ii) render-dc-overlays.py emits the option only for a declaring charm, READING
the set from provider-bundle-check with ast rather than restating it (the same
rule APP_OCTET already uses). render() keeps its purity property: the set is a
PARAMETER and the default REFUSES rather than defaulting to empty, because an
empty set renders a plausible artifact with the option nowhere. Both overlays
re-rendered: exactly SIX lines removed per DC and nothing else -- every vip
string byte-identical, so all v6 legs are retained.
(iii) tests/provider-bundle-check 44 -> 48/48. T43 reproduces the attempt-1
defect; T44 proves presence-not-truthiness; T45 is the positive control; T46
asserts the DIAGNOSIS.
MUTATION PASS -- six mutations, every one killed tests. And one NEW assertion
was found to be DECORATION and was REPLACED rather than kept: T46's first form
could not fail under any mutation, because a non-declaring charm with no option
reaches neither branch. Re-written to catch the fold-9a-into-9b simplification
and re-proven.
Gauntlet ALL GREEN (93); repo-lint 0 fail. The fixed dc0 deploy input now
sweeps CLEAN on option names: 75 assignments, 20 schemas, 0 unknown.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
| 2026-07-29 |

Ruling 3 commit 2: dual-stack ADD -- R2 and R11 are now BUILT, L3-9 resolved
...
Both per-DC VIP overlays re-rendered dual-family: every app carries
prefer-ipv6: true and a six-address vip, and vault .61 + designate .62 are
built. Measured both DCs: 13 clustered VIPs (13 dual-family) + 12 hacluster
principals all carrying a VIP -> PASS. With dc-ha-scaleup stacked: 13
principals, PASS -- R6's ruled ordering (VIPs before the HA overlay) is now
satisfied and executable. Two ruled-but-never-built decisions became
artifacts in one pass.
L3-9 RESOLVED. dc-dc-ipv6-family-matrix.yaml is narrowed to ceph-mon only;
its ten duplicate vip + prefer-ipv6 pairs (every value an unrendered token)
are gone, removed TOGETHER -- removing the vips alone would have recreated
the defect deliberately. Both merge orders now PASS, i.e. order-independent,
which is the actual fix. ceph-mon's ULA-only networks survive because they
exist in no other file. The two Launchpad citations arguing octavia lb-mgmt
IPv6 was an open risk are removed: both were read in full and both failed,
and R8 closed that question on 2026-07-27.
Also corrected at source: CURRENT-STATE described L3-9 as "the dangerous
merge order is the one that PASSES". Measured -- that stopped being true
when invariant 9 shipped on 2026-07-28. The merge semantics it describes
remain accurate; only the green-over-loss conclusion is retired.
Gate repairs the agents caught BEFORE the edit:
- phase-01's deploy guard would have ABORTED THE DEPLOY AGAIN -- its HI regex
(5[0-9]|60) excludes .61/.62, so it would have read 13/11/0 against a
required 11/11/0. Widened, counts moved to 13, verified 13/13/0 -> DEPLOY.
Second near-miss on this one guard across two commits.
- pre-flight-checks CHECK 1 hardcoded if(n!=3) and would have failed all 13.
Now takes a triple OR a sextet and asserts a sextet's last three legs are
really v6. Proven able to fail on both new paths.
Harnesses re-pointed, never deleted. T16/T17 asserted R11's gaps were OPEN;
inverted to the surviving invariant and PAIRED with new T16b/T17b that remove
a VIP and demand the check still fires. T20/T21 had become no-ops that would
have gone GREEN testing nothing -- inverted. A v4-only twin fixture keeps the
pre-dual-stack cases testing their own invariants. The renderer harness now
proves reproduction on both shapes, including new T3b against the live
dual-family overlay.
provider-bundle-check 33/33; render-dc-overlays 18/18; render-baseline 10/10;
preflight 16/16; gauntlet ALL GREEN (85) on vcloud; repo-lint 0 fail / 611.
PREFLIGHT: BOTH STANDING REDS CLEARED, 3 fatal -> 2 fatal. The remaining two
are the deliberately-absent octavia-pki overlay and MAAS unreachable from
vcloud, which R10 measured clears on voffice1.
FLAGGED, not hidden: octavia's dual-family API VIP is an inference from R2
applied evenly, not a quoted ruling. Worth one operator confirmation.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
| 2026-07-24 |
dc1 VIP overlay drafted (overlays/vr1-dc1-vips.yaml)
...
Per-DC VIP overlay for the vr1-dc1 proxy-method deploy (phase-4 Step 4): re-homes
the 11 API-service VIPs from bundle.yaml's vr1-dc0 bands into vr1-dc1's measured
bands (provider-public 10.12.4->64, metal-admin 10.12.8->68, metal-internal
10.12.12->72; host octets .50-.60 unchanged), sourced from lib-net vr1-dc1
PLANE_NAME. Base bundle.yaml stays the vr1-dc0 source of truth; overlay applied
only for the dc1 deploy. YAML valid (11 apps), repo-lint 0 fail.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|