v0.227.1: the damage classifier matched restic's ordinary progress output
gates / gates (push) Successful in 11s

A patch and not a rebuilt 0.227.0: that tag was already running on demo-hp, and
re-pushing changed bytes under a live tag is the :latest hazard with extra steps.

looksLikeRepositoryDamage matched bare "pack ", "tree ", "snapshot ", "blob ". A
HEALTHY restic check prints "check all packs" and "check snapshots, trees and
blobs" -- so any check that failed for a NON-damage reason, a connection dropped
mid-run for instance, would have been classified as a corrupted repository and
told the customer their backups may be damaged. That is the false alarm that
teaches an operator to ignore the true one.

Caught by the NEGATIVE control, built from the real bytes of a real passing
check on demo-hp. The spec made the negative control mandatory and this is what
it was for: a control that has only ever seen the failing case proves nothing.

Signatures are now phrases from restic's own error wording.

Also in this commit: CONTEXT.md records the three rulings (take the flag and
skip, due-ness not a weekday, publish on OffboxReportStatus not the R-331 dead
fields) plus the measurement a future session would otherwise assume wrongly --
THE STRUCTURE CHECK DOES NOT CATCH SILENT CORRUPTION. README documents the job,
the route and the config, and corrects a line that listed four debug backup
routes when only two exist. REUSE gains three rows, including one that records
R-398 was my own mistake so nobody re-files it.
This commit is contained in:
2026-08-30 21:22:23 +02:00
parent 0d52a42c17
commit 45770f2282
6 changed files with 270 additions and 8 deletions
+29 -1
View File
@@ -7,7 +7,35 @@
>
> Ask Claude Code: "Please update CONTEXT.md with what we did today"
Last updated: 2026-08-30 (v0.226.0 — R-353/R-357/R-358/R-360: the restore tells the truth)
Last updated: 2026-08-30 (v0.227.1 — R-359/R-397: the off-site store gets checked)
> **2026-08-30 — v0.227.0/v0.227.1. THREE RULINGS, recorded so none is re-litigated.**
>
> **1. The integrity check TAKES the single-writer flag and SKIPS rather than waits.** `resticStep`
> self-heals a crash lock by running `unlock --remove-all` and retrying, and its own comment records
> why that is safe: every caller holds the in-process single-flight mutex, so any lock it meets is
> stale. A check that did not take the flag could meet a **live** `forget --prune`'s lock from this
> same box, remove it, and retry over the top of it. It skips rather than waits because waiting would
> pin the nightly backup behind a check, and a skip costs nothing — due-ness makes tomorrow try again.
>
> **2. Due-ness, not a weekday.** A daily job asking "is the last successful check older than 7 days?"
> catches up after downtime; a Sunday-gated job silently skips a week every time the box is off on a
> Sunday. **R-341 is that failure**, and no `Weekly` primitive was added to the scheduler.
>
> **3. The result is published on `OffboxReportStatus`, NOT on `report.BackupReport`'s `IntegrityOK` /
> `LastIntegrityCheck`.** R-331 retired those the day before, because the hub card rendering them read
> `Integrity Unknown` for every customer forever. Giving them a live value would resurrect a card that
> was deliberately removed and break `TestBackupReport_DeadFieldsStayZero`.
>
> **AND THE MEASUREMENT THAT MATTERS MOST, because it is the thing a future session will assume
> wrongly: the structure check that ships ON does NOT catch silent corruption.** Measured on demo-hp —
> a pack corrupted without changing its size returned `no errors were found`, exit 0. Only
> `--read-data*` caught it. The structure check does catch missing packs, broken indexes and unreadable
> snapshots, which are real; it does not re-hash pack contents. **R-399 is therefore not merely a
> bandwidth question.** The cost curve is measured and small at today's store size (100% costs +12%
> wall-clock over structure-only, 39.2 s vs 35.0 s on 134.3 MB) but does NOT extrapolate — the
> structure check's cost tracks the index, read-data's tracks the data.
> **2026-08-30 — v0.226.0. TWO RULINGS THIS SESSION MAKES, recorded so neither is re-litigated.**
>