9842c52853
Records the wire encoding (string enum, empty = legacy not unknown) and the two judgement calls: the fail-safe direction is unchanged (unknown is still due), and a service with no lister stays ABSENT because calling it unknown would starve a genuinely new box on a pre-R-84 build.
71 lines
3.8 KiB
Markdown
71 lines
3.8 KiB
Markdown
# REPORT — R-88 Part 2: the agent can say "unknown" (v0.105.0) (2026-07-27)
|
|
|
|
**Overwritten** per the standing rule. Agent **v0.104.0 → v0.105.0**. Producer half of a wire
|
|
contract; the controller consumer is v0.178.0.
|
|
|
|
## What was broken
|
|
|
|
`newestArchiveOn` promised in its own doc comment that *"errors and unsupported services degrade to
|
|
'unknown', never to 'no backup'"*. Its `(time.Time, bool)` signature made that **impossible**: an
|
|
error and a genuine not-found both returned `(zero, false)`, so `/backup/due` emitted a POSITIVE
|
|
`"no successful backup recorded yet"` with a nil age. The controller read that as *never backed up*,
|
|
fired its window-gate safety valve, and quiesced customer app stacks **outside** the backup window —
|
|
what happened during the 2026-07-27 PBS outage. The comment described an intent the type forbade.
|
|
|
|
## The wire encoding, and how the zero value is handled
|
|
|
|
**A string enum**, matching the repo's existing convention (`phase` on `/backup/status`):
|
|
|
|
```
|
|
age_state: "known" | "absent" | "unknown" (omitted entirely by a pre-v0.105.0 agent)
|
|
```
|
|
|
|
The zero value is `""`, and it means **"legacy agent, no information"** — never "unknown". A `bool`
|
|
would have made the legacy case indistinguishable from a real `false`, which is the trap the task
|
|
named. The controller maps `""` (and any unrecognised future value) to `AgeStateLegacy` explicitly.
|
|
|
|
Internally `archiveLookup` (`found`/`absent`/`unknown`) replaces the old bool, so the doc comment's
|
|
promise is now something the type can actually express.
|
|
|
|
## Two decisions worth stating
|
|
|
|
**The fail-safe direction is unchanged: unknown is still DUE.** An agent that cannot read the storage
|
|
must never suppress a backup. Only the *window-gate bypass* narrows.
|
|
|
|
**A service with NO lister deliberately stays `absent`, not `unknown`.** This broke a pre-existing
|
|
test (`TestBackupDue_ServiceWithoutLister_UnchangedBehaviour`) and the test was right: calling it
|
|
"unknown" would stop the controller firing its first-backup valve on a pre-R-84 build, so a genuinely
|
|
new box would never back up outside its window and nobody would notice for weeks. On that path the
|
|
in-memory record is the only registry that exists, so its absence means "no backup recorded" in the
|
|
only terms available. `unknown` is reserved for a lister that was asked and could not answer.
|
|
|
|
An **unparseable** in-memory timestamp is now `unknown` too — a backup did happen, we simply cannot
|
|
date it. It previously fell through to the same positive "never" claim.
|
|
|
|
## Tests — 29 packages ok, 0 failed; `build`/`vet`/`test` each rc=0, run separately, vet unpiped
|
|
|
|
+5. Red-proofs observed and restored, in both directions:
|
|
|
|
| Mutation | Observed |
|
|
|---|---|
|
|
| error path → `archiveAbsent` (the pre-fix collapse) | `an unreadable storage must report age_state="unknown", got "absent" — that is a POSITIVE claim of 'never backed up' built out of two absences` |
|
|
| `!found` → `archiveUnknown` (the over-correction) | `a genuine never-backed-up tier must report age_state="absent", got "unknown" — the controller only licenses a first backup outside the window on ABSENT` |
|
|
|
|
## Deployed — producer BEFORE consumer
|
|
|
|
demo-hp then demo-felhom, both `felhom-agent 0.105.0`, service active, previous binary kept as
|
|
`.bak-0.104.0`. **Verified on the live wire** from inside guest 9201, over the exact route the
|
|
controller calls:
|
|
|
|
```
|
|
tier=local due=True age_state=known age_seconds=91097 reason=older than cadence
|
|
tier=felhom-pbs due=False age_state=known age_seconds=100172 reason=within cadence window
|
|
```
|
|
|
|
## NOT yet live-validated
|
|
|
|
- **No `unknown` state has ever been observed on real hardware.** Both boxes report `known`; the
|
|
unknown path is unit-proven only, and reproducing it live means making PBS unreadable, which must
|
|
not be done to ep0.
|
|
- The `absent` path is likewise unobserved live — it needs a genuinely fresh tier.
|