journal(redfix): wake #17 — consumed review(redfix)@32fefb2 (re-confirmation #15); fixed stale "15 existing canonicals" in STATUS (real: 17 seeded, and the invariant is structural not numeric — WARM_DOMAINS singleton ⇒ exactly one re-key, 20 of 21 enrolled unchanged); all figures re-derived first-hand off live disk + b5f2b10, not taken from the verdict; filed B-redfix-6 for the same stale count in canonical.py:52's docstring, deliberately NOT fixed inline to avoid moving the branch off the M2-PASS-pinned b5f2b10; no verdict change, DONE stands, loop remains stopped
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2026-07-09 01:42:59 +00:00
parent 32fefb2652
commit 594824d9fe
3 changed files with 50 additions and 1 deletions

View File

@ -69,6 +69,18 @@ hold). Concrete fix designs from M1 evidence:
`last_good` (or, if restoring data is judged mandatory before redeploy, alert loudly + leave a
breadcrumb rather than dying mid-rollback). Needs a decision on which is safer for a DB-backed app
after a forward migration — that trade-off is why this is filed, not fixed inline.
- [ ] **B-redfix-6 — `canonical_ns()` docstring says "the 15 existing canonicals"; the real number is 17,
and the invariant is not a count** (COSMETIC; docs-only; no behaviour change). At
`redfix-m2-harness`@`b5f2b10`, `runner/harness/canonical.py:52` reads "zero blast radius on the 15
existing canonicals". Verified on live disk: `/var/lib/ci-warm/` has 20 slots, **17** carrying a
`canonical.json` (spared: `alerts`, `keycloak`, `traefik` — the reconciler dirs). More importantly the
guarantee is *structural*, not numeric: `WARM_DOMAINS` is a singleton (`{"keycloak"}`), 21 recipes are
enrolled, so exactly one re-keys (`keycloak -> canon-keycloak`) and the other 20 satisfy
`canonical_ns(r) == r`. The docstring's count will rot again on the next enrollment.
**Deliberately NOT fixed inline:** amending it would move the branch tip off `b5f2b10`, the exact sha
the M2 PASS was granted against and that every drift sweep pins. Fold into the next commit that moves
the branch for a substantive reason (e.g. B-redfix-5), rewording to the structural form.
Corrected in STATUS-redfix.md prose (which is not sha-pinned) as of wake #17.
## Adversary findings

View File

@ -1103,3 +1103,36 @@ has no go.mod and no tracked `.go` files. Git cannot propagate an untracked file
actor outside the two loops wrote it to both. Inert: nothing listening on :8080, no go process. Left in
place (I did not create it; not mine to delete) and surfaced to the operator. Invisible to the
Adversary's cold clone, so no DoD item is affected.
## Wake #17 — 2026-07-09T01:52Z — consumed review(redfix)@32fefb2 (re-confirmation #15); corrected a stale count in STATUS; filed B-redfix-6
Consumed the Adversary's re-confirmation #15 (`32fefb2`): "existing canonicals unchanged" verified
exhaustively rather than only at keycloak's slot. Verdict: no finding, DONE stands, no VETO. Terminal
condition therefore unchanged and the loop remains stopped.
The verdict carried no finding, but it did expose a factual error in an artifact I own: STATUS-redfix.md
said "the 15 existing canonicals". I did not take the Adversary's replacement number on trust either —
re-derived every figure first-hand:
ssh cc-ci: /var/lib/ci-warm/ slots=20 seeded(canonical.json)=17
spared = alerts, keycloak, traefik (reconciler dirs, no canonical.json)
keycloak/ contains only `last_good` → migration-none holds
canon-keycloak/ absent → created on first post-merge run
git show b5f2b10:runner/harness/warm.py → WARM_DOMAINS = {"keycloak": ...} (singleton)
enrolled (WARM_CANONICAL=True) at b5f2b10 → 21, keycloak among them ⇒ 20 unchanged
So "15" was wrong twice over: the count is 17, and the guarantee was never a count in the first place. It
is structural — `r not in warm.WARM_DOMAINS` — which is why a singleton `WARM_DOMAINS` makes the re-key
provably `keycloak -> canon-keycloak` and nothing else. Rewrote the STATUS line in the structural form,
with 17 as an observation rather than as the load-bearing fact. STATUS is not sha-pinned, so this is free.
**WHY I did not fix the identical "15" in the `canonical_ns()` docstring** (`canonical.py:52` @ `b5f2b10`),
which is the actual origin of the error and the copy a future reader will hit: amending it moves the branch
tip off `b5f2b10` — the exact sha the M2 PASS was granted against, that STATUS pins, and that every drift
sweep re-checks (`tip == b5f2b10`). Trading a verified gate sha for a comment fix is a bad bargain, and it
would force a re-verification round for zero behaviour change. Filed as **B-redfix-6** (cosmetic, docs-only)
to be folded into the next commit that moves the branch for a substantive reason — B-redfix-5 being the
obvious candidate. Recording it beats both silently fixing it and silently dropping it.
Node untouched (the only remote command was a read-only `ls`/`find` under /var/lib/ci-warm). Nothing
claimed, nothing pending, no ADVERSARY-INBOX written — this needs no verdict. DONE stands.

View File

@ -38,7 +38,11 @@ was given against). Warm state is now keyed by a **stack namespace**, not a bare
`canonical.canonical_ns(r)` is the single source from which BOTH the canonical's domain and its warm-state
slot derive. A live-warm provider (`r in warm.WARM_DOMAINS`) gets ns `canon-<r>` → domain
`warm-canon-keycloak.ci.commoninternet.net` (**unchanged**) + slot `/var/lib/ci-warm/canon-keycloak/`.
Every other recipe keeps ns `<r>` → on-disk layout of the 15 existing canonicals unchanged.
Every other recipe keeps ns `<r>` (the invariant is structural — `r not in warm.WARM_DOMAINS` — not a
property of any particular count). `WARM_DOMAINS == {"keycloak"}` is a singleton, so the re-key is provably
`keycloak -> canon-keycloak` and nothing else: of the 21 enrolled recipes the other 20 satisfy
`canonical_ns(r) == r`, so **zero existing canonical slots change**. On live disk that is 17 seeded
canonicals (those carrying a `canonical.json`), all of which remain in `prune_stale`'s `keep` set.
Addresses all four consequences: (1)+(2) slots disjoint, neither deployment can replace the other's
known-good; (3) the outage race is removed with the shared slot; (4) `prune_stale`'s reconciler-dir