docs: R-181 closed, R-156 closed, R-110 + R-115 rulings recorded, R-182 filed
gates / gates (push) Successful in 7s
gates / gates (push) Successful in 7s
R-181 CLOSED (controller v0.193.0 + v0.193.1) and proven live on demo-hp for BOTH reserve terms. The reserve is now a per-app, per-run ADMISSION decision taken before the app's first write and covering all three write legs, and it gained a size term. The refusal's wording was not weakened; the behaviour moved so it became true, verified by sha256 tree fingerprint. R-156 CLOSED — papra's template mounts the app's own data root. Precondition re-measured rather than inherited (both boxes were wiped today). Part 4, documentation only, nothing built: - R-110 WAITING-ON-OPERATOR -> READY. Ruling: option (b), the installer's publish channel moves to a TAG. Recorded with the condition that decides whether it works at all — it must cover BOTH the /scripts/ git-sync and the nine files the installer fetches from raw/branch/main. - R-115 WAITING-ON-OPERATOR -> READY. Ruling: mechanism (b), a build-side gate refusing to deploy or vouch an unpublished version. The third instance (agent v0.120.0) would have silently downgraded both demo boxes while succeeding. R-182 NEW: the periodic status refresh has no admission scope, so a refused app re-alerts on every poll (measured: a second alert pair 13s after the run's). Pre-existing in v0.192.0; deliberately not fixed in the R-181 task. capability map: the local-backup row moves to PROVEN-LIVE in BOTH halves. ROADMAP: R-165 collapses to CLOSED; R-181 collapsed into it. 07-backup-architecture.md: the reserve's contract stated as what the code provides (S-1 — an architectural contract changed in the same session). STATUS.md trimmed 150 -> 111 lines, "What's broken" no longer holds shipped work, and the stale "After:" line (pointing at work that shipped on 2 August) is fixed.
This commit is contained in:
+36
-4
@@ -60,10 +60,42 @@ demo boxes were wiped and reinstalled from golden 0.192.0 and taken through clai
|
||||
proved the disk shape *and* the delivery route rather than one of them twice. Live shape on both:
|
||||
`mp0` at `/var/lib/felhom`, `backup=1`, **no `mp1`**; `/var/lib/docker` and `/mnt/sys_drive` both real
|
||||
mounts of its subdirectories via `/etc/fstab`; ONE `df` figure and one device id on all three paths;
|
||||
3/3 reboots each with the binds surviving every time. **What is NOT proven is B2** → **R-181**: the
|
||||
floor guards `captureAllRecoveryUnits` and not `runVolumeDumps`, which is the leg that fills the
|
||||
volume, and its refusal message's "the previous unit is untouched" was measured false. R-165 is
|
||||
therefore **IMPLEMENTED**, not PROVEN-LIVE.
|
||||
3/3 reboots each with the binds surviving every time. B2 was **not** proven on that pass → **R-181**:
|
||||
the floor guarded `captureAllRecoveryUnits` and not `runVolumeDumps`, the leg that fills the volume,
|
||||
and its refusal's "the previous unit is untouched" was measured false. **R-181 CLOSED the same day
|
||||
(controller v0.193.0 + v0.193.1), so R-165 is now PROVEN-LIVE in both halves** — see S-14.
|
||||
|
||||
**S-14 — the reserve is a per-app, per-run ADMISSION decision, not a capture check (2026-08-03, R-181;
|
||||
controller v0.193.0 + v0.193.1).** B2 as first shipped was consulted in exactly one place —
|
||||
`captureAllRecoveryUnits`, a few KB — while `RunDBDumps`' database leg and `runVolumeDumps` wrote the
|
||||
bulk into the same `backups/primary/<app>` tree, first and unguarded. The reserve was therefore
|
||||
consumed by the very write it exists to bound, and the refusal then claimed *"the previous unit is
|
||||
untouched"* about a tree the earlier leg had already rewritten (182,272 B → 2,147,666,432 B under a
|
||||
manifest that had not moved). **Sixth entry in `CLAUDE.md`'s table of shipped guarantees the code did
|
||||
not provide, and the fourth of those found on live hardware rather than by review.**
|
||||
|
||||
- **`internal/backup/admission.go` — `admitApp` is now THE gate**, and every per-app write leg calls
|
||||
it. One verdict per app per run covers all three; they share one per-app root, which is what makes
|
||||
that honest.
|
||||
- **Decided lazily at the app's first write, never once at run start** (app A's dump can put app B
|
||||
under the reserve), **never re-decided between an app's own legs** (that is the split it closes),
|
||||
and **reset per run**.
|
||||
- **Ahead of `DumpAppVolumesSafe`**, which stops the stack as its first act — a refusal decided
|
||||
inside it has already bounced the app. **After** the volume-less check, which has no write to gate.
|
||||
- **Size term added:** *would THIS app's write cross the reserve?*, estimated from the app's previous
|
||||
`.sql` + `.tar`. **No history → headroom-only**, deliberately — otherwise the first backup is the
|
||||
one that can never happen.
|
||||
- **A container-based `du` was MEASURED and rejected**, not waved away: median **~355 ms/volume** over
|
||||
66 runs on demo-hp, on volumes holding tens of KB (container start-up, not the walk). Decisive on
|
||||
top: `docker run` needs the writable layer, so the instrument can fail under exactly the pressure
|
||||
the reserve handles.
|
||||
- **The wording was NOT weakened; the behaviour moved so it became true**, and it is checked by
|
||||
sha256 tree fingerprint, never by reading the log line — the log line is what lied.
|
||||
- **v0.193.1**, found by the proof run itself: a 178 KB estimate printed as `0.00 GiB`, which reads as
|
||||
*no estimate available*. Rendering moved to `humanizeBytes`; arithmetic still in GiB.
|
||||
- **New finding, deliberately not fixed here → R-182**: `GetFullStatus`'s periodic capture sweep has
|
||||
no run scope, so a refused app re-alerts on every status refresh (measured: a second identical alert
|
||||
pair 13 s after the run's). Pre-existing in v0.192.0; R-181 changed neither caller.
|
||||
|
||||
**S-11 — D-c's routing, and why R-158's own proposal was overruled (2026-08-02, R-167 SHIPPED).**
|
||||
Decision D-c splits two signals by AUDIENCE, and the split is the ruling: **a fill warning is the
|
||||
|
||||
Reference in New Issue
Block a user