0011 — A seat EMITS its version; a seat nobody can read is UNKNOWN, never current
- Status: Accepted
- Date: 2026-09-07
- Deciders: the session closing
p5-fleet-deploy-trinityon the fail-marker tracker, writing up the decision made while building the fleet-deploy reader (agent-smith#415). Written at decision time, per ADR-0004 — the reasoning would otherwise have lived only in a PR body. - Relates to: agent-smith’s ADR-0001 (the multi-agent seam: one checkout, several seats — that repo’s numbering; this repo’s 0001 is the Architect singleton), ADR-0003 (rungs integrate by signals, never by calls), ADR-0009 (a signal must fail when the system fails).
The problem, paid for in a fix that shipped and never arrived
agent-smith PR #376 fixed the false-amnesia banner — the reply that opens
"I don't have this thread's earlier turns for this reply". The fix was
verified the way this fleet verifies things: zero occurrences from Smith's own
checkout after it merged.
On 2026-09-07, between 02:39 and 02:44Z, Trinity emitted that same banner three times.
Trinity is the clara seat: the same codebase, under a different AGENT_SLUG,
on a different machine, out of a different checkout. The fix had been merged for
days. It had never reached it.
Why nothing noticed, and why neither instrument was broken
The ledger read 0. It records posts made by the agent_smith package on
this box — the 63% blind spot agent-smith#399 measured and wrote down. A seat
posting from another host is not under-counted there, it is absent. And the
absence rendered as a zero, which reads as clean.
Nothing anywhere reported which seat runs which commit. The per-seat fact
existed: deploy_state.record_boot has every worker declare, at boot, the
commit it imported, into that seat's own state dir. But the only reader,
deploy_freshness.probe_smith_deploy, asks this_boot() — this process, this
host. Ask "is #376 live?" and the answer you get is one seat's answer wearing
the fleet's clothes.
So a merge was treated as a deploy. For one seat that was true. For the other it was not even close, and there was no surface on which the difference could appear.
The decision
1. A seat's running version is a SIGNAL THE SEAT EMITS, not a question anyone asks it. Every seat's worker already declares its commit at boot; that declaration is the contract. Nothing may replace it with a probe of the seat's disk — the deploy script syncs files first and bounces daemons second, and the bounce is deferred while a batch queue runs, so disk shows the new commit for many minutes while the old code is still serving. The running process is the only witness to what the running process imported.
2. The fleet reader READS those emissions. It never calls a seat. This is
ADR-0003 applied to versions: fleet_deploy walks the roster, resolves each
seat's record through agent_ident.seat_state_dir, and compares each sha to
main. It opens no connection to another machine, runs no command anywhere but
its own host, and asks no seat anything. A reader that reached out would make
every seat's availability a dependency of every other seat's readability — the
coupling the ladder exists to refuse.
The cross-seat resolver is load-bearing and is deliberately not the reader's
own state_dir(): it skips the bare SMITH_STATE_DIR rung, so a reader whose
own override is set cannot resolve every seat onto its own directory and report
its own commit back as everyone's. A reader that silently aliases every seat
onto itself is worse than one that finds nothing — the second says so, the first
fabricates.
3. A seat whose emission cannot be read is unknown. It is never live, and
no roll-up may read clean while one exists. There is deliberately no path from
an unread seat to an aligned verdict, and the coverage clause rides the clean
line as loudly as the loud one. This is the whole content of the incident: the
ledger's 0 was an absence, and absence read as health.
Corollaries, each of which is a place the rule could have been quietly broken:
- The count of commits a seat is behind is
Nonewhen it could not be established, never0—0is the assertion this seat is current, and that is precisely what was not checked. - An unread seat stays in the roster rather than being filtered out of it.
A list that drops the seats it could not reach is how a
0comes to look like a clean sweep. - "That seat is behind" outranks "I could not tell about another seat". A blind
probe must not suppress a divergence it happens to sit beside — the defect
deploy_freshness.should_pagewas found making on 2026-09-06.
4. A boot record is not a liveness signal, and must not be rendered as one.
It says which commit a worker imported, at the moment it imported it. Its age
proves nothing about health: a worker that has not restarted in a month is
correct, not stale. Seat liveness stays where the catalog already puts it — the
per-seat launchd pair (agent_ident.seat_daemon_labels). Reading the record's
age as liveness would be exactly the proxy-instead-of-the-thing substitution
ADR-0009 was written against.
The consequence we are choosing on purpose
On the mini today, Trinity reads UNKNOWN — and it will keep reading UNKNOWN until someone changes something. Its boot record is written on its host, and there is no transport that carries it here.
That is uncomfortable and it is the right answer. The alternative — omitting the seat, or defaulting it to "presumed current" — is the exact failure this ADR exists to end, and it is what the fleet had before: a silence that looked like a clean bill of health. A row that says nobody can say is strictly more information than no row at all, and unlike the silence it is actionable.
Two supported ways to close it, neither of which this decision mandates:
- Run the reader on that seat's own host. Same code, same rule, and the seat it cannot see from there is this one.
- Point
<SLUG>_SMITH_STATE_DIRat a synced copy of the other host's record. This is the documented per-seat override and is honoured by the resolver precisely so a synced emission becomes readable without new machinery.
A general cross-host transport for seat emissions is a real decision with its own trade-offs (which store, what freshness, who writes it) and is explicitly out of scope here. It gets its own ADR when someone builds it. Until then the gap is named on the surface rather than papered over, which is the smallest honest thing and was the missing thing.
Nothing in this decision deploys anything. Updating a seat on another machine is a human / other-machine action; the reader states the remedy and stops.
Consequences
- Every new seat is covered the moment it joins
agent_ident.SEATS. The roster is read, never copied — the reasonseat_daemon_labelsandsibling_slugsderive from it rather than hardcoding. - "Is commit X live?" is now a question with a per-seat answer, and a fleet-level answer that refuses to exist while any seat is unread. Surfaces that previously quoted the single-seat answer should say which seat they mean.
- A
SYSTEMS.mdentry for a system whose subject is coverage must declare signals that prove the reader ran, with the verdict in thedetailpanel — not signals keyed on the verdict. A fleet being briefly behind is the normal state after every merge; colouring the row red for it would train people to ignore it, which is how ADR-0009's "green means the thermometer works" fails in the other direction.