R-85 Phase 4: docs — the UNATTENDED path is documented as unproven

- ROADMAP: R-85 row. Code SHIPPED; rotation NOT YET OBSERVED LIVE, stated as
  such rather than written as done.
- Capability map: a new row for UNATTENDED restore-proof, IMPLEMENTED not
  PROVEN-LIVE, kept distinct from the R-82 row that a MANUAL selftest earned.
  That distinction is the same one the activation-vs-arrival split made.
- 03-host-agent §8: the scheduler covers every tier, oldest-proven first; the
  spec is per-run; a restore-test joins the one-heavy-op gate. The safety
  properties that must not be re-derived are listed.
- 07: restore-proof recorded as a per-tier property. Doc still NOT ratified.
- 06: corrects S4.1's 'the offsite restore-test now runs unattended' — it
  silently stopped being true when local_backup_target was retargeted to 'local',
  the SECOND time in that doc that a correct mechanism was broken by its input
  changing underneath it.
- CONTEXT + REUSE.

Hub gate green (17 packages, rc=0).
This commit is contained in:
Claude Code
2026-07-27 07:33:40 +02:00
parent b802a9e7de
commit 57ba3c7c8c
7 changed files with 67 additions and 1 deletions
+27
View File
@@ -21,6 +21,33 @@ reader meets the warning before the content, not after acting on it. Origin:
versions stale (live v0.173.0), and cited as authoritative throughout the R-80 diagnostic. Ratifying
or retiring it is → **R-83**.
- **2026-07-27 — R-85: the DR tier is restore-tested UNATTENDED, and its failure is HEARD.** agent
v0.104.0 + hub v0.77.0. R-82 proved a PBS restore round-trip **by hand**; three defects kept the
unattended path from covering it. (a) `buildRestoreTestScheduler` built ONE runner on
`cfg.Backup.BackupTarget()`, so the offsite tier's archives were never candidates — the DR tier
could not be restore-tested unattended AT ALL. (b) the `Spec` was an immediately-invoked function
evaluated once at daemon start, so nothing tier-varying was expressible and any config change
stayed stale until restart. (c) a failed restore-test was a `[WARN]` line with **no event, no
notification, no gauge** — true for the LOCAL tier that was already being tested, so the loudest DR
signal this system produces was inaudible. **(c) was the one that mattered:** rotating tiers
without it would only mean two tiers can fail silently instead of one.
**Ruling (operator, 2026-07-26): oldest-first (Option 1)** — never-proven sorts first, no cadence
knob; the per-tier last-proven timestamp is reported so the achieved interval can be **measured**
before anyone decides a knob is needed.
**Shipped:** per-run `SpecBuilder`; `PickRestoreCandidateOn` (a tier with no archive NO-OPS);
persisted `RestoreTestState` (survives restart; credit only on SUCCESS); `backup.InFlight`, the
host-wide one-heavy-op gate shared with the backup path (a LINK concern — an offsite restore pulls
multi-GB over the tunnel a backup pushes one); hub `restore_test_failed` / `restore_test_stale`,
kept DISTINCT and anchored on R-81, operator-tier only.
**Also fixed a time bomb I planted in Slice C:** a deadline test hard-coded the incident timestamp
`2026-07-18T18:31:06Z` while comparing against the REAL clock — harmless under one 26h threshold,
but once the offsite tier got an 8-day limit it passed all day and began failing at exactly 18:31
UTC, 8 days later. A test that passes at commit time and fails hours later is worse than one that
fails immediately.
**NOT yet proven:** rotation has not been observed selecting both tiers across consecutive
UNATTENDED cadences — a multi-day window at a 24h cadence. Manual restore-proof IS proven (R-82).
Spec: `documentation/backlog/SPEC-r85-phase4-5-2026-07-26.md`.
- **2026-07-26 — R-82 SHIPPED: the backup target split (local daily + offsite weekly).** agent
v0.97→v0.102.0, controller v0.174→v0.175.0, hub v0.76.0, host-install 1.20.0. `BackupTarget()`
returned ONE string and `BackupCadence()` ONE 24h window, so "local daily AND PBS weekly" was not