Not a new design round. Every bet resolved, and one acceptance turned
out to be satisfiable vacuously.
Acceptance 2's in-drain clause said "the live descendant's named late
output absent" without saying how the descendant stays live. It does
not, by default: `poll_one` TERMs the whole group on leader exit. The
first fixture's marker was therefore absent on both paths, and the pin
would have stayed green with the collapse fixed.
Bets 1 and 2 hold — every site took a directed outcome without
restructuring, and every consequence is reachable, so the lane does not
shrink. Bet 3 resolves the shutdown coupling as real and measured. Bet
4 is falsified exactly as its own clause anticipated: `ProcessEvent` is
keyed by `ProcessId` while the ledger is keyed by pgid and is
deliberately independent of managed records, every production consumer
polls per known id, and `take_all_events` has no production consumer at
all. Q#RL3 is answered accordingly and reporting is parked as its own
lane.
Also records the four sites and the two reusable lessons in
`docs/agent-handoff.md` — that a seam for a background loop has to be
directed, and that an absence assertion is only as good as its
fixture's ability to produce the thing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
Refine the framing's in-drain test seam: a one-shot probe error cannot
survive the 50 ms quiescence interval, so the test-only override lasts
for one drain context and remains per-supervisor. Name the in-drain
SIGKILL as a non-observable local fact rather than adding an untestable
seam, and synchronize the revision-three ledger record.
Three blocking and two major findings, all accepted, all verified in the
code first.
- **§0 named the wrong journey step**, and contradicted Q#RL5 in the same
document. The ledger arms only for `spec.group`, which spawn rejects
for PTY mode, so no terminal reaches it. The only production
`group = true` caller is compile mode, making this journey step 9
(build/test) plus general pipe-process cleanup.
- **A fourth site was missed.** `final_drain_runtime` collapses every
probe errno to "dead" while no tick runs, discards its SIGKILL result,
and sets its own flag. It is not identical to the persistent ledger —
a later tick can retry that, this decision is terminal for the drain —
and its consequence differs: a false "dead" cancels the readers, so
the failure mode is truncated output rather than a leaked process. It
also constrains the seam, being a free function with no `&mut self`.
- **The staging contradicted itself**: "Bet 1 ships alone" against an
acceptance requiring failure-path tests, under one-branch/one-PR. It
was also wrong on its own terms — a seam with no tests does not show
it reaches the intended production calls. The first PR is now seam
plus behaviour-preserving tests, still diagnosis-only.
- **A generic seam is the wrong shape.** `shutdown()` calls
`self.signal(*id, SIGKILL)` before its ledger force-kill, so one
shared "next kill errno" would be consumed by the wrong call and the
test would pass while proving nothing. The seam is now site-directed
with four independently addressable outcomes, expressing more than one
pending result because the coupling test needs two at once, and with
fixture cleanup stated rather than assumed.
- **§1.3 overstated the loop coupling.** Early exit needs the ledger
empty AND `any_running()` already false. The precondition is now in
the ground truth and in Bet 3's fixture requirement.
Framing only. No code.
Unparked from PR #200's §5, which retired the premise justifying the
ledger's leniency and deliberately changed no disposition.
Scouting found three silent failures where #200 named two. A probe error
of any errno drops the entry and cancels escalation; a failed escalating
SIGKILL is recorded as a success and never retried; and `shutdown()`
discards its own force-kill result identically — on the path written
specifically to stop a leak at editor exit.
Two facts shape the lane. `shutdown()`'s final loop terminates when the
ledger empties, which happens through the same silent drop, so the probe
error that hides a leak can also end the cleanup loop early — the probe
cannot be made strict in isolation. And all three paths are untestable
today: `tick_reap_ledger` and `shutdown()` call nix directly and consult
no injection seam, unlike `signal()`'s `forced_kill_errno`, so every one
of the five existing ledger tests exercises only the success path.
Diagnosis first; no disposition change is proposed. Stage A of the signal
lane had three tolerance rules rejected across three revisions, each for
concluding something about one entity from something about another, on
this same data structure.
The framing states plainly that none of the three has been observed:
#200 saw an explicit SIGTERM fail in `signal()`, not a ledger call.
Framing only. No code.