| 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
|

Values-file provenance symmetry; repair the mangled ledger rotation note
...
Two small corrections found on review.
(a) The values file recorded `apex_record` only on the dual-family path, so
the dc0 v4 file carried no provenance at all -- and the asymmetry would have
read as a bug once commit 2 gives dc1 the apex field. Added `source_v4`,
recorded on BOTH families, because the v4 prefixes come from lib-net.sh and
NEVER from the apex: a values file carrying only `apex_record` misattributes
half its own inputs. Re-derived dc0; the rendered overlay is byte-identical
(a3b30e40...) and dc1 still reproduces exactly.
(b) docs/session-ledger.md's third rotation note was left MANGLED by an
earlier edit -- a sentence broke off mid-number and ran into a stray fragment
of the 2026-07-25 MAAS-admin-recovery summary. Flagged at this session's open;
repaired here rather than only reported, with a note saying so and a pointer
to that summary's archived body.
Gauntlet ALL GREEN (85) on vcloud; repo-lint 0 fail.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

Ruling 3 commit 1: bundle.yaml is VIP-free; dc0's VIPs are now a RENDERED overlay
...
The 11 inline vip: lines are gone from bundle.yaml and live in
overlays/vr1-dc0-vips.yaml, GENERATED by scripts/render-dc-overlays.py from
render/values/vr1-dc0-vips.yaml -- the renderer's first real output.
placement's then-empty options: block was dropped rather than left parsing
as null. Ruling 3's dual-stack ADD is commit 2 and is NOT in here.
PROVEN NEUTRAL by the ruling's own named check: provider-bundle-check on the
pre-extraction bundle and on the merged pair produce line-for-line identical
output, same known designate failure included. A structural diff separately
confirmed only vip moved -- applications 56 -> 56, relations 108 -> 108,
every other key byte-identical.
The 11 inline comments were carried, not dropped: extracted verbatim by
parser rather than retyped, via new optional per-app comment support in the
renderer. An app with no comment emits none, so dc1 still reproduces
byte-for-byte at 1634 bytes. The B1/B5 tokens stay DEFINED in bundle.yaml's
header and the overlay header names that, so the references do not dangle.
The blast-radius repair is the bulk of this, and every item was found BEFORE
the edit by the read-only agent sweep:
- preflight.sh P2 validated the bare base (11 phantom failures post-move) ->
merged input.
- pre-flight-checks.sh CHECK 1 read the base as raw text and would have seen
ZERO VIPs. This is BLOCKER-1, fixed the ruled way and not by bumping the
count. Measured trap: the file sets IFS=$'\n\t', so a space-joined string
reached grep as ONE filename, grep exited 2, pipefail propagated and the
gate died silently mid-check. Fixed with a bash array.
- phase-01's RUN block gates juju deploy on 11/11/0 and would have read
0/0/0 and ABORTED THE DEPLOY. Both guards now span base + overlay, and a
second latent bug was fixed in the same edit: grep -c over two files prints
one count PER FILE, so the bare $( ) captured a two-line string and every
numeric test would have failed anyway. Now awk-summed; verified 11/11/0.
- phase-01's Octavia SAN derivation raised KeyError, swallowed by || true
into an empty VIP. Now reads the overlay, deriving 10.12.4.57.
- phase-00 teardown, dc-dc-phase4's "NO VIP edits" guidance, appendix-A L3,
and render-baseline's now-unverifiable bundle hash all repaired.
Harness 30 -> 31. The fixture base is now bundle + dc0 overlay, since that
pair is the deploy input; T16 renamed to match. NEW T31 asserts the bare base
fails for every clustered principal, so "deployed without its overlay" is a
tested state rather than an assumption.
Gauntlet ALL GREEN (85) on vcloud; repo-lint 0 fail / 610 files scanned.
Still red and expected: CHECK 1 at OK=11 want 13, and designate -- R11's
.61/.62 remain ruled-but-not-built, which is commit 2's job.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|

Render-pipeline step 4: the renderer, reproducing a reviewed artifact byte-for-byte
...
scripts/render-dc-overlays.py. Two stages, split exactly where forward item
F2 froze the interface: `derive` (apex + lib-net.sh -> a per-DC values file)
and `render` (values -> overlay text). `render` is PURE -- no apex, no
network, no clock -- so it is offline-testable and a future CI job re-runs
only `derive`.
ORDER INVERTED BY MEASUREMENT. The plan was ruling-3's VIP extraction first.
Three read-only agents measured two facts that reversed it: the byte-for-byte
reproduction window is still open (the live dc1 overlay is still identical to
the frozen fixture) and closes on its own when the R2/R11 reconciliation
lands; and the extraction's blast radius is far larger than ruling 3's "2
commits" -- it breaks the phase-01 deploy gate (juju deploy runs only on
11/11/0), the Octavia SAN derivation, preflight in two places, and 8 of 30
harness cases. Better done BY the renderer, so dc0's overlay is a validated
output rather than a hand edit.
A TEXT emitter, not yaml.dump: a round-tripper destroys the comment header,
normalises the quoted vip scalar, and imposes its own key order -- all three
are load-bearing bytes. Two things are INPUT rather than invented: the 12-line
comment header (lifted verbatim via --from-overlay, so a reproduction run is
honest about which bytes the tool actually generates) and the ascending-octet
emission order (sorting by name reproduces nothing). The ruled app->octet map
is READ with ast out of dc-plane-apex-import.py rather than restated as a
second drifting copy.
RESULT: output hashes to 3f93ecb3..., identical to both the committed overlay
(1634 bytes) and the frozen fixture. PROVEN ABLE TO FAIL, not merely observed
passing -- three seeded faults all fail the compare (wrong octet, dropped
header, dc0 prefixes against the dc1 artifact).
THE ARITY WORK PAID FOR ITSELF WITHIN THE HOUR. The first dual-family output
was malformed: the values file stores each v6 /64 base with trailing colons
stripped, and the emitter joined with a single colon -- 2602:f3e2:f03:11:50,
not a valid address, and it still looks like one. provider-bundle-check,
fixed yesterday for exactly this class, rejected all 13 applications. Locked
by T13/T13b.
End to end: apex -> values -> renderer -> overlay -> gate. The dual-family
dc1 render with R11's ruled-but-unbuilt apps produces 13 VIPs, all
dual-family, PASSING provider-bundle-check --dc vr1-dc1 including the new
hacluster invariant. Nothing committed has been regenerated by it yet.
tests/render-baseline gains T6, the reproduction case its README invited --
ADDED, with T1-T5 deliberately not repointed at live, and comparing against
the FIXTURE because live is supposed to diverge. T6 proven able to fail by
making the renderer sort alphabetically.
New harness 17/17; render-baseline 10/10 (was 9); gauntlet ALL GREEN (85) on
vcloud, manifest re-recorded after the drift gate correctly caught the
addition; repo-lint 0 fail / 608 files scanned.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|