docs(v0.232.0): CHANGELOG, three CONTEXT rulings, README (R-411/408/407, R-414, R-412a)
gates / gates (push) Successful in 14s

This commit is contained in:
2026-09-01 10:36:52 +02:00
parent 8b55de734c
commit 62c6a8a98a
3 changed files with 114 additions and 3 deletions
+54
View File
@@ -1,3 +1,57 @@
## v0.232.0 — one writer at a time, and a check that can actually run (2026-09-01, R-411/R-408/R-407, R-414, R-412a)
**MinAgent: 0.129.0** (unchanged)
**THE WALK FOUND THREE MORE ENTRY POINTS THAN THE REPORT DID.** R-411 named one function missing
`acquireRunning`. Fixing it and then pinning the invariant with an AST walk surfaced **four** in total:
| function | why it mattered |
|---|---|
| `RestoreOffboxScratch` | the reported one |
| `OffboxRestorePrepareFull` | **the second request in the customer's own two-step full restore, and the one that actually shells `restic stats`.** The UI reaches it FIRST, so flagging only the restore would have left the collision reachable by the ordinary path |
| `RestoreSharesScratch` | R-411's exact shape on the **shares** tier: `unlockStale` + `resticStep`, a live web caller, and its sibling `PlaceSharesRestore` has always taken the flag |
| `RestoreOffbox` | no production caller today, but the same pattern — flagged so a future caller inherits the guard, not the defect |
`OffsiteInventoryList` is **registered exempt with its reason**: it issues only `restic snapshots
--json`, measured not to take a lock, and flagging it would make browsing a page refuse during a
backup for no safety gain.
- **THE REAL DELIVERABLE IS THE WALK, not the acquire.** `offbox_integrity.go:28` asserted *"Every
off-site operation takes `acquireRunning`"* since v0.227.0, nothing checked it, and it was **false
for months** — the **ninth** instance of this project's most-repeated class. `resticStep`'s licence
to run `unlock --remove-all` rests entirely on that sentence, so a false sentence there is a licence
to delete a live operation's lock. It is an **AST walk, not `strings.Contains`** — a commented-out
call still contains the string. **Red-proofed twice:** removing the acquire fails it naming
`RestoreOffboxScratch`; an unregistered fake entry point fails it naming the fake.
- **R-407 — two sentences corrected in place, not deleted** (R-360's rule). `check` *does* write a lock
file; and **`restic stats` takes one too**, which is the fact nobody had and the one that made R-411
possible at all.
- **R-414 — the proof could not run at all on a box with no registered drive.** The determination came
out as **neither** "missed" nor "deliberate": R-356's own test comments say the scratch resolver
*"still resolves … only the DESTINATION moves"*, so it was **out of scope**, and it was never ruled
out on state-only grounds — the one comment about a `systemDataPath` fallback belonged to
`PlaceOffsiteRestore`, concerned bulk **userdata**, and R-356 overruled even that. So §6.3's rule
applies and **now has a fourth consumer**.
- **The fallback is SCOPED**, because the two callers ask different questions and one predicate
answering both is the R-356 defect itself: a **unit-only** restore may fall back to the system data
path (§7 records as `[FACT]` that a driveless app's unit already lives there indefinitely, and that
the same-device placement is *"intended, not a defect"*); a **full** restore keeps today's refusal,
because it pulls bulk userdata onto a state-only tier.
- **And the silence ends either way:** a proof that cannot start records `cannot_run` rather than an
`Err`, so `last_proof_result` is **never absent** — absent already means *"controller too old"*, and
a second meaning on one field is the `StatsKnown` trap one level up. Recorded **without** advancing
per-snapshot due-ness, so the app stays retryable once a drive is registered.
- **A defect I introduced and live validation caught:** the fallback resolved a scratch the cleanup
then refused to delete (*"not inside a proof root"* — its accepted-roots list is built from
registered drives, which a driveless box has none of). Every nightly proof would have left a copy
behind on exactly the boxes the fallback exists for. Fixed, and pinned by a pair of tests — one that
the copy IS deleted, one that a path outside every proof root is still **refused**.
- **R-412 leg 1** — a per-app push whose unit carried no dump and no tar now says so, at `WARN`.
Wording only; no guard, and the capture is untouched (08 §8.2). **Leg 2 stays OPEN.**
- 18 new tests, 1689 → 1707. Red-proofs run and reverted byte-identical for the walk (×2), the
driveless verdict, the push wording and the scratch leak.
---
## v0.231.0 — the box proves its own off-site copy still holds something (2026-08-31, R-87)
**MinAgent: 0.129.0** (unchanged)