Broke the pattern of re-probing B-redfix-8 (wakes #37-40, operator-only, adds nothing) and instead attacked the artefact the operator acts on: "mergeb5f2b10, NOT 07fc6d4". Applied this phase's own lesson — verifying a fix's stated invariant beats verifying its shas, and mutation-testing is what makes a "+N tests" claim meaningful. - Lineage:b5f2b10=07fc6d4+ exactly the F-redfix-4 fix; fix symbols absent at07fc6d4. - Reproduced the pre-fix defect cold (stdlib only; no pytest/awk/curl on orchestrator, no python3 on cc-ci): both canonical + live reconciler resolved to <root>/keycloak/snapshot, no guard. - Invariants GREEN atb5f2b10. Mutation A (canonical_ns -> bare recipe) and Mutation B (guard -> no-op) each go RED on exactly the right invariant; mutation A leaves the non-provider invariant PASS, so the probe is specific, not globally fragile. - Guard is wired into both destructive paths, ahead of the destructive work. Drove the real F-redfix-4 scenario through the PUBLIC api: refused, live known-good intact. - Disbelieved then confirmed two Builder claims: "10 new tests" (exactly 10, coverage matches) and "no migration on cc-ci" (keycloak slot holds only last_good, no canon-* slot) — the latter is load-bearing because the fix ADDS a way for restore() to raise, and B-redfix-5 leaves the rollback restore() outside the try/except. Unreachable today; recorded as a merge precondition. - B-redfix-5 re-verified accurate atb5f2b10(warm_reconcile.py:533-537). - "Zero blast radius": 8/8 sampled canonicals on cc-ci record domain=warm-<recipe>, guard passes. Verdict: merge guidance CONFIRMED. No new finding. M1+M2 PASS stand, DONE stands, no VETO. B-redfix-8 unchanged (OPEN/HIGH/operator-rotation-only, not re-probed by design); B-redfix-5 deferred. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SoraVF2hkEMExHswFX1g4M
This commit is contained in:
@ -1206,3 +1206,66 @@ declares a still-live public credential inert on a broken probe. **No new findin
|
||||
M1 + M2 PASS stand; `## DONE` stands; no VETO. B-redfix-8 remains **OPEN, HIGH, operator-rotation-only** —
|
||||
sole close path is a correctly-computed sentinel that differs from `3fcea78925015fc9`, which only operator
|
||||
rotation produces. I cannot rotate a Class-A1 input (§4.4) nor rewrite published history (`--force` forbidden).
|
||||
|
||||
---
|
||||
|
||||
## Wake #41 — 2026-07-09T08:10Z — merge-target guidance verified BEHAVIOURALLY (mutation + e2e). No new finding.
|
||||
|
||||
Deliberately did **not** re-probe B-redfix-8 for a fifth time (wakes #37–#40 all did; it is
|
||||
operator-rotation-only and re-confirming adds nothing). Instead attacked the one artefact the operator
|
||||
will actually **act on**: the instruction *"merge `redfix-m2-harness`@`b5f2b10`, NOT `07fc6d4`"*. If that
|
||||
is backwards, the operator merges the F-redfix-4 defect. Prior wakes only ever checked that claimed
|
||||
artifacts **existed and matched shas** — which is precisely the weak check that let F-redfix-4 hide for
|
||||
seven re-confirmations. So this wake tested the fix's **stated invariant**, and mutation-tested the test.
|
||||
|
||||
**Lineage.** `b5f2b10` = `07fc6d4` + exactly one commit (`fix(keycloak): key warm state by stack
|
||||
namespace…`). `canonical_ns` / `_assert_slot_not_foreign` present at `b5f2b10`, ABSENT at `07fc6d4`.
|
||||
`b5f2b10` is *not* an ancestor of `main` — correct and expected: nothing is merged; the operator merges.
|
||||
|
||||
**Pre-fix defect reproduced from cold** (worktree @ `07fc6d4`, stdlib only — no pytest anywhere; `awk`,
|
||||
`curl`, `which` absent on the orchestrator, `python3` absent on cc-ci):
|
||||
domains already differed (`warm-keycloak…` vs `warm-canon-keycloak…`) yet `registry_path` → `app_dir(recipe)`
|
||||
and `seed_canonical` → `warmsnap.snapshot(recipe, …)`, so **both resolved to `<root>/keycloak/snapshot`**,
|
||||
with no guard. Same probe @ `b5f2b10` → no collision. Caveat, stated plainly: I demonstrated the **slot
|
||||
collision + absence of guard**, not an executed clobber — `snapshot()` needs docker past the guard.
|
||||
|
||||
**Invariants @ `b5f2b10` (all GREEN):** slot/domain/app_dir disjoint for every `WARM_DOMAINS` recipe;
|
||||
non-providers keep the bare `<recipe>` ns (gitea/discourse/mumble/bluesky-pds/mattermost-lts); guard raises
|
||||
`SnapshotError` on a foreign slot, permits its own, permits an unclaimed slot.
|
||||
|
||||
**Mutation test — the probe has teeth.** Mutant A (`canonical_ns` → `return recipe`) → RED on the 3
|
||||
disjointness invariants, invariant 2 still PASS (specific, not globally fragile). Mutant B
|
||||
(`_assert_slot_not_foreign` → no-op) → RED on exactly the foreign-slot invariant. Both killed; tree restored.
|
||||
|
||||
**Guard is wired, not dead code.** Called at `warmsnap.py:158` in `snapshot()` (BEFORE `_assert_undeployed`
|
||||
and before the staging teardown) and `:209` in `restore()` (before the volume clear). Drove the real
|
||||
F-redfix-4 scenario through the **public** API — `snapshot(live_slot('keycloak'), canonical_domain('keycloak'))`
|
||||
→ refused with the F-redfix-4 message, live known-good intact. Structurally blocked *and* behaviourally blocked.
|
||||
|
||||
**Two Builder claims disbelieved, then confirmed:**
|
||||
1. *"10 new tests"* → exactly 10 `def test_` added, names match the claimed coverage incl. foreign-slot
|
||||
refusal in **both** `snapshot` and `restore`. (Could not execute them: no pytest on either host.)
|
||||
2. *"no migration on cc-ci — keycloak's dir holds only `last_good`"* → cold `ssh cc-ci`:
|
||||
`/var/lib/ci-warm/keycloak/` contains **only `last_good`** (no `snapshot/`), and **no `canon-*` slot exists**.
|
||||
|
||||
This mattered: the fix **adds a new way for `restore()` to raise** (the guard), and B-redfix-5 leaves the
|
||||
reconciler's rollback `restore()` outside the try/except. Composed, a foreign-slot raise in rollback would
|
||||
leave live keycloak undeployed after `abra.undeploy()`. That composition is **unreachable on cc-ci today**
|
||||
precisely because the keycloak slot carries no snapshot meta. Recorded as a merge precondition, not a defect.
|
||||
|
||||
**B-redfix-5 re-verified accurate at the merge target** (`warm_reconcile.py:533-537`): `abra.undeploy` →
|
||||
`wait_undeployed` → `warmsnap.restore` sit outside the try/except that guards only the upgrade (520-525);
|
||||
`deploy_version` at 537 is likewise unreached if `restore()` raises. DEFERRED.md's description still holds.
|
||||
|
||||
**"Zero blast radius on the 15 existing canonicals"** spot-checked on cc-ci: 8/8 sampled
|
||||
(gitea, ghost, drone, mumble, plausible, immich, hedgedoc, n8n) record `domain=warm-<recipe>…` in
|
||||
`snapshot/meta.json`, which is exactly what post-fix `canonical_domain()` returns for a non-provider →
|
||||
guard passes, no migration.
|
||||
|
||||
**Verdict: merge guidance CONFIRMED — `b5f2b10` is the correct merge target; `07fc6d4` carries the defect.**
|
||||
No new finding. M1 + M2 PASS stand; `## DONE` stands; **no VETO**. B-redfix-8 remains OPEN/HIGH/
|
||||
operator-rotation-only (unchanged, not re-probed this wake by design). B-redfix-5 remains deferred/open.
|
||||
Merge precondition for the operator: `/var/lib/ci-warm/keycloak/` must still hold no `snapshot/` at merge
|
||||
time (it doesn't today) — otherwise B-redfix-5 × the new guard can wedge the live OIDC provider on rollback.
|
||||
Did not read JOURNAL-redfix.md before forming this verdict; read the fix's commit message only as git history
|
||||
(code), and independently re-derived every claim I took from it.
|
||||
|
||||
Reference in New Issue
Block a user