The drill is complete. Teardown done in three layers plus Gitea; the live catalog's every `image:` line is proven identical to before. WHAT WAS MEASURED. 21 edges across 19 apps, on scratch guest 9202 through the product's own guarded Update, against a PRIVATE DRILL CATALOG so the live catalog carried no test reference at any point: 14 proven, 3 failed, 4 inconclusive. Each app seeded and read back through its OWN front door, with a negative control on every readback. Ten of the fourteen printed a verbatim migration line. Up from the three apps this project had ever measured. THE RESULT THAT MATTERS. R-618, P1: three of the 53 templates name a health probe the app does not answer, and because the guarded update WAITS on that same probe, a SUCCESSFUL update ends by STOPPING a working app. tandoor was measured serving HTTP 200 on the new version at four samples across five minutes, docker's own healthcheck green, and was then stopped and the household sent to a restore they did not need. zipline and wger are the same defect, both confirmed live. The gate that catches all three is static and cheap: both health checks already sit in the same file. WHAT THE NIGHT ANSWERED that was open. The UNATTENDED HOLD (312.9 s, pressed once, never again) — which needed a purpose-built image store, because the rule that makes automatic updates safe is the same rule that refuses the obvious way to break one. MariaDB across a major through the real button, all four observables, first time. PostgreSQL across a major, refusing exactly as predicted, with the conversion costed at ~9 s of engine work. There is NO single-flight: five updates ran at once and all ended honest. And the two EARLY power-cut phases nobody had cut in. TWELVE NEW ROWS (R-615..R-626), register 303 -> 315, and eight existing rows updated with what was measured — including two CORRECTIONS: R-606 records the pre-flight refusals as reaching an English household in English and they do not, and R-446/R-458 are both narrower than their rows state. Two instrument fixes were needed before anything could be trusted: the unattended caller turned every success into a timeout (R-623), and one of my own reproductions was wrong and is kept labelled with what it actually measured. Interventions: zero. No controller, agent or hub code written. The hub was never touched beyond the floor the operator asked for. Gates: repo_gates.py --fast, all 15 OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
3.3 KiB
B5 — a power cut in the two EARLY phases nobody had cut in
R-520 cut in pulling (nothing had run — the easy case). R-610 cut after starting (the migration
had run — the dangerous case). The two that were left are the ones that touch the customer's COPY
rather than their data.
Instrument limit, stated on both, never glossed: the poll is 200 ms and pct stop returns in
4–10 s, so the phase at the DECISION is observed and the phase at the FREEZE is inferred.
Cut 1 — during backing-up (privatebin, backup_max_age lowered to 1m so the phase happens)
phase 'backing-up' OBSERVED at 2026-09-21T20:07:33.345Z — pulling the plug NOW
`pct stop 9202` returned after 9.65s
After the boot the box said so ITSELF — three positive observables, not an absence:
[appstop] crash recovery: an app-data backup (volume dump) (op "volume-dump:privatebin") was
interrupted and left 1 app(s) stopped — restarting them: [privatebin]
[appstop] crash recovery: restarted privatebin after the interrupted an app-data backup (volume dump)
[stacks] update recovery: privatebin was interrupted in backing-up (started 2026-09-21T20:…)
| the pin | did NOT move |
| the app | running, and a fresh paste seeded and read back → data intact |
| the household reads | „A frissítés megszakadt, mert a vezérlő újraindult, mielőtt az új verzió elindult volna." |
| in English? | No — the same Hungarian sentence on the English page (R-606, the original instance, re-confirmed) |
Cut 2 — during safety-dump (privatebin, a real pending edge)
phase 'safety-dump' OBSERVED at 2026-09-21T20:19:22.234Z — pulling the plug NOW
`pct stop 9202` returned after 3.96s
| recovery lines | none for privatebin — and no update journal on disk |
| the pin | did NOT move (…/paste:2.0.1, unchanged) |
| the app | running, fresh paste seeded and read back → data intact |
| the household reads | the ordinary „Frissítés elérhető — ma" — no interrupted sentence at all |
The two cuts differ, and the difference is the finding rather than a discrepancy. A cut in
backing-up leaves a trace the box acts on at boot (an app stopped by the dump, and an update
recorded as interrupted); a cut in safety-dump leaves nothing to act on, and the box says nothing
because there is nothing to say. Both end in the same place: nothing moved, nothing half-written,
the data readable.
The claim this leg existed to test
A backup artefact half-written must not be left looking whole. No half-written artefact was
found on either cut — the backup listings before and after are in each leg's 00-/01- files,
and the zero-byte sweep found none.
A second thing this leg proved, for free, across a REAL power cut
[bootrecon] "glance" is a boot orphan by intent but is HELD (held after a failed update
(2026-09-21T19:53:02Z) — restore it from its backup to start it)
— NOT starting it; whatever is holding it owns its recovery
09 §6.1 records that three unattended paths honoured no hold before v0.237.0 and now do. That is
now proven across a genuine power cut: the boot sweep met a held app after an unclean shutdown and
deliberately left it alone.