diff --git a/docs/active-work.md b/docs/active-work.md index 0399359..52cb239 100644 --- a/docs/active-work.md +++ b/docs/active-work.md @@ -333,29 +333,38 @@ compatible. githubsucks/test-ambient-config-isolation ``` -## Reap-ledger silent failures — FRAMING OPEN, revision 1 +## Reap-ledger silent failures — FRAMING OPEN, revision 2 - **Branch `reap-ledger-silent-failures`**, worktree `../pmacs-reap-ledger`, based on `githubsucks/main` @ `22df6ab`. **Framing only; no code, no PR yet.** - `docs/reap-ledger-silent-failures-framing.md`, revision 1. + `docs/reap-ledger-silent-failures-framing.md`, revision 2; one review + round closed (three blocking, two major, all accepted). - **Unparked from PR #200's §5.** #200 retired the premise that justified the ledger's leniency and deliberately changed no disposition; this lane owns what it refused. -- **Three silent failures, not the two #200 named.** A probe error of - any errno drops the entry and cancels escalation; a failed escalating +- **Four sites, not the two #200 named.** In the persistent ledger: a + probe error of any errno drops the entry and cancels escalation; a failed escalating `SIGKILL` is marked as succeeded and never retried; and `shutdown()` discards its own force-kill result the same way — on the path that - exists specifically to stop a leak at editor exit. + exists specifically to stop a leak at editor exit. **Plus the in-drain + twin** `final_drain_runtime`, which collapses every errno to "dead" + while no tick runs; a false "dead" there cancels the readers, so its + failure mode is truncated output rather than a leaked process. - **The blast radius is exactly what the ledger exists for:** a TERM-ignoring descendant that outlived its leader with output redirected. Neither leader state nor reader state can see it; only group liveness can. A silent drop leaks the one process nothing else - is watching. + is watching. **Journey step 9 (build/test), not step 8** — the ledger + arms only for `spec.group`, which spawn rejects for PTY mode, so no + terminal reaches it; compile mode is the only production caller. - **`shutdown()`'s final loop terminates when the ledger empties**, which happens via the same silent drop — so the probe error that hides a leak can also end the cleanup loop early. That coupling is why the - probe cannot be made strict on its own. + probe cannot be made strict on its own. **Its precondition is + `any_running()` already false**, so the fixture must be a leader that + exited leaving a survivor; any other shape tests the other arm of the + disjunction. - **None of the three has been observed.** #200 saw an explicit `SIGTERM` fail in `signal()`, not a ledger call. The premise is falsified and the path exposed; the occurrence is not evidence these @@ -363,8 +372,12 @@ compatible. - **They are also untestable today**: `tick_reap_ledger` and `shutdown()` call `nix` directly and consult no injection seam, unlike `signal()`'s `forced_kill_errno`. All five existing ledger tests - exercise the success path only. **Bet 1 ships the seam alone and - first** and is worth landing even if the rest is abandoned. + exercise the success path only. The seam must be **site-directed and + multi-outcome**: `shutdown()` calls `self.signal()` before its ledger + force-kill, so a single global slot would be consumed by the wrong + call, and the coupling test needs two pending outcomes at once. The + first PR is the seam **plus** the tests that exercise it — a seam + without tests does not show it reaches the intended calls. - **Diagnosis first, no disposition change proposed.** Stage A of the signal lane had three tolerance rules rejected across three revisions for the same shape of error on the same data structure.