R-456 (doc half): a partly-dead stack is not a boot orphan — the rule written in 02-controller-module-map.md; the test pin is owed to the next release
gates / gates (push) Successful in 19s

This commit is contained in:
2026-09-13 19:48:11 +02:00
parent bcb65984cd
commit 8914ab089e
2 changed files with 12 additions and 1 deletions
@@ -143,6 +143,17 @@ want this running?* — with the same three-way table, absent falling back to th
container count in both. Their agreement is pinned from both sides against one fixture table, because
an import cycle prevents testing them together. R-170 closed the last gate that still guessed.
**A partly-dead stack is NOT a boot orphan — written down (R-456, 2026-09-13).** `isBootOrphan` requires
the stack as a WHOLE to be down: one live member (`bookstack-db` running while `bookstack` is gone)
keeps the stack out of the sweep, although `desired_state: running` is recorded and the app container
is missing. Measured 2026-09-02 on demo-hp: `docker rm -f bookstack` → the sweep found only `bentopdf`;
removing `bookstack-db` too made the whole stack an orphan and the next pass repaired it in 6.3 s.
This is deliberate as far as anyone can tell — repairing half a stack while its database is live is not
obviously safe — and the customer IS told, because `classifyRunStates` counts a degraded stack as down
(`StateDegraded` is in `IsDownState`). What does not happen is the automatic REPAIR. **The rule is
recorded here so it is not re-derived from an absent observable; the test that pins it is owed to the
next controller release** (R-456 stays open for that half).
**The sweep observes a SETTLED fleet, not a single early sample.** It samples (name, state, container
count) every 5 s, calls the fleet settled after 3 identical samples, and sweeps **once**, at the end.
The window ends on settled or a 50 s budget, and the log says which. Two constraints bound it: