docs: R-182 closed, R-90 closed on measurement, R-86 unblocked, ep0 record corrected
gates / gates (push) Successful in 7s

R-182 CLOSED (controller v0.194.0 + hub v0.90.0/.1), proven live on demo-hp. The
hub's notification_log for the run reads: two per-app failures RECORDED, one
digest SENT naming both, and the customer channel SKIPPED with operator_only.
Against the measured previous behaviour — two failures, one email naming one
app, one leaving no trace anywhere.

Scenario D proved itself on an event I had not planned: disk_critical alarmed on
two filesystems, the second was collapsed by the cooldown, and that collapse is
now visible WITH ITS KEY. Yesterday it would have left nothing at all.

A gap the spec did not anticipate is recorded with its fix: the per-app event
also fires from the periodic sweep, outside any run, so making it record-only
would have created a NEW silence. The sweep emits a digest too, with no run_id,
so it stays under the ordinary hourly cooldown.

ep0: MEASURED on the box — 7757 MB (8 GB), 4 vCPU, and the 4 GiB swapfile
SURVIVED the resize and is active (checked, because a resize is a stop/start).
The 40 GB local disk is UNCHANGED, so no disk figure was touched anywhere.

Five documents corrected — three of which the task's list did not name, found by
searching. Two audit/evidence documents ANNOTATED, body untouched: they record
what was true when written and that is their value.

R-90 CLOSED. R-86 unblocked and re-ranked, stated honestly: 8 GB is comfortable,
not unbounded — the original OOM was a 14.46 GB restore — so the restore-test
cadence should still be paced, just not by fear of the endpoint.

target-selection.md's "D-d did not name ep0 either way" is deliberately left
standing. It is the operator's question, not CC's.

STATUS.md 127 -> 83 lines, items rather than sentences.
This commit is contained in:
2026-08-03 14:00:54 +02:00
parent f21e7caed1
commit e34b614e5b
13 changed files with 279 additions and 279 deletions
+27
View File
@@ -123,6 +123,33 @@ Two rulings, one shape: something became live because someone pushed, not becaus
that bumps a version, before publishing — and a gate that fails on the normal path is one people
learn to ignore.
**S-16 — a backup run NOTIFIES ONCE and RECORDS ALWAYS, and those are different things
(2026-08-03, R-182; controller v0.194.0 + hub v0.90.0/.1).** Measured: nine per-app capture failures
reached the hub, two were mailed, seven were dropped by a cooldown whose key carries no app
identifier — *before* `LogNotification`, so they left no row anywhere.
- **The record:** `recovery_unit_capture_failed`, per app, unconditionally, now routed
**record-only** by the hub (`recordOnlyEvents`) — stored and logged every time, never competing
for an e-mail slot.
- **The notification:** `backup_run_failures`, ONE per run, listing every failed app with its leg
and reason plus the counts and free space. **A clean run emits nothing.**
- **A suppressed operator event now leaves a `suppressed` row** carrying the key that suppressed it —
for every operator type. *"We chose not to e-mail you"* and *"nothing happened"* must never look
identical; that is the whole finding, stated as a rule.
- **The periodic sweep gets a digest too, with NO `run_id`**, so it stays under the ordinary hourly
cooldown. Without it the sweep's failures would be recorded and never notified — a new silence
created while closing one. A real run's digest carries a unique `run_id` precisely so the cooldown
can never collapse a manual run into the nightly one.
- **Why the silence is safe:** the hub's deadline check raises `expected_backup_missed` from report
freshness, independently of any mail the box sends (`monitor/deadline.go:396,417`). **If that check
is ever weakened, this design loses its footing.**
- **Not taken, and why:** putting `app` in the cooldown key. It fixes the swallowing by producing one
mail per failing app — a dozen on a full disk.
**ep0 was rescaled by the operator to a CX33 (2026-08-03): 4 vCPU, 8 GB RAM, measured on the box, and
the 4 GiB swapfile survived. The 40 GB local disk is UNCHANGED** — a CPU/RAM resize only, so no disk
figure in any runbook needed correcting. That closed **R-90** and unblocked **R-86**.
**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
CUSTOMER's** (they can free space, delete files, add a drive) and **a per-app backup capture failure