CAMPAIGN-11 Phases 2+4: the fault journal, the campaign document, and hub v0.97.1's missing heading
gates / gates (push) Successful in 8s

Phase 2 (eleven injected faults) and the §4 positives that were owed.

- §4.1 MEASURED, twice: the box's rendered GetFloor() is 0.200.0, and a
  cold-started controller logs "settle-gate: GO — at/above floor 0.200.0"
  against the same line reading "floor still unknown" while the hold was in
  force. Also corrects the brief's plan: SetFloor's line is u.dbg(), gated on
  logging.level=debug and written to the logger, so it can NEVER reach the
  debug ring — a restart alone would not have produced it.
- §4.2 still NOT measured, deliberately: the venue has an off-site target, so
  needsOffsiteCredential correctly returns false. Recorded, not inferred from
  the unit test.
- F1 PARTIAL, F2 PASS, F3 FAIL, F4 FAIL, F5 PASS, F6 PASS, F8 PARTIAL.
  F3+F4: a hub outage and a stopped agent are both rendered as "this code does
  not open your package", in 0.056 s and 0.030 s — no unseal attempted. The
  agent's own err field distinguishes them exactly and it is discarded at the
  HTTP boundary; the R-216 capability gate answers source=version and cannot
  see reachability.
- R-217's fix HOLDS under exactly its fault (F5), verified with the false-claim
  strings absent and accented positive controls present.

hub/CHANGELOG.md: v0.97.1 had no heading of its own — the change was written
into the v0.97.0 entry while the deployed tag is 0.97.1. Given its own entry,
marked as added retroactively. Second occurrence of the class (agent 0.90.1).

Evidence: documentation/tests/campaign11-evidence-2026-08-05/journal-phase24.md
No product code changed.
This commit is contained in:
2026-08-05 23:13:47 +02:00
parent 3a539ea530
commit 04ac465da6
3 changed files with 841 additions and 8 deletions
+28 -8
View File
@@ -1,3 +1,31 @@
## v0.97.1 — the held-floor REASON must match the hold's CAUSE (2026-08-05, CAMPAIGN-11 follow-on)
> **Entry added retroactively 2026-08-05 (CAMPAIGN-11 Phase 2).** The change shipped and **is** the
> deployed image (`felhom-hub:0.97.1`, commits `a7f1d27` + `79e31ac`), but it was written into the
> **v0.97.0** entry instead of its own — so a reader matching the running tag against this file found
> no `v0.97.1` heading at all. Second occurrence of a version deployed without its own entry (the
> first was agent `0.90.1`). Nothing about the change is new here; only its heading is.
Adding a second hold reason and leaving both surfaces printing the first is `CLAUDE.md`'s corollary,
and it happened here: the freshly deployed hub logged
```
managed floor HELD for c11: agent "0.125.0" < MinAgent 0.113.0
```
— a comparison that is **FALSE** (0.125.0 is *above* 0.113.0) for a box held because its floor sat
above the vouched golden. Both the ACK log line and the Hosts-dashboard `HeldReason` now come from one
`ManagedFloorDecision.HoldReason()`, with `RequestedFloor` kept so the message can name the floor that
was asked for (`Floor` is cleared to `""` on a hold, and a reason naming an empty floor tells the
operator nothing). `TestResolveManagedFloor_HoldReasonMatchesTheCause` pins each reason to its cause.
**A true alarm that misdescribes itself is one the operator learns to dismiss.**
**Confirmed live in CAMPAIGN-11 Phase 2**: the corrected sentence is what the hub logged for c11 every
15 minutes until the golden rebake released the hold —
*"held: floor 0.200.0 is ABOVE the vouched golden 0.192.0, so its agent requirement is unknown — vouch
a golden carrying the floor's controller (publish-train rule 1)"* — and it stopped, as it should, once
golden 0.201.0 was vouched.
## v0.97.0 — the floor stops being served past the agent it depends on (2026-08-05, CAMPAIGN-11)
**R-216, the hub half.** `ResolveManagedFloor` exists to *"never push a controller past the agent it
@@ -41,14 +69,6 @@ either way. **Only rows that actually carry an identity blob count**: the pre-v0
retain nothing the screen could be talking about. It is a boolean and a timestamp; it grants **no read
path**, which is still unbuilt (R-199's inventory).
**And the hold REASON now matches the hold CAUSE.** Adding a second reason and leaving both surfaces
printing the first is `CLAUDE.md`'s corollary, and it happened here: the freshly deployed hub logged
`managed floor HELD for c11: agent "0.125.0" < MinAgent 0.113.0` — a comparison that is FALSE
(0.125.0 is above 0.113.0) for a box held because its floor sat above the golden. Both the ACK log
line and the Hosts-dashboard `HeldReason` now come from one `ManagedFloorDecision.HoldReason()`, and a
test pins each reason to its cause. A true alarm that misdescribes itself is one the operator learns
to dismiss.
Tests: `managed_floor_test.go` — the campaign's exact numbers, held-regardless-of-agent, Scenario C
(uncoupled untouched), floor==golden unchanged, unparseable golden. **Red-proof: removing the
floor-above-golden branch reproduces the campaign's measurement exactly.**