docs: STOP-1 + STOP-2 evidence — all three legs PROVEN LIVE; new R-55

Dead primary: degraded in 13 s, exactly one app_start_failed, banner rendered and
self-cleared. Boot orphan: recovered in one attempt with zero alerts. Dead dhclient:
detected in 57 s on process liveness while the lease was still live, healed 120 s after the
kill — the tunnel never dropped, so the outage was prevented rather than observed.

P1 answered as a by-product: bookstack StartedAt == the moment bootrecon StartStack
returned, so unless-stopped did NOT resurrect it. F5 hypothesis confirmed.

New R-55, surfaced by the leg designed to prove the opposite: the boot bind gate recreates
and STARTS every deployed drive-backed app unconditionally, so a customer Stop does not
survive a reboot for those apps. Predates R-52 and does not implicate it, but it narrows
R-52's practical scope and needs a ruling.
This commit is contained in:
2026-07-21 12:56:39 +02:00
parent 907e5ce65c
commit 3d28862db3
3 changed files with 34 additions and 8 deletions
+29 -4
View File
@@ -65,15 +65,40 @@ Endpoint/host-level, no browser (none on DooPlex). Everything claimed live in th
reports was read out of journald or the agent's own capability self-check on felhom-pve. No claim in
any of the three reports rests on a test that only proves a seam.
## 5. An ordering question for the operator (STOP-1 vs STOP-3)
## 4b. The STOP legs RAN — all three (2026-07-21, operator-present)
The ordering below was accepted, executed, and all three legs passed. Full evidence chains are in
the two implementation reports and in the ROADMAP rows; the capability-map row is now
**PROVEN-LIVE**. Headline: dead primary → `degraded` in **13 s** with exactly one event; boot orphan
→ recovered in **one attempt** with **zero** alerts; dead dhclient → detected in **57 s** on process
liveness alone and healed **120 s** after the kill, roughly 80 minutes before the outage would have
started — `cloudflared` never dropped (`Up 29 hours`).
**One real gap surfaced, and it is the opposite of what the leg was designed to prove → new R-55.**
STOP-1's R-52 leg was meant to show that a customer's deliberate Stop survives a reboot. It does
not, for any **drive-backed** app: the boot bind gate (`internal/web/intermediary.go`) selects on
`Deployed && HDD_PATH` alone and runs `StopStack` + `StartStack` on every match, never consulting
whether the app was stopped on purpose. immich, stopped from the UI seconds earlier, came back
running. **R-52 is not implicated** — its own gate behaved exactly as specified (immich, at zero
containers, was never a candidate), and this behaviour predates it. Two consequences are worth an
operator ruling: a customer's Stop is silently undone on drive-backed apps, and R-52's practical
scope is narrower than the brief assumed, because the gate reaches every drive-backed app first.
**P1 is answered, as a free by-product of that leg.** bookstack carries `restart=unless-stopped`,
the Docker daemon came up at ~10:53:15Z, and the container's `StartedAt` is `10:53:28.05Z` — the
exact moment `bootrecon`'s `StartStack` returned. Docker did not resurrect it; the F5 hypothesis is
confirmed.
## 5. The ordering question (resolved)
The brief's Phase A says **do not hand-deploy** the controller — the floor save at **STOP-3** is what
deploys 0.156.0, banking another single-fire self-update datapoint. But **STOP-1 exercises the
controller legs**, which need 0.156.0 to be live. As written the two are in the wrong order.
The resolution that keeps both intentions is: **do the STOP-3 controller floor save first** (floor →
`0.156.0`), let the box self-update — that IS the R-23 datapoint — and then run STOP-1 against the
new version. The agent half of STOP-3 (manifest → 0.92.1) is independent and can happen at any
Resolved as: **STOP-3's controller floor save first** (floor → `0.156.0`), box self-updates — that
IS the R-23 datapoint — then STOP-1 against the new version. **Done, and the datapoint is banked:**
`[selfupdate] Post-update startup: update successful (0.155.0 → 0.156.0)` followed by
`Current version 0.156.0 is up to date` — one swap, no re-fire. The agent half of STOP-3 (manifest → 0.92.1) is independent and can happen at any
point. Flagged rather than assumed, because reordering an operator's STOP sequence is not CC's call.
## 6. Follow-ups this session surfaced (none actioned here)