---
name: spt-core-findings-backlog
description: "3 NON-blocking spt-core findings (operator-surfaced post-parity-arc 2026-06-17): mint registry-first → todlando, doyle gates. Dispatched."
metadata: 
  node_type: memory
  type: project
  originSessionId: 16531b26-c5ac-4120-bfb8-113daef39d8f
  modified: 2026-07-29T12:05:26.307Z
---

**NEW SEED 2026-07-29 (ACCESS-CONTROL W2b incidentals, todlando-found, doyle-banked): CLI-SURFACE STRINGS IN DIAGNOSTICS HAVE NO CHECKER.** Two shipped operator-facing strings (`ACCESS_STORE_DEGRADED`, `ACCESS_STORE_MINTED`) told the operator to run `spt access ...` — which does not parse (real path `spt endpoint access ...`); fixed in-diff on build/sender-stamp, rustdoc+ADR-0053 instances carried in the same xtask-gen commit. Class = same as the xtask docs-drift gate but for PROSE: diagnostics/rustdoc naming CLI surfaces drift silently. Hardening shape: gate leg extracting `spt ...` command strings from diagnostics/rustdoc and validating against the actual command tree. Not milestone-A; operator ranks. todlando's latent-scan unit pins its own verb string as the interim discipline.

**NEW SEED 2026-07-29 (ACCESS-CONTROL W1, todlando limit (a), doyle-accepted): ADVERTISEMENT-RETRACTION — a newly-DENIED (or newly-invisible) endpoint's registry row is WITHHELD from the next advertisement push, never actively retracted; a viewer holding an old row keeps it until decay.** W1's DISCOVER gate deliberately matched the existing per-subnet visibility-hiding precedent (advertise_if_visible → Ok(None)) instead of inventing a second convergence story. If real retraction is ever wanted, ONE wave must fix BOTH the visibility and DISCOVER arms together — never one-sided. Unranked; operator ranks.

**⭐ NEW CLASS SEED 2026-07-27 (todlando RCA, doyle-accepted "best RCA of the night" + banked as a CLASS; lane RULED hertz's, own thin PR, must NOT ride #104): EDGE-TRIGGERED-GAP + DROP-DON'T-BLOCK ⇒ THE "NOTHING-FOLLOWS-A-DROP" OUTCOME HAS NO REPRESENTATION.** First victim: `spt-daemon::attach::wedged_viewer_does_not_stall_controller` TIMED OUT at the 240s nextest cap on kitsubito (#104 attempt-1 Linux, FIRST sighting ever) — a loop whose own bound is 20s. Structure (source-verified): `Brain::read_event()` == `read_event_until(None)`, and `read_frame_until(None)` is an UNBOUNDED blocking read on BOTH conn shapes (`read_frame(stream)` for Whole, bare `frames.recv()` for Split — only the `Some(deadline)` arm has the recv_timeout budget); `attach::read_controller_event_resuming` (src/attach.rs:165) always takes that None path inside its own loop; the test checks `while now < deadline` only BETWEEN iterations ⇒ zero events = blocked forever = 240s harness kill. The correct shape already exists ~30 lines away (`viewer_reads_marker_no_displace` uses `read_event_until(Some(now+200ms))` + `Err(_) => continue`) — the VIEWER helper got a per-read bound, the CONTROLLER helper never did. MECHANISM (the class): gap detection is EDGE-TRIGGERED (`is_output_gap` fires only when a forward-jump frame ARRIVES) while b4's controller DROPS frames via `try_send` at `CONTROLLER_CHANNEL_DEPTH=4096` — so when the 200KB burst AND the trailing marker are dropped in ONE overflow window and the echo child then goes quiet, NEITHER accepted outcome is reachable (marker needs a frame; `ControllerIrrecoverablyBehind` needs two ARRIVING gaps). Fast box ⇒ marker beats the overflow ⇒ green, which is why it took this starvation to surface. ⇒ latent TEST-LIVENESS defect independent of the night's root cause. NARROWED-NOT-CLOSED (doyle's second question): drain was ALIVE at 15016ms (the bounded write + conn=3 poison IS the drain working on schedule) and the controller conn was OPEN-and-silent not closed (closure ⇒ Err ⇒ the test's `Err => panic!` arm fails FAST) ⇒ consistent with observation-side starvation, NOT the isolation property breaking — but that is inference from ABSENCE, so it needs the probe. FIX SHAPE (approved): `read_controller_event_resuming_until(..., deadline)` with today's fn delegating `None` (production `serve_attach` byte-identical) + per-read deadline in the test + a NAMED zero-event outcome + **discriminating oracle: at the deadline attach a FRESH reader and read the ring — burst present ⇒ the controller's own bounded channel dropped it (main/box, observation-side); nothing ⇒ the child never echoed (box starvation upstream)**. AUDIT SWEEP owed by the fix PR: every timed observer in the b4 plane whose success needs a NEXT frame over a transport that may drop then go quiet. Box context: `NTP_TOTP_UNCORRECTED` all-NTP-unreachable on kitsubito in that window. Attribution SETTLED: not leg C — spool/inject cannot reach the attach plane; paired base-vs-2aae246 run now OPTIONAL. Spec handed to hertz at `.claude/reports/2026-07-27-attach-viewer-liveness-spec.md`. Kin [[verdict-from-exit-not-from-silence]] (a watcher needs its own liveness proof), [[window-assertion-load-direction]].

**NEW SEED 2026-07-27 (operator challenge, doyle-assessed — CI-RUNNER-INFORMANT, P3 infra/DX): CI runners (both on SPT_DEV subnet) push run outcomes via `spt send` instead of agents polling gh.** Feasible today transport-wise; QUEUED semantics fit (busy agent drains at safe point). ⚠ THREE reshapes required vs the as-proposed `--from CI-KITSUBITO` shape: (1) **operator-stamp spoof** — `--from` is a reply LABEL not identity (cli.rs:6874-6880 "`--from` alone never confers an agent identity"); a bare-CLI send with no perch session classifies LocalUserCli ⇒ user-msg gate RE-STAMPS the body as `user-msg` typed envelope = CI speaking with operator voice. Fix: registered send-only informant endpoints (`ci-kitsubito`/`ci-hfenduleam`) so origin classifies endpoint — precedent = `spt-shells` informant (reporting.rs `send_deferred(id,"spt-shells",ctx)`), EXCEPT CI uses default window (should wake; spt-shells just got ruled never-wakes, leg C). (2) **"whoever kicked off CI" not derivable at runner** — GH actor = shared account; commit co-author trailer parseable but author ≠ actor (gater merges regardless). Route: gater fixed + trailer-agent. (3) **push never replaces poll** — runner crash/force-cancel/pre-step YAML error ⇒ no message, silence ambiguous ([[absence-needs-sibling-probe]]); keep thin long-interval poll belt. Minor: terminal-event + first-red granularity only (per-stage = turn-start spam); hfenduleam notify step must hit LIVE SPT_HOME without daemon-autostart from CI env. ⭐ LIVE-DEMONSTRATED 2026-07-27: operator sent doyle a bare-CLI message stamped `--from probably-the-user-being-smug` — arrived wearing the label, plain msg. Confirms label = zero trust input; could equally impersonate an AGENT id (`--from todlando`). Single-box trust posture makes this by-design for humans, but it means the registered-informant-endpoint reshape is the ONLY receiver-side discriminator, not optional hardening. ✅ DISPATCHED 2026-07-27 (operator-ruled build-now, infra-grade): todlando building v1 (branch `ci/runner-informant`) — NO REQ/registry (not product surface), `--from CI-<RUNNER>` label accepted v1, registered endpoints stay the someday-hardening. Ranked constraint = clone-to-new-runner: one repo script `.github/scripts/ci-notify.sh` + one `if: always()` notify job, zero per-runner config. Notify best-effort (`|| true`, never reds CI); doyle always + trailer-agent best-effort; default window; hfenduleam live-SPT_HOME + no-autostart guard; poll belt retained. Spec sent SENT:todlando (full text: session scratchpad ci-informant-dispatch.md).**

**FAMILY MEMBER (new victim, PROCESS-DEATH arm) 2026-07-28 (todlando+doyle, #117's MAIN merge run 30332016141 @9d7af01, Win): spt::resume_no_control_steal_e2e `brain_respawn_keeps_every_session_controller_and_still_promotes` — failed 2x in-run at IDENTICAL 1.258s, no assertion text, NTP_TOTP_UNCORRECTED banner, dies right after 3 controller-attaches + conn=4 write-start.** ⭐ THE DISCRIMINATING FACT: 1.258s is BEFORE any deadline the test owns (20s baseline precondition, 45s ready wait) ⇒ it is NOT the test's own assertion — process-level death, the bare-exit/no-panic-banner signature of the external-termination family; the test itself `kill_pid`s at teardown, so cross-test kill on a REUSED pid is on the suspect list (box churned hard that night). N_SESSIONS=3, so conn=4 = the brain-spawn/supervise boundary, not the resume discriminator. doyle's initial SEAM CALL was #116's controllable/pid-role re-key; **my static read refuted the mechanism and doyle accepted it**: `converge_dead_relay`'s role gate is a STRICT NARROWING (converges FEWER rows — a steal needs something to do MORE, not less), the +222-line bulk is `api/startup.rs` = the `spt api listen/bind` entry which never executes in a `daemon brain` + in-process-broker test, and info.rs is additive. Test file untouched since the update-wedge work (03c7109). **At-sha rerun (leg 1) GREEN — one sighting stands, nothing routed.** If it recurs: first cut is process-death vs assertion (capture child exit status + whether a panic banner exists AT ALL), seam second. ⭐ RULE EXERCISED: direction-of-change beats seam-adjacency as an attribution argument — "my diff can only do less of X" refutes "my diff caused more of X" without needing a repro.

**FAMILY MEMBER (new victim, 1st g2 sighting) 2026-07-28 ~05:04Z (todlando, PR #117 run 30329922262 Win Phase B): spt-daemon::inject_control_wedge `g2_no_commit_deadline_faults_binary_and_does_not_wedge_controller_input`, FAIL 3.833s, 181/182 else green.** Failing arm = the `spooled` assert (inject_control_wedge.rs:1581): "after the FAULT a subsequent inbound delivery must EVENTUALLY SPOOL (delivered=false) — bounded retry converges (20 attempts)" — a BOUNDED-RETRY window assert, so by [[window-assertion-load-direction]] load makes convergence slower ⇒ load pushes it toward budget-exhaustion = red. doyle's box datum: had just run 3 full suites back-to-back. Untouched seam (diff = spt-msg::ring + cmd_ring only; no route into the wedge commit deadline); all 5 new ring units green on the same leg. At-sha rerun (doyle, `--failed`) GREEN, same sha aebc3b79, no code change between red and green. Disposition: rerun-as-tally, deadline-budget family, DISTINCT from the g6 tally (g6 passed 0.714s on the red leg). ⭐ PREDICTION for the curve: g2 reds should track ATTEMPTS-EXHAUSTED, not a wrong terminal state — if a sighting ever shows the wrong terminal state instead, it is NOT this family.

**FAMILY MEMBER (new victim) 2026-07-27 (doyle, PR #99 run 30237893434 Win Phase B): spt::endpoint_teardown_authority_e2e `stop_reaps_the_hosted_subtree_and_run_recovers_the_endpoint` — "the re-run mints exactly one FRESH session — got []" (0 vs 1) at e2e:608, 47.3s, 179/180 else green. Registry-only diff (cannot be product); same suite green on #95/#96 runs same box same day; window-assertion load direction: load pushes AWAY from the mint window (slow spawn/bind after stop-reap) ⇒ red-under-load consistent with the Phase-B reap/spawn-latency family (random-victim rotation, fleet host + CI serialization day — box was saturated: 6-run queue). Disposition: rerun-as-tally (dispatched). If it recurs on a QUIET box: real candidate for the re-run-mint window being too tight vs stop's async reap — same widen-the-bounded-poll hardening class as member #2.**

**FAMILY MEMBER (new victim) 2026-07-23 (doyle, PR #68 rerun, run 30030498405 roll 2): spt-daemon::daemon_e2e daemon_hosts_lifecycle_and_survives_brain_restart — Phase B SERIALIZED red, panic daemon_e2e.rs:334 "child exit must reap the session from the broker table" (reap missed a 2s bounded poll, 200×10ms). Reap-latency neighborhood = kin of member #2 (a_reap_clears_control_stamps, no-body). Roll 1 victim (member #4 autostart) PASSED this roll; Phase A 1926/1926 — random-victim rotation across consecutive rolls of ONE run = the family signature on the permanent cause (CI on fleet host; box measured at baseline: 215 GB free, 29 spt-family procs, no transient hog). Note "serialized on a now-quiet box" in the phase name is FALSE on this host — Phase B serializes tests against each other, not against the resident fleet. Hardening candidate if it recurs: widen the reap poll cap (2s → bounded 10s) — reap LATENCY under fleet contention is not reap FAILURE. Disposition: rerun-as-tally (roll 3 dispatched).**

**⭐ FIELD CONFIRMATION 2026-07-23 (lia RCA, Athenaeum-Library Linux node, 0.40.0 daemon — the C1 + seed-A cluster's UNSHIPPED remainder observed live, BOTH directions at once; triaged + captures requested, POOL WITH EMPHASYS's same-node set).** Stale-ALIVE (Librarian omp-spt: status online, NO process — is_perch_alive is status-authoritative-never-pid BY DESIGN, liveness.rs:140; the reconciler that keeps status truthful for this class = the C1 gap) + Stale-DEAD (crm-intake claude-spt: status dead, claude process RUNNING — suspect stored pid = dead bind-subprocess, dead-rec-pid class; capture will confirm) + wake-launches-nothing (reported Dormant→Active, blocked by stale alive=true = seed A's identity-unverified wake, near-verbatim). Recovery only via stop+run — matches missing terminal normalization. ⭐ CANDIDATE UNIFIER for the whole Athenaeum node file: OOM-killed HARNESS with surviving daemon → stale-ALIVE → no relaunch → deaf/#10 → repair attempts hit pty-EACCES case → this report. dmesg OOM capture requested. Cluster fix design already banked (seed A atomic terminal mutation + C1 split cleanup + custody-pair wake verification). Mixed-image caution flagged (broker 0.40.0 / binary 0.41.1 staged — lia holding restart deliberately, baseline preserved). EVIDENCE STATE 2026-07-23: Librarian stale-ALIVE divergence REPAIRED-BEFORE-CAPTURE (info.json lost; class stands on report+code); **crm-intake stale-DEAD PRESERVED LIVE** — daemon alive=false vs real claude pid 1385832 (+translate 1385837); read-only captures AUTHORIZED immediately (info.json verbatim + ps on stored pid = dead-rec-pid closer; dmesg OOM grep = unifier test; findmnt noexec = emphasys's probe folded in); MUTATING actions (restart, clearing crm-intake, repro cycles) stay pooled via operator Reavo. ⭐ Hold-scope lesson applied: read-only captures never wait on pooling; only mutations pool. CAPTURES LANDED 2026-07-23 (lia, all read-only): **(a) dead-rec-pid CONFIRMED EXACT + DEEPER** — crm-intake info.json verbatim: pid 1385288 DEAD (no such process) vs live daemon-spawned claude pair 1385832/1385837 (ppid=daemon, ~34m); AND status="unbound" + session_id="" + rest_state="suspended" ⇒ the live harness NEVER COMPLETED BIND — a spawn-ran-bind-never-landed permanently-unbound perch, not merely a stale read. ✅ stderr grep LANDED (lia): mechanism CLOSED — **bind NEVER ISSUED** (full-log grep: zero BIND/USAGE/CONFLICT lines for the id in daemon.stderr.log AND daemon-effects.log; only a LIVENESS_RECONCILE_OFFLINE at spawn epoch + one channel-closed controller session). ⇒ #9 unification DENIED on evidence (attempted+refused vs never-issued = opposite entries into the unbound seam). ⭐⭐ CORE DEFECT CRYSTALLIZED (lia's predicate, doyle-adopted verbatim into the wave design): **RECONCILE MUST VERIFY PROCESS IDENTITY BEFORE OFFLINE-STAMPING — broker-session absence alone is not death**; the reconciler offline-stamped seconds after spawn while the OS pair lived 34+ min = the stale-DEAD generator, custody-pair machinery is the fix seam. ⚠ SEPARATE banked question: LIVENESS_RECONCILE_OFFLINE fired AT SPAWN EPOCH — if the pulse can offline-stamp inside the spawn-to-bind window, that race needs its own closure in the wave. Why-never-bound ✅ RESOLVED by lia's M1 capture 2026-07-23 — NOT the hook (perri's claude-spt EXONERATED: hook path verifies healthy, zero hook-trace entries because CC NEVER BEGAN A SESSION — no transcript dir, no session-env, 34min in ep_poll): the block is UPSTREAM, **the --remote-control transport never established**, and the daemon log's crm-intake block IS its broker end (one controller attach → writer-exit channel-closed in the same ms at spawn epoch; claude waits forever on the dead channel). ⚠ ENV ANGLE RETRACTED IN FULL 2026-07-23 (lia self-caught: the "near-empty environ" was a GREP-FILTER ARTIFACT — prefix-filtered read presented as totality, the week's instrument lesson again; UNFILTERED environ = 17 healthy vars incl full PATH + injected SPT_ENDPOINT_ID/SPT_SESSION_NAME/SPT_INJECT_VERIFY_ECHO=1; daemon environ also healthy, systemd athenaeum-spt.service, PATH present). Source-side chain reads stand as facts (adapter inherits; core role-spawn inherits, no env_clear; daemon env = ceiling) but carry NO defect here. HARNESS-SPAWN-ENV-FLOOR seed DEMOTED to principle-without-evidence — crm-intake is NOT its support; file only if a real bare-ceiling incident ever lands. NET EFFECT = the defect signature got PURER: RC establish wedged 34min in ep_poll with a fully-correct environment + broker-side controller attach dying writer-exit channel-closed in the same ms at spawn epoch. ✅ NODE FILE CLOSED TO M4 2026-07-23 (lia M3 done, node fully 0.41.1): **ZERO-SOCKETS verdict from the pre-kill live bundle = the file's decisive fact** — wedged claude's fd table was stdio-on-broker-PTY + eventpoll/eventfd/inotify ONLY, no socket ever created ⇒ RC establish never reached transport; CC blocked on an INTERNAL eventfd wait pre-socket, 34+ min, correct env + injected SPT identity. Broker-side channel-closed block REINTERPRETED: core's own spawn-side attach dying separately (CC never had a socket to drop). Perri's half = ONE question now (dispatched, window closed, bundles frozen with lia — PRESERVE-INDEFINITELY flagged 2026-07-23 at perri's request): what does CC's -n --remote-control wait on internally pre-socket, and can it block forever. PERRI WORKING HYPOTHESIS (logged as hypothesis, NOT finding — perri explicitly declined to guess CC internals; real answer to follow from CC source or bare-spawn repro): RC defers socket creation behind an internal session-ready/bootstrap gate fed by something the daemon-spawn path delivers post-fork; if it never arrives CC parks forever on the eventfd, no timeout — matches the 34-min zero-socket wait exactly. Perri ENDORSES the core-side banking: pre-socket handshake wedge is structurally invisible to adapter self-heal ⇒ establish watchdog/timeout is CORE's to own (wave input confirmed). CORE WAVE INPUTS FINAL: no supervision for handshake-wedged harness + reconciler stamps over it + reconcile-inside-spawn-window race + identity predicate on both offline AND demote forks. M3 replay observations: Librarian CLEAN auto-replay (autostart working on 0.41.1); ex-crm-intake offline-clean (correct for killed unbound pair) — stale-DEAD divergence RESOLVED on-node. Minor data: ~8s broker status self-report lag post-restart (observability datum, lia verified-before-flagging); stale-notice retirement confirmed live in the field ("Already up to date counter 75"). Rename anomaly ✅ ATTRIBUTED (Reavo confirms intentional operator rename, closed no-trace). M5 ✅ DONE (0.3.22, Librarian ready=true, commune-loop CLEARED). M4 ✅ DONE (swapfile 2G live, swappiness=10 — the zero-swap OOM cliff that STARTED the file is removed). **🏁 ATHENAEUM NODE FILE FULLY CLOSED 2026-07-23** — sole open thread: perri's async ruling on the frozen crm-intake capture (non-blocking). POST-CLOSE ROOT ATTRIBUTION (lia, root granted): all 4 OOM kills confirmed (matches oom_kill=4) — **spt daemon/broker ITSELF killed 3× at 2.9/2.9/3.0G anon-rss** (Jul 22 08:59, Jul 23 13:24, Jul 23 22:19) + omp harness 1× (Jul 22 23:37, anon-rss 1.85G, total-vm 76G — leading candidate for the original Librarian drop; 76G virtual datum routed to emphasys). ⭐ NEW SEED: **DAEMON-FIELD-RSS-GROWTH** — consistent growth-to-~3G-then-kill cycle on a small multi-endpoint 0.40.0 node = coordinator memory-footprint question in its own right; candidates: registry/digest-hub/stream-ring retention (kin of the CLOSED REGISTRY-STALL retention family — recurrence-of-kin, take seriously); discriminator when opened: **RSS TRAJECTORY over uptime** (emphasys's method, adopted — monotonic climb = leak, plateau = bounded working set), by subsystem if obtainable, on a long-lived multi-endpoint daemon. SIBLING DATUM RESOLVED: the omp 76G total-vm = unremarkable V8 reservation (heap cage/code-range/arenas, uncommitted — emphasys read, adopted); the real number is 1.85G RSS, attribution = oh-my-pi HARNESS (not the omp-spt adapter), same trajectory discriminator, standing low-priority observable if anyone has an active omp endpoint under watch. ⭐ WAVE RANK INPUT (lia's cascade framing, adopted verbatim): a daemon that dies under memory pressure and restarts is its OWN CASCADE SOURCE — reconcile races a fresh coordinator over half-dead endpoints; the liveness cluster's divergences are what the cascade leaves behind, demonstrated end-to-end on this node. ⭐⭐ TWO NEW WAVE INPUTS: (1) spawn-to-bind window's SECOND FACE — a handshake-wedged harness sits forever with NO supervision/watchdog while the reconciler offline-stamps over it (pairs with the reconcile-inside-the-window race); (2) the channel-closed-at-spawn trace = concrete broker-side artifact for the wave's tests. Kinship candidate (lia): sibling of #10 bound-then-deaf — keep separate until evidenced (three-shapes discipline). READ-ONLY PHASE CLOSED (lia, 4 results): **(1) Librarian stale-ALIVE generator FOUND** — HOSTING_AUTHORITY_DEMOTED line 15184: "no broker session, but a relay holds the endpoint — demoted to no-claim instead of offlined" [REQ-LISTEN-PRESERVES-HOSTING-TOPOLOGY] = the MIRROR arm of crm-intake: reconcile decides liveness from broker-session/relay TOPOLOGY alone, never process identity; the identity predicate must govern the demote-vs-offline fork too (both arms + verbatim lines = wave design input). **(2) pty error CLEAN NEGATIVE in all daemon logs** — mechanically correct: endpoint stop/run failures print on CLI stderr (operator terminal), never daemon log; capture = operator scrollback or next recurrence. **(3) NEW LINUX HAZARD, ADAPTER-owned (grounded: path omp-spt-env-v1 + error string absent from core source; core's capture_read_env stamps the perch at bind)**: omp-spt env snapshot in /tmp reaped by systemd-tmpfiles ~10d → ECHO_COMMUNE_FAIL every turn, strikes 3/3, loops forever (Librarian in-loop NOW). Routed to emphasys with fix cautions (NOT XDG_RUNTIME_DIR — also volatile; durable state dir + rebuild-on-missing fallback). CORE DOCS-RIDER SEED: published adapter guidance — durable adapter state must not live in /tmp. **(4) OOM CONFIRMED rootlessly** (oom_kill=4 in /proc/vmstat + cgroup memory.events, Swap 0 on 3915M) — sufficient for the wave; victim attribution root-gated nice-to-have. POOLED MUTATION LIST v2 (lia caught a doyle sequencing defect: M2's hard kill is NODE-WIDE and would destroy M1's evidence — the crm-intake pair is daemon-parented; corrected order adopted + M2 offered OFF-NODE to emphasys's dev box since the discriminator is node-agnostic): M1 crm-intake harness-log captures FIRST (gated on perri) → M2 #10 discriminator ACCEPTED BY EMPHASYS 2026-07-23, runs on THEIR node — ⚠ their dev node = HFENDULEAM (the shared fleet host!), so doyle imposed the hard guardrail: ISOLATED SPT_HOME resident-broker rig only ([[isolated-resident-broker-field-repro]] pattern — temp home, own daemon, throwaway endpoint, kill-by-specific-pid never by image, CI-idle window), fleet daemon untouchable; baseline 0.40.x pulled binary + 0.41.1 rerun, same captures; ALSO pairs hazards: emphasys takes adapter-side KH "durable state not in /tmp", core keeps the docs-rider → M3 daemon restart to 0.41.1 WITH CAPTURES ARMED AROUND THE RESTART (stderr window + both info.json before/after — a real restart with real endpoints = free replay observation) → M4 root dmesg + swap provisioning → M5 /tmp stopgap post-emphasys-fix. All disruptive steps Reavo-approved first; nothing on a clock. **(b) noexec RULED OUT** (ext4 rw,noatime,discard) — pty case back on the verbatim-error-line capture; emphasys notified. **(c) OOM undetermined without root** (no persistent kernel journal, sudo denied) but **Swap 0 on 3915M host** = hard-cliff enabler banked; root dmesg + swap-provisioning recommendation flagged to operator Reavo. Operator ranks — this confirmation is a strong rank-forward argument for the C1/A wave.**

**NEW SEED 2026-07-23 (flynn/ball-b field probe, alchemy W16 gate — CROSS-NODE SHELL DRIVE, filed as spt-bs-core #70, flynn watching): owner on node B cannot spawn (SHELL_ADAPTER_UNREGISTERED, node-local spawn, cli.rs:11765) or drive (NO_SHELL existence miss, per-owner AND node-local, cli.rs:11753) a shell instance on node A.** NOT a bug — the M5 design's NAMED DEFERRALS now carrying first field motivation (shellwake.rs:266-302: cross-node shell link = D8c; fresh-spawn-on-named-node = shell_wake_spawn_anywhere instantiate-anywhere grant seam; ADR-0023 target-side authorization). Requested shapes in #70: (a) spawn --node <label>, (b) owner-instance resolution across nodes over the existing command channel. Triage cautions banked in the issue: route through the existing resolve_wake/forward_wake seams (no parallel mechanism), presence/MRA D6 for instance location, transport-agnosticism of the command channel = VERIFY not assume. Motivation: remote agents want direct Requests-Hub CRUD without Liaison proxying. Operator ranks.** **✅ RULED 2026-07-24 (operator grill): SPLIT into two legs. Leg (b) cross-node owner-instance DRIVE ships FIRST, queued BEHIND the idle-edge milestone (activity push + seal-on-idle + pull surfaces + cross-node digest pull); leg (a) spawn-on-named-node DEFERRED until a consumer needs remote instantiation rather than remote drive — (a) presupposes (b) and carries the whole spawn-anywhere-grant/ADR-0023 consent surface. Resolution rule (glossary'd): unqualified ref resolves LOCAL-FIRST (a local match wins even when same-ref instances exist elsewhere); refuse-ambiguous ONLY when multi-remote AND no local; `ref@node` = exact escape hatch; never a silent cross-node pick. Co-bringup rule (operator): `persistent` auto-online is node-qualified — owner online at node N brings up only the LATEST instances qualified to that endpoint@node pairing; stale same-ref instances on other nodes do NOT auto-wake. Transport-agnosticism of the command channel stays VERIFY-at-triage.**

**⏫ MEMBER #4 THIRD SIGHTING 2026-07-23 (doyle, PR #68 CI run 30030498405 Win Phase A — discrimination pass PROMOTED, now 3 data): endpoint_autostart_e2e saved_endpoint_replays, SAME assert (perch carries run A's sid; session_b==session_a) with the sharpest body yet: ENDPOINT_AUTOSTART line proves the replay MINTED fresh (new sid + pid) yet the perch read at assert time still held run A's sid — the fresh harness's BIND lost the race (or never landed). Sightings: 2026-07-19 local mirror (44s), #55 merge-run 29890856839, this (37s). The banked discrimination question is now urgent: rig-race (assert window too tight for bind-under-load) vs PRODUCT race (fresh-session stamp racing readers = real ordering hole). ⭐ NEW KINSHIP: emphasys omp-spt #10 (deaf-after-autostart-replay, entry below) — a replay whose fresh bind is slow/lost is a candidate SHARED seam; if discrimination finds a product race, #10 may be its field face. Carry both into one pass. Disposition for #68: not the PR's delta (file untouched, pre-existing multi-head sightings); rerun-as-tally.**

**🏁 IDLE-EDGE W1 CLOSED 2026-07-25 — ship counter 76 (v0.42.0 @8492c75, PRs #72/#73/#74/#75), field-verify verdicts: perri PASS (full cycle — both edges live-proven: idle arms, one ping at base, wake's busy edge disarms+resets, next idle re-arms at base; REQ-REBOUND-ACTIVITY-SEAM int closed @c5741bb; golden-byte wire tripwire pinned; their no-repeat sentence honestly retracted-then-upgraded), flynn PASS (mint-then-idle tag fired with NO nudge, method-clean: tag as last act of turn then stop; playbook interim note replaced with 0.42.0 floor; compound with cb6550d input_seq anchoring), liam RECUSED (their endpoint's turns have not sealed since 2026-07-24 ~05:20, immediately post-/sptc-setup — pre-existing, predates 0.42.0, filed below). perri hard-block CLOSED; the 2026-07-24 locked activity contract is field-proven with zero contract changes (months-old mock tests passed unchanged against live frames = settled-vocab-first process proven, precedent for future seams). WAVE PROCESS EPITAPH (todlando's words, canonical): one lesson, three victims — contracts reconstructed from summaries instead of reading the source of truth (perri: published docs; todlando: the tree; doyle: this ledger). Corollaries now standing: gater checks the ledger BEFORE ruling; consumer-impact triage RE-DERIVED at ship time from the filings ledger, not frozen at wave planning (flynn found their seal-on-idle stake buried under my stale 'informational' framing). RECONCILE NOTE: 2026-07-25 shell-seed entries exist in TWO voices (doyle top-block, todlando tail ~372-390) — canonical consolidated seed = **SHELL-LAUNCH-TRUTH** (absorbs SHELL-STALE-ONLINE + both its sightings, SHELL-SPAWN-DOA both legs, perri's author-side dying-words observation): root = shell info.status is a bind-time-stored flag NEVER reconciled against child liveness (relink gates on it, linkhost.rs:411-423); mechanism = liveness reconciliation via the shipped custody predicate (process_identity tri-state, resume_custody.rs:150-158 mirror + ABA rig), REQUIRES (pid,started_at) pair-parking in SHELL_PID_FILE (today bare pid every site) with legacy-reads-as-Unproven + Unproven-inverts-per-caller + todlando's rider: Unproven is a REGULARLY-TAKEN branch on loaded hosts — deferral must be teardown-recoverable and SAY WHY; plus per-instance spawn log FILE (KH 5.6-safe) for dying words; plus DEAD-REC-PID-hazard-does-not-apply note (worker pid ≠ shell child pid). {adapter_dir} PARITY FIX rides same wave, behind LAUNCH-TRUTH (ruling superseded 2026-07-25: pure parity via shared inject_adapter_keys, meaning = source_dir fleet-wide; teaching-refusal design SHELVED; consumer = RELEASE path only after perri retracted their dev-rig premise — cargo-install-then-adapter-add works today, documented; flynn's alchemy .spt = founding evidence; REQ lean: fold onto REQ-MANIFEST-SUBST as fourth surface). NEW SEED (separate, unranked): {ADAPTER-DIR-FLEET-MEANING} — whether source_dir is the right fleet-wide meaning (deleted-source hazard already ships on three surfaces; shell spawn must not answer unilaterally). NEW SEED: **ADAPTER-CONFORMANCE-HARNESS** — second documented-but-unenforced wire-contract failure this month (perri discarding MAC stamps — security-shaped, pause-latch silencing, fixed their side @dfb3e4c REQ-HAZARD-REBOUND-FRAME-MAC; after EVENT-PART reassembly); todlando's framing canonical: 'each surfaced only because a human went looking — a core gap in how we ship contracts'; shape = extend the adapter digest-proof tool pattern to shell-frame conformance. NEW SEED: **SEAL-DUAL-TRIGGER-ABSENCE** (liam filing, P2 — silently blinds scanner consumers; ⏫ RCA NARROWED same day by liam's co-located discriminator: flynn's endpoint on the SAME daemon (pid 54156, 0.42.0) seals every turn with real seqs while liam's never does → CORE SEAL PATH EXONERATED for this fault, endpoint-specific; owner leans ADAPTER session-identity/digest-source binding rotated at /sptc setup — consistent with entry-append surviving (39 entries) while Input-stamping died at the boundary; note liam's last good input_seq was small-counter 8 vs flynn's large composite — possible pre-rotation source being chased. ⏫⏫ PROBABLY NOT DUAL (todlando, doyle-adopted as leading hypothesis): symptom (ii) no-idle-seal is a CONSEQUENCE of (i) extraction-death — turn identity derives from the extracted Input record, so with no Input landed since the boundary the idle edge has no new turn to stamp and correctly no-ops; one cause, two symptoms (entry-append path alive, Input-extraction path dead, one boundary, one death — fits the 39-entry headless accretion exactly). RCA ORDER RULED: prove/kill extraction-death FIRST (is Input-record extraction running at all on liam's endpoint since 05:20 07-24); only if extraction is ALIVE and the idle edge still fails to stamp is this core-side (then a genuine seal defect worth a REQ). Restart-check discriminator DEMOTED to cheap hygiene (liam's roster-visible activity flips prove the observation leg works there — pre-0.42.0 daemon unlikely). DISCRIMINATOR (b) fresh liam session (operator restart, whenever convenient — liam correctly refuses self-teardown): still-null ⇒ core escalation; heals ⇒ claude-spt session-binding filing to perri, evidence near-complete. WORKAROUND NOTE RETIRED (todlando ruling, doyle-adopted, supersedes my keep-yours instruction to liam): drive-one-more-command is retired on the two valid legs — it provably never helped the broken class (liam never sealed under old rules either) and is unneeded for the healthy class; replaced by the fault-shaped line 'input_seq=null on the newest turn = endpoint not sealing AT ALL — endpoint-level fault, not a scanner problem'. COMPANION SEED (todlando, next-wave candidate): NEVER-SEALING-OBSERVABILITY — a silently never-sealing endpoint is undetectable today without a human reading --last 1; warn surface keyed on idle-endpoint-with-newest-turn-open-beyond-N (diagnostic warn, never an inferred seal — heuristics stay banned from sealing itself). ⚠ TWO CLOSING GUARDS (todlando, banked verbatim): a GREEN fresh-session restart does NOT close this seed — silent permanent extraction death at /sptc setup with no notice IS the defect, the restart only assigns the owner; and three-independent-reads-one-arrow is the strongest evidence shape we get but the arrow still points at an UNPROVEN extraction-death — stays RCA-first, agreement never promotes to proven cause before someone reads whether Input extraction is actually running. Hub linkage stub vs #19/#12 approved, liam mirrors): liam's endpoint = one perpetual partial turn since /sptc setup completed 2026-07-24 ~05:20 (input_seq null, 37 entries spanning a day; older turns sealed fine, input_seq=8 @05:18); skip-partial correctly hides it from scanners → W16 0-mints-from-3-tags + frozen cursor both explained. NOT a 0.42.0 regression (reproduced under old next-input sealing). CORRECTION to liam's framing, banked: the next-input fallback still SEALS when needed (no-op only when already sealed) — their endpoint hits a DUAL absence: no Input records extracted since the setup boundary AND no idle-triggered seal, despite their activity key visibly flipping in perri's roster sample. The conjunction + the setup-boundary timing = the RCA anchors; owner (adapter extraction vs core seal path) undetermined — RCA before assignment; kin liam-Hub #19. Field-verify preamble for future idle-edge waves (perri, two false-negative contaminants): clear your own harness's background tasks first (completion wakes you mid-measurement); let a first-online shell educate once, measure the NEXT boundary. Shell-wave queue after this close: #70 leg-b + LAUNCH-TRUTH + adapter_dir parity + SHELL-CMD-RESULT-CHANNEL + #61-63 + BRINGUP-BIND-TIMEOUT candidacy — operator ranks.**

**NEW SEED 2026-07-25 (flynn filing, two verbatim-quoted probes, doyle code-confirmed same hour — SHELL-SPAWN-SELF-CONTAINED, P2 contract-conformance: a released shell adapter CANNOT ship its own binary; every portable spawn option is closed — ⚠ SUPERSEDED where it conflicts with the 🏁 W1-close entry above: the FIX RULED below was replaced by the parity ruling; premise narrowed to the release path).** Probe 1: bare program token → os error 2 despite the binary sitting in the install dir — the v0.8.0 install-dir-before-PATH program-token resolution does NOT cover [shell].spawn (install-on-demand prose reads as a general guarantee; its enumeration quietly excludes shell spawn). Probe 2: {adapter_dir} → no-value substitution error — `fill_spawn_command` (shellhost.rs:127-139) fills only id/adapter_name/link_token/perch_dir and bypasses the runtime's inject_adapter_keys/command_for machinery entirely (runtime.rs:364,486 — where {adapter_dir} is documented 'available wherever substitution runs', ADR-0029). Two docs pages disagree; both probes rolled back clean. CONSEQUENCE: only escape = out-of-band PATH placement — defeats self-contained .spt, and PATH fragility is the exact surface that broke this node 2026-07-22. FIX RULED (doyle, both arms, small): (1) fill {adapter_dir} in fill_spawn_command when the adapter has an install source (mirror inject_adapter_keys semantics: no install_dir ⇒ key absent ⇒ existing loud no-value error — documented behavior); (2) extend install-dir-first program-token resolution to BOTH shell launch legs (detached + broker-hosted) — makes the v0.8.0 prose true; PATH fallback unchanged, N-1 safe (templates not naming the key fill byte-identically; bare names that resolved via PATH still do). (3) docs reconcile: [shell] key list gains {adapter_dir}; install-on-demand enumeration gains shell spawn. QUEUE: rides the #70 leg-b cross-node shell drive wave (shell-surface kinship, queued directly after IDLE-EDGE W1) unless operator ranks sooner; REQ mints registry-first at wave activation (registry tail = active collision zone now). flynn UNBLOCKED interim: local manifest-only copy, absolute-path spawn, [update] section dropped so an update cannot re-register the unspawnable shipped manifest (that dropped-[update] wrinkle must be UNDONE at fix-verify — note for the field-verify checklist). Evidence: flynn probes 2026-07-25, both refusals verbatim; alchemy release = first self-contained shell .spt attempt.**

**⏫ SECOND FACE 2026-07-25 (perri filing, operator-confirmed — BRINGUP-BIND-TIMEOUT, folds into the Athenaeum wave input "no supervision for handshake-wedged harness"; rank-forward, now TWO independent field triggers): spt-hosted ccs-profile endpoint hangs INDEFINITELY at bringup, force-stop required.** Trigger this time: ccs delegate left PATH so `volta run ccs` STALLS — the .cmd resolves (file exists) but never returns; adapter shim's unbounded child wait (correct for healthy sessions) waits forever. Adapter-side fix VETOED on grounds doyle ratifies: detecting present-but-stalling needs running the CLI (--version probe) = latency tax on every healthy bringup; sync existence check can't catch it (file exists); truly-absent CLI already handled (exit 2 ~1s, verified). CORE-OWNED FIX (consistent with the crm-intake ruling "establish watchdog/timeout is CORE's to own"): bringup-bind timeout in the daemon — spawned harness endpoint that doesn't bind its perch within N seconds ⇒ tear down the wedged launch child + surface a clean worded bringup failure. DESIGN CAUTIONS BANKED FOR THE WAVE: (1) the timeout and the reconcile-inside-spawn-window race are TWO ARMS OF ONE FIX — the watchdog must not become a second racer stamping over a slow-but-live bind (identity-verified teardown via the custody predicate, Unproven ⇒ no-kill); (2) N must clear slow-but-healthy harness cold starts (CC first-boot class) — configurable floor, loud diagnostic naming the child + elapsed; (3) repro asset LANDED: BigscreenVR/spt-claude-code @3074c2e `docs/findings/launch-cli-hang-repro.sh` (RED-first, run `sh docs/findings/launch-cli-hang-repro.sh <path-to-claude-spt>`; script also records the proposed fix + both design cautions) = the wave's RED-first rig seed. Adapter-side analysis + repro: perri 2026-07-25. Operator ranks; pooled with C1/seed-A/custody cluster.**

**NEW SEED 2026-07-25 (flynn filing, need-not-defect — SHELL-CMD-RESULT-CHANNEL, P3, capability request with a real consumer): shell drive commands return only the spool ack (SHELL_SPOOLED, documented); the shell's answer arrives later as an ordinary message — so a Liaison driving `create` on a submitter's behalf cannot answer 'filed as #N' in one turn (two-message pattern or idle-wait, the mint-then-wait shape W1 just killed elsewhere). flynn proposes either (a) sync/awaitable drive with timeout or (b) CORRELATION ID on the spool ack, echoed by the shell on its reply, so the caller matches answer-to-command without heuristics. DOYLE DESIGN LEAN at triage (ruling deferred to wave activation): (b) — additive, transport-unchanged, no blocking CLI wait against arbitrary shell latency; (a) contradicts the async command-class design. Open design question for the wave: whether the spool row's existing internal identity can BE the correlation id (single-source, no new mint). flynn building NO workaround (their own plan gate — correlate-later mechanisms become permanent); recorded resolved-NO in spt-alchemy ROADMAP.md pending core. Queue: shell wave neighborhood. SIDE DATAPOINT folded into the #61-63 SHELL-CLI-TRUTH entry: `--json` placed AFTER the shell op is consumed as a positional and refused as 'op help takes at most 0 arg(s), got 1' — a flag-placement mistake wearing a manifest-vocabulary costume, #61's claim-by-clap class + #63's teaching-error class in one probe (docs line owed: --json precedes the ref).**

**⏫ SECOND SIGHTING + DELIBERATE REPRO 2026-07-25 (perri, rebound-0, during v0.42.0 field acceptance — upgrades this seed's evidence state): killing a HEALTHY resident reproduces the full signature ON DEMAND — `shell list --json` stays status online, `shell relink` refuses SHELL_ALREADY_ONLINE ('relink is the online switch — nothing to do'), teardown+respawn the only recovery (identity destroyed — and for a persistent shell, identity is the point). perri's fix framing folds in: the same post-spawn liveness truth that would catch SHELL-SPAWN-DOA must also RE-OPEN relink for an instance whose child is gone. THREE-SEED SHELL WAVE now: STALE-ONLINE (this) + SPAWN-DOA + SELF-CONTAINED, one liveness/spawn-truth neighborhood, queue together on #70 leg-b. Full record: spt-rebound-tool docs/FIELD-VERIFICATION-0.42.0.md. Original entry:**
**NEW SEED 2026-07-25 (flynn field observation, HFENDULEAM alchemy-0, doyle-banked — SHELL-STALE-ONLINE, shell arm of the liveness-cluster family): `spt shell list` reported a shell ONLINE with NO process on the box (only the hub daemon + a sibling shell alive); drives to it returned SHELL_SPOOLED and were never drained — SILENT black-hole, zero staleness diagnostic; `spt shell relink` REFUSED with SHELL_ALREADY_ONLINE ("relink is the online switch — nothing to do") — the documented recovery path is unreachable EXACTLY when needed; only teardown + re-spawn cleared it.** Death mode = parent-process-tree reap (same as base claude-spt launches). THREE DEFECT FACES: (1) shell status is status-authoritative-never-pid — the C1/identity-predicate class (Athenaeum stale-ALIVE kin), shell flavor; (2) command-class spool to a dead-process shell has no staleness signal (spool-forever reads as delivery); (3) relink's online-refusal trusts the same stale status — recovery needs a liveness probe before refusal, or a force path when the process is provably gone (route through the shipped custody/process-identity predicate — proc.rs tri-state — NOT a new aliveness guess; kill/refuse arms invert on Unproven per the family-member-#5 discipline). Self-heal shape: probe-then-allow-relink or reconciler offline-stamps dead-process shells (identity-verified, both arms). Evidence: flynn message 2026-07-25 (post-PATH-fix verify); no captures — next occurrence wants shell info.json + status provenance. Operator ranks; kin entries: Athenaeum liveness cluster, custody-pair wave inputs.**

**TWO ITEMS 2026-07-25 (perri v0.42.0 field-acceptance interim; ⚠ BOTH CORRECTED BY TODLANDO GROUND TRUTH same day — my first banking repeated perri's misreads): (1) ✅ CLOSED — drive-poll status-line 'docs gap' was a MISREAD: status lines (DRIVE_DELIVERED:/ACTIVITY_DELIVERED:/DRIVE_EMPTY:) and all diagnostics go to STDERR (eprintln, reporting.rs:527-535); STDOUT carries frames only. perri read a MERGED stream. The help was literally true but silent on the split — fixed by precision in PR #75 (merged @163e0f6, doyle-gated): help now states the stdout/stderr split + a must-not-key-on-line-count warning; publishes with next cut. Lesson: a consumer reading merged streams is a foreseeable reader — document stream splits explicitly. (2) SHELL-SPAWN-DOA (renamed from LAUNCH-TRUTH; mechanism corrected, todlando): SHELL_SPAWN_FAIL already exists and fires with rollback on LAUNCH failure. perri's case: CreateProcess SUCCEEDED (powershell.exe started fine), the child then EXITED IMMEDIATELY on its own — and NOTHING OBSERVES THE CHILD post-CreateProcess BY DESIGN (launch_shell spawns detached, stdio discarded — KNOWN-HAZARDS 5.6: an inherited pipe on an immortal child hangs any capturing caller). So a dead-on-arrival child = no exit code, no stderr, no liveness recheck, hopeful SHELL_SPAWNED line, perch offline forever, zero signal. FIX SHAPE (must NOT reopen 5.6): post-spawn liveness grace check (pid alive after grace, or bind-handshake-not-seen-within-N) + a per-instance spawn LOG FILE for the child's dying words (file handle carries no immortal-pipe hazard). Silent-failure class. Repro verbatim: interpreter+script template (powershell -File <abs>.ps1, both slash flavors) DOA; native .exe first-try. KIN: flynn's SHELL-SPAWN-SELF-CONTAINED — queue together on the #70 leg-b shell wave. Evidence: perri field report + todlando shellhost.rs read, 2026-07-25.**

**⭐⭐ NEW SEED 2026-07-25 (hertz RCA, PINNED same hour with live captures — UPDATE-GENERATION-ATTACH-ORPHAN, P1 RANK INPUT: recurs on EVERY `spt update apply` for every pre-update-attached view, operator-visible each release; REOPENS the update-wedge saga closed 2026-07-10 with a NEW DISTINCT ROOT, not v0.30.4-kin):** `update apply` promotes a new BRAIN generation (gen stamp + BRAIN_RESUMED restoring session cursors; the broker image stays old — 'coordinator cycle' = brain swap). Pre-update Attach dispatch workers stay BOUND TO THE DEAD GEN-0 BRAIN PIPE: block ~15s, fail os error 233 'No process is on the other end of the pipe', retry 0/1/2 against the dead pipe, views freeze (no control, no stream) while endpoint processes + sessions stay alive. VICTIM RULE (explains multiple-but-not-all + survives the operator's perri/deployah counterexample): frozen = viewers ATTACHED PRE-update; healthy = unattached or attached POST-promotion (hertz has the full stream↔endpoint map; RC establish streams pair attach-stream-id-minus-one). SHARPENED BY HERTZ'S OWN CORRECTION (initial 'no stall-evict evidence' superseded by fresh status): the v0.30.6 bounded 15s detector DID fire (~47s post-promotion, stall_evict_count 0→16) and retired broker controller slots — but that cleans BROKER truth only; it never delivers EOF/reconnect to the frozen client side, so reattach stays manual. FIX DIRECTION (hertz, doyle-endorsed): update promotion must explicitly terminate/invalidate every old-generation Attach dispatcher so clients receive EOF and enter RC reconnect — or transparently migrate/rebind dispatchers to the new-generation brain; AND stall-eviction/generation-invalidation must couple to client-terminal close/EOF, never just clear broker state. REGRESSION RIG (hertz): attached + unattached endpoints held across an update; assert attached clients remain-live-or-EOF+reconnect, unattached unaffected, sessions survive. Ruled OUT by captures: PTY loss, controller-socket backpressure, the historical attach-flood (distinct background churn). Full daemon stop/start is NOT this defect (real process death ⇒ real EOF ⇒ reconnect). Incident: 2026-07-25 v0.42.0 apply on HFENDULEAM, victims todlando/flynn/doyle/hertz, live captures taken pre-reattach. Operator ranks — candidacy for fix-before-next-release given per-update recurrence.**

**⭐ NEW SEED 2026-07-25 (hertz RCA, doyle-verified on-box same hour — BROKER-RESTART-JOURNAL-GENERATION, P2, cross-node convergence decay with a LYING health signal): HFENDULEAM had QUIC 'healthy (4/7 peers connected)' while `endpoint list` rendered ZERO remote-node sections (subnets claim 4/6 nodes) and last_registry_admit stale.** MECHANISM (hertz, source-verified: effect.rs:213-229 markers exist verbatim): the durable effect-journal's dedup SURVIVES a broker restart but the in-memory conn/stream handle table DOES NOT — post-restart, replayed net-dial/stream-open ops return applied-but-'no longer held (broker restarted); retry with a fresh op_id', the pump does NOT take its own retry hint (aborts peer work instead), registry convergence decays/evicts remote rows, and status keeps reporting healthy from QUIC alone. Onset: daemon.stderr.log BROKER_BIND_FAIL/DAEMON_EXIT then every peer leg failing with the marker. FIX SHAPES (hertz, doyle-endorsed at triage): (a) generation-scope resource-producing journal entries to the broker lifetime OR include broker generation in their dedup key; (b) pump remints + retries ONCE on OP_NO_LONGER_HELD_MARKER (effect::with_tracing_retry semantics rc already uses); (c) health honesty — peer status DEGRADED when connected peers exist but registry admission is stale past the cadence/eviction window (the healthy-from-QUIC-alone read is the same lying-signal class as stale-ALIVE). REGRESSION RIG (hertz): restart broker with surviving brain/pump op journal; assert fresh handles minted, bilateral registry rows reconverge, endpoint list exposes remote nodes. OPS NOTE: the v0.42.0 `spt update apply` broker bounce heals this node's instance incidentally (fresh journal generation) — field-verify runs in the healed window; the defect remains for every future broker restart until fixed. Kin: registry-stall retention family (closed — recurrence-of-kin discipline), stale-ALIVE lying-signal class, DAEMON-FIELD-RSS-GROWTH's restart-cascade framing (a daemon that restarts under memory pressure hits THIS on every cycle — the two seeds compound). Operator ranks; candidate rider on the #70 leg-b cross-node wave (that wave PRESUPPOSES healthy cross-node convergence).**

**MSG-BODY-CORRUPTION STATUS 2026-07-25 (routing: EMPHASYS DRI, operator-corrected; perri filing retracted): MODE 1 ✅ SHIPPED — omp-spt 0.3.27 LIVE (GH Latest, adapter.spt sha256 9e116eb3…5789, commit caef6af; endpoints adopt via `spt adapter update omp-spt` + restart — hertz's adoption rides the pending fleet bounce; resend-on-empty workaround relaxes for mode 1 only). Root cause (emphasys): parsePeerShortforms ran maskMarkdownCode (backtick runs + fences blanked to spaces) to LOCATE @< @> delimiters, then sliced the DELIVERED BODY from the MASKED copy instead of the original — every backticked span shipped as spaces. Fix: mask locates only; body sliced from original at aligned offsets (masker is length/position-preserving); regression tests in. Lesson class: a locator artifact used as a content source. MODE 2 (empty-body inbound) OPEN — LEADING HYPOTHESIS (doyle 2026-07-25): INBOUND SIZE CAP drop-not-spill — the empty-arrival dispatch was ~2000 bytes; claude-spt's parallel cap is 1800 bytes and SPILLS to file with a notice (correct behavior, observed working repeatedly); if omp-spt's cap drops/blanks instead, that is the empty tag, explains first-contact coincidence (first message happened to be long) and shorter messages surfacing fine. Discriminating probe dispatched: hertz asked whether doyle's two latest long dispatches arrived with bodies; synthetic 2500-byte vs 500-byte control send suggested to emphasys. Hand-back-to-core clause stands only if the cap proves core-side (upstream of adapter decode). Original filing detail below:** (mode 1) BACKTICK-SPAN STRIP — hertz's peer messages composed with Markdown backticks around identifiers/commands arrived with those spans REMOVED (blank gaps mid-sentence, twice; an empty parenthetical once); hertz confirmed the wrapper, now avoids backticks as workaround. Candidate mechanism: the adapter's tag-inside-backticks-is-quotation rule over-applied to arbitrary backticked spans in bodies. (mode 2) WHOLE-BODY LOSS — doyle's first dispatch to hertz (no backticks in it) surfaced in hertz's context as an EMPTY msg tag, zero body; hertz then FABRICATED a detailed task from the empty delivery and attributed it to doyle (self-diagnosed honestly on challenge; repo/inbox sweep confirmed no external source). Downstream cost: a phantom tasking + a full correction round. Behavioral rider (fleet discipline, doyle-issued): an empty or gap-ridden inbound message is a RESEND request, never material for reconstruction — verify-don't-infer is the standing rule (same trust class as SUBAGENT-DRAIN-STEAL and todlando's refuse-unverifiable-relay). Possible kin: EVENT-PART conformance probe seed (chunking). Evidence: hertz messages 2026-07-25 (two corrupted + confession), doyle dispatch log (SENT:hertz, body lost). Routed to perri.**

**✅ FIELD INCIDENT CLOSED 2026-07-24 (SUBAGENT-DRAIN-STEAL, claude-spt, perri root-caused + shipped adapter v0.25.8 @3044d30 same day): a parent session's QUEUED perch mail drained into a spawned subagent's context — CC fires the drain hook inside the subagent for its tool calls (parent fires none while waiting), drain never checked context, subagent shared the parent session_id so it resolved the parent endpoint.** Caught via todlando's refuse-unverifiable-relay discipline (a doyle ruling surfaced as a subagent's relayed claim). Fix: is_subagent guard defers wholesale in subagent context; mail surfaces main-conversation-only; + adapter KNOWN-HAZARDS 5.1 / REQ-HAZARD-SUBAGENT-DRAIN-STEAL doc+impl+unit. ⭐ SEED RIDING OUT OF IT (doyle-ruled seed-not-REQ, defer-until-consumer): **SUBAGENT-OWN-MAIL** — agent_type/agent_id in the hook payload = the same correlation ids spt-core records on worker perches (<parent>-w<N>), so a subagent's drain hook COULD route worker-poll <worker-id> and subagents would receive their OWN mail rather than deferring the parent's. Mint a REQ only when a real consumer wants to message a worker mid-run (candidate first consumers: doyle→test-engineer mid-task rulings — the exact shape this incident faked). Evidence: incident thread 2026-07-24, spt-claude-code @3044d30.**

**NEW SEED 2026-07-24 (todlando Leg D build, doyle-banked — UNBOUNDED-PEER-READ class, P3-until-next-new-family, then P2): resthost.rs and linkhost.rs read peer reply streams UNBOUNDED — same shape that hung `endpoint digest <id@old-node>` forever in Leg D (an N-1 peer classifies an unknown stream family Unknown and drops it WITHOUT a FIN; caller reads forever, zero output).** Safe today ONLY because their families are old enough that every field peer knows them; the exposure is structural new-family-vs-old-peer, so it bites the NEXT new stream family too. Fix shape (proven in digestlink, ⚠ CORRECTED 2026-07-25 — the first ratified shape was a NO-OP, todlando caught + landed the real one): the fix is the SPLIT/PUMP CARRIER AT CONSTRUCTION (`cold_start_pump`), NEVER a budget passed at the call site — `Brain::read_frame_until` honors a deadline ONLY on the Split arm; the Whole arm is a bare read that DISCARDS the deadline BY DESIGN (a mid-frame timeout abandons a half-read frame and desyncs/poisons the carrier — brain.rs names the case), and `cold_start` builds Whole, so a caller-side budget computes a deadline the transport throws away and the CLI still blocks forever. Landed mechanism to copy: (a) construct the pump carrier for the verb (WAN dial rides it; reply read self-caps at PEER_REPLY_READ_BUDGET); (b) the verb REFUSES an unbounded carrier BEFORE any wire I/O, naming cold_start_pump in the error — the two carriers are indistinguishable at the call site (both &mut Brain), so the guard must be a mechanism, not a comment (a comment was already in the tree and the first implementation wired the wrong carrier anyway); (c) delete any budget-fallback shims rather than leaving traps. Still true: use `read_event_until`, NOT `read_peer_reply_until` (the latter reclassifies TimedOut away for the pump's drop arm). Second-order edge, also paid for: converting a SHARED cold_start brain to pump moves every co-resident verb onto a bounded carrier — give the bounded verb its OWN pump brain + dial, and budget-match the link class (production budget on real WAN; a short budget reports a slow-but-healthy link as a silent peer). Standing rule candidate: every NEW stream family ships on a bounded carrier with the refuse-unbounded guard from day one (checklist item at family mint). Evidence: Leg D digestlink defect + fix, IDLE-EDGE W1.**

**NEW FIELD REPORT 2026-07-23 (emphasys omp-spt #10, doyle code-triaged same hour — DEAF-AFTER-AUTOSTART-REPLAY, hypothesis pinned to seed A's family, captures requested).** Adapter 0.3.19 + core 0.40.0 (N-1): daemon OOM → restart → autostart replay binds OK, then endpoint DEAF — sends land in digest, no harness turn, db-wal frozen; suspend+wake recovers. CODE-GROUNDED HYPOTHESIS: autostart replay is always-fresh-never-resume BY DESIGN (autostart.rs:85 shape (a)) and runs NO Wake edge; bind normalizes no rest state; delivery holds deferred rows while effective rest reads resting (poll_drain_holds_deferred_while_resting_and_releases_once_on_wake) → stale rest record surviving the OOM leaves the replayed session delivery-held = deaf; suspend+wake recovers because Wake is the only normalizing edge. DIRECT KIN of seed A (REQ-REST-TERMINAL-NORMALIZE — the missing terminal normalization, now with a THIRD path: daemon-death-then-replay, alongside session-death and cmd_stop). Discriminator sent to emphasys: suspend → kill daemon → restart should reproduce WITHOUT OOM; captures owed (rest record + info.json post-deaf, daemon stderr ENDPOINT_AUTOSTART/WAKE_RESUME lines, 0.41.0 retest). ⭐ THIRD SITE 2026-07-23 (Librarian@Athenaeum-Library via emphasys, post daemon restart): 2 sends entered turns ~10s (bodies empty = ADAPTER bug, fixed omp-spt 0.3.21, cleanly disentangled by emphasys), 3rd NEVER turned in 6+min (SENT(WAN), digest-only) — replay-deaf class datum. SAME REPORT's pty claim ANSWERED-DENIED (doyle, code-grounded): "pty Permission denied" blocking endpoint stop→run CANNOT be a lingering-pty-owner mechanism — every run allocates a FRESH pair (openpty per spawn, pty.rs:63, non-exclusive) and stop = TEARDOWN-AUTHORITY tree teardown (0.39.0, field-verified). Discriminator sent: OpenPty(...) vs Spawn(...) wrapper — Spawn EACCES = the PROGRAM (top candidate: 0.3.20 update dropped the exec bit; onset-at-update fits); ps-after-stop capture tests lingering-processes separately. Compounding-loop narrative REFUSED until each link has own evidence. FOLLOW-UP same day: emphasys withdrew pty theory, countered "then core's update extraction dropped +x" (their packager provably ships 0o755, FATALs otherwise) — doyle walked the FULL core chain and DENIED that too, by construction: tar -xf (host tar preserves modes) → move_into/copy_dir_all via std::fs::copy (copies permission bits, not umask-subject; cli.rs:6216) → crc_swap stages fs::copy + commits by rename (crc_swap.rs:144). NEW CANDIDATE fitting EACCES-with-perfect-bits: adapters dir on a NOEXEC-mounted filesystem (managed/library host) — findmnt added to captures. Verbatim error line (OpenPty vs Spawn wrapper) stays the branch-deciding capture. ⚠ HYPOTHESIS DOWNGRADED same hour (doyle self-correction, sent to emphasys): the stale-rest link BREAKS at bind — InfoJson::new writes rest_state None (info.rs:276) and establish_perch carries forward only controllable/cwd/type, so the replay harness's successful bind WIPES stale rest intent; delivery-hold-while-resting cannot explain deaf AFTER a good bind. SURVIVES: the design difference (replay = fresh-never-resume, no Wake cascade — wake also relaunches persistent shells + re-arms delivery paths) and the mechanism-agnostic discriminator (suspend→kill→restart, both sides). Mechanism now OPEN; emphasys captures decisive (post-deaf info.json esp rest_state/session_id/status, ENDPOINT_AUTOSTART stderr, db-wal state, omp harness process state). Core-side isolated rig deferred to the rest-normalize wave unless captures point back at core. Adapter PR #11 = mitigation, correctly framed as not-root-fix by emphasys. OOM itself (1.4G peak / 3.8G host) = SEPARATE perf data point, logged not folded. Emphasys #9 evidence (5 captures) still outstanding. Evidence: omp-spt#10.**

**NEW SEED 2026-07-23 (deployah post-reversal, doyle-adopted with a scope correction): ATTACH-REPLAY-LEG-LABEL-LIES — P3 test-honesty class, rides todlando's anchor fix.** attach_idempotent_replay leg 2 CANNOT true-red on fix breakage (header-documented: passes with discriminator disabled, Brain exactly-once cursor eats re-sent ranges; discrimination lives in the unit matrix) — yet its panic label says "RED PRE-FIX: the replay re-synthesized..." — claiming exactly the discriminating power the leg lacks. That label misled TWO readers in one incident (deployah escalated believing a shipped fix's oracle went red; doyle built a structural dig case on it). Scope correction vs deployah's framing: the header is already honest — the defect is the LABEL (and any failure-path copy) contradicting the header, the F-1 diagnostic-lie class applied to a test's own assert message. FIX SHAPE: leg 2's message names what a red CAN mean there (unexpected bytes in the absence window — innocent sources include delayed PTY echo; see header) and points at the unit matrix for fix-breakage claims; plus todlando's anchor fix (drain both echoes/quiescence) and a header sentence naming the double-echo hazard. Rule candidate for the test-honesty family: a leg's failure message must not claim more discriminating power than the leg's own header grants it. Evidence: 2026-07-23 incident thread, [[window-assertion-load-direction]].**

**✅ CLOSED 2026-07-23 — RIG ARTIFACT, EXONERATED BY MEASUREMENT (todlando three-arm matrix on kitsubito, doyle-ratified; v0.41.0 attached-view changelog line STANDS AS WRITTEN, hertz leg 3 UNBLOCKED, v0.41.1 cut sequenced through the anchor-fix PR).** Matrix: main 64/120 loaded + 13/13 serial; tag 3aecc35 76/120 + 13/13; CONTROL (replay deleted, verified single SUBSCRIBE_DECISION) 27/120 loaded AND 1/13 serial — window catches the child's SECOND PTY echo with zero replays; every red one clean-oracle body, zero timeouts. ⭐ THE TWIST (sharpens, not softens): control reds SERIAL too — the shipped leg's serial-green was an ACCIDENT: the replay's read_outcome pumps for Subscribed and its Ok(_)=>{} arm incidentally EATS echo #2 pre-window; load delays cat past that drain → red. So the leg was never a sound absence check even when green, and the merge-run red was the leg being honest for the first time. REMEDY approved, todlando landing test-only PR: (a) anchor the FULL echo pair (two occurrences or drain-to-quiescence), (b) explicit drain-to-quiescence after read_outcome, (c) header names the double-echo hazard. Release path: anchor PR → doyle gate → green merge-run → deployah cuts v0.41.1 from that head (run-level-green rule intact, no exception). ORIGINAL DOWNGRADE ENTRY BELOW KEPT: → PROBABLE RIG ARTIFACT, measurement pending (todlando refuted doyle's structural read from artifacts, doyle re-verified + retracted): the oracle is INVERTED — test's own header records leg 2 passes with the discriminator DISABLED (Brain exactly-once cursor drops re-sent ranges; discriminating oracle = unit matrix, green everywhere), so it cannot true-red on fix breakage; and the anchor is mid-line-pair (cat under real PTY mints FIRST twice — line-discipline echo + writeback; pump_until returns on first substring hit; delayed second copy = innocent load-gated source; observed 7-bytes-one-copy fits it, cannot fit a from_seq=0 batch). Shipped W1 fix NOT implicated on this evidence; v0.41.0 changelog line stands; hertz leg-3 hold lifted-in-principle pending todlando's three-arm looped A/B (main vs 3aecc35 vs REPLAY-REMOVED control — the decisive arm; prediction: red all three loaded, green serialized). If it holds, remedy = rig anchor fix (drain both echoes/quiescence before window) + header sentence naming the double-echo hazard; deployah's v0.41.1 cut releases. Full lesson banked in [[window-assertion-load-direction]] (founding case = first counterexample; enumeration completeness needs a second reader). ORIGINAL (RETRACTED) ENTRY KEPT BELOW for the record:** attach_idempotent_replay leg 2 red = REAL-DEFECT signal against the W1 bug-4 idempotent-replay fix v0.41.0 SHIPPED. Red on #66 merge-run 29995900179 (kitsubito Linux full-parallel, 1/1903, assertion at attach_idempotent_replay.rs:234 "replay re-synthesized the initial batch... FIRST") AND in doyle's local Windows unbounded battery same day. NOT flake, by [[window-assertion-load-direction]] (ruled off this incident): leg-2 window is ANCHORED (pump_until consumed the FIRST echo pre-replay) and the forbidden bytes have ZERO innocent sources (only post-history attach = the replay itself) ⇒ oracle cannot false-red; loaded red = history really re-delivered; serialized-green = the race under-reporting, NOT a discharge (doyle RETRACTED its tally entry same day — the other 9 of the 10-red gate tally stand as load-family). BREADCRUMB NARROWS THE HUNT: failure body shows SUBSCRIBE_DECISION decision=idempotent printed AND history flowed — decision right, delivery wrong ⇒ race DOWNSTREAM of the decision point (a batch-synthesis/release path the idempotent branch does not gate under load); establishing trace includes controller-replaced conn1→conn2 + writer-exit channel-closed just before — replaced-conn teardown racing batch suppression = candidate. W2 NOT the story (deployah src-delta check: broker.rs + this test untouched in v0.41.0..main). DISPATCHED todlando 2026-07-23: loop-under-load A/B on kitsubito, main 2342fd6 vs tag 3aecc35; doyle prediction on record = red BOTH arms (W1-era load hole). ⚠ STANDING HOLD: hertz field leg 3 (bug-4 replay on a real update) MUST NOT run until verdict — it would exercise exactly this seam against a claim under suspicion ("no longer freeze attached views" changelog line). Closure standard = looped-repro-then-green (v0.36.0). If red-on-both: defect predates the 0.41.1 range; cut-with-Known becomes an operator/deployah call.**

**FAMILY MEMBER #5 + MECHANISM SHARPENED 2026-07-23 (doyle triage PR #66 W2 CI red; todlando's split adopted): shell_sleepwake_e2e sleep_wake_cycle_drives_from_both_ends, Win Phase A, run 29977242525 — bare exit 1, stdout truncated at "running 1 test", ZERO panic banner, died 3.0s in mid-wake = external termination, the family's process-level-death signature exactly.** Joins the environmental-cause family below (line ~19). NOT W2 code: test file untouched, zero source overlap, Linux + both n1-gates green, disk fine (262 GB). MECHANISM SPLIT (todlando, doyle-adopted): PR #58's reap-by-EXECUTABLE-PATH is safe under pid reuse; **kill-by-STALE-PID-FILE is the open half** — hygiene reaps/`kill_waker_at`/daemon.pid taskkills act on a pid read from a parked file = a claim about the past; bounded-8 Windows pool recycles pids fast enough for the claim to be wrong, victim = whoever inherited the pid. Lives in family legs 3/4 (operator-only + out-of-scope), NOT shipped by #58. ⭐ EPISTEMIC: a green rerun does NOT falsify — recycle just missed a neighbor that round; reds tally contention, greens prove nothing. DISCRIMINATING CAPTURE (needs a rig leg, not a rerun): victim's OWN pid at test start vs pids in neighbors' parked pid files at kill time. Candidate mechanism fix if promoted (todlando pointer, doyle code-grounded 2026-07-23): DON'T mint a new identity check — route pid-file kills through the SHIPPED custody predicate (REQ-RESUME-CUSTODY-IDENTITY / ADR-0047 d1: `spt_store::proc::process_identity` tri-state Present(start)/Absent/Unproven @proc.rs:598 — existence from process TABLE first, start time as discriminator only, fresh handle closed immediately, KH 7.50-safe). Kill only on PROVEN pair match. ⭐ TWO deliberate design points: (1) the Unproven arm INVERTS per caller — revive/reap-skip = leak (tolerable), kill-on-guess = this incident; kill path defaults NO-KILL on Unproven, decide explicitly, never inherit; (2) SCOPE FACT (doyle, on-box): today's pid files park the PID ALONE (`child.id().to_string()` — waker @shellwake.rs:218, shell.pid same class), so the fix requires pid-file writers to park the (pid, started_at) PAIR at spawn — the format change IS the work; the predicate is free. (3) N-1 FORMAT DISCIPLINE (todlando 2026-07-23, both arms = the custody pair's own discipline applied to its serialized form): **(a)** LEGACY pid-only file reads as Unproven → NO-KILL — correct, but names a real CHANGEOVER WINDOW: kills against pre-format files don't happen until the next spawn rewrites the file, so whatever they cleaned leaks, bounded + self-healing (one spawn per parked child), strictly better than the incident; builder chooses this deliberately, not via census discovery. **(b)** NEVER silently upgrade a pid-only file by reading the live process's CURRENT start time and parking it — that manufactures exactly the claim the pair exists to check (the process wearing the pid NOW is the thing in question); read-legacy-as-Unproven is the only honest handling. Evidence: run 29977242525 job 89111562727; todlando exchange 2026-07-23.**

**NEW SEED 2026-07-22 (doyle code-sweep answering deployah's coverage question — candidate REQ-NOTIF-GATE-ALL-DRAIN-SURFACES, P2; the 0.41.0 validity gate misses a THIRD drain surface).** Three production drain surfaces exist; gate covers two: relay non-deferred drain (relay.rs:74 ✓) + active-window poll (api/delivery.rs:236 ✓); **READY-AGENT listener drains UNGATED — listen-startup backlog (spt-msg ready.rs:154) + since-startup drain_spool (ready.rs:190), both raw drain_non_deferred_audited_at → (from,body) → EVENT composition at delivery edge.** Root = LAYERING: notifgate lives in spt-daemon, spt-msg can't reach it — the single-implementation-no-drift goal (notifgate.rs:118) is enforced-impossible for this caller. Population LIVE: first-fire targets any online perch incl. ready agents → notify copies land on ready spools → notif_id copy whose row dismisses delivers stale TODAY, injected-turn shape. ⭐ Scope honesty: rider contract said "BOTH presentations" — built as contracted; the miss = doyle's surface count at triage, not todlando's build. FIX SHAPE: push gate core down-layer to spt-store (owns spool AND notif store; classify already pure) so all surfaces share one impl by construction + surface-enumeration test that fails on any new ungated drain caller. ⭐ RANK INPUT (deployah 2026-07-22, doyle adopted): this seed carries a PER-CUT changelog cost while open — its Known entry ships in v0.42.0 and repeats every release until fixed; a Known repeating across consecutive releases reads as a permanent property. Argues the seed forward in queue rank (not into W2). Changelog: corrective note rides the fixing release, scoped to ready-listener case (shipped claim true for the field-report surfaces). Hertz's specific envelope still discriminates their instance (deployah predicts legacy no-notif_id — likely right; ball-b = live agent = gated relay surface). notif.rs:740 drain_all_at = test fn, production-callers claim survives. Evidence: [[v0410-published]], doyle sweep 2026-07-22.

**TRIAGED 2026-07-22 (doyle post-v0.41.0 queue item): flynn #61-63 = SHELL-CLI-TRUTH mini-wave, code-grounded, dispatch-ready AFTER W2-C2 (same executor, zero file overlap with W2 but todlando single-threaded).** All three pre-accepted from the 2026-07-21 W5 exchange, routed doyle. (1) **#61 P2 correctness (silent-intent-drop class):** `ShellCmd::Cmd` op = `Vec<String>` positional capture (cli.rs:12141-12172) without trailing-var-arg semantics → a trailing global flag (`--json`) after the shell op is claimed by spt's OWN clap parse, op spools with CHANGED semantics, no error. Design lean recorded on the issue: LOUD REFUSAL is the floor; `--` separator may ride; blanket pass-through least likely. (2) **#62 P3 parity:** `shell send` body on stdin — precedent in-tree (cmd_notify/send stdin-trim @cli.rs:6822/7068, REQ-HAZARD-ENVELOPE-CR-LINESAFE parity pattern); argv multi-line bodies are shell-hostile (alchemy payloads hit constantly). (3) **#63 P3 teaching error:** arity refusal should name the one-quoted-tail convention (`spt shell cmd <ref> <op> "--state done --json"`). REQs mint registry-first at wave activation (NOT now — registry tail is todlando's W2 collision zone). Evidence: issues #61-63, doyle code-read 2026-07-22.

**NEW SEED 2026-07-22 (v0.41.0 field-verify preflight — DEBUG-PIN TOOLING HAS NO UN-PIN STEP AND NO RESIDUAL SIGNAL; candidate = xtask debug-pin lifecycle completion, P3 tooling class. SCOPE CORRECTED same hour, deployah retraction doyle-adopted: NOT a fleet risk, NO census).** Provenance (hertz, honest): the ENLYZEAM pin was hertz's OWN creation this task — xtask debug-pin/debug-rollout deployed the byte-tap build (release-keys.json channel=debug key_id=dev-debug-2026, cached signed debug set counter 74 @f31849c, Windows-only); cleanup omission theirs, NOT pre-existing state. RETRACTED: "other nodes may be quietly stranded" + fleet census (unsupported — bounded to boxes that hosted a debug rig). SURVIVES (mechanism-shaped): the tooling's pin outlives its task silently — no un-pin verb, no operator-visible signal a pinned node stopped being stable-eligible; at v0.41.0 it nearly manufactured a false obs-3 NOT-OBSERVED (caught by hertz's unprompted sibling probe, [[absence-needs-sibling-probe]]). Fix shape at triage: xtask debug-unpin (archive-and-restore = what hertz did by hand) + pinned-channel state LOUD in status/digest. Runbook half (channel-pin sweep on ex-rig boxes) rides deployah's docs lane. Evidence: [[v0410-published]].

**NEW SEED 2026-07-22 (v0.40.0 release incident — OBS rider SUBSCRIBE_DECISION pin emits under the broker OutputLog lock; emit-after-lock hygiene fix, P2).** The rider's always-on breadcrumb is a synchronous eprintln (daemon stderr → FILE via redirect) inside resolve_subscribe's &mut self section — fs I/O under the lock, KH 7.12 class, on the take/stall-evict path. Passed review TWICE (doyle cited the become_controller perch-write precedent; deployah filed spec-matching) — precedent-citing is how lock-I/O grows. Suspected (not established) as amplifier in the #56 brain_decouple reds on the disk-starved box. FIX SHAPE (doyle-ruled): format under lock into a buf, WRITE after the lock releases — file-sink move alone is the same bug in a different hat. ACCEPTANCE = the staged A/B loop (scratchpad/discriminator-brain-decouple.sh, zero-disk-growth revision: prebuilt targets, concurrent prebuilt-binary load, no workspace-build generator) run at leisure, never against a release clock. Files regardless of the #56 third-run color; if third run went red-with-headroom this became the release-blocking fix instead. Kin: KH 7.12, [[hfenduleam-disk-full-ci]].**

**SIGHTING 2026-07-25 (todlando, IDLE-EDGE W1 local sweep, HFENDULEAM ~35 spt procs live — tallied, not resolved): spt-daemon --lib, 5-run local tally = 1 red (name LOST to a grep filter — unrecoverable) + 1 HARD WEDGE (test binary reached 22.41s CPU then STOPPED — zero further progress for an hour until pid-targeted kill of 47996 + cargo parent 43068; not slow, stopped) + 3 greens (timeboxed rerun 623/0 in 20s). Wedge signature matches the family's process-level-stall class + the standing daemon-lib-deadlocks-on-live-host rule; greens prove nothing per family epistemics. Process lesson banked (todlando's own): NEVER background a suite without a hard timeout wrapper — the wedge sat silent an hour; everything since runs under `timeout -k`. CI remains authority for the suite.**

**⭐⭐ FAMILY RE-ROOTED 2026-07-22 (deployah third-run analysis, doyle-ratified): NOT N flaky tests — ONE environmental cause picking a RANDOM victim per run: CI executes on the host that runs the live agent fleet.** Evidence: #56 runs 1/2/3 killed a DIFFERENT single daemon-spawning test each time (brain_decouple ×2 starved-disk → adapter_translate → adapter_digest at 105.9 GB free) while sibling tests in the same families passed alongside; victims die PROCESS-LEVEL (bare exit 1, no assert output — same signature as the fork + broker-reap watch-items below); box census during runs: 43 live spt-family processes (29 spt / 12 claude-spt / omp-spt / spt-mobile-host), 6486 handles, vs 1881 tests Phase-A full-parallel many spawning daemons/binding endpoints. Kin hazards realized: [[e2e-leaked-daemons-shared-box]], [[seedmap-test-collides-live-daemon]], [[hfenduleam-hosts-flynn]]. WAVE SHAPE REORDERED (cause-side first): (1) leaked-test-daemon sweep mechanism (scoped to test/temp exe paths — never machine-wide) + census tooling; (2) Phase-A parallelism cut on the Windows leg (ci.yml/nextest — deployah option c, ratified); (3) OPERATOR DECISION REQUEST — ANSWERED, RULED NON-OPTION (operator 2026-07-22, canonical in e2e-leaked-daemons-shared-box.md: “NON-OPTION for now — stop proposing it”; do NOT re-propose; sightings accumulate in the family record instead): CI runner off the agent-fleet host (option d — census + run table attached; same host also just took the disk escalation); (4) member hardening (bounded-poll rigs etc.) only for members that STILL red after cause-side legs. Member-by-member hardening alone = chasing casualties, family never closes. Acceptance stays looped-repro per member. RELEASE-CYCLE MITIGATION used for v0.40.0: quiesce-partial window (scoped leaked-daemon sweep + all-agents-hold + single watched rerun) — doyle-ruled, reusable shape. Individual member entries below stand as evidence records.** The four: (1) fork_forks_homes (Win, bare exit-1, no body); (2) broker::a_reap_clears_control_stamps (Win, no body captured); (3) shell_e2e teardown Directory-not-empty (Linux, os 39); (4) endpoint_autostart_e2e::saved_endpoint_replays (Win CI, session-id freshness assert at 44s — replay's fresh-session stamp lost a timing race under Phase A full-parallel; #55 merge run 29890856839). All: green isolated/rerun, none in the wave's changed seam, all under saturated parallel load. Read: heavy e2e rigs (and possibly product paths) carry timing assumptions that only hold on an unloaded box. Wave shape when activated: per-rig bounded-poll instead of fixed-window reads (the registry_lifecycle 2026-07-19 hardening shape), teardown reap-writers-first, and a triage pass distinguishing rig-race from product-race (autostart #4 needs that discrimination FIRST — a session-id stamp racing a reader could be a real product ordering hole). ACCEPTANCE (deployah rider 2026-07-22, doyle-ratified, = the v0.36.0 lesson): each family member closes on LOOPED-under-load repro-then-green, never on a single rerun-green. Operator decides queue placement.**

**NEW SEED 2026-07-22 (doyle W2-merge CI — shell_e2e Linux teardown race, P3 watch-item, load-flake family).** `spt::shell_e2e mock_shell_binary_drives_the_full_link` red ONCE on kitsubito (Linux) Phase A full-parallel, W2 merge run 29887846895: teardown assert at shell_e2e.rs:291 — `SHELL_TEARDOWN_FAIL: io: Directory not empty (os error 39)`. Same commit green on Windows CI leg + doyle's isolated full battery (2050/2050). W2 diff = notif/presence/store only, ZERO shell overlap → flake call defensible (not inside the wave's changed seam). Class: Linux teardown-vs-writer race (recursive delete racing a straggler write — same Linux-under-CI-load family as the registry_lifecycle 2026-07-19 seed). Hardening target: bounded-poll teardown or reap-writers-first in the shell_e2e rig. Reds again → RACE, loop under load. Evidence: run 29887846895 (rerun dispatched).**

**NEW SEED 2026-07-22 (todlando NOTIF-TRUTH W2 preflight — broker reap-stamps test observed-once red under parallel load, P3 watch-item, NO failure body).** `spt-daemon broker::tests::a_reap_clears_the_control_stamps_but_never_the_hosting_authority` failed 1/1 in todlando's `cargo test -p spt-daemon --lib` full-parallel preflight (591 passed, 31.9s wall), passed instantly isolated (0.05s). W2 diff touched NO broker code. ⚠ assertion/panic output NOT captured (preflight grep kept only result lines) — no failure body exists. DISTINCT from the fork_forks_homes seed (different binary, different seam). Recapture net = any future full battery with output capture; reds again → RACE, loop under load with --no-capture. Control-stamp/reap seam = KH 7.27/7.29 + C3 poll-vs-reap neighborhood — if it recurs, check those first. Evidence: todlando preflight 2026-07-22 (doyle transcript).**

**NEW SEED 2026-07-22 (doyle NOTIF-TRUTH W1 gate @d289787 — fork test observed-once red under cold parallel load, P3 watch-item).** `spt::bin/spt cli::tests::fork_forks_homes_and_deletes_exactly_the_source` failed ONCE in the isolated-worktree gate battery (first cold nextest run on a fresh throwaway target, 16-way parallel, ~15 tests in flight): bare process exit 1, ZERO panic/assert output captured (stdout showed only "running 1 test") — process-level death, not an assertion. Discrimination run same sha: 1x isolated w/ --no-capture GREEN (all FORKED/SAME_ID/TAKEN/NO_SUBNET/COLLISION legs printed), 0/20 isolated loop, full --no-fail-fast rerun 2043/2043 GREEN incl this test under load. NOT attributable to W1 (notif-only diff; no fork/homes seam overlap). Shape smells like shared-state collision under first-run load (env/home dir? bare exit = possibly std::process::exit path in the fork CLI under a lost race). Per [[e2e-leaked-daemons-shared-box]]/v0.36.0 lesson: observed-once + repeat-green ≠ closed — if it reds again ANYWHERE, upgrade to RACE and loop-under-load with --no-capture to catch the exit path. Evidence: gate-battery.log first run (fail at 213/2043), this session 2026-07-22.**

**NEW SEED 2026-07-21 (doyle PR #48 gate rider — envelope attr line-safety unenforced; candidate REQ-ATTR-LINESAFE-ENFORCED, P2).** `event_attr_escape` (spt-proto envelope.rs:60-65) does NOT touch `\n`/`\r` — the "attr values are line-safe by construction" claim (envelope.rs:59 comment, now mirrored on the published frames page) is unenforced convention. Concrete hole: `compose_file_frame` (shellchan.rs:103-109) embeds the ORIGINAL FILENAME in the `path` attr (`files/<xfer-id>-<name>`); Linux permits `\n` in filenames → raw `\n` inside an attribute → multi-line frame → breaks one-line envelope framing + line-framed MAC verify. Body side safe (name body escapes `\n`→`<br>`). Fix shape: normalize-or-refuse at xfer-accept/compose time (filename sanitization), NOT a codec change (attr codec deliberately has no `<br>`; adding one would be a wire-format change). Sweep other attr sources for user-controlled content while there (op/verb vocab-checked, ids minted — path/<name> is the known hole). Filed during frames-encoding docs gate (v0.39.3 wave); see [[frames-encoding-docs-defect]].

**✅ DISPATCHED 2026-07-17 as ACTIVE MILESTONE — operator rolled REGISTRY-STALL + DAEMON-LIFECYCLE (entries at lines below: emphasys triple, rest-normalize, spawn-fresh, cycle-honest) into ONE milestone REGISTRY-LIFECYCLE; see [[registry-lifecycle-progress]] (triage @1b54e50: ADR-0040/0041 + KH 7.44/7.45 + 14 REQs; todlando building W1). Original entry kept below for design context.** — REGISTRY-STALL (hertz post-close v0.36 field RCA, doyle code-verified ALL legs same day, ACCEPTED IN FULL; active HIGH regression on prod: recurring 15-25s Registry-family CONN_WRITE_POISONED + always-on CPU. Full RCA canonical at .claude/reports/2026-07-17-registry-stall-rca/; fixes B1-B5 + regression seams ride verbatim.) Supersedes the v0.36 "broad poison fingerprint dead" clean-window claim (Attach/PTY calm STANDS — W1 fix valid; the same blocking/replay class recurs for Registry family). **(B, P0) Registry stream history + replay write amplification — 4 verified legs:** (1) sender retention: pump push_feed (pump/mod.rs:1116-1122, ~30s cadence) opens one fresh stream per feed on the long-lived pump conn; NOBODY retires locally-initiated rows (dispatcher = sole retire_stream caller, skips initiated_locally at dispatch.rs:470) → sender rows accumulate forever; (2) O(history) IPC: broker stream_infos (nethost.rs:1805-1823) filters `retired` only, NOT initiated_local server-side → full historical row set serialized to dispatcher EVERY poll; (3) write amplification: serve_registry_feed (dispatch.rs:996-1040) per 64KiB NetStreamData chunk calls apply_node_labels + apply_feed_flips, BOTH end in write_snapshots (registryhost.rs:295,342) = up to 2 full-registry atomic rewrites per chunk, synchronous in brain's read_event loop → brain stops draining IPC → broker SubscriberSeat writer blocks → 15s bound → CONN_WRITE_POISONED → dispatcher re-replays from seq 0 (finished Registry rows non-terminal by design, finished_row_is_terminal Attach-only); (4) resource retention: retire = eligibility-only, physical entry/subscriber/threads live until conn close → long-lived pump conn never frees (broker ~550 threads observed, only 4 active). FIELD: 12 CONN_WRITE_POISONED since gen1, ALL family=Registry attempt=0 endpoint=- (endpoint=- BY DESIGN — Registry has no endpoint key; hertz's prod-endpoint-key residual stays PENDING, needs endpoint-bearing family failure), elapsed 15.5-25.4s, streams 524→6411; broker 11.4%/core, brain 15.5%/core sustained. FIXES (hertz shape, doyle-accepted, ordered): B1 retire locally-initiated fire-and-forget feed rows on successful FIN (or explicit one-way-family terminal semantics); B2 filter initiated_local+retired server-side in stream_infos before IPC clone; B3 transactional feed apply — merge in memory, write_snapshots ONCE at EOF/bounded batch, never per-chunk×per-kind; B4 failed Registry replay must not remain indefinitely redispatchable (fix at source, NOT deadline bump); B5 audit physical StreamEntry/subscriber teardown on one-way completion (bound long-lived-conn resources). REGRESSION SEAM: long-lived pump + dispatcher int test, N registry rounds one conn — eligible rows plateau O(active); physical counts plateau; snapshot writes O(feeds) not O(chunks×kinds); brain refresh = zero historical Registry replay; zero poisons; bounded thread baseline. GATE ADDITIONS (doyle): every leg keeps redispatch D1/D1b + mesh-recovery legs green (retire machinery + registry gate = substrate); B2 wire-visibility check (older brain vs filtered stream_infos = N-1 question at triage). **(A, P0 rider — DROPPED-RIDER ESCALATION):** brain self-hash per-500ms-heartbeat — ALREADY RULED 2026-07-15 as W4 rider (entry below: OnceLock once-per-process digest, doc-comment fix, digest-counter==1 gate, breadcrumb-truthfulness leg) but NEVER BUILT (THE-FORKENING W4 closed without it); hertz re-measured live 2026-07-17: 61.29 MiB/s predicted vs 63.91 observed (4.1% err), 15.5%/core brain. Fix design stands as ruled — rides REGISTRY-STALL W1. Evidence: C:\Users\decid\AppData\Local\spt-core\logs\daemon.stderr.log (first poison line 3136); hertz measured PID census 2026-07-16/17. DISCRIMINATORS ANSWERED (hertz 2026-07-17, doyle-verified): all 12 poisons = FRESH physical conns (1243→13782, none open now) + 12 distinct streams = fresh-carrier replay churn NOT one wedge; all attempt=0, ZERO breaker trips = not retry-ladder/breaker driven (each poison first attempt on fresh stream; one outlier stream5846=53.0s); Win32 GetThreadDescription census broker total 589 = unnamed 546 / conn-watchdog 33 / spt-broker-net 7 — vs only 30 open BrokerConns + 13 subscribers per log lifecycle → ~500 excess unnamed = retained SubscriberSeat writers (nethost.rs:196 bare unnamed thread::spawn, doyle-verified) parked until conn-close sweep that never comes on the long-lived pump carrier. ⚠ ATTRIBUTION CORRECTED (hertz final cross-check, doyle-verified broker.rs:3246/3280): retention is FAMILY-AGNOSTIC — my_stream_subs detaches ONLY at conn-loop exit, NO net-stream unsubscribe verb exists (KIND_UNSUBSCRIBE = PTY-session only) → completed sync/update seats on the pump Brain carrier retain too; Registry rows stay the independent driver of enumeration/amplification (B1-B3). B5 therefore = CROSS-FAMILY bounded seat lifetime (unsubscribe verb or seat-scoped release), not Registry-scoped. RIDER (doyle): name all spawned daemon threads (SubscriberSeat writer minimum — `sub-writer-s<id>`) so future censuses aren't 93% blind; cheap, rides W1. Lane: doyle triage (ADR/REQs registry-first) → todlando builds → doyle gates → hertz field-verify (owns incident logs). Kin: REDISPATCH-STALL (same blocking class, closed W1 = substrate), DAEMON-LIFECYCLE C2 leases (stream lifetime classes — coordinate at triage, B1's one-way terminal semantics = same neighborhood).**

**✅ DISPATCHED 2026-07-16 as ACTIVE MILESTONE — see [[redispatch-truth-progress]] (triage @3d9f2ed: ADR-0038 + KH 7.41 + 4 REQs; todlando building W1). Original candidate entry kept below for design context.** — REDISPATCH-TRUTH (hertz source-level RCA, doyle seam-verified same day; NEW RANKED-FIRST, displaces MESH-RECOVERY). `spt daemon refresh` / `spt update` (same brain-cycle path, applyhost.rs) freezes active remote `spt rc` sessions: fresh brain's `dispatch::run_dispatch_loop` starts with an EMPTY per-process `claimed` set and enumerates EVERY broker-held peer stream — including FINISHED historical attach streams, because `NetShared.streams` has NO removal path (doyle verified: single `.insert` @nethost.rs:649, zero remove/retain; `StreamLog::finish` marks only) and the claim condition (`initiated_locally || next_seq==0 || !claimed.insert`) has NO finished filter (verified dispatch.rs ~211). Replayed historical Attach → `attach_as(Control, same origin)` same-identity silent `become_controller` (no Displaced signal) steals the CURRENT controller; replayed EOF then `detach_session` CLEARS it → live serve loop still believes Controller but sink deselected = operator sees FROZEN PTY; detach + fresh `spt rc` recovers (explains no-PTY-restart recovery). ADJACENT: opener classification reads `peek_first_line` from ring seq 0, but StreamLog = bounded 4096-chunk ring — a high-traffic ACTIVE stream's Request record evicts → replay classifies Unknown/Failed → claim inserted pre-spawn, never retried = active stream PERMANENTLY ABANDONED. Field: 4/5 endpoints frozen across TODAY's two doyle refreshes (deployah-recovery + v0.33.0 apply) + lia on the update; DISPATCH:N:Failed lines in fresh generations = supporting evidence; stall-evict 15→17 baseline likely same fingerprint. Existing e2e `attach_survives_target_brain_restart_exactly_once` BYPASSES production rediscovery (manually re-serves a known short stream) — why CI never caught it. Fix shape (hertz A-D, doyle-endorsed): A finished rows retired from redispatch eligibility; B restart-durable opener/classification metadata pinned OUTSIDE the evictable data ring (per-stream immutable fact until close); C retryable claims (distinguish active/retryable vs served vs finished, no hot-loop); D three production-path regressions (historical+current same-origin restart = no steal/clear + exactly-once; >4096-chunk opener-evicted restart = durable classification resumes; injected transient worker failure = claim retry, no dup controller). DISTINCT from the CLOSED 0.30.x resume-steal saga (that was brain session-cursor resume, fixed cursor-only 0.30.5/6; this is the NET DISPATCHER leg — do not re-anchor old theories). Possible kin (verify at triage, don't assume): deployah zombie controlled-by latch [[REQ-ENDPOINT-CYCLE-HONEST seed]]. Canonical RCA artifact: `C:/Users/decid/.omp/state/spt-endpoint/hertz-refresh-rca.txt` (OMP state, NOT yet a repo report — copy into .claude/reports/ at triage). Incident logs (hertz preserves): `C:/Users/decid/AppData/Local/spt-core/logs/daemon.stderr.log` + `.log.1` (brain generations 2/3, the DISPATCH:N:Failed lines). Lane: doyle triages → todlando builds → doyle gates → hertz field-verify (they own the incident logs).

**✅ DISPATCHED 2026-07-16 as ACTIVE WAVE — see [[redispatch-stall-progress]] (triage @7488c1a: ADR-0038 Amendment + KH 7.43 + 5 REQs; todlando building W1). Original entry kept below for design context.** №4 (hertz v0.34 PTY/RC 20-30s STALL RCA — doyle seam-verified dispatch.rs:414 broad Err(_) fallback + StreamLog::attach discard-and-continue replay-under-lock same hour, ACCEPTED; RANKED ABOVE ALL — field regression on live v0.34, recurrent stalls, poison interarrival median 95.5s. REDISPATCH-STALL W1: doyle triage (ADR-0038 amendment + REQs registry-first) → todlando builds P0 1-6 → counter 63 fast-follow after MESH-RECOVERY's 62. Full RCA in doyle transcript 2026-07-16 sptc-drain spill; fix design 1-9 + seven-test matrix + fast-field-discriminator ride verbatim.)** MECHANISM (not one new timer): W1 retryable claims (500ms/1s ×3) + broad ANY-Err opener fallback (dispatch.rs:414 — comment intends old-broker-only) + throwaway peek subscriber → StreamLog::attach synchronously replays ENTIRE retained ring under the per-stream mutex, `let _ = sub.write()` discards errors, iteration continues past failure, poisoned subscriber stays installed → 15s CONN_WRITE_POISONED windows (33 observed, all 15,000-15,154ms exactly) compose with unbounded Whole-brain reads + distinct unbounded wire conn + NetHost 10s send into 17-62s observed DISPATCH tails. Field: 4361 stream-sub-attach records/gen, 584 PUMP_PEER_FAIL; per-stream not broker-wide (unrelated conns progressed mid-poison — falsified). COMPANION: control-steal via stale attach replay — doyle precision note: D1/D1b prove FINISHED rows never serve; observed steal likely rides UNFINISHED-stale rows (raw-close no-FIN viewports = emphasys C2 feeding this) — discriminating observable next live catch = stolen row's finished+retired flags; fix 6 (ownership/generation validation before attach/detach) covers both shapes. P0 FIXES (accepted as filed): (1) fallback ONLY on explicit UnsupportedVerb/old-broker — transport timeout/EOF/poison = Failed/requeue bounded, never a second replay subscriber; (2) replay stops at FIRST write failure, failed subscriber REMOVED (attach+append+finish all); (3) writes OFF the StreamLog mutex — bounded per-subscriber writer queue, enqueue-under-lock/IO-outside, overflow=detach+resume-from-cursor; (4) attach worker completion + forwarding BOUNDED — brain-subscriber poison cancels paired serve/wire worker; (5) retries CLASSIFIED — pre-setup transient may retry, deadline-poisoned replay = circuit-broken global backoff, never reinstall until prior subscriber fully gone (NOT a revert to v0.33 abandonment); (6) terminal-exclusion enforced pre-serve + ownership/generation validation (stale worker never detaches replacement controller); (7) bounded redispatch worker pool + batched cold enumeration, no claim locks during I/O; (8) clone-then-drop sessions lock before detach_if/info.json I/O; (9) keyed stage telemetry (gen/stream/family/endpoint/attempt/conn + replay/poison/cancel/worker-outcome + gauges + PTY high-water/RC cursor). DOYLE GATE ADDITIONS: every leg keeps redispatch D1/D1b green; test-7 mixed-image = REAL streams (handshake-only N-1 insufficient — rider). MISSING-COVERAGE census (fair, rides wave): D3 never poisons an installed subscriber; conn_blackhole ≠ StreamLog subscribers; daemon_refresh ≠ cross-node attach continuity. COORDINATE at triage w/ DAEMON-LIFECYCLE C2 leases (fix-4 bounded forwarding = same neighborhood, no double-build). Operational caveat kept: update --restart's 30s rc reconnect loop = distinct + bounded, not this.**

**NEW SEED 2026-07-16 №3 (hertz emphasys RCA — false ONLINE+CONTROLLED after daemon restart / /exit / raw PTY close; doyle seam-verified startup.rs:636-641 + livehost.rs:680-682 same day, ACCEPTED IN FULL; completes the 3-report DAEMON-LIFECYCLE cluster w/ Issues A+B — cluster now RANKED FIRST post-MESH-RECOVERY. Full report in doyle transcript 2026-07-16 (sptc-drain spill file); fix set 1-6 + regression matrix 1-10 + P0/P0/P1 ride verbatim.)** THREE distinct defects: **(C1, P0) hybrid ONLINE classification + skipped reconcile** — cmd_listen stamps status=online from manifest psyche_init alone (live_capable, startup.rs:636), no persisted-state/hosting-authority check → ready_agent/controllable=false hybrid rows born online-authoritative; livehost reconcile skips state!=live_agent (:680) AND gates cleanup on controllable=true → dead-PID hybrid survives every restart (is_perch_alive trusts status=online, skips dead-PID rejection — every reader faithfully resurrects). Fix: creator gate on actual persisted state/hosting authority + legacy self-heal after SUCCESSFUL broker query (never interpret broker-failure as empty set) + SPLIT control cleanup (clear controlled/driven_by/viewer_count for every endpoint absent from session truth regardless of state/controllable) from offline classification (live_agent+controllable=true only) + terminal signoff/owner-loss = atomic CAS-guarded offline+ready/address removal WITHOUT overloading soft api session-end (/clear must preserve live listener). **(C2, P0) raw viewport stream leak** — rc opener Brain dies without FIN; its attach net stream is deliberately restart-durable → target serve_attach never sees NetStreamEof, never detach_session → controller slot + CONTROLLED stamps survive even full broker restart. Fix: explicit stream lifetime/lease classes — RC attach/view = ConnectionBound (FIN on opener conn EOF), inter-brain durable stays durable; NEVER globally retire on Brain disconnect (breaks brain-swap); preserve detach_if identity (late close from A can't evict newer B). DOYLE RULING: lands as ADR-0038 AMENDMENT; D-legs must keep brain_swap/daemon_refresh/redispatch green (v0.34.0 retire machinery = substrate). **(C3, P1) poll-vs-reap ordering race** — KIND_SESSIONS snapshots controller truth under lock, writes stamps after unlock; exit-waiter reap between = old poll relatches controlled=true. Fix: session/generation-validated convergence or serialized per-endpoint stamp transitions; no fs I/O under global locks (KH 7.12); clear all three fields every no-session path. Kin: KH 7.27 (child-reap only), KH 7.29 (its off-lock convergence ENABLES the relatch), gateway Defect B (directly causal, now realized), 2026-07-14 emphasys-ABSENT seed (this RCA explains it). NOT kin: Issues A/B (independent families — hertz's own discrimination, verified). emphasys left untouched as triage evidence.

**NEW SEED PAIR 2026-07-16 (hertz perri-lifecycle triage — doyle seam-verified all cites same day, BOTH ACCEPTED; strongest-grounded members of the DAEMON-LIFECYCLE cluster, likely front it as next-milestone candidate after MESH-RECOVERY. Full report in doyle transcript 2026-07-16; test lists ride verbatim.)**
**A — definitive session death leaves rest intent Active → zombie WAKE_RESUME loop (candidate REQ-REST-TERMINAL-NORMALIZE).** rest_state = intent, distinct from liveness; cold masks Active→effective-Suspended (resting.rs:225-236) BUT wake-resume path decide_resume (livehost.rs:322+) reads RAW stored rest state → dead session with preserved Active = outstanding wake intent, reconcile offlines then a later pass RESUMES it from the ledger (perri field: repeated `WAKE_RESUME:perri … anchor-int-proof` across generations; daemon.stderr.log.1:928/932-934 + current :82…:2933). mark_offline (lifecycle.rs:567-568), livehost liveness reconcile, and cmd_stop (cli.rs:6935-6948) all stamp status=offline ONLY — none touch rest_state/dormant_since_ms. FIX (hertz shape, doyle-accepted): ONE store-level atomic mutation for definitive hosted-session loss — status=offline + rest_state=suspended + clear dormant_since_ms in the SAME info.json write; used at authoritative broker-session-loss/liveness-reap + cmd_stop. NOT daemon_rest_event(Suspend) (effective already Suspended → no edge → raw Active survives); NOT transition echo (harness dead — terminal normalization, not graceful edge; graceful shutdown keeps echo-before-teardown); NOT blanket offline⇒suspended in readers (destroys explicit-Wake semantics — wake writes intent first, reconcile consumes; normalize ONLY on definitive online/unbound→offline/reaped observation or explicit Stop). Tests: atomic-pair store unit (never mixed); livehost regression (session vanish → offline+suspended, next reconcile NO WAKE_RESUME); endpoint_stop extension (incl already-offline/raw-Active input); explicit-wake guard (suspended/offline→Wake→Active→launches ONCE); RefuseLivePid-then-valid-bind custody race (revived seat NOT stranded suspended). Kin: HOSTED-LIVE COMEBACK (lia ready=true alive=false — likely same missing-terminal-transition family), deployah zombie ALREADY_LIVE latch.
**B — `endpoint run --create` silently reattaches/no-op-acks, never creates (candidate REQ-SPAWN-FRESH-TRUTHFUL).** Help promises fresh session (cli.rs:359-360) but dispatch discards create (cli.rs:1385-1393, `create: _` — doyle-verified comment says 'only matters as ABSENCE of --resume'); live preflight maps broker-live→Reattach or ALREADY_LIVE exit 0; even past preflight the broker dedups EVERY labeled SpawnReq (broker.rs:3235-3302) returning ordinary Spawned(existing) — SpawnReq/Spawned carry NO disposition (msg.rs:260-333), so CLI prints success for a spawn that never happened. Existing tests codify no-dup safety, NOT freshness truth (run_no_dup_session_e2e, wake_single_flight). FIX (hertz shape, doyle-accepted): broker = atomic authority, split policies Fresh/RejectExisting vs ResumeOrReuse; wire = NEW KIND_SPAWN_FRESH with typed conflict (distinct kind fails LOUD on N-1 broker vs silently-ignored serde-defaulted field — matches wire discipline), sharing single-flight/PTY spawn body; Fresh at AlreadyLive/lost-race returns typed conflict NEVER Spawned(existing); conflict contract exit 1 + stable `ENDPOINT_CREATE_CONFLICT:<id>:…no session was created`, no attach, no state mutation, never kills the live session; preflight stays UX-only (can't close TOCTOU). DOYLE PRODUCT RULING: omitted --resume keeps the documented create-default = fresh-and-conflict same as explicit --create; ensure/attach = a NEW documented mode if ever wanted, never silent overload. Scope: create = [session.self] + fresh provisional session material + new broker PTY; reuses endpoint identity/history; harness-conversation freshness stays adapter-owned. Tests: intent-aware decision matrix; --create-over-live E2E (exit 1, exact token, no attach, same broker PID); concurrent-fresh race (one Created one Conflict, never two children, never Reused-as-success); mixed fresh/resume race; offline/raw-Active+stale-ledger create; N-1 IPC loud-fail never-Created. KEEP A/B SEPARATE: A removes stale auto-resume contenders, B makes create truthful vs legitimate live sessions.

**NEW SEED 2026-07-17 (doyle PR #18 gate — test-env hygiene: live-agent shell env poisons inject tests; RCA PINNED same day).** inject_control_wedge `wan_arrival_to_idle_spt_hosted` red in EVERY dev-shell run (todlando baseline + doyle isolated worktree) but green in CI + green with `env -u`: broker.rs:2318 `echo_capable = SPT_INJECT_VERIFY_ECHO is_some()` — live-agent sessions carry the adapter-exported var, test brokers inherit, Layer-2 echo-verify force-enables, dummy PTY never echoes → respool-once (looked exactly like the F029 commit-miss shape; wasted a gate arbitration). runtime.rs:50/INJECT_ECHO_ENV_VARS already documents+scrubs this for runtime spawns; TEST rigs never scrub (:3210 sets it deliberately for the opt-in leg). FIX: env::remove_var(INJECT_ECHO_ENV_VARS) in inject-test init (except opt-in leg) — ✅ LANDED 0c70253 (todlando rider, retro-gated). FOLLOW-ON SEED (doyle 2026-07-17, deployah PR #19 flake triage): scrub is WEDGE-RIG-ONLY — globalize at next test-harness wave (shared rig init for ALL daemon-spawning tests, or ci.yml env: block); until then any daemon-spawning test run from a live-agent shell inherits echo-verify. ⚠ SUPERSEDED same day: the PR #19 kitsubito resume red was NOT starvation flake — reclassified SUSPECT-KIN of the REDISPATCH-STALL replay-order race (fix 3 outside-mutex replay enqueue lost replay-then-live ordering; xfer push_survives red = the bug, todlando RCA). Resolution rides fix/redispatch-stall-w1-replay-order gate (resume repeat-run leg); if resume STILL reds post-fix → reopen as own item. Ledger detail in [[redispatch-stall-progress]]. LESSON kept: flake-disposition inside the wave's changed seam needs mechanism or repeat-proof, never 'green isolated' alone. LESSON (gate discipline): dev-shell-red + CI-green + clean-HEAD-red = suspect SESSION ENV before box-state — `env -u` the SPT_*/OWL_* set is a 30s discriminator.

**NEW SEED 2026-07-19 (doyle RC-RENDER-TRUTH v0.38.1 PR #32 gate — registry_lifecycle Linux-flake under CI load; registry-family int-hardening).** `spt-daemon::registry_lifecycle::oneway_rounds_plateau_rows_seats_and_a_refresh_replays_nothing` failed ONCE on kitsubito (Linux) in PR #32 CI: expected `(1,0)` got `(0,0)` — a historical row didn't land before the refresh = SETUP RACE, not a logic error. FLAKE not a regression: Windows passed the identical test+code same run; W4 touched registry.rs/registryhost.rs COMMENT-ONLY (CONTEXT:386 sweep, zero registry code) and never touched registry_lifecycle.rs. Heavy timing-sensitive replay test; the (0,0)/(1,0) shape matches the known registry-family timing recurrence (REGISTRY-LIFECYCLE shipped v0.37, but this int-rig has a residual load-sensitive setup race). ⭐ PROVEN PRE-EXISTING (doyle): main @7b524d0 (before ANY W4 code) reds the IDENTICAL test at the IDENTICAL assertion registry_lifecycle.rs:371 (fresh-dispatcher-re-applies-ZERO-historical-feeds) — so it is a pre-existing Linux-under-load flake, independent of W4 and independent of the merge (#32 merged past it, branch protection allows). HARDENING TARGET: make the oneway-rounds rig deterministically wait for the historical row to land before the refresh assert (bounded poll, not a fixed sleep), so a loaded Linux CI box can't lose the setup race. Fold into a registry int-rig hardening pass. Evidence: PR #32 CI 2026-07-19 (doyle diagnosis).

**✅ BUILT + SHIPPED v0.39.0 (TEARDOWN-AUTHORITY W3 @e85faff: width-aware ScreenGrid + one-CPR-per-DSR; REQ-SCREENGRID-WIDTH + REQ-DSR-SINGLE-CPR registered + evidenced; changelog "Wide characters no longer misalign" = this work). ⚠ STALE-ENTRY LESSON 2026-07-22: this entry was never annotated at dispatch, and doyle quoted it to hertz as "build-ready in the backlog" weeks after it shipped — operator caught it against the changelog. Post-ship history: 0.39.0 field red on similar symptoms re-rooted to resize-transition atomicity (NOT width — "W3 width model not falsified") → fixed v0.39.3 geometry-epoch + v0.39.4 presentation barrier. The registered REQ's OPEN DISCRIMINATOR (no-resize interior debris = second root) is now REALIZED as v0.39.4 field bug 3 ([[v0394-field-bugs-hertz-rca]], OPEN, capture protocol pending OBS rider). Original seed kept below for design context.** SYMPTOM: `To`/`Wh`/`Es` 2-char scraps at physical col 1 on blank rows in Claude settings + a 2-col left-shift — the exact overflow signature of unmodeled wide-cell continuations during synthesized attach repaint. ROOT (doyle-verified: screen.rs:127 `Cell{ch,pen}` NO width field; put_char:338-342 always `col+=1`, pending_wrap advances ONE display cell regardless of glyph width): ScreenGrid models every Unicode scalar as width-1, no wide-lead/continuation, no width-0 combining marks, no half-normalization in ECH/EL/ED/ICH/DCH/resize. A width-2 glyph → 1 modeled cell → model undercounts physical cols → CUP/ECH index wrong cells; render_repaint (577-642) emits one stored char per modeled cell and SKIPS wholly-default modeled rows (598-607) → overflow wraps into next row's left margin and SURVIVES there. Appears after attach/in dense-Unicode menus because the broker's SYNTHESIZED current-screen repaint reconstructs a physical client screen from the under-width model; Claude/Ratatui differentials then can't erase the misplaced cells. NOT: rc overlay (STATUS_ROW_ENABLED=false, row-only), PTY resize (col-preserving), transport trim (byte-exact), DECSTBM (row not col; W3 tracks it), exit/teardown (final-frame only). So ORTHOGONAL to v0.38.1 (W4) — not a blocker, v0.38.1 ships on its own merits. FIX CONTRACT (hertz, = the spec): width-aware grid — grapheme cell-width under product width policy; WideLead+WideContinuation; width-0 combining attaches (no advance); normalize BOTH halves before replace/erase/ICH/DCH/resize; wrap/pending-wrap in DISPLAY cells, never split a wide glyph at right edge; repaint emits lead once/skips continuation/preserves full rectangular baseline incl blanks; invalidate+repaint on resize/width-policy change. REGRESSION CONTRACT (BINDING, carry verbatim): DO NOT compare ScreenGrid to itself (shares the defect) — apply repaint bytes to an INDEPENDENT width-aware stateful emulator, assert physical cells. 6 cases: (1) [CORRECTED per hertz 2026-07-19 — the old no-EL 3x10 trace had a LEGITIMATE original wrap so the authoritative screen also scrapped = not a clean state-equivalence oracle] raw trace `ESC[1;1H[2wide][2wide]ABCDEFTo ESC[2;1H ESC[2K ESC[3;1HSearch`: width-aware VT — ?? cols1-4, ABCDEF cols5-10, `To` wraps row2, then CUP row2+EL CLEARS it → authoritative row2 BLANK, row3=Search. ScreenGrid — ?? cells1-2, `ABCDEFTo` fills cells3-10 so it believes row2 always blank → CUP+EL no-op; synth repaint emits row1's 10 scalars as 12 physical cells, re-wraps `To` to physical row2, skips modeled-blank row2 → false stale `To` above Search. ORACLE: feed raw to independent width-aware emulator (authoritative) vs feed ScreenGrid's synth repaint to a FRESH instance of the SAME emulator, compare cells — current code MUST fail. (2) CUP overwrite (1x20 `[2wide][2wide]Today`+CUP1;5 NEW) matches width-aware authority (unchanged, still valid); (3) combining-mark zero-cell survives attached; (4) replace/erase/ICH/DCH across a wide half → no orphan lead/continuation; (5) wide glyph at final/penultimate col wrap; (6) production broker cold-attach wire test (wide child frame → synth repaint → next raw differential → independent emulator == authoritative child screen). SEPARATE REQ-DSR-SINGLE-CPR: reader.rs answers DSR `ESC[6n` with FIXED `1;1` before forwarding the query → child may get two CPRs (one false); own requirement, own test (child gets exactly one accurate CPR per DSR), does NOT mutate ScreenGrid. WIDTH POLICY — RESOLVED (hertz 2026-07-19, doyle-accepted): spt-term shares ratatui's pinned **unicode-width 0.2.0** + **non-CJK / ambiguous-width=1** policy (the authoritative child TUI is ratatui 0.29, which resolves through unicode-width 0.2.0 — matching the oracle to the child is what stops the differential-erase divergence). Pin the version in WORKSPACE deps so picker + ScreenGrid cannot silently diverge. Document ambiguous-width=1 + the exact unicode-width crate/Unicode-table version as PROTOCOL STATE — bumping it is a COMPATIBILITY change requiring attach/repaint corpus re-tests. Do NOT depend on host wcwidth/locale. unicode-width is width-only, NOT a grapheme model — use grapheme clustering SEPARATELY for combining/ZWJ storage. Add golden ambiguous-width + emoji/combining cases against this pinned policy. Lane: doyle triage (ADR + REQ-SCREENGRID-WIDTH/REQ-DSR-SINGLE-CPR, needs operator GO as fresh milestone) → todlando builds → doyle gates → hertz field re-verify (owns the settings-menu screenshots + repro). Evidence: hertz RCA 2026-07-18 (scratchpad reply-hertz-screengrid.txt has doyle's full acceptance/routing).

**NEW SEED 2026-07-19 (doyle local-CI mirror during GH Actions outage — autostart replay session-mint red under full-suite load, Windows-only; int-hardening / possible product race).** `spt::endpoint_autostart_e2e saved_endpoint_replays_on_daemon_restart` failed ONCE in a full local Windows Phase-A run (1811 tests, warm gate target, dev-user session with live agents on box): panicked endpoint_autostart_e2e.rs:410 "autostart replay must mint a FRESH session … but the perch still carries run A's session". Same commit: Linux full-suite GREEN (same test passed), Windows isolated loop 10/10 GREEN. OUTSIDE #37 blast radius (rig-only shellwake diff) — did not block the merge. Two candidate shapes, undischarged: (a) rig/box condition — run executed as interactive user beside LIVE spt infra (CI runs session-0 runner account; kin of the SPT_INJECT_VERIFY_ECHO env-poison lesson above — env/infra discriminator NOT yet run); (b) real load-sensitive product race: autostart replay reads the perch's session before the fresh-mint lands under parallel-suite contention — kin of REQ-SPAWN-FRESH-TRUTHFUL (seed B above: create/reattach truth) and the registry_lifecycle setup-race hardening seed. NEXT DISCRIMINATOR (cheap): repeat full-suite Windows run from a scrubbed env/runner account; if it reds again, capture the perch info.json at failure. Fold into the same int-rig hardening pass as the registry_lifecycle seed. Evidence: local CI mirror logs 2026-07-19 (scratchpad ci-local-win.log/.err, session 650aa13f).**

**⭐ NEW SEED 2026-07-20 (todlando composed perri's round-4 finding with digesthub.rs; doyle re-grounded cite-by-cite): DIGEST-HUB-CROSS-CONSUMER-WINDOW-CONTAMINATION — P1, cross-consumer blast radius, SHIPPED since the hub existed.** Hub state is keyed by ENDPOINT ID ALONE (`map.entry(id.to_string())`, digesthub.rs:117) and ALL THREE control arms project with the REQUESTER'S OWN `over` and publish it into that shared state — snapshot :201-202, reproject :219, subscribe :227-228 — then `project_and_publish` (:115-132) diffs against the stored snapshot, bumps `version`, and fans a `from == 0` FULL REPLACE to every live subscriber. CONSEQUENCE: a bystander running `spt endpoint digest <id> --last 1` collapses every concurrent `--follow` client's view to one turn, and two consumers polling at different depths oscillate `version` with NO content change — so `version` does not mean "the digest changed", it means "the last published projection differed from the previous one, for any reason including another consumer's window depth". `--last` READS as a per-call presentation knob at the CLI and is actually a WRITE into shared daemon state. ⚠ NOT ONLY CROSS-CONSUMER — CROSS-MODE WITHIN ONE CONSUMER (todlando, from project_and_publish): a single hybrid follow+snapshot design perturbs ITSELF, which is how perri hit this before anyone hit it from two processes. So "just run one consumer" is not a workaround. ⭐⭐ **OBSERVED IN THE FIELD 2026-07-20, not inferred** (perri tested on their node; doyle re-derived from source). Passive `--follow --json`, quiet endpoint, ~50s, no action by the observer: `version=330 from=0 turns=6` → `version=331 from=0 turns=12` → `version=332 from=11 turns=1`. Frame 2 is a `from==0` FULL REPLACE in which the WINDOW DEPTH ITSELF jumped 6→12 — a content change slides a window, it cannot resize one — and **12 is claude-spt's own WINDOW constant, so the depth FINGERPRINTS the publisher**. COMPETING READING KILLED (do not re-litigate): "frame 1 was a depth-12 window holding 6 turns and 6 real turns landed" is excluded by the observed `from` — `window_input_turns` trims from the FRONT (`turns.drain(..cut)`, spt-term/src/projection.rs:445-459) keeping the last n input-bearing turns, so activity APPENDS at the tail leaving the head equal-by-value, and `common_prefix_len` would give from=6/turns=6, never from=0. A trailing-entry replace-in-place could change the head only when the window holds ONE turn (only the last turn mutates) — excluded at 6 turns. Remaining paths: cap changed between publishes (the contamination) or the spanned-session set changed (needs a session boundary; none on a quiet endpoint). REPRO (passive): attach a `--follow` client, have any other consumer pull at a non-default depth, watch the `from==0` depth jump. ATTRIBUTION — **⚠ CORRECTED 2026-07-20 (perri), the strong version was WRONG and doyle had already repeated it in the v0.39.0 change notice.** Originally: *claude-spt's own healer contaminating claude-spt's own follower*, 12 = their interrupt watcher's `--last 12` republished every 15s per hosted live endpoint per node, "narrower blast radius than a bystander but much higher duty cycle". **claude-spt ships NO `--follow` consumer.** The healer's `--last` was the only WRITER; the oscillation was seen by perri's ONE-OFF DIAGNOSTIC follow. **SURVIVES:** the phenomenon, the frames, the exclusion argument, and the *observed-not-inferred* standing — a `--last N` pull still writes shared per-endpoint state and bumps `version` for every concurrent reader. **FALSIFIED:** the blast-radius/duty-cycle claim — no shipped follower was being contaminated, so the field consequence was POTENTIAL, not realized. Split recorded deliberately rather than rewritten tidy, so nobody re-reads the strong version as evidence later. perri's `--follow` migration was BLOCKED on this and is now unblocked-not-started, so the remedy landed BEFORE the consumer that needed it. **Doubles as the standing lesson: an ATTRIBUTION is a premise like any other — this one was accepted because it made a tidy story (one actor, self-inflicted, high duty cycle), and the tidiness is exactly what stopped anyone asking whether the follower shipped.** Their remedy is the escape hatch itself (raise manifest `window_turns` 6→12, drop `--last`): depth belongs in the adapter manifest (resolved once as the effective default, so every consumer of that endpoint sees ONE depth), never in a per-call flag. **Corollary: a consumer that is not the endpoint's adapter cannot set the default at all — for them the depth rule is a HARD CONSTRAINT and no flag makes a non-default depth safe.** FIX SHAPE: serve `over`-customised pulls WITHOUT storing them; publish only projections made at the endpoint's CANONICAL depth (per-request projection ≠ published state). Own wave; product, not doc. INTERIM (shipped in W4b): the page rules programmatic consumers to the DEFAULT depth with the reason attached, `--last` = human/one-shot — a deliberate contract narrowing (doyle's call), which also satisfies the earlier "compute the pair at a constant depth" requirement by construction.**

**NEW SEED 2026-07-20 (perri W4b round-5 audit, doyle-ruled): DIGEST-INTERRUPT-HAS-NO-KIND.** No entry kind represents an INTERRUPT, so a consumer detecting one must key on a HARNESS MARKER STRING appearing in `Turn.input`. A harness wording change therefore SILENTLY stops a consumer's healing and nothing on this contract can warn them — a harness's TEXT is load-bearing for a consumer's CONTROL FLOW, the layering violation the adapter-boundary rules exist to prevent, arrived at from the other direction. Field-relevant: claude-spt's shipped interrupt watcher depends on it today. Design question for whoever opens it (an `Interrupt` entry kind, or something narrower). Not TEARDOWN-AUTHORITY scope.**

**NEW SEED 2026-07-20 (perri W4b round-4, doyle-ruled): DIGEST-ENTRY-IDENTITY-GAP.** Injected entries (Boundary/Context) never carry `seq` and never "commit", and a PREAMBLE turn (input null, projection.rs:404-411 — exactly where Boundary entries live) has no `input_seq`. So no reading mode can dedupe them soundly: positional keys are stream-scoped (window indices renumber on a slide), durable ids do not exist for these kinds, and content hashing is the fragile fallback. W4b DOCUMENTS the gap (identify injected entries by kind+ts+body within their enclosing turn; say the key is weaker than the others) rather than solving it. Product fix: give injected entries and preamble turns a durable identity on this contract.**

**NEW SEED 2026-07-20 (perri W4b round-3 blind-read, doyle-grounded; ⚠ SHARPENED round 4 — the selecting condition is RECORDS-ON-DISK, not liveness: a torn-down endpoint WITH history serves REAL LAST-KNOWN CONTENT INDEFINITELY, so a watchdog sees plausible activity forever, not silence; only a no-records endpoint serves empty): DIGEST-FOLLOW-NONEXISTENT-ENDPOINT-INDISTINGUISHABLE.** `project_endpoint_digest` (digest.rs:134) returns a `Digest` BY VALUE with no failure path, so a torn-down / never-existent endpoint yields an EMPTY digest: `--follow` subscribes successfully, delivers an empty base, and streams nothing forever. A watchdog cannot distinguish a dead endpoint from an idle one — **digest silence is evidence of nothing in either direction**. W4b documents that honestly (establish endpoint liveness out-of-band; never infer from absence of activity), so the doc side is closed; product side open: subscribing to an endpoint with no records should be distinguishable from subscribing to a live idle one (typed no-such-endpoint / has-never-had-records signal). Kin: [[DIGEST-FOLLOW-END-EXIT-LIE seed above]]. ⭐ FIELD JUSTIFICATION (perri audited their SHIPPED healer against the page, 2026-07-20): their code is SAFE BY LUCK, not design — `parse_digest_view` does `turns.last()?` so an empty digest yields `None` and `heal_decision` treats `None` as HOLD; that guard was written for TRANSIENT digest misses by an author who could not know permanent-empty was reachable. A correct outcome resting on an unknown premise is not a correct design — do not let "the field is fine" defer the product fix.**

**NEW SEED 2026-07-20 (perri W4b delta blind-read, todlando+doyle grounded): DIGEST-FOLLOW-END-EXIT-LIE.** `follow()` (digesthub.rs:328-332) returns `Ok(())` on ANY `read_frame` error, so `spt endpoint digest --follow` exits **0** with no message when the daemon stops/restarts mid-stream — an abnormal end reporting success, the F-1 diagnostic-lie class. A watchdog cannot distinguish "user ended it" from "the pipe died". Fix shape: distinguish connection-dropped from user-ended (typed end + non-zero or an explicit marker line), keeping the CLI's clean-exit path for the intentional case. Doc-side is CLOSED by W4b (page states: follow exits on drop, treat exit as resubscribe, do not read the exit code as a verdict). Product-side open. Kin: the alive-but-wedged daemon still looks idle (no heartbeats).**

**NEW SEED 2026-07-20 (perri W4b delta blind-read, doyle-ruled): DIGEST-RUN-IDENTITY (supersedes the interim in DIGEST-VERSION-RESTART-LIFETIME below).** `version` is process-lifetime, so a restart that returns to a previously-seen value makes a `!=` comparator report UNCHANGED and silently SKIP a wholly different digest — perri's framing, adopted: `>` fails LOUDLY (a stall you notice), `!=` fails SILENTLY (content you never see, = their v0.25.2 37-min black hole). W4b ships the safe INTERIM (version gating is an optimization never a correctness boundary; compare the PAIR (version, max agent-produced seq) — sound because **seq is restart-stable**: persisted ledger ordinal + on-disk line idx, digest.rs:288-292/223-226, so version is the only process-lifetime number on the contract; plus a slow unconditional pull bounding any residual collision to one interval). PRODUCT FIX: surface a real run identity as a top-level integer in BOTH the snapshot object and the `--follow` delta, so the pair becomes an identity. **Binding constraint: use the EXISTING broker-owned brain generation (brainproc.rs write_ready/parse_ready_generation) if its lifetime matches the digesthub map's — do NOT mint a second authority for the same question** (W2's two-liveness-authorities defect). Open grounding question: which process owns the hub map and does its reset track generation exactly. Additive on the wire (serde default).**

**NEW SEED 2026-07-20 (perri W4 blind-read inference #3, doyle-grounded same day): DIGEST-VERSION-RESTART-LIFETIME.** `EndpointSt.version` is in-memory hub state (digesthub.rs ~86/~124), no persistence — daemon restart resets it to 0 and a version-gated poller comparing `>` stalls until the counter re-climbs. W4b documents the contract honestly (process-lifetime; compare `!=`; a DECREASE = restart ⇒ full re-pull), so the doc side is CLOSED. Open product question: should version persist across restarts (or carry a generation/epoch field so a reset is detectable without heuristics)? Same shape as the ADR-0044 stamp-generation family. Not TEARDOWN-AUTHORITY scope (adjacent-work refusal precedent). Evidence: perri blind-read report `spt-claude-code/.claude/reports/2026-07-19-digest-json-blind-read/REPORT.md` (perri's node) + doyle grounding 2026-07-20.**

**NEW SEED 2026-07-17 (hertz v0.35.0 field-verify rider — remote update systemd stop leg exit 1, self-healed; low-pri update-tooling).** During MESH-RECOVERY field-verify upgrades: remote update's systemd stop leg returned exit 1 AFTER installing; `spt daemon start` then reported already-running; status proved broker_image 0.35.0 — no node half-updated. Worst effect = a noisy nonzero exit on a leg that succeeded by another path (diagnostic-lie-adjacent: exit 1 where outcome was fine). Verify which stop path returns 1 (unit not running? race with respawn?) + whether the leg should tolerate/classify it. Fold into next release-tooling/update wave. Evidence: hertz field report 2026-07-17 (in [[mesh-recovery-progress]]).

**NEW SEED 2026-07-16 (hertz v0.34.0 field-verify rider 1 — mixed-version rc attach fails during rollout window; N-1 rc path check, fold into rc-truth mini-wave).** During REDISPATCH-TRUTH acceptance: 0.33-viewer → 0.34-target rc attach attempts failed in the SOURCE brain with `brain IPC read deadline elapsed` (KITSUBITO pre-upgrade → deployah@HFENDULEAM post-upgrade). Cleared by upgrading the viewer to 0.34.0 — so worst effect = rc unavailable across a version-skew window, self-heals on update. But wire verbs were designed N-1-safe (net-stream-retire/opener best-effort on older broker); an rc attach DEADLINE (not clean refusal) under skew suggests a leg awaiting a reply the older/newer peer never sends — deadline-instead-of-refusal is the diagnostic lie shape. Verify: which side timed out, whether a version-gate refusal with truthful copy is possible. Evidence: hertz field report 2026-07-16 (in [[redispatch-truth-progress]]). Kin: rc-truth mini-wave (RC refusal-copy truth legs), N-1 wire discipline.

**NEW SEED 2026-07-16 (hertz v0.34.0 field-verify rider 2 — stall_evict telemetry is process-lifetime, resets on broker replacement; tiny observability leg).** stall_evict_count/stall_evict_last_ms zero on full broker replacement (17 → 0 across v0.33→v0.34 update). Fine for live diagnosis, but breaks longitudinal baselines exactly at the boundary you most want them (before/after an update that touches the eviction path — this milestone's criterion 3 needed a doyle ruling because of it). Candidate: persist eviction counters (or a lifetime-total + since-boot split) in daemon status. LOW-PRI; fold wherever broker telemetry next opens. Evidence: hertz field report 2026-07-16.

**NEW SEED 2026-07-16 (operator field — v0.34.0 release notes contained v0.33.0's notes; CHANGELOG version-ladder lint candidate).** deployah's bump commit eb9fd86 consumed the `## [0.33.0]` heading line while inserting the new section (Edit-anchor-consumption class — 2nd strike, kin todlando's D2-tag loss in REDISPATCH gate round 1) → v0.33.0 body rode inside `## [0.34.0]`, runbook copies section verbatim → published notes doubled. ✅ FIXED same day (deployah PR #15, doyle verified+merged @37f0b38): heading restored, published body trimmed (zero leakage, assets intact), runbook step-2 now carries the grep-the-ladder self-check. LINT SEED (still open): xtask/CI check — CHANGELOG `^## \[` ladder must be contiguous+descending, each released version's heading present; cheap grep, catches the whole consumption class at the gate instead of in the field. Fold into next release-tooling/xtask wave.

**NEW SEED 2026-07-16 F-043 (perri field, delivery-loss class — cross-node presence LAG converts to SILENT message loss via the non-spooling NO_PERCH verdict; candidate REQ, fold into MESH-RECOVERY W1 resolver chain or mint standalone at that triage).** FIELD: from HFENDULEAM, sends #2/#3 of a 5-send sequence to gaki-n AND slammie-n on GRAVITY-NVDA-PC returned NO_PERCH while #1/#4/#5 were SENT(WAN) — and gaki-n attests its relay was up CONTINUOUSLY (single bringup, uninterrupted intra-node messaging the whole window). So a TRANSIENT presence/registry read produced the terminal no-perch-anywhere verdict mid-sequence. THE STING: NO_PERCH is the non-spooling outcome — sender is told the target does not exist (misleading diagnostic), nothing spools, target never knows = silent cross-node loss. Fix shape to settle at triage: a presence read that MAY lag must not be able to select the drop verdict alone — verify against roster/registry validity before NO_PERCH, or degrade to spool-with-notice on uncertainty (kin the QUEUED contract: uncertain ≠ nonexistent). Target node core 0.32.0 (broker logs available); perri falsification pass scheduled (post-adapter-update shortform retry); raw outputs in perri's transcript (timestamps available on ask). Kin: MESH-RECOVERY resolver-chain (cache/roster divergence — likely same root family), F-023/F-024 WAN delivery, REQ-CONV-1 falsification, exactly-once carrier-claim cluster; possibly the gaki-n S2/S3 shortform limbs (an alternative sender-side shape). Lane: doyle scoped -> fold at MESH-RECOVERY triage; perri = field partner.

**NEW SEED 2026-07-18 (todlando W1 rig finding, RC-RENDER-TRUTH PR #28 — `endpoint stop` contract vs surviving session; candidate REQ-STOP-SESSION-CONTRACT, daemon-lifecycle family).** `endpoint stop` terminal-normalizes the row (offline+suspended, REQ-REST-TERMINAL-NORMALIZE) but does NOT reap the live broker session (stop = SOFT by design, listener+markers only) → follow-up `run --resume` dup-guards ENDPOINT_ALREADY_LIVE over a "stopped" endpoint (guard is HONEST — tree genuinely alive, REQ-ENDPOINT-CYCLE-HONEST probes it — but the UX contradicts: operator stopped it, list says offline, resume refuses citing live). NOTE post-W1 wrinkle: the W1 honest-session gate now lets `spt rc` ATTACH to a stopped-but-session-alive endpoint (honest session outranks the offline row) — arguably correct (the session IS there) but makes stop's soft semantics visible. DECIDE at a daemon-lifecycle wave: stop offers/performs bounded session teardown (compose with REQ-UPDATE-FINISH-COMMUNE-FLUSH echo-before-reap), or resume REATTACHES instead of refusing, or stop's copy names the surviving session. Kin: deployah stop/run wedge (shipped fix covers dead trees; this is the LIVE-tree sibling), KH 7.45. Lane: doyle scoped → operator-ranked.**

**NEW SEED CLUSTER 2026-07-18 (hertz RCA stale-glyphs/missing-whitespace across picker + rc PTY surfaces — doyle seam-verified all 4 legs same day, ACCEPTED IN FULL; candidate RENDER-LIFECYCLE wave, hertz's ranked order rides verbatim).** VERDICT: NO shared whitespace-trimming defect — raw PTY bytes preserved end-to-end; symptoms = 3 distinct render-lifecycle failures + 1 secondary, one shared invariant violation: physical terminal mutated/terminated outside its renderer's ordered state model. **(1, P0) broker Exit OVERTAKES final Output:** exit waiter (broker.rs:3757-3792) direct-writes KIND_EXIT via all_sinks() while normal output queues through controller_writer (1675-1778) — per-conn gate serializes writes but NOT producer order; serve_attach returns on Exit immediately (attach.rs:610-617), rc returns on that record (rc.rs:1995) → final EL/SGR-reset/cursor-show/?1049l stranded. DAMNING: test broker.rs:375-407 ALREADY documents Exit-before-Output and compensates by post-exit draining — production rc doesn't (doyle-confirmed verbatim). FIX: PTY drain/writer = sole FIFO sequencer, Exit enqueued behind all prior output per sink; optional Exit{after_seq} watermark defense (P2). Regression: child emits `XXXX ESC[2K ESC[?25h ESC[?1049l` then exits → exact Output precedes Exit through production broker→attach→rc. **(2, P0) rc NEVER unconditionally restores display state:** RawGuard::drop (rc.rs:841-856, doyle-confirmed) restores mouse/Win-console-mode/raw-mode ONLY — no SGR reset, no alt-screen leave, no cursor-show, no DECSTBM reset; every exit path (detach/child-exit/displacement/stall/fatal/30s-reconnect-give-up) can leave the terminal dirty; reconnect banner clears+homes then give-up prints at centered cursor. FIX: separate display-RAII guard from input guard — on EVERY exit path incl. unwind, best-effort SGR reset + full scroll-region reset + cursor show + leave alt screen + clear/home BEFORE restoring prior output mode, then parting prose; idempotent. Regression matrix: dirty sink `?1049h ?25l SGR31` × every PumpEnd/error class → cleanup postlude precedes final prose. **(3, P0) picker invalidates ratatui diff baseline via out-of-band stderr:** purge runs INLINE under the active TUI (picker/mod.rs:165-173, doyle-confirmed) while cmd_endpoint_purge writes diagnostics to stderr (cli.rs:12707-12826) → physical alt-screen mutated without updating ratatui's previous Buffer → next draw skips cells ratatui believes blank = stderr glyph fragments (exact x-purge symptom; NOT ScreenGrid). FIX preferred: purge core returns structured outcome with NO terminal output, picker sole renderer via model.flash; alternatives suspend/restore + baseline reset. Regression needs stateful/recording backend (pure TestBackend snapshots CANNOT catch baseline desync). **(4, P1) ScreenGrid cold-repaint state gap:** grid tracks DECSTBM (screen.rs:789-793, doyle-confirmed) but render_repaint (577-623) never replays it → client/server grids scroll against different regions post-repaint = stale/moved rows (trailing-blank omission after ED2 is CORRECT, not the bug). FIX: replay every tracked render-affecting mode (min DECSTBM) before final cursor placement + stateful emulator contract. **HERDR PRIOR ART (ogulcancelik/herdr v0.7.4 @02a6e874, AGPL — IDEAS ONLY, no code copy without license review):** one baseline per surface; blanks are real cells; attach/reconnect/resize/write-failure invalidates baseline → full clear+repaint; diff all cells or EL row suffixes; commit baseline only after successful delivery; idempotent comprehensive teardown + panic hook. Do NOT import its multiplexer stack; do NOT copy its thin-client bug (ignores stdout write errors, commits anyway). RANKED: P0 legs 1-3, P1 leg 4, P2 after_seq watermark + semantic baseline. Kin: rc-truth wave (same rc.rs neighborhood — compose at triage, maybe same milestone two waves), KH 7.44/7.45 substrate. Lane: doyle triage → todlando builds → doyle gates; hertz field partner. **NEW SEED 2026-07-17 (hertz RCA perri offline/running contradiction — doyle seam-verified rc.rs:1178-1187 same day, ACCEPTED IN FULL; THIRD core leg of the rc-truth mini-wave, candidate REQ-RC-HONEST-SESSION-AUTHORITY).** VERDICT: attach-path AUTHORITY SPLIT, not duplicate harness, not zombie false-positive. Broker hosts an HONEST live perri session (resume.pid 49780 tree fully alive, SessionProbe::has_live_session_honest=true) while the persisted perch row says offline (stale info.json: dead pid 47752, status=offline, never re-bound after WAKE_RESUME). `spt rc perri` trusts the offline row and refuses PRE-IPC ("offline — nothing to attach to", rc.rs:1184); `endpoint run --resume` consults broker truth first (cli.rs:2010 has_live_session_honest, ADR-0041 single authority) → ENDPOINT_ALREADY_LIVE + clean reattach via run_attach_session_confirmed; `--create` correctly ENDPOINT_CREATE_CONFLICT — decisive A/B/C repro. KEY FALSIFICATION: the fast-fail's own doc-comment invariant "`offline` is stamped only on session DEATH, so it never co-occurs with a live session" (rc.rs:1163-1164) is FALSIFIED in the field — doyle's W4 'accepted boundary' note covered only the transient pre-bind resume window, not a PERSISTENT stale row over an honest session (documented-invariant-falsified class, kin REQ-CONV-1). FIX (hertz shape, doyle-accepted): normal `spt rc` runs the same bounded has_live_session_honest gate BEFORE the offline fast-fail — honest session exists → run_attach_session_confirmed regardless of persisted status; no honest session → existing refusal stands; zombie/dead client tree → refusal/reap, NEVER attach. Reuse SessionProbe, NO new liveness heuristic. Regression matrix rides verbatim (offline-row+honest-session=attach / offline+none=refuse / zombie=refuse). SECONDARY OPEN QUESTION ✅ CLOSED 2026-07-18 (operator field, post-UNBOUND-flip rc attach): the resumed harness never self-bound because it sat STUCK at a FAILED NATIVE RESUME inherited from the endpoint-state defect root-caused before v0.37.0 — SessionStart never fired → perch never bound → all inbound to perri undelivered for the window (senders: resend anything still relevant). Operator recovered perri. Directly validates REQ-RESUME-UNBOUND-STAMP's operator-recovery purpose: truthful UNBOUND let the operator rc in and SEE the wedged TUI instead of a false "offline — nothing to attach to". (Original hypothesis kept for context: resumed env had SPT_ENDPOINT_ID but NO SPT_HOST_PID/OWL_SESSION_ID/CLAUDE_ENV_FILE, no adapter hook-trace entry — consistent with SessionStart never firing; kin gaki-n dead-anchor family + rest-normalize A.) **FOURTH LEG 2026-07-18 (hertz follow-up, operator-spotted second root seam; doyle-accepted — candidate REQ-RESUME-UNBOUND-STAMP, state-machine fix NOT merely hidden by the rc honest-session bypass; both legs land, writer-truth + reader-truth):** v0.37.1 EXPLICITLY leaves resume pre-bind status OFFLINE — rc.rs:1117-1120 + 1167-1174 document that existing-perch resume gets NO UNBOUND stamp (W2 skeleton-write short-circuits on existing perch, called 'accepted'). SEMANTIC DEFECT: UNBOUND lifecycle meaning = broker session exists + harness not bound, REGARDLESS of fresh vs resume — the W4 acceptance was wrong at the state-machine layer. FIX (hertz shape, ratified): resume launch transitions an existing offline perch → UNBOUND before/with broker spawn; generation/session-safe ROLLBACK to offline on spawn-fail/session death; bind owns UNBOUND→ONLINE. ⚠ FIELD MUTATION NOTE: hertz manually flipped perri info.status offline→unbound under .info.lock atomic replace 2026-07-18 (verified alive=false/unbound=true, subnet Active, broker tree live) so operator can `spt rc perri` — perri's current row state is HAND-EDITED, not organic; don't read it as repro evidence post-edit. Organic pre-edit info.json (status=offline) preserved at `C:/Users/decid/.omp/state/spt-endpoint/perri-info.pre-unbound-manual.json` = the repro evidence. **✅ gaki-n INCIDENT ROOT PINNED 2026-07-17 (hertz RCA v2 + SAME-DAY CORRECTION, doyle-accepted): stale relay anchor = dead inherited `SPT_HOST_PID=20076` env — NOT elevation, NOT SID theft (SID allegation retracted; 40b… was the correct resumed hook SID). ⚠ CORRECTION (operator-grounded): gaki-n was ALREADY on claude-spt v0.24.0 at report time → 'outdated v0.22, fixed by v0.24' theory WITHDRAWN — do NOT re-anchor it. The failure ON CURRENT v0.24.0 proves the ACTIVE PRIMARY DEFECT (promoted from residual-hardening): Toolhelp self→claude.exe walk failed/returned none while dispatch PPID=1; SessionStart omitted the export but did NOT unset the inherited dead value; live.md accepted any dead numeric>1 with no liveness/ancestry check → deterministic SEEDED then fail-closed STALE_SEED. FIX (adapter/perri lane, now primary): (a) on anchor-resolution failure UNSET the inherited var — never leave a stale numeric standing; (b) live.md verifies process-alive + claude ancestry before using SPT_HOST_PID; (c) RCA why Toolhelp walk itself failed on gaki's box. NO CORE CHANGE — startup seed custody/liveness fail-closed behavior ruled correct. hertz separately diagnosing a perri lifecycle contradiction (in flight). The two core RC defects below (harness-only refusal lie + qualified-target leakage) STAND — unaffected, still the rc-truth mini-wave.** NEW SEED CLUSTER 2026-07-16 (hertz RCA "broken elevated endpoints" — doyle seam-verified the core legs same day; candidate RC-TRUTH mini-wave, mint at next rc/attach wave — NOT folded into REDISPATCH-TRUTH). ⚠ PARTIAL RETRACTION same day (operator correction): the gaki-n FIELD INCIDENT is NOT explained by this cluster — gaki-n was genuinely SPT-HOSTED (launched from an ELEVATED Windows Terminal), bare `spt rc gaki-n` returned not-running while same-machine slammie-n worked, AND slammie-n's shortform to a LIVE gaki-n still failed after perri's canonical send succeeded. hertz harness-only classification does NOT cover it; shortform failure OPEN — do NOT re-anchor the harness-only theory on gaki-n. The two seam-confirmed core defects below STAND on their own evidence (Librarian repro + code chain), they are just not the gaki-n RCA. **HERTZ CORRECTED REPORT landed same day (full text `.claude/reports/2026-07-16-gaki-n-elevated-rc/hertz-corrected-report.md`): root NOT proven, no seed to mint — next action = CAPTURE/REPRO (their plan A-E, needs an interactive UAC elevation grant = OPERATOR-assisted on a Windows box). Ranked: RC leg R1 highest (session ended, liveness residue survived — sessionless-row/orphan-listener class kin seed #5/#6), R2 = two broker universes (REAL SOURCE HAZARD spotted: broker socket name hashes spt_home() LEXICALLY, no Windows canonicalize/case-fold — alias spellings can mint distinct in-memory brokers over the same files; candidate core guard ONLY after a two-alias test proves it, hertz plan E); shortform leg S1 highest (0.23 Stop scanner missed end-of-final-reply tag — the scanner-sensitive leg; v0.24 failure-loudness already narrows S3). Key deduction: de-elevated broker spawns unelevated children regardless of caller token ⇒ caller elevation ALONE cannot explain a missing session in the same broker. REPRO PROGRESS 2026-07-16: hertz capture script at `C:\Users\decid\.omp\state\spt-endpoint\gaki-uac-repro.ps1`; ⚠ MUST run under `pwsh` NOT powershell 5.1 (spt's informational stderr `PUMP_IPC_READER: spawned` + EAP Stop = terminating NativeCommandError, dies pre-registration). Normal leg CAPTURE_OK by doyle (gaki-normal-probe live, dir Temp\spt-gaki-uac-repro\20260716-041446-normal, preserved unpurged); ELEVATED leg = OPERATOR-pending (interactive UAC; pwsh invocation line); remote probes source = kitsubito, hertz owes the probe block. Probes to purge only after hertz says capture complete.** Original (still-standing) findings: VERDICT: elevation is NOT an endpoint state/routing branch anywhere in core (no elevated datum in InfoJson/listener registry/Instance/spool/WAN/send-resolution — hertz falsified that hypothesis). Elevated agents run external/harness-hosted (daemon/broker forcibly de-elevated per KH 5.7; true elevated spt-hosting = the already-deferred consented elevated PTY-host satellite). Messaging to elevated harness-hosted endpoints WORKS (SENT(WAN) confirmed live). TWO REAL CORE DEFECTS: **(1) RC harness-only refusal LIES** — direct `spt rc <id>` never preflights the already-known `harness_only`/`controllable=Some(false)` fact (local + gossiped rows both carry it); it dials, gets empty refused attach, and maps EVERY no-output refusal to stale-row copy ("it may have ended, or the registry row is stale") — reproduced deterministically 2x live on `ONLINE - HARNESS ONLY` Librarian. Fix = refuse BEFORE attach with truthful copy ("online but harness-hosted; spt does not own its terminal"). Candidate REQ-RC-HARNESS-ONLY-REFUSAL; gate = live remote Instance{harness_only:true} → direct RC refuses pre-stream, names harness-hosted, never says stale. **(2) Qualified-RC target leakage (doyle seam-CONFIRMED, no e2e yet)** — `establish_attach` (rc.rs:1389) resolves/dials via `wansend::resolve_and_dial_owner` → `Address::parse` accepts `[subnet:]id[@node]` (wansend.rs:126), but rc.rs:1435 passes the ORIGINAL qualified string as wire `AttachRequest.endpoint_id`; target `resolve_local_session` (attach.rs:202) compares verbatim vs bare `HostedSession.endpoint` → `spt rc id@node`/`subnet:id` dials the RIGHT node then gets the same no-live-session refusal. Existing cross-node RC tests use bare ids only. Fix = carry resolver's canonical bare id separately from user-facing qualified target. Candidate REQ-RC-QUALIFIED-TARGET-CANONICAL; gate = bare + id@node + subnet:id all succeed vs remote broker-hosted target, wire always carries canonical bare id. ADAPTER LEGS (perri lane, mostly shipped v0.24.0): hyphenated shortform parser EXONERATED (verbatim copy, hyphenated_targets_parse PASS); real msg-report root = target's Win live bringup failed (empty SPT_HOST_PID behind msys pseudo-init) + OLD Stop path silently discarded delivery-failure confirms — v0.24.0 self-sends failed confirms + logs refusal (units PASS; live int deferred). ELEVATED ACCEPTANCE (record for satellite era): launch harness-hosted under elevation → canonical send lands+drains, roster HARNESS ONLY, RC refuses truthfully; do NOT claim RC support until the elevated PTY satellite exists. Lane: doyle scoped → todlando builds the 2 core REQs at an rc-truth wave → doyle gates; hertz = field partner (they hold the live repro).

**NEW SEED 2026-07-16 (doyle, operator field — deployah stop/run WEDGE: zombie hosted session trips ALREADY_LIVE while list says OFFLINE; candidate REQ-ENDPOINT-CYCLE-HONEST, daemon-lifecycle wave).** Operator did the natural cycle (`endpoint stop` → `endpoint run`): stop is SOFT by design (listener+markers only, hosted session tree survives) → run hit ENDPOINT_ALREADY_LIVE + controlled-by-node latch while `endpoint list` said OFFLINE; `endpoint shutdown deployah` said NO_EDGE (state machine already at target — CONTRADICTS the dup-guard's live claim). Recovery that worked (order): scoped taskkill /T of the deployah tree (claude-spt launch → ccs → node → claude, 10 procs) → `spt daemon refresh` (drop stale brain-held record; broker/PTYs untouched) → fresh `endpoint run --adapter claude-spt:ccs --id deployah` = ONLINE ready=true alive=true, session resumed, psyche echo-commune fired. (Reap-vs-refresh contribution not disentangled — both were needed in sequence; refresh ALONE was tried first and run still refused... actually refresh came AFTER reap; pre-reap graceful legs all failed. Repro would need a controlled zombie.) Fix candidates: (a) ALREADY_LIVE guard liveness-probes the claimed session's client tree before refusing (dead-client session → reap + respawn honestly); (b) an `endpoint restart` verb doing stop+tree-teardown+run atomically; (c) reconcile shutdown's NO_EDGE state machine with the dup-guard (two sources of "is it live" disagreeing = the contract lie shape). Kin seeds: #5 orphan-listener false-ONLINE, #6 endpoint-massacre, HOSTED-LIVE COMEBACK (lia/emphasys 2026-07-14 — same daemon-lifecycle family, mint together). Lane: doyle scoped → todlando builds at a daemon-lifecycle wave.

**RESOLVED 2026-07-16 (doyle, perri fresh-install diagnosis — reclassified DOCS GAP, fixed PR #11; operator re-grounded the triage frame).** Original seed wrongly called the fallback-notice-on-failed-post-step a core masking BUG — CONTEXT.md documents it as DELIBERATE ("a post-step failure never swallows the adapter's own notice"), and it is adapter-avoidable within design (verify-then-notify). Real defect = PUBLISHED-DOCS GAP: post-step's ADD-time run (v0.19.0 ruling), 120s foreground bound, no-background-leg, ADAPTER_UPDATE_POST_FAIL/nonzero-exit contract all unpublished; overview.md linked a manifest.md [update.post] section that didn't exist. FIXED: PR #11 docs/update-post-contract (manifest.md reference section + verify-then-notify pattern + overview/checklist corrections + CONTEXT.md add-time catch-up). Adapter-side guidance to perri stands (foreground reconciler, nonzero on fail, verified-success custom notice, exit-code check). LESSONS (binding for perri-triage): answer from the PUBLISHED surface, not source — a question answerable only from cli.rs IS the docs gap; and check candidate core findings against CONTEXT.md before calling bug (documented-deliberate ≠ defect). Facts that stand: [update.post] runs on ADD since v0.19.0 (9305d19); add has NO core background leg.

**⚠ REVISED 2026-07-16 same day — 2nd RED on rerun (LESS load): NoReply at :1121 (suspend op) 0.36s FAST-FAIL = load-lottery theory KILLED; re-adjudicated DIFF-COUPLED until falsified, gate HELD, handed todlando w/ trace read (run-2 trace: TWO stream-sub-attach on stream=1 30ms apart = in-serve tracing-retry re-dial suspect, not the 500ms claim backoff; short-lived opener-query conns; BrokenPipe on 2nd subscriber; ranked hyps: opener-query round-trip perturbs rest-serve op/no-longer-held seam > claims-mutex poison killing dispatcher thread > load+latency tipping short reply window). Solo x12 green + zero not-pinned lines still stand. Windows heavy leg 33/33+9/9 green = Linux-only manifestation. Original 1st-sighting entry below.** FLAKE SIGHTING 2026-07-16 (doyle, PR #13 CI kitsubito Phase-A — `wansend::tests::remote_rest_suspends_and_wakes_with_the_deferred_gate` NoReply at 1.82s, 1st sighting, WATCHING; diff-EXONERATED by mechanism check). Real-broker UNIT inside spt bin that spawns a PRODUCTION `run_dispatch_loop` + two brokers (wansend.rs:1078) = #14/#15 heavy shape running in the light pool. Under 16-way Phase-A burst the bounded rest-reply deadline blew (NoReply = honest bounded outcome; CONN BrokenPipe = teardown noise). Exoneration: solo ×12 PASS @0.28-0.32s same box same merge-sha (fail ran 1.82s = load); AND the PR's new opener-not-pinned→backoff path did NOT fire (zero "opener not pinned"/DISPATCH:Failed lines in the job log) — checked specifically because the diff changes the dispatcher path this test rides. `gh run rerun --failed` applied. IF IT REPEATS: move the wansend real-broker units into the FLAKE-LEDGER #14 heavy-unit group (kin rc real-broker units). SEPARATE WATCH (product, not test): the new `first_line` not-pinned→Err→3-strike-terminal path narrows behavior vs the pre-fix blocking peek for SLOW-OPENER request streams under load — mechanism did not fire here, but if a field box ever shows `DISPATCH:N:Failed("stream N: opener not pinned yet")` ×3 on one stream, that stream's pull is abandoned for that brain generation = seed a bounded-wait or higher-budget shape for request families.

**FLAKE SIGHTING 2026-07-16 (doyle, PR #9 CI — brain_resume_conn_deadlock viewer-count seam race, 1st sighting, WATCHING).** hfenduleam Phase-A full-parallel: `daemon_resume_leaves_zero_brain_subscribers` seam-check panic (brain_resume_conn_deadlock.rs:346) "subscribing resume MUST attach >=1 viewer to session 3 (got Some(0))" — while its OWN CONN_LIFECYCLE trace shows `viewer-attach session=3 vid=0` fired (conn=5): attach-event vs count-observation race under burst load, not a product wedge. Diff exonerated (PR #9 = ci.yml+toml only; 1717/1718 green, Linux leg full green). gh run rerun --failed applied. One sighting = watch, don't ledger; if it repeats, candidate = the seam waits/polls for count>=1 with deadline instead of one-shot read (test-side fix), kin Phase-A-burst class above but LIGHT-legit (no daemon tree — a timing seam, not misclassification).

**NEW SEED 2026-07-16 (doyle, perri install-docs cross-check — schema $id still points at DEAD public host).** docs-site/src/reference/schema.md advertises manifest.schema.json at `https://sabermage.github.io/spt-releases/manifest.schema.json` (lines 5, 28) — the retired public GH-Pages host (ADR-0036 killed public docs; the schema now ships as a RELEASE ASSET on bs-releases, confirmed in the v0.32.0 asset list). NOT a doc-only fix: the URL doubles as the schema `$id` (identity adapters' manifests may reference), so changing it is a wire/contract question — decide new canonical `$id` (versionless asset URL? spec-internal URN?) + whether old `$id` strings stay accepted. Fold into the next docs/release-channel or manifest-schema wave. Found while fixing the WIDER install-docs drift (asset names): every install snippet printed target-triple names that never existed on the channel — fixed in PR #8 2026-07-16; the drift class root = docs written from aspiration not from a published-asset listing; candidate xtask lint = assert doc-named assets ⊆ update-set.json/release listing. Kin [[the-forkening-plan]], perri claude-spt README repoint.

**NEW SEED 2026-07-15 (doyle W3+W4 gates — CI Phase-A burst flake class: spawned-child-yields-nothing; candidate REQ fold into a CI-reliability/test-harness wave).** RECURRING across 2 independent runs + 2 platforms, 6 sightings: kitsubito 5× "PRECONDITION: brain never came up" 30s-timeouts (W3 attempt-2: multi_subnet_bringup + run_no_dup_session; W4 attempt-1: live_adapt_translation_swap ×2 + run_no_dup_session AGAIN — run_no_dup_session = 2× repeat offender) + hfenduleam 1× translate_proof empty-stderr 1.6s fast-fail (translation binary produced NOTHING; todlando local preflight same box same sha GREEN). SHARED SHAPE: a freshly spawned child process (daemon or translation binary) produces ZERO output under the Phase-A full-parallel burst; brain.stderr.log dumps EMPTY = wedge upstream of broker bind (the W3 ordering-RCA discriminator — reusable). NOT branch-anchored (two different branches, diffs touch neither boot nor translation spawn paths). **ROOT PINNED (doyle on-box RCA 2026-07-15, W4 attempt-2 red): Phase-A MISCLASSIFICATION.** Ruled out: OOM/fork/TasksMax (journal silent, 16 cores/15GB/TasksMax 18371). Positive: run_no_dup_session SOLO on warm _work tree = PASS 10.7s — a real-daemon e2e with ~10s bringup in the "light pool, full parallel" phase; 16-way daemon storm blows the 30s readiness deadline probabilistically (rotating victims = load lottery). The 4 kitsubito offenders all spawn real daemon trees = HEAVY by nextest.toml's own documented sweep criterion, all postdate the last sweep. Aggravator: kitsubito resolves dns.iroh.link v6-first with NO default v6 route ([[broken-ipv6-poisons-iroh-discovery]] tell) = fixed boot pad every daemon. FIX = FLAKE-LEDGER extension (dispatched todlando as W4 rider 2026-07-15): add bind_honest_cross_perch_e2e + live_adapt_translation_swap_e2e + multi_subnet_bringup_e2e + run_no_dup_session_e2e to the HEAVY list in ci.yml Phase A + Phase B + nextest.toml override (three strings identical). translate_proof (hfenduleam 1×, empty-stderr fast-fail, todlando-local-green) stays Phase A — watching, extend on next sighting. RESIDUAL SEED: consider v6 default-route repair or v4-preference on kitsubito (boot pad shrinks); LESSON: every NEW e2e that spawns a daemon tree must enter the HEAVY list at birth — candidate CI lint (grep new tests/ for CARGO_BIN_EXE + daemon run vs the filter lists). Sweeps: always exe-path-scoped ([[e2e-leaked-daemons-shared-box]]). Lane: doyle owns (CI infra). Kin [[seedmap-test-collides-live-daemon]], [[the-forkening-plan]] W3/W4 gate ledger.

**INCIDENT SEED 2026-07-15 (LIVE, doyle↔todlando pair, BOTH boxes) — message BODIES vanish; stub renders bodyless. ROOT (OPERATOR-GROUNDED 2026-07-15): the RCA-03 PROJECT-CONTEXT synchronous-git fanout TIMES OUT UserPromptSubmit — the park-drain consumes the .park files but the hook is KILLED before its additionalContext injects → bodyless stub.** MECHANISM EXACT (hertz 2026-07-15): CC kills command hooks at ~30s (field 30031-31629ms both boxes, no hooks.json override); UPS hook DESTRUCTIVELY drains park FIRST (hook.rs:1048-1070) then self_id → `spt whoami --json` subprocess — **core `whoami` ALIASES full cmd_endpoint_list (cli.rs:6609-6612)** → 100+ serial git children → 30s ceiling → hook killed BEFORE emit (hook.rs:1114) → parks already deleted → body black-holed. THREE fixes, three layers: (1) adapter v0.21.0 verified resolver (perri, in flight) = removes observed trigger for SID-proven hooks, NOT structural; (2) NEW adapter hazard REQ = TRANSACTIONAL park drain — never delete/commit park rows until context emission guaranteed/ACKed, or recoverable custody across hook death — **same effect-before-irreversible-consume class as F-032 (drop-file delete) + F-034 leg b (seed burn)**, third strike of the pattern = candidate cross-cutting design rule in CONTEXT/KH; (3) core: PROJECT-INDEX removes the fanout globally AND the whoami de-alias ask is now FORMALIZED as perri's identity-only-API filing (**F-040**, claude-spt docs/SPT-CORE-FINDINGS.md @d775b38 — settled after two collisions, note names F-037/038/039 owners): core identity-only resolver, session→endpoint|null, NO list/registry/project/Git/network; endpoint-info DISQUALIFIED as carrier (also runs latest_project_ref, reporting.rs:953). Adapter harness-hosted/mismatch fallback stays deadline-vulnerable until it ships → correctness-critical, fold into PROJECT-INDEX milestone W1 or standalone micro-REQ ahead of it. STATUS 2026-07-15: ✅ INCIDENT CLOSED — adapter v0.21.0 published + activated both boxes (operator /reload-plugins both sessions); pair-traffic acceptance PASSED both directions (long bodies, proof-of-read specifics). Field TRACE evidence (todlando box): `TRACE UserPromptSubmit total=55ms ... identity[verified-env]=0ms park-drain=0ms` (totals 55/412/444ms) — 30s identity fanout GONE from hook path. PR-carrier workaround retired, spt primary. Residual CLOSED same day: perri ran the induced-kill leg (planted staged-uncommitted .park.pending + real 0.21.0 hook fire → verbatim REDELIVERY w/ loud trace, clean post-commit; @8a9f9ae) — REQ-HAZARD-PARK-DRAIN-DEADLINE int done BOTH halves (field happy-path + induced death-recovery). CORE SEEDS STAY OPEN: PROJECT-INDEX (CLI latency class persists outside hooks) + F-040 identity-only API (harness-hosted fallback still deadline-vulnerable). Seed classification per hertz ask: DELIVERY CORRECTNESS, not latency. Evidence (stands): body intact in spool (row 201, delivered=1, idle-inject), clean ENDPOINT_INJECT no echo-miss, msgpark dirs cycled w/ zero .park files, HOME==USERPROFILE. **FALSIFIED DOYLE THEORY (do NOT re-anchor): F-036-psyche-park-drain — the hook-trace CONFLICT tail was OLD noise (07-09/10 era), custody guard holds, no foreign drain; operator corrected before perri minted on it.** F-036 core legs (a)+(c) remain unbuilt but are NOT implicated here — keep their original priority, don't ride this incident. **CONSEQUENCE: PROJECT-INDEX candidate PROMOTED — not a latency item, it BREAKS MESSAGE DELIVERY (UPS timeout) on any box with real perch/branch counts; my mesh-vs-index ranking now genuinely open, operator call.** WORKAROUND: doyle↔todlando ride bs-core PR comments until adapter v0.21.0. Kin RCA-03/[[bigscreen-spt-commands-slow-background]], F-037, perri UPS-timeout lane.

**NEW HAZARD SEED 2026-07-15 (PC hard-crash ~03:15 HFENDULEAM — subnet.json MEMBERSHIP WIPE; candidate REQ-HAZARD-SUBNET-JSON-CRASH-SAFE).** After hard crash + daemon auto-restart, identity/subnet.json = {"subnets":[]} — SPT_DEV + BIGNET membership GONE on disk (todlando observed nodes 4/3 pre-crash). Two candidate legs: (a) crash-window write truncation (is subnet.json written via atomic temp+rename like brain.ready, or in-place?), (b) boot self-heal on unparseable file WRITES CLEAN-EMPTY instead of refuse-and-preserve (.corrupt sidecar + loud) — file mtime 03:21 ≈ daemon boot, suggests (b) at least participates. Either way: machine-enrollment state must survive crashes; losing it silently severs ALL cross-node legs while status reads green locally. RECOVERY RECIPE (proven 2026-07-15): member node generates code (`sudo spt subnet show-code <NAME>` — kitsubito, passwordless sudo, first output line = 6-digit TOTP rotating 30s), this box `spt subnet join <NAME> --code <c>` ELEVATED (UAC script pattern, fetch+join in ONE script to beat rotation). SPT_DEV restored; **BIGNET still unpaired — no reachable member (flynn box/mobile hold it), OPERATOR ACTION needed.** Kin: F-032/F-034-b/park-drain effect-before-durable class (if leg b), crc-swap-old-litter (crash-window file classes). Lane: doyle scopes → todlando builds → doyle gates; mint at a durable-state/crash-safety wave (or W4 rider if operator wants it in-milestone).

**W4 RIDER RULED 2026-07-15 (hertz RCA, spt-releases issue #1 — brain self-hash CPU + breadcrumb-lie; doyle code-verified + ACCEPTED, mint at W4 dispatch).** brainproc.rs: BRAIN_HEARTBEAT=500ms loop calls write_ready per tick (:221 initial + :287 loop); write_ready recomputes current_exe()+full fs::read+SHA256 EVERY tick (2 full self-hashes/sec, every node, since v0.4.0 @a52f8c6 composition drift — current_exe_hash doc-comment still says "one per brain start"). STRENGTHENED: per-tick re-hash reads the current_exe PATH → post-swap resident-old-bytes brain publishes the NEW file hash = breadcrumb LIES in the enlyzeam class it exists for; no-metadata-invalidation is load-bearing correctness (belongs in REQ title). FIX (ratified): once-per-process digest capture (OnceLock), reuse per tick; 500ms write cadence untouched; failed capture stays None no per-tick retry; fix doc-comment same commit. GATES: injected digest-counter==1 invariant across initial+N publishes; D7 A/B process-replacement E2E retained (new process publishes new hash first write = truthfulness leg). Report: .claude/reports/2026-07-10-brain-self-hash-cpu/README.md. Lane: todlando builds in W4 → doyle gates.

**MILESTONE CANDIDATE 2026-07-15 — MESH-RECOVERY (hertz RCA bundle 02, doyle code-verified + converged; NEXT-milestone pick for operator at v0.32.0 boundary, doyle-RANKED FIRST).** Pinned trap: PRESENCE_DIAL_FAILED unconditionally `PeerAddrStore::drop_seed` (pump/mod.rs ~869-880); resolver = cache-else-id-only, NEVER consults valid `RosterEntry.address`; cache refills only on a successful seed-proof connection → isolation prevents its own repair. **REQ-CONV-1's own doc-comment claims "a stale addr never strands a peer" — FALSIFIED in the field (HFENDULEAM+ENLYZEAM symmetric sequester, both sides green-status)** → fix amends a documented design invariant (registry + CONTEXT touch). Plus independent cache-invariant defect: `PeerAddrStore::put` validates neither outer key nor outer==address.id (persisted poison rows proven live). Shape ruled w/ hertz: ONE contract, 3 waves — W1 resolver chain (cache→validated-roster→id-only) + nondestructive retention + startup/roster-merge reconcile; W2 invariant enforce+repair-or-reject+migration rebuild-from-roster (NOT delete-file — cold recovery depends on failing id-only); W3 stage-split the 10s PUMP_PEER_FAIL token + truthful health (live peer count, last successful dial, all-peer-fail duration) = acceptance surface, same milestone. Rotation machinery REJECTED from W1 (retention+fallback suffices). Kin: todlando 07-14 pump stall (restart-cured, this class; 115MB log C:/spt-diag/pump-stall-2026-07-14/), [[subnet-peer-pump-stall-rca]] (different leg, fixed 0.30.1), PUMP_PEER_FAIL-unstamped seed above. Canonical RCA: .claude/reports/2026-07-10-hertz-session/02-mesh-isolation-rca.md. Lane: doyle triages→todlando builds→doyle gates, hertz field-verify partner.

**MILESTONE CANDIDATE 2026-07-15 — PROJECT-INDEX (hertz RCA bundle 03, operator-direction pre-agreed per hertz; doyle-RANKED SECOND but operator may flip — this likely pins the operator's own daily pain).** Root pinned: `endpoint list`/picker spawn 100+ sequential git processes per invocation (cli.rs ~2954 per-perch `latest_project_ref` → picker/data.rs project_history fanout, O(P×B+C); measured 29-35s @13 perches × 7 p-branches on HFENDULEAM). **Almost certainly the [[bigscreen-spt-commands-slow-background]] root too — list-shaped commands.** Shape converged: persistent materialized project index — spt-store owns format+read path (daemon-offline reads = store reads), daemon owns SOLE single-flight async writer (load-persisted-at-start, ready-without-warm, background reconcile, atomic replace, last-known-good on failure); readers NEVER run git; invalidation = event-driven (session/cwd, context commit via branch-tip fingerprint + debounced reconcile — no single authoritative commit path exists today, rename/fork/purge, periodic low-freq) ; behavioral parity on project precedence (session-cwd → origin-cwd → context-recency). Gate rulings pre-made: complexity COUNTERS are the CI gate (one branch enum, ≤1 tree scan per changed branch, one derivation per distinct cwd); strict wall-clock budget test = manual acceptance ONLY (shared-runner flake class). Canonical RCA: .claude/reports/2026-07-10-hertz-session/03-cli-project-index-latency-rca.md. Lane: doyle→todlando→doyle, hertz field-verify.

**SEEDS 2026-07-15 (hertz RCA bundle 01 deltas vs shipped W6 — PTY residual stays INCIDENT-GATED, no speculative fix, hertz owns next-incident correlation w/ capture contract):** W6/F-039 already landed report items 1-3 (attribution split, conn ids, stamps, write-lifecycle records) + item-5 harness exists-but-proxied (upgrade seed above). NEW: (a) independent-progress surfaces for PTY input / PTY output fanout / broker req-reply / viewer attach (report item 4 — the freeze-shape discriminator); (b) HAZARD-class discriminators, both indefinite narrow paths: rc.rs ~1948 local stdout write_all/flush without deadline (can freeze one rc output pump), broker→pty.rs ~235 one session's PTY-input writer can block indefinitely (bounded input queue then drops). All three = mint at the next PTY/observability wave, not before.

**NEW SEED 2026-07-14 (todlando v0.31.0 field-verify 2/2, HFENDULEAM daemon restart — HOSTED-LIVE COMEBACK failures, seed-#6 endpoint-massacre kin; RCA data preserved).** Sequence: `daemon stop --force` (guard listed 6 hosted live sessions: doyle,lia,emphasys,mobile-gw,perri,todlando) → start → status. mobile-gw auto-returned (F-038 --save PASS) BUT: (1) **lia ready=true alive=false** — hosted live session did NOT come back despite the stop-guard's "they come back on next daemon start" promise; (2) **emphasys ABSENT from local-endpoints entirely** post-restart (was in the hosted-6; SPT_DEV endpoints 13→12) — straight seed-#6 update-finish-endpoint-massacre territory, now reproduced on a plain stop/start (not just update-finish). RCA fuel: pre-restart stderr preserved `C:/spt-diag/pump-stall-2026-07-14/daemon.stderr.pre-restart.log` (115MB — also holds the pump-stall + torn-line evidence). Mint candidates: REQ-DAEMON-COMEBACK-HONOR (guard promise = contract) + fold emphasys leg into seed #6. ALSO same restart: their live pump-stall CURED (if a NEW stall appears on 0.31.0 it's a fresh class — 0.30.1 fix stands). ALSO rider: no `spt daemon restart` verb exists (stop+start only) — W4 DAEMON-REFRESH-adjacent rider, decide at W4 dispatch. Lane: doyle scopes → todlando builds → doyle gates; activate at a daemon-lifecycle/endpoint-durability milestone.

**RIDER 2026-07-14 (cross-box confirm of todlando's deadline-litter finding):** doyle's bigscreen box SPT_HOME root ALSO litters ~200 `deadline-*.json` (uuid + session-named) — matches todlando's 209 on HFENDULEAM. Systemic, not box-local: deadline files never reaped. Small cleanup REQ candidate (reap-on-consume or startup sweep), fold wherever deadline seam next opens.

**NEW SEED 2026-07-14 (doyle field, bigscreen box — STALE update-notify: spt-update fired "v0.31.0 available, run spt update apply" on a box ALREADY running v0.31.0; operator-confirmed current, apply NOT run).** notif_id `c8939d2f…:148`, subnet BIGNET, arrived on doyle's perch 2026-07-14. Candidate roots: notify leg compares against a stale cached/last-seen local version instead of live binary version, OR the notification was minted pre-update and drained late (kin the spool ghost-redelivery cluster below). Same box also shows spt CLI calls at 15+s apiece (memory [[bigscreen-spt-commands-slow-background]]) — possibly kin symptom, unconfirmed. LOW-PRI (worst effect: operator runs a no-op apply), but a wrong "update available" prompt erodes update-UX trust right as THE-FORKENING W4 rebuilds that surface — candidate fold into W4 gate checks or a notify-correctness rider. Lane: doyle scoped seed → fold at W4 or a notify milestone.

**NEW SEED 2026-07-11 (doyle W6 gate review — PUMP_PEER_FAIL unstamped; candidate fold into any future attribution wave).** W6 F-039 stamped all CONN lifecycle records (wall+mono + conn id) but PUMP_PEER_FAIL — the OTHER half of the field 1:1 churn correlation — still has no stamps/ids; correlation still relies on stderr interleave order. Small additive leg when attribution neighborhood next opens. Kin REQ-CONN-POISON-ATTRIBUTION, [[msg-identity-milestone-progress]].

**NEW SEED 2026-07-11 (doyle W6 gate review — blackhole harness consumes count seams, not attribution records; candidate REQ upgrade).** conn_blackhole_lifecycle proxies inv-3/inv-5 via conn_handler_count seams because CONN_LIFECYCLE/CONN_WRITE_* records are eprintln stderr — uncapturable in-process. Registry prose says harness "consumes" the records (drift, accepted at gate). Upgrade shape: child-process rig scraping daemon stderr makes inv-3/inv-5 DIRECT + closes the residual watchdog/parked-writer leak invisibility (disclosed in-test). Kin REQ-CONN-BLACKHOLE-LIFECYCLE-HARNESS, [[msg-identity-milestone-progress]].

**NEW SEED 2026-07-10 (doyle W3 gate review, same F-032 class — `write_resume_commune` DIRECT-ROUTE project-slice loss; candidate REQ folds into any future commune-durability wave).** `signoff::write_resume_commune` (spt-live signoff.rs:119) routes the boundary self-commune via `route_slices` with NO drop file — under an empty project_id the `<project-context>` slice is silently dropped with NO preserve mechanism (F-032's fix is drop-file-centric, doesn't cover this direct route). Same data-loss class, different entry. Fix shape at activation: either route through a pending-file carrier like the W3 preserve path, or refuse-and-log-loud so the caller retries. Kin REQ-HAZARD-COMMUNE-INGEST-BLACKHOLE (W3, the sibling fix), [[msg-identity-milestone-progress]].**

**F-038 CORE SHIPPED v0.31.0 shape (a) `spt endpoint run --save`; field-verify PASS 2026-07-13 (flynn box, operator-run daemon bounce: --save + daemon restart + auto-return works). REMAINING RIDER = THE LIVE SEED — REQ-DAEMON-SERVICE-INSTALL (daemon-at-boot):** **⚠ SHARPENED 2026-07-18 (gaki-n field, gravity-nvda-pc Win11 v0.37.1): the IN-BINARY `spt install` bootstrap does canonical-dir + user-PATH + first daemon start but SILENTLY LACKS the two legs only installer/install.ps1 carries — at-logon scheduled task (REQ-INSTALL-8, 'spt-core daemon', ONLOGON, `daemon start` NOT `daemon run` per REQ-INSTALL-10, /RL LIMITED) + inbound-UDP firewall rule (REQ-INSTALL-7, 'spt-core inbound UDP') → binary-bootstrapped Windows boxes are boot-orphaned AND inbound-unreachable with no rendered cause. Rider scope now: fold both legs into the binary bootstrap (or the install-service verb) with truthful skip-notices; Windows intended shape re-confirmed = at-logon task, never Session-0 service (M8 decision 17; task=boot-only, start=detached spawn, stop=IPC per traceable-reqs.toml:1126). gaki-n given manual verbatim legs 2026-07-18, applying elevated; ✅ BOTH LEGS APPLIED+VERIFIED same day (Get-ScheduledTask: RunLevel=Limited, LogonType=Interactive, at-logon trigger, action `<exe> daemon start`; netsh verbose: rule enabled all profiles; daemon left running, task idempotent). FIELD FOOTNOTE for the rider build: the install.ps1:202 `\"`-escaped /TR form is PS-5.1-safe but BROKE under pwsh7 `--%` stop-parsing (schtasks 'Invalid argument - daemon\"'); no-spaces path works unquoted (`/TR "<exe> daemon start"`, stored Task-To-Run identical). When the rider folds these legs into the binary bootstrap, quoting moves into Rust argv (no shell) = class dissolves; if install.ps1 stays, review /TR escaping under pwsh + spaces-in-path.** flynn's verify surfaced the scope gap in the field: --save covers endpoint-at-DAEMON-start only; their box is managed_by:null (no OS service) so at OS boot NOTHING starts the daemon — interim logon scheduled task STAYS as the daemon-at-boot bridge + rollback (no longer endpoint bringup; that's --save's job now). Full task retirement needs the install-service rider below (kitsubito's hand-rolled systemd --user unit = prior art). OS-boot replay of --save itself = confirmatory pending next real reboot (bounce was daemon-only; box boot time still 7/10). flynn marked SPT-CORE-NEEDS #7 SHIPPED-in-0.31.0 with scope note. Original seed kept below for design context. **NEED (original):** Gateway-class endpoint (mobile-gw) must come back up WITH the daemon — phone treats gateway as infra; box reboot / daemon cold start leaves it down until hands-on (bit them 2026-07-08). flynn docs sweep (llms-full) CONFIRMED missing-feature not docs-gap: rest/wake manual-only; ONLY `subnet attach/detach --save` persists a startup default; no endpoint analog, no manifest autostart field, no api surface. PROPOSED SHAPES (any acceptable to filer): (a) `spt endpoint run --save` startup-default replayed at daemon start (symmetric w/ subnet --save); (b) endpoint-level autostart flag or adapter-manifest default for hostable_types Gateway; (c) daemon-start wake of endpoints active at daemon shutdown (rest_state already persists — their Defect-A work proved it survives re-bind). RIDER nice-to-have: documented OS-service registration recipe or `spt daemon install-service` verb (their box runs managed_by:null → daemon-at-boot also unprovisioned; NB kitsubito uses a hand-rolled systemd --user unit = prior art). Filed their side as SPT-CORE-NEEDS.md #7; interim = logon scheduled task (daemon start + wake-or-run mobile-gw), dissolves when core lands. doyle DESIGN NOTE at dispatch: shape (c) is the least-config/most-principled (restore what was up) but interacts with effective_rest_state + the F-035 gateway-liveness reader-parity fixes — settle ordering with that cluster; (a) is the smallest orthogonal cut. KIN: [[gateway-liveness-and-f035-progress]] (same mobile-gw infra lane), boot-race self-heal, daemon-service-detection-gotcha. Lane: doyle scopes → todlando builds → doyle gates; activate post-r4 at a gateway/infra-robustness milestone.**

**NEW SEED 2026-07-10 F-037 (PERRI's ask — arrived as `cli@HFENDULEAM` because perri's endpoint seat is broken = the F-036 from-downgrade victim effect, live-confirmed; feeds claude-spt ADR-0007 stub-based idle delivery — candidate REQ-MSG-SHORT-ID + REQ-MSG-FETCH-BY-ID, ONE wave). ⚠ OPERATOR HAS A DETAILED WRITTEN SPEC for this — GRILL IT (grill-with-docs) BEFORE building; do NOT design from this seed alone. Seed = placeholder census, spec = authority.** ASK: (1) per-message SHORT ID minted at send, exposed on send receipts + poll/delivery frames (adapters render a typed stub `<msg from="x" id="a1b2"/>` instead of typing full bodies into the input box — kills the input-race class + transcript noise; body parks adapter-side until the stub's UserPromptSubmit turn); (2) fetch-by-id verb, working name `spt endpoint msg <short-id>` — returns THAT message's body WITHOUT draining any class (pure read), so a UPS hook resolves stub→body; also lets a checkpoint `/clear <short-id>` carry its wake id across the boundary in-band (/clear empirically tolerates+records an arg). NO urgency — interim slices ship on adapter-local parking; ping cli@HFENDULEAM when the wave lands. doyle DESIGN QS to settle at dispatch: id scope+collision policy (per-endpoint vs node; short=how many chars/bits); retention window (fetchable until drained? TTL? survives daemon restart = spool-row-backed?); auth (target endpoint only? same session-pin discipline); fetch must be side-effect-free (NO delivered-mark, NO repin — kin the psyche-download read-verb-with-write-side-effect seed below); wire = ADDITIVE field on receipts/poll/EVENT frames (ADR-0020 envelope, ADR-0001 stable-format discipline). SYNERGY: id-addressed spool rows compose with the ghost-drain/ack-tombstone cluster + seed #8 REQ-SPOOL-TAKE-AUDIT + the `spt endpoint spool list|ack|purge` operator-verb ask — consider ONE spool-addressability milestone. Lane: doyle scopes → todlando builds → doyle gates. Activate post-update-wedge-r4 (mint REQs registry-first at dispatch).**

**NEW SEED 2026-07-09/10 F-036 (perri field RCA — psyche PSYCHE SEAT-THEFT via daemon identity-env leak; core-side sibling of adapter KH §2.5, adapter FIXED v0.18.8). doyle TRIAGED.** ROOT: the node daemon (`spt daemon run --detached`), when restarted from a session whose env carries `SPT_ENDPOINT_ID=doyle` (routine during core dev / `spt update apply` from inside an agent session), passes that identity var through to EVERY `[session.psyche_resume]` role spawn — role `env_remove` only stripped OWL_SESSION_ID/SPT_AGENT_ID, missed SPT_ENDPOINT_ID. Each psyche claude turn fires SessionStart (`--resume` re-fires source=resume EVERY turn) → adapter hook sees the endpoint id → bind path → rotates doyle's perch to the psyche's OWN sid with a valid prior-sid proof, every pulse — so lia's/deployah's/doyle's-own psyches all brief as `<sptc-active-perch id="doyle">` (hook-trace `CONFLICT:doyle is live under session <deployah|lia-psyche-sid>`, 37 peer msgs drained into lia's psyche transcript). VICTIM EFFECT: deliveries silently eaten by psyche turns, echo communes dark, real-session sends downgraded to `from:cli@node` (self-resolve miss). **doyle per-leg triage: (a) ACCEPTED primary fix** — daemon must SANITIZE inherited per-session identity env (SPT_ENDPOINT_ID/OWL_SESSION_ID/SPT_AGENT_ID) at startup AND before every role spawn (core-layer defense: no adapter env_remove miss can leak identity); today core only strips each role's declared env_remove list (runtime.rs:728) → one missed var infects the node. → REQ-HAZARD (daemon identity-env sanitize). **(b) ANSWERED in-code, NO core change to USE** — core ALREADY honors `recursion_guard_env` on ANY role that declares it: `runtime.rs:740` `if let Some(guard)=&role.recursion_guard_env { cmd.env(guard,"1") }`, applied generically keyed on the role FIELD not the role NAME; "summarizer children" is only the manifest.rs:314/schema.json:306 doc-STRING. So the adapter can declare recursion_guard_env on psyche_init/psyche_resume TODAY; doyle owns the docs-only fix to broaden the schema description. **RESOLVED (b) 2026-07-09: perri adopted immediately — both psyche roles declare `recursion_guard_env=SPT_PSYCHE_TURN` in v0.18.8 (core-set layer-1 + shim self-set belt), gates PASS → behavior proven live. Remaining doyle task = FOLD the schema-description broadening (manifest.rs:314 + crates/spt-runtime/manifest.schema.json:306 — drop 'summarizer children', it's role-agnostic) INTO the F-036 core PR with legs (a)+(c), one clean change post-wedge (no standalone docs churn).** **(c) ACCEPTED defense-in-depth** — bind whose `--set-session-id` == a nested psyche perch's own custody sid is definitionally wrong; core owns psyche-custody.json, guard/reject at bind → secondary REQ leg. OPERATIONAL: infection ONGOING on HFENDULEAM (doyle's seat re-stolen per pulse, deliveries lossy = the QUEUEDs) until daemon RESTARTED FROM A CLEAN ENV (no SPT_ENDPOINT_ID) with v0.18.8 installed = stop-the-bleeding, OPERATOR-driven (doyle won't unilaterally restart node daemon mid-update-wedge-lane). Full writeup spt-claude-code docs/SPT-CORE-FINDINGS.md F-036. Lane: doyle scoped → todlando builds (a)+(c) AFTER update-wedge round-4 → doyle gates; (b) = doyle docs-fix + perri adopts. Mint REQs at dispatch (registry-first). Kin: [[gateway-liveness-and-f035-progress]] (perri field lane), psyche-custody / session-pin cluster, [[perri-question-triage-protocol]] (classified (a)+(c) core, (b) use-it-now).

**NEW SEED 2026-07-09 (flynn field, update-wedge cycle) — GHOST MESSAGE = INJECT-ECHO-RETRY LOOP that never terminates (this is memory seed #9 [[event-envelope-reply-to-removal]]/INJECT-MULTILINE-INTEGRITY in the wild).** ✅ ROOT PINNED (doyle, daemon.stderr.log): a 572-byte doyle→flynn EVENT ("Ack digest defect report…") injects to flynn's translation binary, the ECHO-VERIFICATION fails — `INJECT_ECHO_MISS:flynn: typed head did not echo (attempt 1/2) — re-driving` then `INJECT_HEAD_LOSS_SPOOL:flynn: typed payload head did not echo after 2 attempts — re-spooled loud (delivered=false, recoverable); frame integrity NOT confirmed` — so it re-spools `delivered=false` and RE-INJECTS on the NEXT pump/presence cycle (each `ENDPOINT_INJECT:flynn (572 bytes → translation binary)` follows a PAIR_MEET_UP round; when flynn is ACTIVE it spools instead: `endpoint ACTIVE -> spool (deferred hint)`). flynn RECEIVES every copy fine — it is the delivery-CONFIRMATION (typed-head echo) that perpetually fails → infinite re-drive. So the fix locus = the idle-inject echo-verification / head-loss re-drive giving up-or-succeeding for a persistently-non-echoing payload (bound the re-drive count → drop-loud or mark-delivered after N, don't re-drive forever). Ties DIRECTLY to seed #9 (head-loss on idle-inject, non-deterministic terminal-readiness race, core-side broker/translate typed-inject pacing) — this is that bug failing to TERMINATE. No clean targeted purge: deleting the recipient spool row doesn't stop it (the inject-retry re-creates a fresh row each cycle — observed: deleted ids 37/38 → 39 → 41 kept appearing); real flush = daemon reload (nuclear) or the inject randomly echo-succeeding. **TWO WRONG ROOTS en route (corrected, kept as method-lesson):** (1) "spool redelivery without ack/tombstone on drain" — FALSIFIED (it re-INSERTS new rows, not re-offers a delivered row); (2) "a LEAKED SECOND DAEMON (pid 30648+brain 42980 @ Temp\claude\f035-check\debug\spt.exe) is the sender" — that leak was REAL and doyle killed it (path-guarded scoped; good hygiene + flagged as a candidate phantom "unresponsive peer" for the wedge dial-load) but it was NOT the ghost source (ghost continued as id 41 after the kill). METHOD LESSON: for a "message keeps arriving" report, the daemon.stderr.log INJECT_* lines are the fast discriminator (inject-retry vs re-send vs re-offer); the spool DB (`SPT_HOME\owlery\<recipient>\spool.db`, SQLite messages table, inspect via Python sqlite3 — no sqlite3 CLI on box) shows symptom rows not the driver. Also still cleaned: a leaked debug daemon is worth killing regardless ([[e2e-leaked-daemons-shared-box]], [[worktrees-under-project-root]]). During the v0.30.4 update-wedge cycle on HFENDULEAM, a single doyle→flynn message ("Ack digest defect report…") was delivered to flynn's perch THREE times, identical body, spread across ~15+ min, long after superseded — flynn read = spool redelivery without ack/tombstone on drain. REFINED REPRO (flynn, 2026-07-09): the row redelivers on EVERY listener attach — 6x total and counting (4x post-cold-restart burst + 2 more at each fresh session-start) — so it is NOT a one-time cold-restart replay; the spool row is never marked delivered/tombstoned on drain, so every `ready`/attach re-drains the same body. Fix target: the drain path must ack/tombstone (advance delivered cursor) for this message class; today it reads-without-acking. Origin dup likely injected during the wedge/starvation window and stuck non-ackable. CADENCE (flynn, 2026-07-09, copies 8-11): re-drains on EVERY LISTENER ATTACH = every TURN END (adapter re-attaches per turn) → a poisoned row is PER-TURN SPAM to the recipient, actively degrading their context each turn, persists across cold-restarts. NO OPERATOR REMEDIATION today: no CLI to inspect/ack/purge a spool row (notif dismiss = notifications-only; `endpoint stop` preserves spool; no how-to) → recipient is stuck until the drain-ack fix. So the fix REQ should BUNDLE an operator-facing spool inspect/ack/purge verb (e.g. `spt endpoint spool list|ack|purge <id>`), or explicitly rule it intentional. Sender-side escape hatch (invasive, last-resort): the row lives in the recipient's inbound spool store on disk — a targeted on-disk purge is possible but risky (offered flynn, declined; they're ignoring the ghost). ALSO this cycle: wire msg MIDDLE-TRUNCATION ×3 (one ate a full doyle ruling mid-delivery → mitigated by writing rulings to a repo disk doc + pointing the agent at the path; keep wire msgs short, front-load the load-bearing point). BOTH plausibly symptoms of the SAME brain/broker IPC stress that causes the wedge (all incidents clustered in the wedge turbulence) — but the tombstone-on-drain gap is a DISTINCT broker/spool REQ from the update-wedge fix. Kin: seed #8 REQ-SPOOL-TAKE-AUDIT (record which caller took each row — this RCA would've been instant with it), F-033 dup-delivery, #9 REQ-INJECT-MULTILINE-INTEGRITY (truncation, same neighborhood), [[send-body-from-file-not-inline]]. Lane: doyle scopes → todlando builds → doyle gates. Activate at a broker/spool-durability milestone (NOT round-3 scope — captured, not derailing the wedge fix). flynn black-box digest report (already-fixed, informational): spt-mobile/docs/bug-reports/spt-core-digest-gen-union.md.

**NEW SEED 2026-07-09 F-035 (perri field, contract-grounded — DISPATCHED todlando for the FOLLOWUP release, RCA-first) — core VIOLATES the published `--active-only`/`--ephemeral` delivery contract at the busy→idle PARKED-DRAIN (REQ-SEND-WINDOW-DRAIN-HONOR).** CONTRACT (cli.rs `spt send` help, PUBLISHED): `--active-only` = "Deliver only through the target's own poll... **never wakes an idle target**"; `--ephemeral` = "**Drop** the message if it cannot be delivered in its window, instead of spooling". CODE (verified): `send_windowed` (spt-msg/deliver.rs:188-200, ADR-0028 W2) spool-TAGS the delivery-window (`default|idle_only|active_only`); active_only = spool-only-NO-wake by contract (deliver.rs:191). ROOT = the busy→idle parked-drain (idle-edge surface) surfaces active_only rows (an idle-WAKE, contract says never) + doesn't DROP ephemeral on a window-miss — it ignores the row's window tag. FIX = the drain honors the window tag (active_only never idle-surfaces/wakes; ephemeral drops on window-miss). ADAPTER correct as-is (passes --active-only --ephemeral); perri PROTOTYPED then REVERTED a Stop-hook idle-before-scan reorder (would mask the core bug — right public-surface discipline). perri logged repo docs/SPT-CORE-FINDINGS.md @52f42d3. Classified (c) core-contract-violation (NOT missed-doc — perri cited the published contract). Lane: doyle scoped → todlando RCA-first (pin the idle-edge drain seam that ignores the tag) → doyle gates. Rides the FOLLOWUP release (with the gateway hotfix). perri = field-verify partner. Kin [[v0150-w1-activity-gated-delivery]] (activity-gated delivery), REQ-INST-6 deferred_held (the resting drain gate).

**NEW SEED 2026-07-09 (flynn field + doyle RCA, spt-core 0.30.x, mobile-gw DOWN) — a GATEWAY endpoint can never stay online: `api listen` writes status=online ONLY for live-capable endpoints + re-bind wipes rest_state (candidate REQ-LISTEN-RELAYHOLD-ONLINE + REQ-HAZARD-BIND-REST-STATE-CARRY).** SYMPTOM (flynn, spt-mobile-host): `spt endpoint wake mobile-gw` reports WOKE:(Suspended→Active) every call but list/suspend stay Suspended; `endpoint run` brings the host up ONLINE ~3s then it self-suspends ('suspended by operator'). doyle RCA (code-pinned via flynn's raw-info.json probe — 14 ticks host-ALIVE, `status` key ENTIRELY ABSENT throughout): **NOT wake-persistence** (wake writes rest_state=active intent fine) and **NOT a 0.30 regression** (effective_rest_state cold→Suspended is v0.26.0, commit 5ccc817 — crash is the trigger). **TWO CORE DEFECTS.** (B, the self-suspend ROOT) `cmd_listen` (spt/src/api/startup.rs:486-491) gates `info::set_status(ONLINE)` on `live_capable` = `manifest.session.psyche_init.is_some()`. A gateway (no psyche_init) is NOT live_capable → status=online is NEVER written → info.json `status` stays absent → the registry/list liveness `is_registry_entry_alive` (liveness.rs:152, status-based: only ONLINE||UNBOUND = alive) reads it stale/offline → `effective_rest_state` → Suspended → the gateway self-suspends every boot. The relay-hold lights the presence BADGE (relay/gossip) but the authoritative info.json status WRITE is psyche-gated. FIX: a relay-holding listener is ONLINE regardless of live_capable — a successful `Relay::bind`+hold IS the authoritative online signal; set status=online for any persistent listen, not just psyche_init. (Note the is_perch_alive[136] pid-fallback masks it for perch-local readers — status absent→pid-alive→true — but the registry/list path is status-based, so the two liveness fns DISAGREE for a status-absent gateway; the fix also aligns them.) (A, the intent clobber flynn spotted — rest_state:active VANISHED mid-window) `establish_perch`'s build (startup.rs:214-302) carries cwd/controllable/adapter/read_env forward from `prior` but NOT `rest_state` → a re-bind writes a fresh InfoJson that WIPES the wake intent. FIX: preserve `prior.rest_state` on re-bind (same carry-forward discipline). Kin: [[presence-dead-shows-online]] seed #5 orphan-listener (MIRROR image — there falsely-ONLINE, here falsely-offline; both = gateway status decoupled from actual relay-hold). Lane: doyle scoped → todlando builds → doyle gates. **⚠ DISPATCH HELD 2026-07-09 — operator poked a real hole; root INCOMPLETE, do NOT build yet.** Correction: `is_perch_alive` has a PID-FALLBACK (roster.rs:72 uses it; liveness.rs:136 status-absent→pid branch), so a status-absent but pid-ALIVE gateway reads alive=true → effective_rest_state → Active in the PERCH-LOCAL readers. So DEFECT B (status-absent) does NOT alone explain the observed Suspended. The `live_capable` gate is OLD (v0.8.0, commit b115929) — NOT a recent regressor; the regression is CRASH-induced (empty by_id). RECONCILED: ready_agents come online because they're live_capable BY MANIFEST (claude-spt declares [session.psyche_init] even in ready-mode) → not a non-live counterexample. **RESOLVED via flynn's 3 probes 2026-07-09 → DISPATCHED todlando (operator-prioritized, rides the FOLLOWUP release after W2's counter-53 publish; docs/GATEWAY-LIVENESS-DISPATCH.md @main 8f83b9d, RCA-first).** TRUE ROOT = a READER DIVERGENCE: mobile-gw IS advertised (flynn's earlier "empty by_id" was a walker error, retracted); at the same instant for the same pid-alive gateway the human `endpoint list` = ONLINE (roster.rs:72 pid-fallback) but `endpoint list --json` = Suspended (registry projection, cli.rs:2855) → the adapter suspend-honor reads --json → self-suspends. advertised_status DOES use the pid-fallback (registryhost.rs:825) so the daemon computes right; the --json projection drops it. FIX = reader-parity (--json honors the same pid-fallback/local-truth as the human roster for a local endpoint) + REQ-LIST-JSON-LIVENESS-PARITY; DEFECT B (psyche-gated online write) reclassified LATENT NOT the fix (pid-fallback covers absent status; ready_agents = live_capable-by-manifest, not a counterexample); DEFECT A (rest_state wipe on re-bind, establish_perch startup.rs:214-302 doesn't carry prior.rest_state) STANDS → REQ-HAZARD-BIND-REST-STATE-CARRY. [superseded: was UNPINNED awaiting 3 flynn probes (grep mobile-gw in identity/registry/*.json; human `endpoint list` non-json state + whether --json shows it; does mobile manifest declare psyche_init). Candidate readers to trace next: registry advertise loop (registryhost.rs:387 list_self_perch_ids + advertised_status) + the --json subnet projection (cli.rs:2855 resource_projection reads registry rows, empty for mobile-gw). DEFECT A (rest_state not carried on re-bind) stands regardless. flynn froze the state (masterclass raw-field probing; operator's ready_agent counterexample = the gate working).

**NEW SEED 2026-07-08 (perri field, PROVEN live) — `spt api psyche-download` MUTATES the perch pin (SESSION-PIN-WEDGE class; candidate REQ-PSYCHE-DOWNLOAD-READ-ONLY / REQ-SESSION-PIN-REFUSE-NONMATCH).** The verb is documented READ/emit, but on a dead-owner info.json (pids are ALWAYS dead ccs-shims → the dead-owner RESCUE path is the DEFAULT, not an edge) it does a SESSION_REPIN 'dead-owner rescue' to WHATEVER `--session-id <sid>` is passed, with NO validation. perri probing auth passed a BOGUS sid → it re-pinned HER live perch (perri) to `bogus-sid-000` (would black-hole her inbound; recovered by re-running with the real sid). Also: OMITTING `--session-id` returned full context with NO auth (local no-auth read). TWO defects: (a) a READ verb with a WRITE side-effect; (b) an unknown/non-matching sid is rescue-ADOPTED not REFUSED. ASK: make psyche-download read-only, OR refuse a non-matching sid (no silent rescue-repin). Blocks a clean pure-hook auto-psyche-on-golive → perri using a post-READY skill step instead (workaround correct for now, not blocking her lane). Detail file: `C:\Users\decid\AppData\Local\Temp\psyche-download-repin-hazard.md`. Kin: [[presence-dead-shows-online.md]] dead-owner rescue (auth.rs:110-139), seed #5 orphan-listener. Lane: doyle scopes → todlando builds → doyle gates. Activate at a session-pin/auth-hardening milestone. (Delivered as TWO copies — F-033 dup-delivery live-confirmed on this very filing.)

**F-031 RESOLVED = category (a) perri-didn't-read-docs-closely (doyle re-classified 2026-07-08 per operator's perri-triage discipline; NO spt-core change).** perri: `spt send` tokens (SENT/QUEUED/NO_PERCH) ride STDERR not stdout → her hook `$(spt send)` captured empty stdout → false NO_PERCH on DELIVERED peers; fixed adapter-side v0.17.3 (merge stderr). **doyle FIRST ruled 'doc gap → doc it' — WRONG (reflexive, didn't check published docs). CORRECTED:** the stream+exit-code contract is ALREADY PUBLISHED in TWO places — (1) harness-contract **api.md rule 3** ("Status rides stderr; stdout is payload; the exit code is authoritative", explicitly names SENT/QUEUED, "shelling out must capture stderr", "treat the exit code as the success contract: 0=took effect"); (2) **messaging/overview.md:60-75** ("classify success by the exit code — 0 for every delivered/spooled outcome, non-zero for every failure", explicit Success/Failure sections). CODE-CONFIRMED: all send tokens via `ok_line`=eprintln (cli.rs:5832); exit codes SENT/QUEUED→0, NO_PERCH/WAN_*/AMBIGUOUS→1. So NOT a docs gap (b), NOT a parity/feature gap (c) — spt-core provides the authoritative machine contract. GUIDANCE given perri: classify on EXIT CODE (authoritative), read stderr for the human token; her v0.17.3 works, exit-code branch is more robust. **NO doc task, NO code change.** **PROCESS LESSON (operator-enforced): classify EVERY perri finding against PUBLISHED docs + CONTEXT.md FIRST — perri builds blind from published docs, so the default hypothesis is (a) missed-doc, not (b) gap; only escalate to (b)/(c) after proving the doc is absent/insufficient. Don't reflexively 'doc it'.** See [[perri-question-triage-protocol]].

**LOW-PRI COSMETIC 2026-07-09 (perri/hertz, F-034 v0.18.2 verify — NO REQ yet, seed only):** pre-bind self-resolution quirk on a multi-perch node — during a calling session's PRE-BIND window (no perch for it yet), SELF/`whoami` resolves to an EXISTING resident node perch (hertz saw `SELF: perri … self @ HFENDULEAM (14efb80c…)`) instead of 'pending / no self yet' for the not-yet-bound caller. Cosmetic — did NOT affect bind. Root hypothesis: self-detect resolves by node/ancestry and, finding no perch for THIS session, falls to a resident perch. Repro: hertz-v0182-verify.md §Cosmetic anomaly (system temp). Kin REQ-WHOAMI-1 + REQ-SELF-DETECT-PARENT-PID. Mint a REQ if/when a whoami/self-resolution milestone touches this (activate-don't-pre-fail — not worth a REQ for a display quirk now).

**NEW SEED 2026-07-09 F-034 (perri/hertz field finding — /sptc:live normal-session bringup cascade, spt 0.29.0 hertz repro; 3 core REQs MINTED @5555648, adapter leg ALREADY FIXED by perri).** Scope: F-034-sptc-live-core-legs.md + repro hertz-sptc-live-repro.md (system temp). **(a) REQ-ADAPTER-UNRESOLVED-HINT-FORM** — the ADAPTER_UNRESOLVED refusal hint says 'pass --adapter <name>' but --adapter is a `spt api` GROUP flag not a `listen` flag → literal follow = clap 'unexpected argument' exit 2; fix = print the group-level form. **(b) REQ-LISTEN-SEED-CONSUME-AFTER-BIND** (hertz's headline) — `api listen` burns the consume-once ephemeral seed BEFORE validating home/subnet, so HOME_REFUSED (multi-subnet, needs --subnet) fires AFTER the seed's gone → the corrected retry hits NO_SEED (dead end); fix = validate+BIND then consume, a refusal that never bound leaves the seed intact. SAME effect-before-irreversible-consume class as F-032. **(c) REQ-LISTEN-SESSION-ID-FALLBACK** — the SessionStart seed is ephemeral ('consumed within seconds'), GONE for a session going live late / post-daemon-restart, nothing re-fires till next SessionStart → even correct --parent-pid hits NO_SEED; fix (cleanest) = `listen --session-id <sid>` binds from the sid, no seed dependency (adapter knows the sid; drops its manual re-seed). **DOC-GAP (perri, folded into legs b+c as the doc stage):** harness-contract/api.md says seeds 'ephemeral' + listen 'consumes the seed' but NEVER specifies (i) unconsumed-seed lifetime (leg c) or (ii) whether a pre-bind refusal consumes it (leg b) — an adapter author can't build correctly from the public surface; pin both contracts in api.md with the fix. perri's skill verified CLEAN vs current docs (per operator perri-triage ask — the gap is unspecified behavior, not her skill). hertz+perri live-verify. Lane: doyle scoped → todlando builds → doyle gates. Activate at a bringup-robustness fix milestone. **RELATED DESIGN POINT — RESOLVED NOT-A-CORE-BUG (operator ruling 2026-07-09):** the multi-subnet `HOME_REFUSED` hertz hit (needs --subnet) is BY DESIGN, not a defect — CONTEXT.md:640: a NEW endpoint on a multi-subnet node MUST specify its home, "no silent guess" (refuse-and-qualify) BECAUSE home is IMMUTABLE (ADR-0010, no re-home) → a wrong silent guess is PERMANENT (fork+delete to fix). `assign_home` (spt-store/home.rs:71): ≥2 subnets → Ambiguous → refuse; interactive `decide_run_home` (cli.rs:2093) DOES propose a default (MRU-first, Y/n) — only NON-interactive (hertz's Monitor bash, no TTY) refuses. Operator considered a core auto-default (first-joined = `subnets[0]`, the Vec is join-ordered) but **DROPPED it** — instead perri adds an ADAPTER-side step: first-time endpoint bringup QUERIES the user for a subnet choice when >1. So NO core change / NO CONTEXT.md amendment — the design stands, the adapter provides the interactive qualification the non-interactive path can't. (Distinct from F-034 leg b, which stays valid: even with the adapter prompt, a pre-bind refusal must not BURN the seed.)

**NEW SEED 2026-07-08 F-032 (perri field finding — commune-ingest BLACK-HOLE, data-loss; REQ MINTED REQ-HAZARD-COMMUNE-INGEST-BLACKHOLE @6767a4d, required_stages=[]).** LEGACY-SPT-PARITY-GAP. SYMPTOM: perri live-agent /clear — a two-sliced echo-commune (<live-context> role+release recipe + <project-context> v0.17.4 status + Items 3-5 map) INGESTED (source file deleted) yet NEVER surfaced at her next SessionStart resume-pull; adapter EXONERATED (file-write + slicing tags correct). ROOT (doyle triage, code-grounded): `ingest_drops` (spt-live/src/ingest.rs:200) unconditionally `remove_file(&drop_path)?` AFTER `route_slices`, but `route_slices` GATES the project tier on `!project_id.is_empty()` (ingest.rs:156) — an unresolved/owlery-internal cwd at ingest time → empty project_id → the `<project-context>` slice is parsed but NEVER `write_context`/`commit_project`'d, yet the drop is still deleted → project content permanently lost. The live-tier commit (ingest.rs:138-143) DOES precede the delete (durable), so it's specifically the GATED-OUT slice that black-holes. Legacy spt held commit-first-then-delete parity; the modern two-slice ingest broke it. FIX distinguishes precedence-SUPPRESSED (incoming older than durable → already superseded → safe to delete) from NOT-committed-because-un-committable-now (empty project_id / write error → must NOT delete; leave for a later resolvable ingest OR durably preserve the slice). REPRO FIXTURE: `(system temp)/F-032-commune-2026-07-08T222721Z.md` (5595B, sha256 9bc27e18cf385958; perri wrote verbatim from session log 0841835d.jsonl) = the int-test repro. KIN #13 below (same ingest.rs tiering surface — #13 = echo project-primary tiering DEFERRED/untagged→live; F-032 = tagged project slice DROPPED-yet-deleted = the more severe data-loss), [[commune-ingest-pulse-latency-gap]], REQ-HAZARD-DROP-FILE-SINGLE-WRITER (the single-writer delete rule this must make commit-safe), REQ-STORE-CONTEXT-BRANCH-FILL (the empty-project_id gate), REQ-RESUME-CONTEXT-PULL (the SessionStart surface that went dark). Lane: doyle scopes (done) → todlando builds → doyle gates. Activate at the commune/context-memory fix milestone (perri to flag priority).

**NEW SEED 2026-07-08 #14 (operator /diagnose — static musl binary for old-glibc Linux; candidate REQ-PLATFORM-MUSL).** NEED: deploy spt-core to Linux boxes with GLIBC < 2.39 (kitsubito-built `x86_64-unknown-linux-gnu` requires 2.39 → symbol-version fail on older boxes). **Q1 BUILDABLE = PROVEN (doyle built one on kitsubito 2026-07-08):** `cargo build --release --target x86_64-unknown-linux-musl -p spt` → EXIT 0 (2m46s), ZERO source changes, only toolchain (`apt musl-tools cmake` + `rustup target add`, `CC_x86_64_unknown_linux_musl=musl-gcc`). Result: `ELF static-pie linked / statically linked` (ldd = not dynamic), `./spt --version` runs. aws-lc-sys + bundled-rusqlite compiled clean under musl-gcc. WHY it works: TLS=rustls NOT openssl (the usual musl killer absent); C-deps (bundled sqlite, aws-lc-sys, ring) all musl-support with musl-gcc+cmake; PTY=openpty (musl-provided); libc 0.2 musl-ok. **Q2 RELEASE/UPDATE MACHINERY = does NOT support musl (code-certain):** `current_platform()` (release.rs:196-211) has only msvc+gnu cfg arms; `target_env="musl"` → `not(any(...))` fallback → returns `"unknown"` → a musl binary can't self-identify → CANNOT self-update/verify its artifact. Also `KNOWN_TARGET_TRIPLES` (release.rs:190) + PLATFORMS/signing + applyhost.rs:741 + cli.rs:16923 all hardcode `-gnu`; release.yml builds/signs only gnu+windows → no musl artifact published. **CAVEAT (DNS) = REFUTED (doyle ran `spt update fetch` on the static bin 2026-07-08):** it resolved DNS + reached GitHub over HTTPS + downloaded the update-set AND per-platform artifacts — plain DNS works on fully-static musl (only NSS *plugins* mDNS/LDAP break, not used here). Networking fully functional. **Q2 CONFIRMED LIVE same run:** fetch ended `UPDATE_FETCH_REJECTED:NoArtifactForPlatform("unknown")` — binary fetches fine but rejects because current_platform()="unknown" + no musl artifact published. So a manual side-channel musl bin works for EVERYTHING except `spt update`. **OPTIONS:** (1) side-channel MANUAL musl artifact (CI builds+publishes extra asset, operators install/update by hand) — sidesteps Q2, ~ready NOW (built one); (2) first-class self-updating musl tier = thread `x86_64-unknown-linux-musl` through current_platform cfg arm + KNOWN_TARGET_TRIPLES + PLATFORMS/signing + release.yml matrix + update-set publish + apply (bounded milestone); (3) musl-DYNAMIC dodges the NSS/DNS gotcha, still escapes glibc floor. kitsubito now has musl toolchain + a built artifact (target/x86_64-unknown-linux-musl/release/spt). **OPERATOR CHOSE option 2 — first-class self-updating musl tier + triple centralization (GO 2026-07-08, "queue" it).** doyle TRIAGED into milestone MUSL-TIER (triage docs/NEXT-MILESTONE-MUSL-TIER-TRIAGE.md, 3 REQs MINTED INACTIVE required_stages=[] @ traceable tail, check --json exit0): **W1 REQ-PLATFORM-REGISTRY** (target-triple centralization, behaviour-NEUTRAL refactor — one SUPPORTED_PLATFORMS registry; applyhost.rs:740-743 win/linux binary if/else = the N-platform blocker; gnu+windows byte-identical, unchanged-green-suite IS the gate; DESIGN FORK doyle rules pre-dispatch: enum vs const-table), **W2 REQ-PLATFORM-MUSL** (register x86_64-unknown-linux-musl: current_platform musl cfg arm no-more-'unknown', asset spt-x86_64-linux-musl; NO dep changes — build proven), **W3 REQ-RELEASE-MUSL-ARTIFACT** (release.yml musl matrix + assemble + sign + update-set publish; gate = static musl bin on sub-2.39-glibc box self-updates E2E). **STATUS: ACTIVE — operator GO "start now, drive to release publish" 2026-07-08.** Triage PR #60 merged @738eb28. **W1 DISPATCHED to todlando** (ruling docs/MUSL-W1-DISPATCH-RULING.md @0f0bc6e on main): RULED const-table `SUPPORTED_PLATFORMS{triple,asset_name}` (NOT enum — CONTEXT.md:3 'platforms additive, not re-architecture'); current_platform() stays cfg-map + unit-∈-registry; applyhost.rs:740-743 win/linux if/else → N-platform filter; xtask asset-map + KNOWN_TARGET_TRIPLES derive; behaviour-NEUTRAL (gnu+win byte-identical), unchanged green release/update/apply/propagate suite IS the gate. CONTEXT-VALIDATED (no conflict): :3 additive platforms, :828 novel-linux relocatable-binary/handhelds, :575 + ADR-0016 per-platform update-set, NoArtifactForPlatform is DESIGNED. **W1 BUILT @a05d4ff + GATED PASS + BLESSED (doyle 2026-07-08):** const-table SUPPORTED_PLATFORMS{triple,asset_name} single source; KNOWN_TARGET_TRIPLES = const-fn projection (byte-identical, order-preserved); current_platform() UNTOUCHED (cfg+unknown-fallback); applyhost 'other' was TEST-ONLY (prod already routed through current_platform) → registry filter; xtask asset-map derives. 2 new units (projection + membership). Behaviour-NEUTRAL confirmed: clean-env both legs Win 1709/1709 + kitsu 1697/1697, clippy 0, traceable 0. GATE GOTCHA RECONFIRMED: box leaks SPT_INJECT_VERIFY_ECHO=1 → false RED, gate scripts MUST `unset` it (todlando hit it too, PASS-when-unset). **PR #61 up, CI running (watch bm745iinf → merge on green).** **W2 DISPATCHED to todlando** (REQ-PLATFORM-MUSL, branch off feat/musl-w1): add musl PlatformSpec row + current_platform() musl cfg arm + drop musl from 'unknown' fallback; GATE = build musl target then `spt update fetch` prints NoArtifactForPlatform('x86_64-unknown-linux-musl') NOT 'unknown' = self-ID proof. doyle DRIVING: merge W1 on CI-green → gate W2 → W3 (CI+sign+publish+self-update E2E) → release (deployah).

**NEW SEED 2026-07-08 #13 (operator insight + doyle code-read — project-context tier starved: echo-commune's DESIGNED project-primary tiering is DEFERRED/unbuilt (candidate REQ-ECHO-PROVENANCE-TIERING / "memformat pass")).** SYMPTOM: `spt api psyche-download <id>` yields a `<project-context>` slice ONLY for doyle — `tracked/projects/` holds exactly one file (`github-com-sabermage-spt-core/doyle/project-context.md`); every other agent (perri/todlando/deployah/flynn/lia/hall-bf) has only `tracked/agents/<id>/live-context.md`. TWO-PART ROOT (operator's framing, both confirmed): **(1) ADAPTER (claude-spt, perri's half):** the commune prompts are FULLY adapter+manifest — the live-agent commune how-to (the `sptc-active-perch` session preamble) teaches "write a delta" but never the two-slice `<live-context>`/`<project-context>` grammar; the echo-commune SUMMARIZER prompt is the manifest `[session.echo_commune]` template. spt-core spawns the summarizer + feeds history on stdin (echo.rs:4-8) but prompts NEITHER. So agents never tag project detail → untagged→live (ingest.rs:18 fallback). doyle has one only because doyle (live agent) manually emitted a `<project-context>` tag once. **(2) SPT-CORE (my half, the real gap):** the echo-commune is spt-core-DESIGNED project-context-PRIMARY (echo.rs:11-12, per docs/CONTEXT-MEMORY.md) and spt-core stamps its OWN provenance header `Source: echo-commune` (echo.rs:83 stamp_provenance) EXPLICITLY to "drive the tiering at ingest" (echo.rs:80-81) — BUT the pass that consumes it is DEFERRED and never built (echo.rs:14 "the later memformat pass (deferred) inherits the correct tiering"). ingest.rs tiers ONLY on explicit `<...>` tags (`parse_two_slice`) and IGNORES the `Source:` header entirely — so echo project-heavy synthesis falls through untagged→live. spt-core does NOT need the summarizer's prompt to fix this: it already has the provenance stamp to tier echo output project-primary on its own; the mechanism is stubbed. FIX: implement provenance-driven tiering — a `Source: echo-commune` (or any provenance-stamped) body routes project-primary via the header, no summarizer tags required; live-agent manual `<project-context>` tags still honored. Kin: [[commune-ingest-pulse-latency-gap]], echo pipeline (W1 REQ-ECHO-DROP-DIR-RESOLVE), CONTEXT.md:659-662 (per-agent-per-project tier). Adapter half pinged to perri 2026-07-08. Activate at a context-memory/psyche milestone triage.

**NEW SEED 2026-07-08 #12 (operator field, 0.28.0→0.29.0 swap window + doyle code-read) — one-step `update fetch --apply` uses the RISKIER in-place brain-handoff, not the daemonless `--finish` swap (candidate REQ-UPDATE-ONE-STEP-SAFE-SWAP).** FIELD: operator ran `spt update fetch --apply` (box on 0.28.0) → daemon INSTANTLY WEDGED: no control input to any session, could not reattach, `spt daemon stop` HUNG, had to force-kill everything via Task Manager. ROOT of THIS instance = 0.28.0 code drove the apply (pre-W2 brain-decouple + pre-W3 promote-drained + it `ensure_daemon_announced` the OLD broker up pre-swap) = the exact indefinite-wedge class W2/W3 fixed IN 0.29.0 — the fix ships in the version being installed TO, so the update FROM 0.28.0 still hit it. FORWARD GAP (0.29.0, doyle code-read cli.rs): `fetch --apply` (5370) → `cmd_update_apply(false)` = daemon-up → `apply_staged` = IN-PLACE brain handoff (now bounded by BRAIN_WRITE_DEADLINE 15s + promote-drained gate, so recoverable not indefinite) — BUT the SAFEST mechanism is `apply_staged_daemonless` + full daemon restart, reachable ONLY via the two-step `update fetch` (no --apply) then `update apply --finish`. So the ERGONOMIC one-step (`fetch --apply`) picks the riskier in-place path; the safe path requires knowing about `--finish` + two commands. FIX CANDIDATES: (a) route `fetch --apply` through the daemonless finish path by default; or (b) add `fetch --apply --finish` / make `--apply` imply finish when the daemon is up; (c) doc: prefer `apply --finish`, commune-before-swap ([[f027-endpoint-spawn-fail-design]] kin, composes REQ-UPDATE-FINISH-COMMUNE-FLUSH #11). GUIDANCE for operator NOW: future updates use `spt update fetch` then `spt update apply --finish` (daemonless swap + clean restart), NOT `fetch --apply`. Activate at next update-hardening milestone triage.

**NEW SEED 2026-07-07 #11 (operator probing --finish, doyle code-read) — MINTED `REQ-UPDATE-FINISH-COMMUNE-FLUSH` (traceable inactive @bc7cb79), impl DEFERRED post-LIFECYCLE-TRUTH (operator ruling).** Gap: `update apply --finish` swap is NOT lossless for live hosted endpoints. The graceful `daemon stop` path (daemon.rs:316-325) raises brain_stop then reaper.reap() KILLS the brain subtree as one unit — NO per-endpoint final echo-commune before the kill. ENDPOINT-SURVIVAL respawns each orphaned online spt-hosted endpoint but from its LAST commune (ongoing per-event echo cadence), NOT an as-of-swap checkpoint → mid-turn/uncommuned work lost across the bounce. Today's mitigation = operator discipline (commune-before-swap). FIX (future): stop/finish path drives each LIVE hosted endpoint's final echo-commune BEFORE reap (bounded+loud: a hung commune times out then reaps anyway, never blocks the swap) so respawn resumes swap-fresh. Composes with ENDPOINT-SURVIVAL (commune→reap→respawn) + W1 echo pipeline. Int: live endpoint w/ uncommuned state → --finish → respawn reflects pre-swap state (RED-first). Activate at the future milestone delivering swap-loss-free updates.

**NEW SEED 2026-07-07 #10 (perri field + doyle code-read) — commune drop-file WRITE/INGEST race on Windows (EACCES os-error-5, intermittent) + psyche_host_error not cleared by non-pulse psyche success (candidates REQ-HAZARD-DROP-FILE-WRITE-RACE + REQ-PSYCHE-STAMP-CLEAR-ANY-SUCCESS).** (A) perri stamp 07:43:18Z: 'commune-sync: writing the commune drop-file failed: Access is denied. (os error 5)', attempts=3, first echo-commune turn post-0.15.5 (shim 07:39:36Z). ROOT PINNED (doyle 2026-07-07 ~01:2x, exact line): fire_echo (lifecycle.rs:790) passes the RAW manifest commune_dir (captured unresolved at :397) into run_echo_commune -> echo.rs:115-117 create_dir_all+join; with commune_dir='.claude' (RELATIVE, claude-spt manifest) and the WMI-launched daemon cwd=System32, write targets C:\Windows\System32\.claude -> os error 5 DETERMINISTIC on this seam. Siblings resolve correctly (ingest :583 + psyche_drop_file :1072 both use resolve_endpoint_drop_dir(raw, endpoint_cwd)) - fire_echo alone skips the resolver; checkpoint path healthy = the 'intermittent' illusion. LATENT WORSE variant: writable daemon cwd -> echo drop written to WRONG dir, silently never ingested (context loss, no error). FIX: fire_echo routes through resolve_endpoint_drop_dir like siblings + unit (relative dir + cwd -> resolved; relative no-cwd -> skip loud). Secondary (original candidates, keep as hardening): EACCES bounded retry; ingest rename-claim; per-producer drop names; perri's cwd-pin ask on the echo claude spawn. Kin KH 5.15/5.16/6.4. (B) Latch-clear gap, three field confirmations (perri): a SUCCESSFUL psyche run via checkpoint/wake (08:22Z source=llm) does NOT clear psyche_host_error - clear only rides the pulse-loop note_turn_outcome Ok. Stale FAILED stamp over a healthy psyche = operator-misleading. Seed: clear on ANY successful psyche op. (C) Echo GATE context (explains doyle verify silence): plain communes do NOT re-fire echo (take_echo_gate anti-loop by design - echo writes a commune, re-echo would loop); doyle's stale 07:30Z stamp persists benignly until next GATED echo. (D) perri v0.15.1 rename/wake fold: field-verify PASS on 0.15.5.

**NEW SEED 2026-07-09 (operator field, doyle self-send probe) — a DEFAULT message DOUBLE-DELIVERS to a BUSY live agent via BOTH carriers (poll + relay); the idle/relay carrier must NOT fire for an active agent (candidate REQ-CARRIER-CLAIM-EXCLUSIVE / REQ-RELAY-NO-BUSY-DELIVER).** OPERATOR OBSERVATION (authoritative): sent doyle→doyle while doyle was BUSY (mid-turn); the message delivered on BOTH the busy POLL path AND the idle RELAY path — the relay/idle delivery should NOT have happened for an active agent. EVIDENCE (doyle spool `SPT_HOME\owlery\doyle\spool.db` row 156): from_id='cli@HFENDULEAM', window='default', delivered=1, **taken_leg='idle-inject'** — the RELAY (idle-inject) claimed a message sent while the endpoint was ACTIVE. The daemon HAS the correct guard (daemon.stderr.log: `ENDPOINT_INJECT:doyle: endpoint ACTIVE -> spool (deferred hint), not injected`) yet the row still ended idle-inject-delivered AND (operator-observed) poll-delivered. So TWO defects: (a) the relay idle-injected to an active endpoint (guard bypassed on the busy→idle edge, or the spooled row got idle-injected when doyle transitioned idle even though a poll was also draining it); (b) NO SHARED EXCLUSIVE CLAIM between the two carriers → the same default row is delivered by both (poll --include-deferred drain AND relay idle-inject) — a genuine double-delivery to the recipient. DISTINCT from F-035 [[gateway-liveness-and-f035-progress]] (that = `--active-only` leaking to relay, LOCKED adapter-root/spt-core-EXONERATED, active_only stays spooled + poll surfaces it) — THIS is a DEFAULT message on BOTH carriers, and it may REOPEN/GENERALIZE the carrier-coordination question F-035 waved off for the default case (F-035's lock only reasoned about active_only's poll-only carrier; it never asserted a default msg can't ride BOTH). KIN: F-033 dup-delivery (general two-copies), **seed #8 REQ-SPOOL-TAKE-AUDIT** (records WHICH caller/leg took each row — the EXACT instrument to confirm the double-claim, currently missing → build it to lock this), the ghost seed above (delivered-flag not preventing re-delivery, same broker/spool neighborhood). RCA-FIRST (report-before-fix, don't assume the mechanism): pin whether the poll drains before/after the relay's delivered=1 mark, and why the ACTIVE→spool guard didn't keep it off the relay. FIX LOCUS (candidate): a single EXCLUSIVE claim/tombstone across both carriers (first carrier to take a row atomically claims it so the other cannot re-deliver) + relay never idle-injects to an ACTIVE endpoint. Lane: doyle scopes → todlando RCA-first → doyle gates. ALSO (separate, operator-flagged same probe): a live agent's own `spt send <t>` CLI stamps from_id='cli@HFENDULEAM' NOT the agent id ('doyle') — the agent-id stamp only rides the adapter/perch shortform path; candidate REQ-SEND-STAMP-AGENT-ID (recipients see cli@node instead of the agent). Activate at a broker/spool-delivery-integrity milestone (composes with seed #8 + #9 + the ghost drain-integrity cluster).

**⭐ ACTIVATED 2026-07-09 (operator directive: "roll a seed #9 fix into the upcoming milestone") — rides the ROUND-3 wedge-hardening milestone (v0.30.5, or fast-follow v0.30.6 if it can't compose with the deadlock-fix gate). LIVE REPRO IN HAND:** the flynn "ghost" this session IS seed #9 failing to TERMINATE — daemon.stderr.log: `INJECT_ECHO_MISS:flynn: typed head did not echo (attempt 1/2)` → `INJECT_HEAD_LOSS_SPOOL:flynn: … after 2 attempts — re-spooled loud (delivered=false, recoverable)` → RE-INJECT on every pump/presence cycle (each `ENDPOINT_INJECT:flynn (572 bytes → translation binary)`), forever; the SAME bug truncated doyle's inter-agent rulings mid-body all session (long msgs lose the middle; the 572B ghost survives). So #9 has TWO harms: (i) head-loss corrupting inject payloads, and (ii) the echo-retry NEVER TERMINATING → infinite re-drive spam. FIX LOCUS (two parts): (a) BOUND the re-drive — after N failed echo-verifies, DROP-loud or mark-delivered (do NOT re-drive forever, do NOT keep re-spooling delivered=false); (b) the typed-inject PACING itself (settle-before-head / bracketed-paste / verify-echo) so the head isn't eaten (core broker/translate seam). doyle to scope → todlando RCA-first (report-before-fix, use the live repro) → doyle gates. SEQUENCE: the deadlock fix (v0.30.5, field-broken P0) ships first / in parallel; #9 dispatched after that fix is underway. Candidate REQ-INJECT-MULTILINE-INTEGRITY [impl,unit,int] — mint at dispatch. Kin: the ghost seed above (same bug, corrected root), [[event-envelope-reply-to-removal]].

**NEW SEED 2026-07-07 #9 (doyle+perri, post-0.15.3) — long multi-line EVENT inject TRUNCATES: head lost, BOTH directions (candidate REQ-INJECT-MULTILINE-INTEGRITY).** Observed 4x tonight (4th: perri->doyle ~01:1x, post-0.15.5, head-loss again) after perri's 0.15.3 receive-leg fix: perri->doyle twice + doyle->perri once, every time the message SURFACED with the leading portion missing (starts mid-word), tail intact. Candidates (perri's framing): enter-coalescing class or multi-part inject seam — a multi-line <EVENT> body written to the PTY/prompt seam loses lines written before some readiness/submit boundary. SEAM RESOLVED 2026-07-07 ~01:4x (perri code-walk + doyle field data): IDLE-INJECT PTY TYPING LEG, core-side. Evidence: (i) all 4 truncated arrivals = turn-start EVENT injects (doyle idle); every mid-turn PreToolUse-envelope arrival intact; (ii) doyle spool rows COMPLETE (row 2: 1669B full body vs ~322B received suffix) -> truncation PAST spool; (iii) adapter emit exonerated by construction (all-or-pointer cap, whole-frame copy; dangling frame drops WHOLE never suffix); (iv) NON-DETERMINISTIC: a 1854B idle-inject later arrived INTACT -> timing race (terminal-readiness/enter-coalescing settle, same class as adapter 0.13.2/3 checkpoint fix), NOT a size cap. Head keystrokes eaten before terminal ready; suffix = post-last-settle remainder. CORE FIX TARGET: broker/translate typed-inject pacing - settle-before-head / bracketed-paste / verify-echo. perri hardening SHIPPED @347f755 (REQ-HAZARD-DANGLING-FRAME-LOUD + her KH 2.9, all three dangling shapes, loud <sptc_frame_integrity> + spool pointer; rides her next release cut). Probe plan closed resolved-no-rig. NOTE: live-SENT injects leave NO spool copy -> truncated live messages unrecoverable (spooled ones recoverable from rows - used to recover perri's first filing). ADDENDUM same night: 0.15.3 cleared the transcript-locate error but psyche turns now fail one seam over — ECHO_COMMUNE_FAIL: claude exited exit code: 1 (fresh stamps 07:30Z attempts:2 = retry mechanics PROVEN live, stamp is display-only, no latch); suspect the echo-commune claude spawn lacks CLAUDE_CONFIG_DIR env, same class as seed #8's root. perri notified with evidence.

**NEW SEED 2026-07-07 #8 (doyle /diagnose, "QUEUED to online perri" RCA) — claude-spt 0.15.2 receive-leg outage: hooks TAKE polled messages and never surface them (node-wide since the 23:41 adapter apply), + echo-commune is CLAUDE_CONFIG_DIR-blind (psyche 3-strikes).** ADAPTER-side roots (perri's domain, handed off with evidence) but two CORE seeds ride it. Proof chain: (1) my 23:46 + 00:00 sends to ONLINE perri → QUEUED (correct: active-window classification, she was mid-turn) → spool rows marked delivered=1 WITHIN MINUTES with .idle UNCHANGED → taken by her session's hook poll, never rendered (operator confirms non-receipt; single claude.exe under her launch tree — NO duplicate session, her own 3-spawn finding ruled out here). (2) SELF-PROBE: `spt send doyle` from my own session → delivered=1 mid-turn, NO <sptc_messages> surfaced → MY leg dead too → node-wide; flynn ACK + perri addendum EVENTs tonight were OPERATOR-RELAYED, not delivered. Boundary: core spool take/ack machinery honest throughout. (3) Psyche 3-strikes (doyle + perri psyche_host_error latched, identical): echo-commune "stdin empty and no transcript located for session <sid>" — VERIFIED root: ccs-instance sessions write transcripts under CLAUDE_CONFIG_DIR (.ccs/instances/bigscreen/projects/...; my 5edb9f02 jsonl exists ONLY there), echo-commune self-locate checks the default ~/.claude/projects → miss; stdin ALSO empty → core does NOT stdin-feed [history] (perri's open contract question — answered by field evidence). read_env.CLAUDE_CONFIG_DIR is RIGHT THERE in info.json for the taking. CORE SEEDS: (a) spool TAKE AUDIT — record which caller (sid/pid/leg) took each row + when; this RCA burned an hour proving who took delivered=1 rows (candidate REQ-SPOOL-TAKE-AUDIT); (b) publish [session.echo_commune] I/O contract NOW (core does NOT feed stdin; self-locate must honor read_env CLAUDE_CONFIG_DIR) — perri built BLIND, this outage is the cost of the unpublished contract (fold into seed #7 docs-wave, PRIORITY UP). Ops recovery: adapter rollback available (claude-spt.exe.old = 0.15.1 sits in install dir; no --tag pin on adapter update — remove + add --tag workaround) or perri hotfix 0.15.3; psyche stamp SELF-CLEARS on first clean turn post-fix (lifecycle.rs note_turn_outcome: strikes reset after stamp, turns keep firing, Ok(()) clears) — no manual wake needed (earlier strike-clear advice WRONG, corrected 2026-07-07). Kin: [[f015b-adapter-apply-silent-noop]] (success-must-imply-effect), [[lockstep-degrade-v0102]], seed #7.

**[PRIORITY BUMP 2026-07-07 ~02:4x: SECOND confirmed occurrence — todlando double-spawned by broker 01:46:32+:35 (pids 390640/214144, both broker children WITH live claude sessions, 3s TOCTOU); duplicate re-stamped OLD sid ee9948ab over fresh 24991e23 FOUR SECONDS after rotation (sessions.log ordinals 2/3) -> perch pinned to zombie -> ALL delivery to todlando dead (LIFECYCLE-TRUTH dispatch blocked by the very bug the milestone fixes; W4 runs SECOND after W1, doyle ruling). RETRACTED from this incident (doyle 02:0x, probe-contamination confession): the 'third tree', 'wake-on-send spawns under sender', 'recursive launch chains', and 'respawn storm' observations were doyle's OWN census probes self-matching the regex (bash->pwsh cmdlines carrying the search literal) - RCA LESSON: process-census probes must exclude their own cmdline (match on ExecutablePath+argv structure, or exclude pwsh/bash names). A legit single wake spawn (337112, broker child) was killed by doyle's sweep due to this fog. Recovery: endpoint run --start rebound clean (ordinal 4, sid 34b67d21).]** **NEW SEED 2026-07-06 #7 (perri addendum, flynn incident aftershock) — spawn-side collision guard admits DUPLICATE endpoint spawns under some daemon lifecycle path (candidate REQ-SPAWN-COLLISION-GUARD-LIVE-DUP).** perri-observed, post-22:53 cold start: THREE independent spawns of flynn's endpoint (`launch --cli ccs --id flynn`) inside ~30min — a duplicate pair at 23:02, a third daemon respawn 23:31:58 WHILE the pair was still alive. PARENTAGE (perri captures): the 23:02:28+23:02:29 pair were BOTH direct children of pid 306368 (the broker) — broker-side endpoint spawn path, duplicates 1s apart = check-then-spawn TOCTOU race in the spawn-side guard inside the broker; third spawn's parent uncaptured (process vanished mid-query). PATH PINNED (recovered perri filing, spool row 2): both dup spawns carried '--resume c73433d8' -> the WAKE/RESUME respawn seam processed one wake TWICE within 1s. DAMAGE MODE (perri finding 3): duplicate-perch writers STOMP info.json - operator /clear rotated sid (06:07:40Z), 31s later the duplicate's compact hook re-stamped the OLD sid back -> post-clear rename+wake injects routed via the contended record and LOST. Guard then REFUSED perri's `endpoint run --create --start` at ~23:43 when the third genuinely was alive (correct verdict — perri RETRACTED the earlier stale-state-misfire half). Net: guard misses under LIVE duplicates on some respawn path (dormancy respawn? update/restart window?) — likely an aftershock of seed #6's daemon-restart chaos (respawns began minutes after the 22:53 bounce). NOTE vs seed #6: dummyharness spt-hosted endpoints got NO resurrection in rig, but flynn's ccs-launched endpoint got RESPAWNED repeatedly — so a respawn path EXISTS for some class; find it, that's the dup-admitting seam. Also: the stale third spawn vanished during perri's stop→wake window — wake path may reap stale PTYs (untested seam either way). SUBS (perri, same filing): (a) DOCS-GAP `[session.echo_commune]` key catalog + I/O contract unpublished (which keys core fills; does [history] output ride summarizer stdin — perri built stdin-fed with self-locate fallback; stdout ingestion contract) → docs-wave queue with seeds #2/#3; (b) missing OPTIONAL role should SKIP, not 3-strike the psyche host (candidate REQ, psyche-host residency family). perri field-verify pending: first real commune/checkpoint on adapter 0.15.2 + v0.15.1 rename/wake fold on clean /clear. Adapter 0.15.2 shipped, flynn single + healthy (sid ce778223).

**NEW SEED 2026-07-06 #6 (doyle /diagnose, v0.27→v0.28 update "broker wedge" RCA) — finishing a core update is an ENDPOINT MASSACRE: the daemon restart the apply notice itself instructs kills every hosted endpoint irrecoverably (candidate REQ-UPDATE-FINISH-ENDPOINT-SURVIVAL + observability/UX subs).** Rig-proven (isolated SPT_HOME, real 0.27 binary = bin/spt.exe.old-48, real signed v0.28 update-set): the brain-only `update apply` itself is CLEAN — three configs (bare; live spt-hosted live_agent heartbeating under broker PTY + digest follower; apply WITH keystrokes injected mid-cycle through an attached rc) all kept PTY stream + control responsive across the swap+brain-cycle (gen bump, start-reason=update, promoted, 0.28 bytes verified). The kill step = the notice's own instruction ("Restart the daemon to finish: `spt daemon stop` then `spt daemon start`"): broker death takes every hosted PTY; after start endpoints stay OFFLINE (NO resurrection/re-run), attached rc freezes at "Reconnecting to local daemon…" forever (never resumes), and — bonus hazard — the rc client AUTO-LAUNCHES a daemon via WMI on reconnect (DAEMON_LAUNCH_VIA_WMI from a client; races operator's own `daemon start` → ALREADY_RUNNING).  Fix directions: (a) daemon start RE-RUNS previously-online spt-hosted endpoints (or stop performs session drain/handoff); (b) `daemon stop` warns on live sessions (the OLD unshipped follow-wave seed — promote it); (c) rc reconnect must not silently freeze — surface session-lost loudly + exit; (d) review rc's WMI auto-daemon-launch for races; (e) OBSERVABILITY: detached daemon nulls stdio → the field window 22:47-22:53 left ZERO logs (this RCA ran blind; rig had to recreate everything) — persist broker/brain stderr to a rotating file in SPT_HOME. RESIDUAL UNPROVEN: whether an additional pre-stop freeze occurred in the field (psyche-hosted agents + WAN pump + controlled sessions not mirrored in rig); operator's answers to the 3 triage questions (freeze at apply vs at stop; stop hung?; what froze first) settle it. Kin: [[crc-swap-old-litter-brick]], seed #5 above.

**NEW SEED 2026-07-06 #5 (doyle /diagnose, mobile-gw false-ONLINE RCA) — orphaned `api listen` holds a dead gateway ONLINE and BLOCKS re-bringup (candidate REQ-HAZARD-LISTEN-ORPHAN, sequel to REQ-PRESENCE-LIVENESS-TRUTH / #11 dead-pid window).** Field proof 2026-07-06: spt-mobile-host (pid 335160) died without reaping its child `spt api --adapter mobile listen mobile-gw --parent-pid 335160` (pid 311752, alive 19:08→23:00+). Chain: (1) `cmd_listen` relay loop (startup.rs:469-476) runs "until the process is killed — the harness kills the process to end the session"; `--parent-pid` is ONLY the bind/auth anchor, there is NO parent-death watchdog → host crash orphans the listener forever. (2) Orphan holds info.json pid + live relay → perch reads alive → registry gossips Active → ONLINE badge, while delivered EVENTs stream to the dead parent's stdout pipe = black hole (SENT but nothing arrives; digest.log frozen 19:25). (3) Dead-owner rescue (auth.rs:110-139) + establish rebind fire only when recorded owner pid is DEAD — recorded pid IS the live orphan → every fresh spt-mobile-host bringup AUTH_REFUSED; nothing can bring the endpoint truly online until the orphan dies. Verified: explicit-pid kill of 311752 → badge flipped OFFLINE within one `endpoint list` and rebind unblocked. FIX candidates: (a) listener watches `--parent-pid` liveness (poll or Win job-object/Linux PDEATHSIG) and exits on parent death; (b) advertised_status/is_perch_alive gate on PARENT liveness too for [session.self]/gateway perches; (c) spt-mobile-host side: spawn listener in a KILL_ON_JOB_CLOSE job object (perri/flynn filing — their half regardless). Headless gateway binaries are exactly the class with no human to notice — hazard-worthy. → operator triage queue.

**NEW SEED 2026-07-06 #4 (doyle /diagnose, enlyzeam BIGNET-join RCA) — REQ-PAIR-8 NTP-offset cache goes stale-WRONG when the OS clock steps under a live daemon (candidate REQ-HAZARD-CEREMONY-CLOCK-STEP).** Field proof: enlyzeam w32time was STOPPED, OS clock drifted +3m30s; after `w32tm /resync` yanked the clock back 210s, the daemon's cached ceremony offset (ntp.rs OFFSET, 15-min TTL, computed against the OLD clock) kept the ceremony clock ~7 TOTP steps in the past → every `subnet join` NO_SEED_HOLDER while fresh-process probes met in <500ms. Daemon bounce healed it instantly (join reached the ceremony, failed only on the test code). FOUR code defects, D1+D3 empirically proven on enlyzeam (operator pressed "what was wrong with OUR code" — bounce alone hadn't fixed it): **D1 (proven 3/3-fail)** `query_unix_secs` binds `0.0.0.0` (v4-only) but `std UdpSocket::send_to` sends ONLY to the FIRST resolved addr — time.google.com resolves 4×AAAA before any A on enlyzeam → primary NTP server permanently unreachable via our code on v6-first dual-stack boxes; redundancy silently halved (pool.ntp.org v4 carried everything; pool's DNS rotation could make windows where BOTH fail). Fix: iterate resolved addrs / per-family sockets. **D2** total NTP failure is SILENT — `unwrap_or(0)`, eprintln only fires on nonzero success; a box running on raw skewed clock is invisible. **D3 (proven by 15:38-refresh/15:45-resync/15:52-miss/15:53-heal timeline)** cache holds an offset computed against the OLD clock across an OS clock STEP for up to 15min TTL — invalidate via (Instant, SystemTime) pair snapshot, force refresh when |wall−mono elapsed| > ~2s; also force ONE fresh query + retry on NO_SEED_HOLDER exhaustion. **D4** join --verbose is blind to the joiner's own ceremony step/offset (member logs PAIR_MEET_UP step; joiner side needed a compiled probe to see). Diagnostic technique banked: ship ignored-test probe exes over ssh, bisect config deltas (fresh endpoint vs NetHost-with-membership vs live daemon). Related consumable gap (perri, same day): `adapter update` has no --tag pin (remove + add --tag is the workaround). → operator triage queue.

**NEW SEED 2026-07-06 (flynn → doyle, post REMOTE-TRUTH merge) — cross-node digest fetch/subscribe (pull-forward of ratified design, candidate next-milestone item).** Premise doyle-VERIFIED: CONTEXT.md digest section (~:499) already ratifies the structured-delta digest stream, names Gateway a subscriber class, and rules access address-gated same as messaging; unbuilt = `cmd_digest` hard-refuses qualified addresses (`CROSS_NODE_M4`, cli.rs:1387 at merge b8d8a2a — "qualified [subnet:]id@node addressing is M4, not yet supported"). Forcing customer: **spt-mobile** ("view live digest of ANY endpoint" from phone needs a paired host to serve digests for endpoints on OTHER nodes). Until it lands, spt-mobile ships most-direct-route (digest only via a paired host co-located with target); when it lands, the spt-mobile host binary proxies transparently — zero app change. Authoritative ask text: spt-mobile repo `docs/SPT-CORE-NEEDS.md` (github.com/SaberMage/spt-mobile); only surviving ask from the 2026-07-06 grill (sender-metadata ask dissolved → ships as --json-payload; Instances multi-node bind = exercise-not-ask). No model change — build = routing the digest verbs cross-node under the existing address gate. → operator triage queue (no milestone queued behind REMOTE-TRUTH).

**SEED 2026-07-06 #2 REVISED (flynn → doyle; operator challenged flynn's framing same day) — three PUBLIC-DOCS GAPS for spt-mobile (docs-only, cheap); crate publish DEMOTED.** Original ask was crate publishing; flynn's correction: (WITHDRAWN) spt-term/DigestRecord relocation — host binary consumes `spt endpoint digest --json` over the subprocess boundary, so the needed contract is the CLI OUTPUT SCHEMA in public docs, not Rust types; (DEMOTED) spt-proto+spt-msg crates.io publish = parse-parity convenience only (host only PARSES <EVENT>; `spt send` composes; phone speaks spt-mobile's own device-link RPC) — still valid whenever operator clears the repo-privacy gate (CONTEXT.md:687 ratifies the path), zero urgency. (NEW, the live ask) three docs gaps on sabermage.github.io/spt-releases, flynn-swept 2026-07-06: (1) `digest --json` row schema — field names, row kinds, and that a delivered user-msg lands as an owl_message context row whose body = the composed <EVENT> verbatim (their msg-id dedup seam); flags + --after seq semantics already documented, output SHAPE nowhere. (2) Full send-outcome vocabulary — quickstart has SENT/QUEUED only; SENT(WAN), QUEUED(idle-only), DEFERRED, NO_PERCH undocumented; adapters need the closed set. (3) <EVENT> escaping contract — exact entity set, amp-last decode order, MAC-stamp prefix on stamped poll frames all unstated. Positive: bind --type / --user-msg identity gate / --json-payload docs held up. Authoritative ask: spt-mobile docs/SPT-CORE-NEEDS.md §3 @3685cf6. Docs are dual-audience + CI-gated (DOCS-STRATEGY); gaps 1–3 look like docs-wave candidates alongside next milestone. → operator triage queue with the cross-node digest seed above.

**SEED 2026-07-06 #3 (flynn docs-gap arc, third filing) — remaining `--json` output schemas undocumented.** `endpoint list --json` documented @47efdaf (doyle, same-day per the operator's standing docs-gap order; incl. the additive-evolution compat posture + a stale worker-verb row fix). The REST of the read/status set (daemon status, subnet status/show-code, endpoint description/role, adapter list/version, notif/grant/access/shell list, how-to) still has flag-only docs — the checklist's old "shapes are in the CLI reference" promise was false. Docs-wave candidate: one shape subsection per command (or a generated shapes page off the DTOs — xtask gen candidate, drift-gated like reference.md). → operator triage queue. **ADDENDUM-2 2026-07-06 (flynn 6th filing, first real adapter field-install, spt-mobile-host v1.0.1 @8812677): three MORE api.md gaps, all FILLED same-day in held commit a9bfe32 (branch docs-api-contract off main@47efdaf — PUSH HELD until v0.28.0 FF-merge lands, then merge + docs-publish):** (1) stdout/stderr/exit contract undocumented — status tags (BOUND:/READY:/SENT:/QUEUED:) ride stderr UNCONDITIONALLY (ok_line→eprintln, only color tty-gated; flynn's 2>$null repro discarded them himself — corrected his console-only model in reply); now api.md rule 3. (2) api poll auth requirement (session-id/token/link; unauthenticated = exit 1 silent) undocumented; now on rule 2 + poll section. (3) ONLINE badge = held relay (seed own pid + api listen; bind alone doesn't light it) undocumented for headless [session.self]/gateway binaries; now "Going ONLINE" paragraph in startup flows. flynn's v1.0.1 workarounds = contract-correct, no changes needed his side; notify him on docs-publish flip.

**ADDENDUM 2026-07-06 (flynn 5th filing, doyle-ruled FEATURE ask not docs gap):** expose registry Instance columns last-active/description/adapter in `endpoint list --json` — spt-mobile endpoint-browser wants them (DESIGN feature 1; SPT-CORE-NEEDS.md §3 item 4); doc @47efdaf deliberately documents only what the binary emits; additive-evolution posture means the fields can land later as new optional keys without breaking shipped parsers. flynn unblocked (renders what exists).

**NEW FINDING 2026-07-02 (doyle, INTERIM-G3-10a316d gate flake RCA) — BranchStore::open_or_init concurrent-init race (NON-blocking, candidate REQ-HAZARD-STORE-INIT-RACE).** `open_or_init` (spt-store branchstore.rs:47) = TOCTOU: `HEAD.exists()` check then NON-atomic multi-step init (`git init --bare` + `git config core.autocrlf false` + worktree config). Two concurrent openers of the SAME fresh store both enter the init branch → concurrent `git config` on one repo → `could not lock config file config: File exists` → hard Err. Field-plausible: any two spt processes first-touching one context store (daemon worker + CLI). Test-proof: pump.rs:442 `pump_and_dispatch_self_drive_the_subnet` red on G3 first pass (test-harness open raced live daemon A's bootstrap-pull init), 3/3 green targeted rerun. Same hazard family as KH 5.15 (unique-tmp) / 5.16 (info-lock lost-update). FIX candidates: config.lock-aware retry, or treat init-race loser as success when HEAD appears (open-after-lose), or lockfile around the init block. → todlando, ride a future wave (NOT F-023 scope).

**NEW FINDING 2026-06-28 (v0.17.0 release, doyle+deployah) — shared-box E2E timing-flake hardening (post-cut, NON-blocking).** The shared self-hosted runners (hfenduleam/kitsubito, also host LIVE agents) keep red-ing releases on LOAD/TIMING-sensitive attach + seedmap E2Es — same starvation class as [[seedmap-test-collides-live-daemon]]. v0.17.0 hit `spt::multi_subnet_bringup_e2e::fresh_unbound_is_attachable_before_bind` (RC_FAIL empty reason, pre-bind UNBOUND attach v0.14.0) RED on Linux-att2 only — same commit 04dc7e9 GREEN on Linux-att1 AND Windows-att2 = confirmed flake, NOT regression. Cost: extra full reruns per release. HARDEN: mark the known timing-sensitive E2E set for nextest retry, or isolate them from the shared-box load window (dedicated serial group / `--test-threads` pin). Track + fix after v0.17.0. (Also: a full `gh run rerun` — not `--failed` — is REQUIRED to re-fire twohost-a/b, which are `needs:test` and SKIP-not-fail when a test leg reds.)

**SHIPPED 2026-06-17 — v0.11.0 PUBLISHED (counter 24, MINOR), doyle GATE-PASS (full source read, composition int non-vacuous) + CI green both runners + hash-checked ✓. PR #24 merged @60257ff. **WALL-B FULLY CLOSED 2026-06-17** — perri E2E-confirmed GREEN on 0.11.0 (operator's exact `endpoint run --start` → populated SPT_ENDPOINT_ID → BOUND perch ~4s → `spt send` → SENT live PTY inject; ghost-roster self-healed; rc-bounce survives). perri landed the missing int ci/launcher/bind-int.sh (REQ-CC-LAUNCHER-BIND, @39e15cc) — the E2E proof the endpoint-run path never had. FLOOR-BUMP scope Q ruled: NO blanket min_spt_core bump (ready/live work on 0.9.0); the <0.11.0 endpoint-run silent-seed = adapter-side clear-error guard (perri, lean b) or doc, non-blocking. orphan pid 60824 self-cleared on the 0.11.0 daemon bounce. FOLLOW WAVE still open (NOT shipped): RC-EOF auto-reattach + daemon-stop active-session warning + owlery watch-handle release-on-teardown + roster-ghost cross-node convergence int.**

(prior) BUILT — PR #24 bundle, awaiting gate → doyle ruled ONE bundle PR. FIVE fixes (grew from 3 — doyle added F-013 + roster-ghost mid-build): REQ-SEND-SPT-HOSTED [impl,unit,int] · REQ-HAZARD-ENV-SUBST/F-013 [impl,unit,int] · REQ-HAZARD-RC-EOF wave-1 [impl,unit] · REQ-HAZARD-DEFERRED-MANIFEST [impl,unit] · REQ-HAZARD-ROSTER-GHOST [impl,unit]. traceable EXIT=0, clippy --workspace clean, full seam sweep + livehost E2Es green. NON-NEGOTIABLE composition int wall_b_endpoint_run_env_then_send_reaches_pty PROVES the full chain (prepare fills SPT_ENDPOINT_ID={id} → broker spawns flagless [session.self] w/ env → child reports EID=wall-b → endpoint-keyed <EVENT> inject reaches same PTY). Commits: f742e26 mint · ec85b21 RC-EOF · e33798e DEFERRED · 4af154d SEND · 7252367 ENV-SUBST · 6dc98df ROSTER-GHOST · d8f0cba composition int. SPLIT OUT to FOLLOW WAVE (NOT v0.11.0): RC-EOF auto-reattach + daemon-stop active-session warning + owlery watch-handle release-on-teardown; + ROSTER-GHOST cross-node convergence int. **F-013 (the real wall-b bind blocker, doyle added mid-build):** endpoint-run threaded {id} into argv but [env.<VAR>].value was NEITHER substituted NOR applied (SpawnReq had NO env field — a MISSING feature, not just unsubst) → flagless `claude` got empty $SPT_ENDPOINT_ID → seed-by-PPID → zero perch → NO_PERCH. Fix: prepare_harness_spawn fills [env] inject from same {key} catalog → new SpawnReq.env (threaded ~16 spawn literal sites) → spawn_program_in_env. **roster-ghost (doyle 2nd finding):** session-end --erase leaves Active roster row w/ no perch → advertise_local heals to Offline. SEND fix = endpoint-keyed broker frame (u64 session_id not CLI-reachable); render_event_whole for PTY inject; delivered:false→spool (doyle-confirmed never false-Sent). NEXT: CI-green → doyle gate → v0.11.0 publish.

Three (now FIVE) spt-core findings surfaced while the operator exercised the freshly-shipped surfaces (v0.9.1/v0.3.0 parity arc — see [[parity-arc-closed]]). All NON-blocking. branch v0.11.0-findings off main@71e4894 (v0.10.0). operator greenlit todlando + perri to PROCEED 2026-06-17. doyle gates. Proposed REQ ids + root causes:

**1. REQ-SEND-SPT-HOSTED** — spt-core does NOT deliver an inbound `spt send` to an spt-hosted endpoint (brought up via `spt endpoint run`, bound via `api bind`, NO `api listen` relay). doyle-agent-VERIFIED with file:line: cmd_bind→establish_perch (startup.rs:441) writes info.json + ready marker + controllable=Some(true) but registers NO message-listener/address; deliver.rs:97 resolve_address→None→spools (deliver.rs:132-140); broker dispatch_input (broker.rs:988) only receives InputReq FROM the brain — no inbound-send→PTY path. NET: a bound spt-hosted endpoint reads "online" but `spt send` silently spools. CONTEXT:187-188 model = daemon (owns PTY) delivers, manifest-configurable (PTY-inject / relay / HTTP). FIX = **OPTION A LOCKED (doyle ruling 2026-06-17, CONTEXT:39/187-188 — spt-hosted "needs no relay", direct PTY injection; B rejected = duplicates relay/socket model spt-hosted doesn't need)**: new endpoint-keyed broker frame KIND_ENDPOINT_INPUT{endpoint,data} → broker scans sessions.values() (broker.rs:510-530) for endpoint==target → write_input, fire-and-forget (no op_id/journal, relay semantics). Bytes = spt_msg::emit::render_event_lines(from,body) = the SAME <EVENT type=msg> every surface emits (ADR-0020, one format). cmd_send gate: controllable==Some(true) && resolve_address==None && online → broker_inject→Sent (un-lies "online"); else spool→Queued. Leg lives in spt bin/spt-daemon (spt-msg can't dep spt-daemon). NUANCE (CONTEXT:188, must handle explicitly): raw PTY-inject mid-active-turn interleaves badly → either (a) A=idle-direct path + active rides perri's poll-hook (MVP, LOG the limit) or (b) gate inject on broker idle/active sense (CONTEXT:161). doyle OK with (a) if logged. INT (non-negotiable): a real endpoint-run endpoint receives a live `spt send` (injected EVENT visible in PTY). Also fix the "online-but-not-deliverable" lie. = spt-core HALF of the wall-b finding (perri owns adapter half: bind hook fired-zero-perch + missing endpoint-run int test; the M12 cc-launcher endpoint-run path was impl+unit-only, NEVER E2E-proven — wall-b its first real exercise).

**2. REQ-HAZARD-RC-EOF** (Finding C) — rc read-loop (rc.rs:352-362) hard-fails on any non-WouldBlock/TimedOut read_event_until error incl UnexpectedEof → RC_FAIL → PTY "crash". Same severed-broker-stream EOF class as F1 seed (v0.9.1 seed_fail_message). Confirmed trigger: a deliberate `spt daemon stop` (broker bounce) severs a LIVE rc. FIX: classify EOF → graceful "daemon restarted — re-run/reconnect" (never raw "failed to fill whole buffer"); consider auto-reattach to the same session on the fresh broker (broker = daemon-lifetime anchor, [[broker-is-daemon-state-anchor]]). Fold side-obs: (a) `spt daemon stop` silently drops active rc/live → warn or graceful-detach; (b) owlery watch-handle lifecycle — torn-down perch dir stays "Device busy" until a daemon stop releases the handle; should release on teardown.

**3. REQ-HAZARD-DEFERRED-MANIFEST** (Finding A) — Pointer-mode (delegated/GhReleaseManaged) adapter reads manifest LIVE from source_dir (registry.rs manifest_dir:146/149); a deferred/un-extracted install → load_manifest fails → registered() (410, filter_map ok()) SILENTLY DROPS it → ADAPTER_UNRESOLVED + cryptic os-error-2 on `adapter use`. FIX: clear diagnostic at resolver + adapter-use (not silent-drop / not bare os-error-2); maybe eager manifest copy at register so host_binaries survive pre-binary-download.

(Finding B = legacy-owl listener death = NOT spt-core, dismissed; see [[parity-arc-closed]].)

**DEFERRED IDEA (perri flagged 2026-06-17, not minted):** capability/per-seam min-version — let an adapter declare "this SEAM needs spt-core >=X" (e.g. endpoint-run needs 0.11.0) WITHOUT bumping the whole adapter's `min_spt_core_version` (which would over-block flows that work on older cores). Surfaced by the wall-b <0.11.0 silent-seed (endpoint-run path needs 0.11.0 but ready/live work on 0.9.0). spt-core manifest feature shape. Mint only if a SECOND adapter hits the same need (one case = doc-note suffices, perri's resolution).

**{node} subst-key catalog gap (perri finding 2026-07-02 → operator-PROMOTED same day into BUILD-F023-WANIDLE wave as REQ-MANIFEST-NODE-KEY; token NODEKEY-FOLD — no longer backlog):** published fill catalog (harness-contract, spt 0.19.1) has NO `{node}` key. Candidate REQ in the ADR-0029 subst-key family: `{node}` = node's advertised label (hostname, daemon-start-refreshed), lazy [strings]-eligible. CAVEATS to document in-REQ: (1) single-token fills only — tokenize-then-fill CANNOT produce a space-carrying argv element, so composite names like "<id> @ <node>" stay adapter-shim territory (perri's claude-spt v0.10.3 launch shim is the reference impl and stays regardless); (2) hostname is locally knowable, so the key is convenience/uniformity, not capability. Related PARKED: unify CC RC-name to "<id> @ <node>" — blocked on proving CC remote-control names tolerate spaces end-to-end; tokeny `<id>--<node>` stays.

**NEW SEED 2026-07-19 (perri digest --json purity — LOW-PRI hygiene, NOT a fleet outage; doyle grounded + perri CONFIRMED same day). Candidate REQ-DIGEST-JSON-PURE, v0.38.2-or-later fast-follow.** ⚠ FRAMING CORRECTED (do not repeat the wrong story): perri's INITIAL report said the `DIGEST:<id> version=N` trailer broke claude-spt receive-heal FLEET-WIDE. FALSE — it was an OBSERVATION ARTIFACT of perri's own `2>&1` diagnostic commands. doyle grounded (cli.rs:1619 = `eprintln!`=STDERR since 16f4c8e 2026-06-03, stdout pure in every version) → perri verified spt_capture (interrupt_watch.rs:188) reads out.stdout ONLY, `digest --json 2>/dev/null` ends pure `}` parses clean. The ACTUAL fleet cause was a SEPARATE adapter bug (D2, adapter-side, FIXED perri v0.25.1): the buried-marker `--last 1` window — deployah's 3 post-interrupt notifies became newer turns and buried the Esc marker under --last 1; doyle+todlando healed only because nothing arrived to bury theirs. v0.25.1 fix = `--last 12` window-scan + heal when marker-in-window AND latest-turn-has-no-entries. LESSON (grounding win): grounding the finding in code flipped a wrong node-wide-outage RCA before it shipped; perri correcting their own changelog/comments/memory. THE CORE fix is still WORTH DOING but LOW-PRI (hygiene for OTHER/future strict json consumers, no active impact — perri's own adapter never consumed the cursor): (1) `--json` output carries NO `version` field (cursor only in the stderr trailer); (2) trailer fires in json mode too. FIX: emit top-level `"version": N` (integer — perri's pinned recommendation, matches the trailer's semantic name; perri has NO hard constraint, tag_scan uses transcript byte-offset .pos not the digest cursor) in the --json object + suppress the stderr DIGEST: trailer under --json (keep for human/non-json). perri keeps first-JSON-value tolerance as harmless N-1 defense. NEEDS: REQ + xtask gen + behavior-change test sweep. Lane: doyle triage → todlando builds → doyle gates. Route after v0.38.1. Evidence: perri finding + correction 2026-07-19, doyle grounding (scratchpad reply-perri-digest-json.txt).

---

## ENDPOINT-SHUTDOWN-TEARDOWN (hertz RCA 2026-07-19, doyle RULED + code-verified, ranked HIGH — likely a DAEMON-LIFECYCLE wave)

**Defect:** `spt endpoint shutdown <id>` on a BROKER-HOSTED endpoint reports `(Active -> Suspended)` but leaves the hosted session, its harness child, and the child `spt api listen` all running. Field-repro'd on native GNU (0.33.0) and independently on HFENDULEAM; defect still present in 0.38.1 source. Result: warm process tree behind a cold-advertised row = live-process LEAK + false state.

**Code truth (doyle-verified):** `cli.rs::cmd_shutdown` (3979) is two legs only — remove ready marker, `cmd_rest(Suspend)`. The Suspend edge (`resting.rs::daemon_rest_event_with_liveness` → apply_event → cascade_shells_on_edge → advertise) fires echo + shell cascade + re-advertise, never touches a session. Irony: cli.rs:3797-3804 ALREADY probes broker-session truth (`has_live_session_honest`) just to force `from=alive` — shutdown KNOWS the session is live, then leaves it running. `cmd_stop` (7071) unregisters address + `terminal_normalize`, which is why stop cleans roster state and shutdown doesn't. `effective_rest_state` (resting.rs:225) maps alive=true+intent=Suspended → Suspended, letting the lie become advertised truth.

**Ruling (doyle, grounded CONTEXT 29-39 / 282-291 / 618-640, PRD R-INST-3):**
- (A) Broker PTY/child termination IS core-owned — CONTEXT:33 gives the broker the PTY masters + spawned harness children, CONTEXT:628 defines suspended as session-closed, CONTEXT:640 makes shutdown the graceful verb reaching it. No core→harness manifest callback (hertz's refusal ENDORSED); `api listen` EOF stays retryable/fail-closed.
- (B) warm + persisted-Suspended is invalid as an END-STATE, legal as a bounded in-flight window. Stored rest field is INTENT not truth (CONTEXT:291) — so the bug is at the WRITER (transaction never completes), NOT the reader. **Do NOT change `effective_rest_state` / REQ-EFFECTIVE-INSTANCE-STATE.**
- (C) hertz's ordered transaction adopted as the spine, THREE amendments: **(1) split by hosting topology, not by verb** — reuse the W4 authority predicate (`controllable==Some(true)`, ADR-0041 amendment / REQ-HOSTING-AUTHORITY-CONTROLLABLE); harness-hosted (CONTEXT:39, core spawned nothing) keeps today's behavior + a corrected doc comment. **(2) kill the DESCENDANT SUBTREE** (`spt_store::proc.rs` kill-root+process_descendants — a direct-child kill misses the surviving `spt api listen`), and on reap-timeout **do NOT stamp cold**: exit non-zero naming the survivor, leave state honest (a cold row over a live process is the WORSE lie). **(3) wrap the existing rest edge, don't rewrite it** — apply_event already echoes before the flip (KH 3.3); outer shape = [rest edge] → resolve SessionInfo → kill subtree → await reap → CAS'd cold stamp (`terminal_normalize(path, Some(sid))` — the arg cmd_stop deliberately passes None) + unregister address → advertise. `reconcile_hosted_liveness` is the existing catch-up net for partials; don't duplicate.
- Kill must NOT go through `Brain::attach()+kill_session()` (brain.rs:622 `require_session()` ⇒ takes a control claim ⇒ controller theft under the ADR-0044 ladder). Needs a dedicated endpoint/sid-keyed broker request, no control claim, idempotent on unknown session.
- Unit `shutdown_soft_stops_and_suspends` ENTRENCHES the bug (asserts marker+intent only) — rewrite, don't extend.

**Public postcondition pinned for omp-spt (gate criteria):** broker-hosted, exit 0 ⇒ no broker session row; process subtree reaped incl. child `spt api listen`; perch ready=false alive=false address-unregistered unbound=false; effective+advertised Suspended (row still gossiped, wake routes); echo/commune + shell cascade ran BEFORE the kill; wake resumes under the recorded adapter. Non-zero ⇒ no guarantee, failure line names the survivor, replay idempotent, escalation `endpoint stop`. Harness-hosted ⇒ only marker down + intent + signoff + shell cascade.

**Gate acceptance:** hertz's list adopted verbatim PLUS assert the descendant `spt api listen` is gone (the leg a direct-child kill silently passes). Needs REQ minted first. Overlaps DAEMON-LIFECYCLE (broker session ownership / lease boundaries) — likely a wave there, not standalone. Awaiting operator GO; REGISTRY-STALL P0 currently ahead.

### ↑ EXPANDED + RENAMED **ENDPOINT-TEARDOWN-AUTHORITY** — RAISED TO **P0** (co-equal REGISTRY-STALL), hertz RCA #2 + doyle ruling 2026-07-19

`endpoint stop` has the SAME defect as `endpoint shutdown` — and it composes into a **lifecycle DEAD END with no in-band exit**. Hit doyle's OWN live endpoint; hertz recovered it out-of-band (scoped kill of broker-owned root PID + descendant reap, recorded sid `fe20b39f…` + adapter `claude-spt:ccs` preserved → daemon reconcile revived doyle under a new root PID, **no context reset**).

**The trap (two individually-correct behaviors):** (1) `cmd_stop` never resolves/terminates the broker session → subtree survives (claude-spt → ccs node → outer claude → nested resumed claude + MCP children); (2) `endpoint run` correctly REFUSES `ENDPOINT_CREATE_CONFLICT` (v0.37.0 no-silent-reattach REQ) *because of* that survivor. Wedged harness ⇒ stop lies, run refuses, rc replays a dead PTY, `rc --take` controls a process that never answers. **Only exit = out-of-band taskkill.**
**Record fix alone is INSUFFICIENT:** post-stop info read status=offline BUT rest_state=active + controlled=true — the surviving host RE-BOUND after the CAS-less `terminal_normalize(path, None)`. Stamping can't win against a living process; **only the reap makes the stamp true.**

**Ruling grounding:** CONTEXT:190 "soft teardown is `endpoint stop`" is the **RECORD** axis (vs purge = hard record wipe) — cmd_stop's own comment confirms (spool.db + info.json preserved); it is SILENT on process. REQ-ENDPOINT-STOP-OFFLINE is written as a pure *marking* req ⇒ today's roster-only behavior is spec-faithful, so this needs a **NEW REQ**, not a bugfix. **Decisive precedent: REQ-HAZARD-DAEMON-STOP-REAP** already ruled that `daemon stop` reaps its spt-hosted children (job object / process group) — same principle, one scope up; `endpoint stop` was simply never given it. ADR-0041 decision 3 calls stop "a DEFINITIVE death observation" — it **asserts a death observation without performing the death**.

**Ruled fix — ONE shared topology-aware broker-teardown primitive serving BOTH verbs** (supersedes the shutdown-only factoring): resolve SessionInfo → sid/endpoint-keyed broker kill with NO controller claim → reap whole descendant subtree → bounded await of broker-row removal → THEN stamp + unregister + advertise. Gated `controllable==Some(true)`; harness-hosted keeps marker/address/status-only. **Only legit differences:** `shutdown` = echo commune + shell cascade FIRST, result rest_state=suspended; `stop` = NO ceremony, result terminal_normalize. Teardown/reap/await/postcondition IDENTICAL.
- **NO ECHO ON STOP (explicit ruling, deliberate CONTEXT:647 deviation):** echo needs a responsive harness; stop exists to work when the harness is WEDGED; echo-with-timeout re-imports the hang. Cost = stop loses the final context delta (why `shutdown` stays preferred). **Action item: CONTEXT:647 needs an amendment line recording the stop exception** so nobody "fixes" it back.
- **Kill must NEVER depend on harness cooperation** (no graceful-input, no PTY-EOF wait). Wedged host = design case.
- **Timeout:** don't stamp offline over a survivor; exit non-zero — and because stop is the LAST rung, its failure line must name the surviving ROOT PID + the scoped-kill remedy.

**doyle self-correction (on the record):** the prior ENDPOINT-SHUTDOWN-TEARDOWN postcondition named `endpoint stop` as the escalation for a failed shutdown. True of stop's INTENT, false of its IMPLEMENTATION — asserted without checking cmd_stop's process behavior (read it for stamping semantics only). Until the primitive lands the honest escalation is the out-of-band scoped kill hertz performed.

**Regression (hertz's list + 3 doyle adds):** subtree + broker row gone; `endpoint run --resume <recorded sid>` makes a NEW PTY not an rc of the old; killed host cannot re-bind rest_state=active; **(a)** info stays offline+normalized across a bounded settle window; **(b)** deliberately nonresponsive harness still reaped in-bound; **(c)** ★ stop → `endpoint run --id <same>` SUCCEEDS, never ENDPOINT_CREATE_CONFLICT — that single assertion IS the user-visible point.

---

## RC-TERMINAL-CAUSE (hertz RCA 3 bug 2, 2026-07-19, doyle-ruled — NEXT MILESTONE after TEARDOWN-AUTHORITY)

**Defect:** an intentional harness `/exit` can enter the 30s reconnect countdown instead of ending clean. Intermittent/version-sensitive — hertz's 0.38.1 repro ENDED CORRECTLY, but the field event coincided with `spt daemon status` showing on-disk 0.38.1 while resident `broker_image: 0.38.0`, `broker_stale:true`. **Do NOT call it fixed off one green run** (hertz's refusal upheld — a freshly-restarted broker is the least informative config for this race).

**Code path once the semantic Exit is missed:** `serve_attach` normally maps `BrokerEvent::Exit` → `AttachRecord::Exit` + FIN (attach.rs:609-615), rc maps that to FINAL `PumpEnd::Exited` (rc.rs:2305). If the wire/brain EOFs BEFORE that record, rc calls `serve_eof_end(rendered_any)` → any rendered viewport returns `Severed` purely from `rendered_any=true` (rc.rs:2021-2032) → `reconnect_class(Severed)` always re-drives → inside the 30s loop ALL establish failures incl. `EstablishFail::NoTarget` (the exact truth after self-exit) are swallowed by blanket `Err(_)` retry (rc.rs:1938-1944).

**doyle ruling — the invariant: TRANSPORT EOF IS NOT A TERMINAL CAUSE.** Broker is the single writer of session truth (CONTEXT:33-36 — it holds the PTY masters + children; nothing else can know why a child ended). EOF means "I stopped hearing," never "it ended." Same error class CONTEXT:291 warns about (trusting a proxy signal over the authority that knows).
- **Layer A (REQUIRED, the real fix):** `Exit` must be a DURABLE terminal record delivered before FIN on every child self-exit, not just the happy ordering; preserve ADR-0043 Output-before-Exit. Needs a broker-image bisect (exit waiter / controller writer / serve brain / connection-bound stream). **Mixed-image is a SUPPORTED config, not an anomaly** — CONTEXT:33 says the broker is the stable kernel that "almost never updates," which is *why* the daemon is split — so **N-1/N broker coverage is MANDATORY**.
- **Layer B (ALSO REQUIRED, not a mask):** retrying a PROVEN terminal absence for 30s is wrong on its own terms — the first retry already learned the truth and discarded it. **LOCAL:** on rendered EOF query the broker session table; absent ⇒ FINAL (Exited/NoLiveSession), present ⇒ Severed/reconnect (legitimate — consulting the authority, not substituting for it). **REMOTE:** a local query proves NOTHING about a remote session; requires an explicit terminal-reason frame from the OWNING node, and until that exists remote KEEPS reconnect behavior (fail toward recovery — a wrongly-final remote attach is unrecoverable, a wrong reconnect wastes 30s). Distinguish `NoTarget` from `DaemonDown`/`Unreachable` instead of blanket `Err(_)` — cheapest part, correct unconditionally. **NEVER make `NoTarget` globally final** — key on owning-node/session truth or broker/node bounce recovery breaks (worse regression than the bug).
- **Why NOT folded into TEARDOWN-AUTHORITY:** different seam (attach terminal-cause vs lifecycle-verb authority), and layer A is an unbounded investigation — doyle refuses to put one inside a milestone already scoped for release. **Coupling flagged instead:** W1's kill path terminates sessions, so W1 int assertions must NOT depend on Exit-record timing (told todlando: assert broker-row + process-tree absence, the truths W1 owns).

**Regression:** real broker-hosted harness that SELF-EXITS on PTY input — NOT `kill_session()`, which is what `attach_viewport_reconnects_across_a_broker_bounce` (rc.rs:2885-2897) does and exactly why existing green coverage masks this path. Repeat to close the race; assert Exit observed + no reconnect-banner bytes + immediate final prose + session row reaped. Separate leg proves a genuine sever still banners/reconnects. Plus the N-1/N broker matrix.

**⚠ Ruling NOT yet delivered — `spt send hertz` returned NO_PERCH (offline, NOT spooled). Resend from `scratchpad/ruling-rc-terminal-cause.txt`.**

---

## WIN-PROC-LIVENESS-ORACLE (todlando build-finding 2026-07-19, doyle-accepted during W1 gate)

**`spt_store::proc::is_process_alive` is UNSOUND as an "is it gone" oracle on Windows.** `OpenProcess` keeps SUCCEEDING for a TERMINATED process for as long as any parent holds an open handle to it — and **the broker always holds one for every PTY child**. So a correctly-reaped harness reads ALIVE. Found the hard way: todlando's W1 int first went red on exactly this; the test now asks the OS process table instead (`proc::process_table()`).

Linux already special-cases zombies; **the Windows half has no equivalent.**

**Consumers to audit:** `broker.rs:291` (`session_is_zombie` → `wrapper_alive = pid.map(is_process_alive)`, plus the `has_live_descendants` scan directly below it) and every stale-row / shell-close reader that asks liveness of a pid it did not spawn. **+2026-07-27: `shellhost::live_launch_winner` (#106, double-launch arbiter — resolve_wake's rule extracted) — a pinned corpse probing alive makes the arbiter stand down a legitimate relaunch and adopt a dead pid as success; ruled NOT a #106 blocker (faithful to existing rule, oracle fix heals centrally), recorded on the PR.**

**doyle note (gate, why it matters more than it looks):** `zombie_verdict`'s `Some(false) => true // dead root, surviving record` arm is the primary zombie classification — and on Windows it may **under-fire**, because the dead root reads alive through this oracle. That interacts directly with the W1 gate blocker (teardown refusing to stamp over a lingering row whose root is actually dead): both want the liveness question asked via `process_table()`, not `OpenProcess`. Rule of thumb to encode: **"can I open a handle" ≠ "is it running"** — for the is-it-gone question the process TABLE is the only honest authority on Windows.

Not W1's to fix (W1 uses `process_table` at its own call site). Sized as a small standalone wave; candidate for the W2 slot of TEARDOWN-AUTHORITY once the lease remainder is scoped, since it is the same liveness-truth family.

**⭐ MIRROR HALF FOUND + FIXED (todlando, #107, 2026-07-27): `process_identity` had the LINUX zombie hole (opposite platform, sibling oracle) — /proc/<pid>/stat answers for a zombie ⇒ Present(matching birth) ⇒ relay_liveness=Held FOREVER for a relay dying as unreaped child of a living parent; convergence never fires (found by his own deliberately-unreaped int child, first Linux run). Fix (in #107): zombie demotion INSIDE process_identity (unix: table-present + !is_process_alive ⇒ Absent) — one-resolver discipline, both oracles agree in one place; resume-custody consumer verified safe (zombie can't hold custody). Two oracles, each missing one platform-half, found from opposite directions — the eventual is_process_alive Windows fix should copy the same in-resolver shape. Non-reaping pinned as load-bearing in the test.**

**⬆ UPGRADED TO FIELD-BLOCKING 2026-07-27 (two independent specimens, one night, operator-rank pressure raised).** flynn's force-killed alchemy-0 (pid 5756) AND liam's independently-measured force-killed shell (pid 25944), identical shape: relink refused SHELL_ALREADY_ONLINE; OpenProcess SUCCEEDS, GetExitCodeProcess ok=True exit=4294967295 (the /F kill code, NOT 259 STILL_ACTIVE), process ABSENT from table. Two owners, two pids, one mechanism — lookalike hypothesis dead. THREE owners' shells sat behind it during the alchemy 0.5.0 install window. Discriminating fix already scoped above (not-STILL_ACTIVE gate / process-table authority — the exit code is in the same handle the probe already holds). flynn holds pids+timings as acceptance fixture.
**RIDERS 2026-07-27 late:** (1) clear latency NOT time-shaped (attempts 1/3/8 across specimens) —
working hypothesis (doyle mechanism, flynn observation): `Get-Process` in a persistent pwsh
session returns a .NET Process object holding an OS handle until dispose/GC ⇒ the PROBING SESSION
pins the corpse, clear = GC-timing-shaped. liam instrumenting handle-holder snapshot; predictions:
holder = pwsh session not broker; $p.Dispose() clears instantly; subprocess probes never pin.
Hygiene rule if confirmed: probe in subprocesses / dispose Process objects. Does NOT narrow the
fix — exit-code gate discriminates on what the handle SAYS, correct under any pinner.
**CONTROLLED RESULT (flynn+liam, same night):** mechanism CONFIRMED — handle obtained while
alive, held across kill: OPEN_OK + real exit code (4294967295, not STILL_ACTIVE), table=False;
Dispose+GC flips to OPEN_FAILED err=87 INSTANTLY. Root cause confirmed from second direction.
BUT the probe-pinning story for THEIR relinks is REFUTED (probes ran post-kill ⇒ no object ever
held) and flynn's control arms were self-confounded (Start-Process -PassThru pins from birth —
honestly disclosed). liam reframe: 4 clears in 0.1-5s, 2 in minutes ⇒ SLOW is the anomaly.
Standing candidate = the SPAWNER's live-obtained handle (which is this seed's FOUNDING line:
"the broker always holds one for every PTY child") — for supervised services the supervisor
holds the child handle BY DEFINITION; slow clear = spawner drop/GC, not clock. Next
instrumentation: identify the holder process at a slow clear. (2) Related
verb seed (flynn framing, keep verbatim for ranking): shell relaunch-onto-new-bits = NOT new
lifecycle behavior, a verb NAMING existing behavior (kill own process → relink; identity, repo
binding, tag cursor preserved — measured twice, two owners) so owners stop paying identity for a
version bump and stop needing to know the kill is safe.
**✅ CAUSALLY CLOSED on the failing surface (liam, 2026-07-27, ratified by doyle+flynn):** REAL
shell instance pid 47076 — pre-kill handle opened on LIVE instance; post-kill: held handle
exitcode=4294967295, table=False; SIX relink attempts under the held handle t=0.1–10.3s all
SHELL_ALREADY_ONLINE; CloseHandle; re-open FAILED err=87; next attempt t=12.3s SHELL_RELINKED.
Not a clock — a drop. FIXTURES LOCKED: unit = dispose-flip; int = the six-refusal held-handle
sequence (causal supersedes the awaited holder snapshot). NAMED ORACLE for the fix leg:
OpenProcess-succeeds is NEVER liveness (pinned corpse openable by design); GetExitCodeProcess on
the handle ALREADY HELD discriminates with zero new syscalls — fix is HOLDER-INDEPENDENT.
flynn's alchemy-0 counterexample RESOLVED via item #22: local spawn/relink/wake run in-process
in the invoking CLI ⇒ spawner handle drops at CLI exit in ms = the fast class; slow class needs
a RESIDENT holder (#22 candidates: daemon reconcile/wake path, cross-node serve arm). Founding
line narrowed: "resident-supervisor-owned pins". SOLE REMAINING OPEN QUESTION (one yes/no,
open-question framing per flynn, no confirmation-shaped instruction): is the holder the daemon —
decides only the secondary drop-on-child-death leg, not the oracle fix. No live-daemon bounce to
manufacture the case (ratified). Seed FIELD-BLOCKING, spec-ready on rank.

**❌ WITHDRAWN 2026-07-19 — F-033 (emphasys, reported then retracted SAME DAY; NOT an spt-core defect).** Reported as "perched request/reply has no non-echoing reply channel" (reply arrives as an ordinary inbound turn and auto-settles; `spt ring --from <transient>` routed the reply into the ACTIVE endpoint; public envelope carries no request/reply or no-response marker). **Retracted by the reporter: root cause is omp-spt TURN CORRELATION across a local user interjection — `completeTurn` selected the latest assistant output without checking for a NEWER user prompt. Adapter-side fix + regression in progress; nothing for core.** Keep the entry rather than deleting it: the same symptom will be re-reported one day, and this is the cheapest record of where it actually lives. **doyle process note — this is why reported-but-unverified seeds get filed as REPORTED and never ranked before code-verification: it was withdrawn before doyle spent a read on it.** Distinguish from real envelope-family items ([[event-envelope-reply-to-removal]] ADR-0020 `reply_to` removal, F-043 NO_PERCH non-spooling) which STAND on their own evidence.

**⚠ NEW SEED 2026-07-19 (doyle+todlando, PR #35 CI — UNEXPLAINED PROCESS TERMINATION on HFENDULEAM; open question, NO culprit identified).** A CI test process (`spt-store branchstore::tests::branches_by_recency_orders_newest_first`) was **TERMINATED, not failed**, at 12:17:23Z. **Proof, not inference — a Rust test binary exits 101 on test failure, never 1:** the victim exited **1**, with NO libtest verdict line, NO `failures:` block, NO panic, NO stderr — AND carried nextest's `(test failed with exit code 1)` annotation, which appears exactly ONCE in the whole run. A known-real assertion failure (run 29673357187, kitsubito) shows the exact INVERSE shape: full verdict + panic, no annotation. Three instruments agree it was not an unhandled exception (doyle's log read: no crash code; todlando's WER check: no APPCRASH at 05:17:23 local; the exit code itself). **Four candidate killers FALSIFIED — do not re-walk these:** (1) concurrent CI job — n1-gate started 12:17:44Z, AFTER the test job ended 12:17:42Z, sequential; (2) the superseded run 29686157820 — cancelled 12:12:38-43Z, 4.5min early; (3) any agent-issued sweep — zero `Stop-Process`/`taskkill /F`/`kill_pid_tree` hits across EVERY Claude transcript on the box in 12:05-12:19Z; (4) CI's own kill steps — `Get-Process spt` without a wildcard is an EXACT name match, cannot match `spt_store-<hash>.exe`. **Honest state: something terminated it with code 1 and nothing we can reach recorded doing it.** Context: the box was in a severe load spike (a normally-millisecond unit test took 23.419s; slowest light-pool tests 23.4/16.8/11.4/11.3/11.2/11.1s) — but saturation is the CONDITION, not the mechanism: **a killer selects one victim, saturation does not**, and the SIBLING `branches_are_independent_roots` PASSED 40ms later doing the same git-subprocess work in the same pool. todlando reproduced the condition HARDER than CI (marker test 26.1/28.9/26.1s vs CI's 23.4s; victim dragged to 17.1s = 11x normal) and it passed **3/3** — a null result with demonstrated capability, which argues AGAINST the load hypothesis rather than merely failing to support it. **TRIPWIRE: on any recurrence, `--no-capture` FIRST, before any fix or re-run** — an orderly `exit(1)` that never unwound still prints nothing with capture off, whereas a panic whose output was merely LOST in the pipe prints to console. **⚠ POSSIBLE CROSS-LINK, deliberately NOT merged:** hertz filed an RCA the same day for a simultaneous freeze-and-recover of EVERY spt-hosted session on this same box, broker provably healthy. Two unexplained events, one box, one day = suggestive, proves nothing. Discriminator requested from hertz: the freeze's wall-clock window — if it brackets 12:17:23Z they are one event. Lane: doyle → operator-rank.

**NEW SEED 2026-07-19 (todlando, Phase-A saturation runs — `atomic::concurrent_writers_never_collide_on_tmp` hit the 240s TIMEOUT backstop; OPEN QUESTION, deliberately NOT filed as a flake).** A sub-second test hit SLOW at 60/120/180s and was SIGKILLed at 240.082s under Phase-A load. **doyle framing: a sub-second test does not become a 240s test because the box is busy — it becomes a 3s test.** 240s with that ladder is the shape of something NOT MAKING PROGRESS, and a test whose subject is CONCURRENT WRITERS CONTENDING FOR A TMP NAME is exactly where a retry-loop livelock would live. Saturation is plausibly the TRIGGER; it is unlikely to be the MECHANISM. Investigate as a possible contention/livelock defect in the atomic-write tmp-name retry path, not as a load flake. Lane: doyle → operator-rank.

**NEW SEED 2026-07-19 (todlando, same runs — `spt::idle_edge_drain_e2e` misclassified LIGHT; doyle RULED, land after #35).** `spool_while_active_then_idle_fires_injection` FAILED for real under Phase-A saturation (REQ-MSG-IDLE-EDGE-DRAIN: pending_before=1 pending_after=1, the ACTIVE→IDLE edge did not drain). It spawns a real endpoint + harness pid + brain, so it **QUALIFIES AS HEAVY under `.config/nextest.toml`'s own sweep criterion**, yet sits in Phase A. FLAKE-LEDGER #15's standing ruling is **classify-by-criterion, not after-the-flake** ⇒ reclassify to the heavy group (all three `<HEAVY>` strings). **NOT folded into PR #35** — that PR is gated and about to merge, and re-opening a gated PR to add scope is how a clean gate becomes a stale one. Land as its own small rig PR after #35 merges.

**⚠⚠ STANDING HAZARD 2026-07-19 (doyle+todlando — HFENDULEAM ran to 0.04 GB FREE DISK; likely root of MULTIPLE same-day "mysteries").** A CI job died `os error 112` ("not enough space on the disk") linking `libspt_daemon`. Box had **FORTY MEGABYTES free**. Dev target `C:\Users\decid\Documents\projects\spt-core\target` = **274.7 GB** (deps 230.2, incremental 42.8); doyle's throwaway gate target added **10.96 GB**. **Neither doyle nor todlando checked free space before launching heavy builds, despite a standing memory ([[hfenduleam-disk-full-ci]]) that says os-112/LNK1318 on this box = disk full, CHECK DF FIRST.** todlando deleted `target\debug\incremental` (42.8 GB, pure cache, self-regenerating) → 34.5 GB, later 64.01 GB free. **`deps` (230 GB) DELIBERATELY NOT deleted** — a cold rebuild imposed on every lane mid-milestone is an OPERATOR call in a declared window with nobody mid-gate, not a unilateral one. Worktree targets are trivial (docs-reorg 0.71, r4-stale-guard 0.92 GB).
**⭐ This became HYPOTHESIS 6 for hertz's simultaneous all-session freeze, and it OUTRANKS both prior candidates.** A box that cannot WRITE is one where everything that logs/spools/checkpoints stalls at once and resumes the instant a block frees — no lifecycle event, no restart, no broker fault. It **survives all four of hertz's falsifications** rather than being touched by them: they tested broker-internal stall states, brain/update handoff, and peer health — **none of those instruments observe a blocked WRITE.** It also explains the 23.4s test outliers without a load spike. **NOT folded in: the 12:17:23Z process kill stays separate** — an allocation failure aborts with a crash code + WER entry and two instruments say there was none.
**⚠ EVIDENCE RETRACTION (todlando's own, unprompted):** their "three heavy rounds at higher load, nothing froze" datum — originally offered against doyle's saturation hypothesis — is NOT a clean control: if disk was the live variable, those rounds ran while the volume drained toward zero and they cannot place each round in that drain.
**⭐ GENERALIZING LESSON:** both agents spent the day measuring instrument-vs-code questions on a box whose ENVIRONMENT neither measured. The 23.4s outliers, the killed process, and hertz's freeze all arrived while the disk quietly drained to 40 MB, and nobody looked until the disk announced itself. **Same defect class as everything else today, one level further out — a claim keyed on the wrong thing, where the thing was the box.** Capture plans must sample free disk + box load, not just process state.

**⭐ NEW SEED 2026-07-19 (todlando's insight, doyle turned it into a search instruction — AN UNREACHABLE STATE IS AN UNGUARDED ONE).** `zombie_verdict`'s PRIMARY arm ("dead root, surviving record") survived years with an UNSOUND oracle feeding it — not because anyone approved, but because **no rig could produce the state, so nothing could ever catch it.** The absence of a test was INVISIBLE: coverage looked fine, the arm looked exercised by its pure unit table, and the one test that would have failed was unbuildable. Discovered only when TEARDOWN-AUTHORITY W2 tried to write the int and found the healthy exit waiter reaps the row before the state can be observed (fixed by the `SPT_TEST_EXIT_WAITER_SUPPRESSED` fault-injection valve). **THE SEARCH INSTRUCTION (doyle), WITH todlando's SEARCHABLE TELL: where else does this codebase branch on a state NO RIG CAN MANUFACTURE? ⭐ THE SIGNATURE IS: a branch whose ONLY test is a PURE UNIT OVER HAND-PASSED VALUES.** That is exactly what hid this one — `zombie_verdict`'s table exercised every arm with hand-passed bools and looked COMPLETE, which is why nobody noticed the PRIMARY arm had never been reached by a real process in its life. The unit was not wrong; it measured the FUNCTION while the unreachability lived in what could FEED the function. So the query is: **pure verdict function + full unit table + no int that produces its inputs for real = candidate.** It also names the fix shape — NOT more unit rows, but a way to MANUFACTURE THE INPUT. Every such branch carries whatever bug it acquired since the day it was written, with no possibility of detection. Starting candidates that FIT the signature: poison classification and the drain failure paths (todlando ranks both as immediate matches). The N-1 branches rank DIFFERENTLY — they already HAVE valves, so they are PRIOR ART (someone hit this class and solved it locally), not unguarded branches. Plus any "this cannot happen" branch that still has code in it. Method: for each such branch, ask what rig could produce its state — if none, either build the valve (fault injection, guarded per the OLD-vs-BROKEN distinction in ADR-0045/W2) or record explicitly that the arm is unguarded. Lane: doyle scoped → operator-rank, AFTER the milestone. Kin: the W2 valve precedent, [[spt-core-findings-backlog]] GEN-OVERLAP-WRITE-ATTRIBUTION (also a state the product gives no way to observe).

**⭐⭐ MILESTONE CANDIDATE 2026-07-19 — HARNESS-HOST-LIVENESS (hertz RCA, reproduced live on HFENDULEAM spt 0.38.1; doyle code-verified ALL FOUR load-bearing cites same day, ACCEPTED IN FULL).** An IMMORTAL ONLINE ROW for a harness-hosted endpoint whose harness is dead. Field state: `rc emphasys --view` says "online but harness-hosted, no session to attach"; broker has no session; info.json `live_agent`/`controllable=false`/`status=online`/`rest_state=active`; **both recorded pids DEAD**, relay row points at a port **nothing listens on**; `last_active_ms` keeps ADVANCING because the daemon Psyche pulses it (`PSYCHE_TURN_FAIL:emphasys`), which defeats time-based intuition.
**⭐ ROOT, sharper than "topology contradiction": `is_perch_alive`'s own doc says "Daemon-hosted (`status` present)" — THAT SENTENCE IS THE BUG.** It treats the PRESENCE OF A STATUS FIELD as proof of hosting topology, but `api listen` writes `status` for a HARNESS-hosted row, so the premise is false at exactly the site depending on it. The authority for hosting topology is **`controllable`** (ADR-0041 minted it for this), and the predicate never consults it. **SAME CLASS AS W1 AND W2 — a claim keyed on the wrong thing** — and the most expensive of the three, because the wrong key yields an immortal ONLINE row rather than a refusal.
**doyle-verified cites:** `liveness.rs:135-143` (`is_perch_alive` returns `status == ONLINE`, comment "daemon-authoritative; never pid"); `liveness.rs:161-167` (`is_registry_entry_alive` keeps a dead relay-owner pid alive on status alone — hertz's word "circular" is exact); `rc.rs:1189-1193` (`harness_only_row` classifies from state+controllable+status ONLY — no relay, no socket, no process); `api/startup.rs` listen persisting `controllable=false` + `status=online`.
**⭐ RULED SPLIT (hertz asked extend-or-mint; the answer is BOTH, non-arbitrarily):** **EXTEND `REQ-HOSTING-AUTHORITY-CONTROLLABLE`** for legs A/C/D — those are NOT new requirements, they are the EXISTING one applied at three sites that predate it; a new REQ would let the old one keep looking satisfied while three of its call sites violate it. **MINT a new REQ** for legs B/E — they need an AUTHORITY that can say a harness-hosted endpoint is alive (lease/heartbeat + CAS-on-sid terminal normalize + daemon reconcile detecting a dead relay owner for the hard-kill path where Drop never runs). Status cannot be that authority; that is the bug.
**FREE ANSWER carried from W2:** for the harness-owner pid probe use **`is_process_alive`, NOT the process table** — the W2 discriminator says it is unsound exactly when the ASKER holds a handle, and core never spawned the harness, so it holds none; it is also the better probe where no process table exists. Say why at the site.
**IN-BAND RECOVERY AVAILABLE TODAY (doyle, from the W1 code): `endpoint stop <id>` CLEARS IT** — the teardown primitive gates on `controllable == Some(true)`, so a `controllable=false` row takes the NotHosted path, claims nothing about processes (correct — core owns none here), runs the record legs and stamps offline. If it does NOT clear, that is a SECOND finding (write path broken, not just the liveness read).
**NOT folded into TEARDOWN-AUTHORITY** — that milestone is scoped and shipping; doyle refused four smaller folds today on the same grounds. Own milestone candidate, 5 legs, hertz's regression shape adopted VERBATIM including the separate live-listener control (that control is what stops the fix declaring every harness-hosted endpoint dead). Lane: operator-rank; expected HIGH.

---

**✅ CLOSED 2026-07-20 — PR #43 merged @1e30626 (`REQ-HEAVY-UNIT-CLASSIFICATION`, impl+unit).** Module-scoped heavy overrides for `applyhost`/`livehost`/`pump` (spt-daemon lib) + `wansend` (spt bin), and `xtask check`'s `check_heavy_unit_classification` now ENFORCES the rule on the SHAPE (a `Broker::bind` after the `mod tests` marker) so it no longer depends on anyone remembering it. **The check found `wansend` itself** — two real brokers + a production `run_dispatch_loop` in the `spt` BINARY's test block, which had a 2026-07-16 Phase-A sighting whose standing ruling was *"move it if it repeats"*; classified on shape rather than waiting for a second sighting. **⭐ The check's OWN first draft substring-matched `<module>::tests` and so missed every module inside an alternation group — the same list-keyed defect it exists to catch, committed inside the check, and caught ONLY by running it red-first against the unfixed config.** Now tokenised, with that case pinned by a unit. CI green both legs both boxes; `spt-daemon --lib` unchanged at 567/567 in 9.3s, so serializing those modules cost nothing measurable. Original seed below, kept for the reasoning.

**NEW SEED 2026-07-20 (doyle, W5 gate — FLAKE-LEDGER #14 escape shape RECURS one package over; the v0.32.0 remedy was never landed).**

**⚠ READ THE STATIC PROOF FIRST — todlando's sharpening, adopted, and it changes how this gets filed.** doyle originally led this seed with a timing observation and hung the argument on it. Wrong order: **the defect is provable from `.config/nextest.toml` ALONE, with no timing evidence at all.** The file has exactly TWO overrides — `package(spt-daemon) & kind(test) & binary(...)` and `package(spt) & kind(bin) & test(/^rc::tests::.../)`. `applyhost`'s tests are `package(spt-daemon) & kind(lib)`, matched by NEITHER, so a unit doing a real `Broker::bind` + `serve()` thread (`applyhost.rs:511 served_broker`) runs in the LIGHT pool at full parallelism. **That is the finding, and it is a static read.** The class is not "this test is slow" — it is *a class-shaped remedy applied to the reporting instance's NAMES instead of to the SHAPE*. Timing evidence is needed ONLY for the frequency, never for the existence. **Generalize when filing any flake-family seed: separate the statically-provable defect from the statistically-estimated rate, and lead with the one that needs no box.**

**Supporting sighting (rate only, and DISCOUNTED — see the caveat):** `spt-daemon applyhost::tests::apply_staged_update_set_refuses_broker_touching_payloads` **TIMED OUT at 240s**, 1 iteration in 8, on hfenduleam (whole preload suite wall 240s vs ~9-12s on the other seven; 566/567 passed). **Same test, same box, same 240s recorded at v0.32.0** ([[v0320-published]]), classified then as a #14 escape with the remedy "route served_broker spt-daemon lib units to heavy-broker-pty". #14 was patched for the `spt` bin's rc units and the identical shape in the `spt-daemon` LIB was left behind. **FIX:** a third override covering `package(spt-daemon) & kind(lib) & test(/^applyhost::tests::/)` (or the served_broker callers by name, per FLAKE-LEDGER extend-on-sighting discipline); `applyhost.rs` is the only lib file defining `served_broker`, so the blast radius is one file. **⭐ THE LESSON WORTH MORE THAN THE FIX: a class-shaped remedy applied to the INSTANCE that reported it.** #14's own text names the class ("real-broker UNIT tests that escape the integration-binary filter because they are not `kind(test)`") and then enumerates four `rc::tests::` names. The enumeration is what shipped. Kin to the enumerate-vs-predicate rule from W4b (*a rule stated as a LIST is keyed on the cases someone thought of*) — same defect, in a test-recipe filter instead of a doc. **HONEST GROUNDING CAVEAT (doyle, against his own result):** this fired at 08:47Z, INSIDE CI run 29728295278's window (08:33-09:04Z) on the same box — doyle ran local loops during a CI job, breaking [[seedmap-test-collides-live-daemon]]'s own rule. So today's trigger was partly self-inflicted contention; the CLASS is independently confirmed by the v0.32.0 CI sighting, but nobody should cite today's timeout as clean evidence of the rate. Lane: doyle (CI infra), small rig PR. Kin [[e2e-leaked-daemons-shared-box]], FLAKE-LEDGER #14/#15.

**NEW SEED 2026-07-20 (doyle, W5 gate — the leaked-fixture sweep is MECHANISM-SHAPED and keeps failing its authors; FOURTH sighting).** `xtask check` / any cargo link step dies with `failed to remove <target>\debug\spt.exe — Access is denied. (os error 5)` when e2e-leaked `spt.exe` hold the file. Sightings: v0.37.0 release, doyle's W4 round-1 rig, todlando's W5 build (six leaked), doyle's W5 gate (six leaked, twice). **doyle's two misses in ONE session are the argument:** pass 1 put the sweep before the suite that CREATES the leak; pass 2 put it before `xtask` but left pass 1's leak alive for pass 2's own BUILD — the suite then failed to LINK and 514 tests never ran. Both were placement judgements and both were wrong. Working shape: a `sweep()` helper invoked before EVERY cargo invocation that links or replaces `spt.exe`, always `-Path`-scoped to the gate's own target dir (never machine-wide — [[no-machinewide-killon-shared-runner]]). **CANDIDATE REAL FIX (not a habit):** have the e2e rigs reap their own `spt.exe` children on teardown (the leak is the defect; the sweep is a dressing), or a `cargo xtask sweep` step the recipes call. Per [[rule-failed-its-author-needs-a-mechanism]] this has now failed four authors including the rule's own users — it does not get a fifth reminder. Lane: doyle (CI infra), fold with the seed above into one rig PR.

⭐ **RCA LANDED 2026-07-21 (doyle) — FIFTH SIGHTING, DIFFERENT PROCESS, SAME DEFECT FAMILY, and the sweep as specified would NEVER have caught it.** The pinning process is **NOT a leaked `spt.exe`** — it is an orphan **`conhost.exe`**. Three `.worktrees/gate-*` dirs refused `Remove-Item` with "being used by another process" at `crates\spt-daemon`, a directory that was **EMPTY**. Probe that found it (keep this — no handle.exe/sysinternals on the box): PEB read per process, `NtQueryInformationProcess`→`PebBaseAddress`, `+0x20` = ProcessParameters, `+0x38` = `CurrentDirectory.DosPath` UNICODE_STRING; script at scratchpad/findcwd.ps1. Result: **11 orphan conhosts**, CWD = `…\.worktrees\gate-{919ed95,329cce2,ci37,a3bb6bb}\crates\spt-daemon\`, all with **DEAD parents**, aged 1-2 days. Scoped kill by those 11 PIDs → all three dirs deleted immediately. MECHANISM: `cargo`/`nextest` set a test binary's CWD to the **package root** (`crates/spt-daemon`), the rig spawns children with **CREATE_NO_WINDOW (0x08000000)**, which — unlike `DETACHED_PROCESS` (0x8) — **still creates a console**, hence a `conhost.exe`, and that conhost **inherits the launcher's CWD**. Abnormal test-binary death (panic/timeout/nextest kill/gate abort) orphans the conhost, which holds the crate dir **forever**. So the leak has TWO shapes: a leaked `spt.exe` pinning `target\debug\spt.exe` (os error 5, the four prior sightings) and a leaked `conhost.exe` pinning the SOURCE tree (this one, which is why worktree removal kept "needing a retry later" — it never would have succeeded). **This is the argument for the mechanism over the sweep, now made twice: a sweep keyed on `spt.exe` by name misses the conhost entirely.** Reaping today is ad-hoc — happy-path `let _ = broker.kill()` at the end of each test (spt/tests/*, spt-daemon/tests/*), which a panic or a timeout skips; only a few rigs have Drop guards (redispatch.rs:137, redispatch_stall.rs:151). **CANDIDATE MECHANISM (doyle, for the rig PR): a Windows Job Object with `JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE`, created and assigned at test-binary startup**, so EVERY descendant — `spt.exe`, brain, broker, conhost — dies when the test process exits, on every exit path including panic and external kill, with no per-test discipline and nothing for an author to remember or place correctly. nextest's process-per-test model fits this exactly; nested jobs are fine on Win8+. Secondary hardening: long-lived detached spawns should not inherit the repo CWD (set `current_dir` to SPT_HOME), which moves the pin off the source tree even if a child does leak. Kin [[worktrees-under-project-root]] (this is WHY the removal retries kept failing), [[e2e-leaked-daemons-shared-box]], [[rule-failed-its-author-needs-a-mechanism]].

**⭐ NEW SEED 2026-07-21 (hertz v0.39.0 FIELD RCA — four defects; doyle re-grounded EVERY cite against main @1e30626 same hour, all four confirmed, three ACCEPTED + one product ruling). #1 IS A SHIPPED-RELEASE-CLAIM REGRESSION — does not wait for a milestone slot.**
**(#1, P0) RC-RESIZE-GEOMETRY-EPOCH — the W3 width work is not falsified, it is running UNDER a broken geometry transition.** `broker.rs::dispatch_resize` calls `session.resize(SurfaceSize::new(req.rows, req.cols))` at :4557-4559 and THEN `recover_log(&log).set_size_and_notify(...)` at :4560, which reaches `self.grid.resize(rows, cols)` at :1492 — **TWO SEPARATE `recover_log` acquisitions**, so the reader thread's append/parse interleaves between them BY CONSTRUCTION (statically provable, no box, no repro needed). On ConPTY the resize itself emits a full repaint asynchronously; the reader can parse that repaint into ScreenGrid at the OLD geometry, then the top-left-preserving `grid.resize` faithfully preserves an already-miswrapped model, and cold attach repaint emits the shifted rows + right-margin scraps operators actually see. hertz's DISCRIMINATOR is what makes this: `cargo test -p spt-term --test screengrid_width_oracle` is 5/5 GREEN while the field is red ⇒ the oracle never crosses the `ConPTY resize emission → ScreenGrid geometry → attach repaint` seam; the surface mock cannot catch it. ⚠ **DOYLE CORRECTION TO THE FIX SHAPE, on record BEFORE anyone builds it:** hertz's first option ("set grid geometry BEFORE invoking ConPTY resize") is **NOT sufficient** — safe on a GROW, unsafe on a SHRINK, because bytes already in flight at the old WIDER geometry then get parsed at the new narrow width and wrap early. Neither pure ordering is correct: **the defect is not the order, it is the absence of a BARRIER — the grid has no notion of "these bytes were emitted under the old geometry."** Required fix = gate/quiesce the drain across the ordered transition + an explicit **geometry epoch** so bytes are always parsed at the geometry they were emitted under + rollback/refetch on resize failure. hertz ACCEPTED this correction. Regression (accepted as filed): Windows real-ConPTY, resize emits a dense frame, compare the subsequent synthesized attach repaint against an INDEPENDENT terminal authority (never ScreenGrid vs itself — the standing RC-RENDER-TRUTH oracle rule). ⇒ **RC-RENDER-TRUTH STAYS OPEN; do NOT close it on this field-verify.**
**(#2, product ruling — doyle's call, NEITHER of hertz's two options).** Adapterless `spt ready` perch (hertz itself: type=ready_agent, adapter=null, controlled=false, ready/alive true) displays plain ONLINE `(unknown adapter)`. Cite confirmed: `model.rs:680-681` returns Online for every non-`live_agent` BEFORE consulting `controllable`; `:683-687` makes amber live-agent-only. **That gate is CORRECT and STAYS.** HARNESS ONLY means one specific thing — a live agent whose session surface is harness-owned rather than a broker PTY; broadening it to "online non-controllable agent-family" makes one label mean two things, which is how a status starts lying. An adapterless ready receiver is a **THIRD truth**: message-reachable, no session surface, nothing to attach to ever. RULING: add a distinct **ONLINE - MESSAGE ONLY** display keyed on **type=ready_agent** (never on absence-of-adapter), never stretch amber, never invent an adapter name. SECOND RULING: `(unknown adapter)` is itself a small diagnostic lie — adapter=null is **ABSENT, not unknown**, and was set deliberately; the copy must say so. `/skill:spt-endpoint` is operating correctly to its adapterless contract and does NOT change. hertz recorded both verbatim.
**(#3, P1) API-LISTEN-DOWNGRADES-HOSTING-TOPOLOGY — worse than "retains", it OVERWRITES.** omp-spt's published sequence `api bind` → identity-preserving `api listen --session-id` yields the contradictory live record emphasys carries TODAY: `controlled=true` AND `controllable=false`, adapter=omp-spt, status=online. Cite confirmed: `startup.rs:191-195` passes `controllable=Some(false)` **unconditionally** on the relay/listen path (comment: "Harness-hosted: the harness owns the process, so there is no broker PTY"), and `:379` is `controllable.or_else(|| prior…)` — **explicit wins, so Some(false) beats the Some(true) that `api bind` EARNED.** The carry-forward discipline that protects cwd/adapter/rest_state does not protect this field precisely because the listen path is not silent about it. Controlled-precedence masks the contradiction blue while attached; detach clears `controlled` and reveals amber HarnessOnly — **detach is not the root, it only unmasks** (hertz, correct). FIX DIRECTION HELD AT TRIAGE: that `Some(false)` is an **ASSUMPTION about hosting authority made by a path that does not know the answer** — `api listen` must not assert hosting topology at all when a broker-hosted session with that session_id exists. Prefer representing **listener custody separately from PTY hosting authority** (hertz's second option); merely preserving `controllable=true` still leaves listen guessing. Regression rides verbatim: bind→listen→control→detach ⇒ alive=true, controlled=false, controllable=true, display ONLINE.
**(#4) API-END-LEAVES-STORED-ONLINE → routed to DAEMON-LIFECYCLE, NOT TEARDOWN-AUTHORITY.** omp-spt `end` misclassifies as ONLINE - HARNESS ONLY instead of OFFLINE/SUSPENDED — same contradictory record as #3 plus non-atomic teardown (adapter stops listener then calls session-end under a ~1.8s total budget; a skipped shutdown callback or budget expiry leaves persisted online after listener death). Same family as the standing **REQ-REST-TERMINAL-NORMALIZE** seed (A, above): definitive loss of a hosted session/listener owner = ONE atomic store-level normalization, and no reader may treat stored online as authoritative once BOTH broker session and listener owner are absent. **Principle kept in hertz's words: a dead adapter cannot repair durable state, so the reconcile obligation is core's regardless of the adapter's budget.** Adapter-side crash/budget-expiry coverage correctly split off to emphasys.
**SCOPE ANSWER (hertz, asked and answered same hour — the reason TEARDOWN-AUTHORITY did not close):** hertz did **NOT** verify v0.39.0's own teardown claims (honest process-tree teardown for stop/shutdown, guarded `purge --force`, self-contained `digest --json`). Executed checks were ONLY: installed CLI/broker image 0.39.0 (stale=false), live picker/lifecycle records, the supplied terminal failures, and the screengrid_width_oracle run. **No positive inference from silence** — the milestone stays open on an explicit answer, not an assumption. Lane: doyle triage (REQs registry-first; #1 needs no operator GO, it is a regression) → todlando builds → doyle gates → hertz field re-verify.

**NEW SEED PAIR 2026-07-21 (flynn spt-alchemy clean-room audit — shell adapter contract gaps; doyle code-verified both same day, BOTH ACCEPTED; gap 2 HARD-GATES alchemy W4 — flagged to operator for priority).** **(1, docs) Shell relay frame vocabulary UNPUBLISHED:** shellchan.rs composes shell_command/shell_text/shell_file (+ close/sensory/drive) frames — the exact contract a shell binary parses — but the published export carries ZERO occurrences of those type names; docs say only "the shell child parses its own vocabulary". Adapters (notify-shell, alchemy) reverse-engineer compatibly. FIX: publish type names + attrs (op, xfer-id, path) + body encodings (command = JSON object of named args) + shell_close; fold in the quoted-composite-tail sharp edge (vocab check refuses extra positionals). Docs-drift-gated. **(2, docs+feature, P1) shell send --file landing UNRESOLVABLE by the shell binary:** blob lands at <shell-perch>/files/<xfer-id>-<name>, frame path attr is perch-relative — but spawn template substitution keys are ONLY {id}/{adapter_name}/{link_token} (shellhost.rs fill_spawn_command:127-131) and the child inherits broker cwd ⇒ no mechanical perch resolution exists. DOYLE RULING: frame KEEPS perch-relative path (absolute in a spooled frame lies across perch moves/node boundaries); ADD additive {perch_dir} spawn-template substitution key (opt-in, N-1-safe) + publish the landing contract with (1). REFUSED: blessing SPT_HOME layout guessing as interim. Sequence-not-version given to flynn per [[no-version-floor-before-it-ships]]. Lane: todlando builds, doyle gates, flynn consumer-verifies from published docs. ⭐ OPERATOR-RULED 2026-07-21: pulled forward as a MINI-WAVE after v0.39.1 published. **✅ BUILT + GATED PASS @5a38c7d same day** (todlando: REQ-SHELL-FRAME-VOCAB doc + REQ-SHELL-PERCH-DIR all 4 stages, red-first both legs, keyless byte-identity N-1 unit, real-binary file-resolution e2e; doyle battery 105/105 + source-read PASS; two battery snags both box-not-branch: 0.0GB disk + poisoned build-script OUT_DIR — see [[hfenduleam-disk-full-ci]]). **✅ PR #46 MERGED to main @88d040e 2026-07-21 (doyle; CI two legs green first try)** → deployah v0.39.2 → flynn conformance pass + alchemy W4 unblock → NOTIF-TRUTH triage. NEW SEED from the wave (todlando, doyle-acked): registration-time template key validation covers SESSION roles only (validate_role_templates) — a shell [shell] spawn/wake template with a misspelled {key} registers fine and faults at spawn; belt-both-ends (validate at adapter add AND keep spawn-time fault) = triage material.

**NEW SEED 2026-07-21 (todlando gate seed, doyle-accepted non-blocking at the presentation-barrier gate @dad6ff2):** ScreenGrid `set_mode` honors only the FIRST param of a multi-param private-mode CSI (screen.rs csi_dispatch h/l arms read `ps(params,0)` only) — pre-existing limitation, now with a small capture-loss face: `ESC[?25;2004h` applies DECTCEM 25 and neither applies nor defers the untracked tail param (2004), so a mixed tracked+untracked mode set loses its tail silently in BOTH live and capture modes. Real children emit these separately (why it has never fielded). Fix shape when picked up: iterate params in the h/l arms — tracked params consume via set_mode per param, untracked params re-encode + defer as a single-param CSI each (capture mode) / ignore (live), preserving emission order. Unit: `ESC[?25;2004h` in capture mode hides the cursor AND defers `ESC[?2004h`; `ESC[?2004;25h` the mirror. Kin REQ-RC-RESIZE-PRESENTATION-BARRIER leg 5, screen.rs one-parser-authority constraint.

**#4 UPDATE 2026-07-21 (emphasys field repro + operator queue ruling):** canonical build-ready record filed by emphasys (fresh `omp-spt-end-record` on spt 0.39.3 + omp-spt 0.3.16: `endpoint run --adapter omp-spt --create` → `spt rc` → OMP /exit exits 0 → row stuck ONLINE - HARNESS ONLY until manual `endpoint stop`; record JSON shows controllable ABSENT=None — the v0.39.1 demotion fired correctly at PTY reap, live_agent+None displays amber per model.rs legacy-self-corrects arm, and NOTHING normalizes stored-online when the listener then dies = the defect). **hertz acceptance criteria BANKED verbatim for the build:** after harness exits 0, broker-owned PTY/session teardown converges the endpoint to OFFLINE without adapter self-stop or manual endpoint stop; no surviving broker process/session row; attach/run behavior stays truthful. **OPERATOR RULED DIRECTLY (doyle AskUser, pull-forward offered as recommended option): KEEP THE QUEUE** — NOTIF-TRUTH next, DAEMON-LIFECYCLE (this) after. Relayed "operator P1" arrived via emphasys AND via hertz post-refusal — see [[emphasys-agent]] relay pattern; evidence accepted, authority claims not.

**NEW SEED TRIO 2026-07-21 (flynn, alchemy Phase 1 hand-drive on 0.39.3 — all accepted, flynn's ranking agreed; doyle reclassified #1 defect-not-feature):** (1) **DEFECT, silent-intent-drop class: inline flag pass-through on `shell cmd`** — `spt shell cmd s1 view #3 --json` never reaches the shell: spt's CLI eats `--json` as its own global flag, the command spools WITHOUT it, owner gets a text answer, no error — semantics changed silently; quoting workaround undiscoverable at failure point. Doyle design lean (recorded, not promised): loud refusal on recognized global flag after a shell op = honest floor, smallest ship; `--` separator = standard conformant, can ride same change; blanket pass-through REFUSED-leaning (every future global flag would silently change shell behavior). (2) **stdin body form for `shell send`** — parity with plain `spt send` stdin body; line-structured shell grammars force shell-quoting-hostile multi-line argv (bash heredoc mangled, PS needed here-string). Additive, N-1-safe, kin [[send-body-from-file-not-inline]]. (3) **arity-refusal teaches quoting rule** — append 'multi-word tails must be one quoted argument' to the vocab-check arity refusal (PS stop-parse turned one tail into 22 positionals; refusal correct but unteaching). Rides next vocab-check-touching wave. flynn to file hub Requests once alchemy self-dogfoods; none block alchemy.

**Hub-dogfood Requests (flynn W5 seeds, filed as GitHub issues 2026-07-22, Bot cards in _spt-bs-core channel — triage AFTER DAEMON-LIFECYCLE releases):** #61 Bugfix silent-intent-drop of trailing global flags after a shell op; #62 Feature stdin body for `spt shell send`; #63 Change arity refusal teaches the one-quoted-tail rule. Each links the 2026-07-21 exchange, doyle = routing target; state changes notify via the Requests channel (no polling owed).

**Two Windows-e2e flake seeds (DAEMON-LIFECYCLE gate fallout 2026-07-22, file post-release, SEPARATELY — different roots, fusing them = the Amendment-1-retraction shape):**
1. **endpoint_autostart_e2e stderr-interleave (corrupt-input race):** saved_endpoint_replays_on_daemon_restart red 2× — brain-stderr banner spliced MID-TOKEN into the ENDPOINT_AUTOSTART line (`adapter==== spt brain stderr — generation 0 — pid … ===cc`). Anchoring is structurally insufficient (todlando's split_once rig survived the same class only because ConPTY spliced at a line boundary — luck). Fix shape: INTERIM = strip the self-delimiting banner (`==== spt brain stderr … ===`) from the captured stream, then match against repaired text (works because the banner is self-delimiting — the property a verdict stream needs); LONG-RUN = framed or dedicated channel for the token. Generalisation for the REQ: a verdict must not share a stream with an unsynchronised writer (kin: 7.55 instrument's stdout protocol line).
2. **registry_lifecycle multichunk snapshot-write-count race (honest-input wrong-count):** multichunk_feed_applies_with_exactly_one_snapshot_write red 1× under box contention — the assertion's input is fine, the count is not; expectation races under load. Distinct root from #1.
Both greened intermittently on identical trees same day (53cdeab/876aba3 green; db06961 ×2 + a2c1dbb red) — intermittent-green-on-red = race, loop-to-characterize when filed (v0360 lesson).
2b. **rc_console DNAR presentation flake (1 sighting 2026-07-27, #98 docs-only rerun-2 Win Phase B):** `spt-term::rc_console_newline_presentation::rc_console_mode_with_dnar_presents_what_the_emitter_addressed` red 7.9s at rs:148 on a docs-only diff (structurally innocent). Third distinct single-red flake family of the night's load window (after silent-peer ×7 + autostart-interleave ×4). Observe; joins hertz's characterization queue only on recurrence.
3. **wedged_viewer 240s block — SEED CLASS: edge-triggered gap + drop-don't-block = unrepresentable outcome (2026-07-27, todlando RCA ratified, hertz owns fix as own thin PR):** controller `read_event()` = unbounded (`read_event_until(None)`; viewer helper 30 lines away has the 200ms bound, controller path never did) + gap detection fires only when a forward-jump frame ARRIVES + b4 try_send DROPS under full channel ⇒ burst + ISOLATED marker dropped in one overflow window = zero frames forever = test's 20s wall-clock check (evaluated between iterations only) never runs = 240s nextest kill. Neither accepted outcome (marker / IrrecoverablyBehind) is reachable in the nothing-follows-a-drop case — that case has NO representation. Fix shape: `read_controller_event_resuming_until` (production delegates with None, byte-identical) + named third outcome + FRESH-READER ring probe at deadline (fresh reader sees burst ⇒ observation-side drop; sees nothing ⇒ upstream starvation). ⭐ CLASS RULE: audit every timed observer in the b4 drop-don't-block plane for outcomes that require a frame to arrive — "a watcher needs its own liveness proof" applied to test oracles. **SECOND CONFIRMED MEMBER same night (#103 Win, 2026-07-27): applyhost::tests::broker_reports_its_compiled_image_version_over_ipc TIMEOUT 240s — Brain::broker_image_version reply loop = read_frame_until(None), unbounded; #105 adds coordinator_image_version with the identical None-loop shape ⇒ hertz's sweep covers both image queries. hertz notified.** **PR #108 (hertz, 2026-07-27) bounds the two spec members (controller diagnostic loop + broker_image_version_until opt-in; production byte-identical); audit ledger on PR record (9 members checked). ⭐ CLASS SHARPENING (hertz): per-read carrier timeouts bound the SLICE only — a live responder feeding NON-MATCHING events starves a match-loop as fatally as silence; only an absolute deadline bounds total wait. DEFERRED SEED (rank separately, PRODUCTION-semantics class not test-infra): per-operation absolute-deadline APIs + starvation tests for stall_evicts / net_status / sessions / announce_coordinator_image / adapter_apply reply loops. coordinator_image_version_until = hertz tail after #105.**

## SEED: activity-transition seam for spt-rebound-tool (perri request 2026-07-24)
- **Primary: core→shell link-scoped activity push.** perri's spt-rebound-tool (kind="shell" adapter, inward idle-nudge) hard-depends on observing its OWNER endpoint's busy/idle TRANSITIONS. Verified no surface exists: `is_idle` = client-side in-process only (api/delivery.rs:103), endpoint-info omits activity, no push. Requirements accepted (perri's, shape is DOYLE'S): (i) link-scoped, owner implied by link token (drive-poll/drivehub precedent); (ii) current state emitted on EVERY transition both directions (redundant same-state resend = harmless no-op, rebound derives edges); (iii) event-driven, not client poll (gates a countdown); (iv) restart-survivable (doyle starting instinct: re-emit current state on re-link). Open design questions: where activity truth lives daemon-side; ride existing shell link event stream vs new verb. **Contract locks in ONE message to perri before code; REQ minted at work start.** perri builds non-core parts in parallel; escalate ranking if it goes blocking on their side.
- **Separate rider seed (rank independently): idle/busy in `endpoint digest --json`.**
- **✅ CONTRACT LOCKED 2026-07-24 (operator grill, doyle; lock message SENT:perri, perri confirmed fit + building):** (1) HOME = activity frames on the EXISTING shell-link event stream (no new verb, link-scoped, owner via link token). (2) SEMANTICS = drive-class ephemeral: latest-wins, current-state-carrying, redundant resend no-op, never spooled/replayed. (3) Both directions; current state emitted on every (re-)link. (4) LATENCY = bounded observation (sub-second class, NOT hard-real-time); frame carries TRANSITION TIMESTAMP (state-took-effect time, not emission) so edge-anchored consumers self-correct. (5) PULL avenues for non-shells: activity on `spt api endpoint-info` + per-endpoint activity (busy|idle) key on `endpoint list --json` (operator addition). Digest rider DISSOLVED — digest stays pure content surface, perri closed it their side. CONTEXT.md carries the model (activity observation entry). REQs mint at work start. MILESTONE-MATES (same idle-edge wave, all operator-ruled same grill): digest SEAL-ON-IDLE (turn seals/gains stable seq at idle transition, next-input demoted to no-op fallback, idempotent + seq-stable + straggler-tolerant — kills liam's mint-then-idle deadlock; liam notified, field re-verify at ship) + CROSS-NODE DIGEST SNAPSHOT PULL (qualified-address refusal lifts for `endpoint digest` + `--after` polling under existing address gate; delta stream stays node-local until a real cross-node subscriber exists).

## SEED: `spt send` live cross-node delivery can hang unboundedly (doyle, 2026-07-27, CI-runner-informant debut)
- **Field shape:** #100's notify job — script clean, daemon up, verdict computed, then `spt send doyle` (recipient LIVE-listening ⇒ live path, cross-node kitsubito→bigscreen dial) hung >5min until job-timeout cancellation; cleanup terminated the orphan `spt` process. `|| true` cannot guard a hang. Any agent scripting `spt send` inherits the same exposure. Kin: [[broken-ipv6-poisons-iroh-discovery]] (kitsubito-relevant); box also logged NTP-all-unreachable same night (network health question). Rerun dispatched = 2nd data point (reproducible vs transient). Infra mitigation (todlando, #100): coreutils `timeout 30` wrap. PRODUCT remainder for ranking: live-delivery dial path needs a deadline (send must be bounded; QUEUED-spool path already fast).
- Second-order: the QUIC/dial deadline family ([[v083-broker-quic-deadline]], [[pump-ipc-deadline-fix]]) never covered the SEND live-relay dial leg — same lesson, new limb.
- **todlando refinements (2026-07-27, ratified):** discriminating observable for the RCA = hang in dial/discovery (IPv6/iroh kin + NTP-dark box datum) vs post-connect write. **Repeatable rig for free:** the #100 notify job = kitsubito-dials-bigscreen on every CI run — better reproducer than anything hand-built. Honest fix shape = bounded-attempt-then-let-it-spool (QUEUED is success; a hang is NOT queued). Infra wrap held until #100 rerun reports (concurrency group would cancel the rerun = destroy the reproducibility data point); wrap = `timeout 30` per-send + loud NOTIFY_SEND_TIMEOUT naming recipient+bound (a notifier's own failure must never be silent) + `|| true` retained + job budget STAYS 5m (raising it would hide the class).

## SEED: churn leaks stale listener registry row (doyle, found 2026-07-24 during F-033 dig)
- **Core defect.** A cross-session listener rebind leaves the DEAD session's registry row unpruned. Frozen evidence: hertz had TWO `.registry` rows — dead `127.0.0.1:64932` (session 019f92d0's listener, process gone) beside live `127.0.0.1:63214` (session 019f932c, pid 36148). ROOT: the boot-row/addr dedup in `ready.rs:114` dedups only against a **same-session** re-bind, so a boot under a NEW session-id leaves the prior session's addr row. RISK: `deliver_tcp` → `registry::resolve_address` (deliver.rs:96) returning the stale row = dead dial; the recycled-pid guard (deliver.rs:110-118) only unregisters if the owning pid is confirmed dead — a recycled-alive pid keeps the stale row, delivery falls to spool → wrongly `Queued`/deferred instead of live `Sent`. Fix candidate: prune prior-session addr rows on rebind (not just same-session), OR resolve-newest-by-stamp + lazy-prune losers. NOT the F-033 deafness (that was adapter-side stdout-drain; SENT proved resolve took the live row here). Kin: churn family (3 hertz boots/57min), [[e2e-leaked-daemons-shared-box]] pid-reuse class.

## SEED: listener-stream EVENT-PART reassembly burden is silently non-conformant (doyle, 2026-07-24, from F-033 close)
- **Core design/hardening.** F-033 ROOT = omp-spt never implemented `<EVENT-PART seq/id>` reassembly the live listener-stream contract requires; core `render_event_lines`→`chunk_if_oversized` (startup.rs:918) legitimately chunks an oversized delivery, adapter parser wedges silently (no error/death until buffer-limit). SECOND consumer to hit this; failure invisible for many boots. The HOOK-drain path already dodges it (`render_event_whole` = ONE never-chunked frame, F-002 self-delimiting). **Two candidate hardenings:** (a) make the LIVE listener stream self-delimiting too (whole frames, no EVENT-PART) — removes the burden, cost = unbounded single-line write on a live pipe; (b) **LEANING (b):** keep chunking but ship an adapter CONFORMANCE probe / contract-lint that feeds an EVENT-PART sequence and asserts reassembly → non-implementing adapter fails LOUD at integration, not silently in field. emphasys offline repro (whole=1 event / EVENT-PART=0+wedge / EVENT-PART+msg=swallowed) = the exact conformance-leg shape, reuse it. Rank against queue. Fix itself is emphasys adapter-side (owns it). **✅ RULED 2026-07-24 (operator grill): option (b) conformance probe, BACKLOG (not the idle-edge milestone — emphasys shipped v0.3.25 with reassembly, large-probe validated, F-033 CLOSED, no live victim). Operator rider: also backlog a chunking OPT-OUT flag (`--disable-chunking` on the listener CLI invocation) — a consumer may elect whole never-chunked frames, accepting unbounded line writes. Both ride any later adapter-touching wave.**

---

**NEW SEED 2026-07-25 — SHELL-SPAWN-DOA: a broker-launched shell that dies on arrival leaves ZERO trace (perri field report, v0.42.0 idle-edge verification; todlando verified the shape in source, filed unranked).**
perri saw `SHELL_SPAWNED:rebound-0 owner=perri pid=<N> status=offline (online at bind)` for a spawn template that never actually ran — dead pid, no log, no notif, no diagnostic anywhere, perch sits offline forever with no signal why. Template was interpreter+script (`powershell.exe -NoProfile -File <abs .ps1> {link_token}`), tried both slash flavors; pointing spawn at a native .exe worked first try.
**Their diagnosis is one step short, and the real shape is worse.** `SHELL_SPAWN_FAIL` ALREADY exists and DOES fire with rollback when the launch fails (`crates/spt/src/cli.rs` ~12131 arm). perri got the success line because **CreateProcess SUCCEEDED** — `powershell.exe` exists and started fine; it then exited immediately on its own (-File path resolution / execution policy / arg parse). So this is NOT "a template spt cannot launch". It is: **nothing observes the child after CreateProcess returns.** `launch_shell` (`crates/spt-daemon/src/shellhost.rs:160-211`) spawns detached with stdio DISCARDED BY DESIGN — `detached_no_inherit` on Windows, `Stdio::null()` x3 on unix — because KNOWN-HAZARDS 5.6 (REQ-HAZARD-DETACHED-PIPE-INHERIT) says an inherited handle on an immortal child hangs any caller capturing spawn's output, forever. So a DOA child yields no exit code, no stderr, no liveness recheck.
**The fix must not re-open 5.6.** Needs a post-spawn liveness check (pid still alive after a short grace, or bind-handshake-not-seen-within-N) PLUS somewhere the child's dying words can land that is NOT an inherited pipe — a per-instance spawn log file the child's stdio redirects to is the obvious shape (file handles do not carry the immortal-pipe hazard). Silent-failure class; the operator-visible symptom is an eternally-offline shell with no explanation.
Workaround given to perri: point `spawn` at a native .exe, or wrap the script in a launcher that logs to a file the consumer controls.
Kin: REQ-SHELL-1 (launch), KNOWN-HAZARDS 5.6. Unranked — operator ranks.

**NOT DEFECTS, from the same perri report (triaged + answered 2026-07-25, recorded so they are not re-filed):**
- *drive-poll "stdout carries status lines"* = **DOCS-UNDER-READ + merged stream.** Frames are `println!` (stdout), `DRIVE_DELIVERED:`/`ACTIVITY_DELIVERED:`/`DRIVE_EMPTY:` are `eprintln!` (stderr) — `crates/spt/src/api/reporting.rs:527-535`. The help was true about stdout and SILENT about stderr, so a merged-stream reader had no way to know. perri's proposed fix (say stdout carries non-EVENT lines) would have made the docs FALSE. Fixed by precision instead: PR #75 `fix/drive-poll-help-stream-split`, adds the stream split + an explicit must-not-key-on-line-count warning. Same shape as the v0.42.0 digest-help fix.
- *`adapter add` requires `[adapter].min_spt_core_version`* = **DOCS-UNDER-READ, NOT a 0.42.0 gate.** Required since the manifest schema first landed (M2a T1, `ae23376`); non-Option `String` at `crates/spt-runtime/src/manifest.rs:138`; `docs/MANIFEST.md:44` already calls it "the ENFORCED compatibility floor" with an example at :29. **No release-notes line owed — one would be FALSE** and would send every adapter author hunting a break that never happened.

**SECOND LEG OF THE SAME SEED, 2026-07-25 (perri final report; todlando verified in source). SHELL-SPAWN-DOA is really SHELL-LAUNCH-TRUTH — a dead child does not just fail silently at spawn, it WEDGES THE INSTANCE.**
perri killed a HEALTHY resident. `spt shell list --json` still reported `status: "online"`, and `spt shell relink rebound-0` — the documented way back — REFUSED: `SHELL_ALREADY_ONLINE:rebound-0: relink is the online switch — nothing to do`. Only teardown + spawn recovers.
**Verified root:** `relink_shell` (`crates/spt-daemon/src/linkhost.rs:411-423`) gates on `info.status == SHELL_STATUS_ONLINE` — a **STORED FLAG**, written once at the binary's bind (`crates/spt/src/cli.rs:16808`) and **never reconciled against the child's liveness**. So the online bit outlives the child unconditionally: the perch believes it is online forever, `shell list` reports a lie, and the one documented recovery command is the one that refuses.
**Same missing truth as the DOA leg** — nothing observes the child after CreateProcess returns — so both legs want ONE mechanism: post-spawn/periodic liveness reconciliation of `info.status` against the recorded child pid, which un-sticks the dead-child instance AND catches DOA. The material is already on disk: `launch_shell` records the child pid to `SHELL_PID_FILE` (`shellhost.rs:206`, `:254`) and other paths already read it (`:346`, `:392`).
**⚠ DO NOT let REQ-HAZARD-DEAD-REC-PID block this.** That hazard says a stored `rec.pid` is NEVER an alive-gate signal — but it is about WORKER perches, where the recorded pid is the ephemeral worker-start HOOK process and is dead by design. A SHELL's recorded pid is the long-lived child itself, so a pid-liveness check IS honest here. Whoever builds this must state that distinction or they will talk themselves out of the only available signal.
Unranked; rides with the DOA leg as one requirement. doyle to rank.

**FIELD-VERIFY TEST GUIDANCE (perri, 2026-07-25) — two contaminants that each cost a FALSE NEGATIVE on an idle-edge verification, seam was fine both times.** Ride these in the test guidance for anyone field-verifying an idle edge: (1) **your own harness's background tasks wake you when they complete**, so the owner never stays idle across the measurement interval — clear them before measuring; (2) **a shell that educates on first online** lands a message at the turn boundary and can END the idle window early — let it educate once, then measure the NEXT boundary.

**NEW 2026-07-26 — F-034: perch/endpoint staleness family (emphasys filing, omp-spt docs/SPT-CORE-FINDINGS.md @c148bdd; evidence = logs + perch records on HFENDULEAM, spt-core 0.39.x). Adapter-side TRIGGER fixed in omp-spt v0.3.29 (Windows launch shim: kill-on-close job object couples hosted tree to daemon + parent-death watch + api-listen relay re-holds perch). Four CORE shapes survived the adapter fix:**
1. **Dead relay still holds the endpoint** — HOSTING_AUTHORITY_DEMOTED fires and `ONLINE - HARNESS ONLY` renders 5+ min after the listen process is provably gone, within ONE daemon lifetime. Kin: [[spt-core-findings-backlog]] churn-stale-registry-row; holds-authority-after-death class.
2. **rest_state sticky** — `endpoint stop` records suspended; later successful `run --create` goes fully ONLINE with rest_state STILL suspended; `endpoint suspend` then NO_EDGEs on a visibly ONLINE endpoint. Stored-flag-never-reconciled class = SHELL-LAUNCH-TRUTH leg-2 kinship.
3. **Dead-owner re-pin did not fire** — perch pid AND parent_pid both dead+freed, fresh spawn's api bind refused `CONFLICT is live under session <old-sid>`; only purge recovered. KH 7.51 identity family; INVERSE of hertz same-ID-adapterless-bind-no-CONFLICT watch item — same seam, opposite failure.
4. **Childless zombie launch shim counts as "a live session"** for ENDPOINT_CREATE_CONFLICT while `list` renders the same endpoint OFFLINE — two liveness authorities disagreeing = REQ-ENDPOINT-CYCLE-HONEST / KH 7.50 family.
Bonus capture: post-abrupt-death respawn attempts die instantly (write-start → writer-exit channel-closed same ms) ~1/min, never recovering. F-032 relation: it is the FIFTH leg of the operator symptom; with 0.3.29 in place, core reaping just the SHIM suffices on Windows (job reaps the tree).
⚠ **Evidence is 0.39.x — DAEMON-LIFECYCLE W1-W3 + 0.40-0.43 shipped since; EVERY shape needs a current-version re-verify before core work dispatches.** Unranked; operator ranks. Full evidence in the F-034 entry (omp-spt repo).

**NEW 2026-07-26 — ENDPOINT-STOP-ON-SHELL half-action (liam specimen, ready-to-mint, requester=liam; flynn offers co-sign + has independent kill/relink evidence). spt-core 0.43.1, reproduced live on HFENDULEAM.**
`spt endpoint stop <shell-instance-id>` (e.g. alchemy-0) answers `STOPPED:<id> (no ready marker; address unregistered)` — reads as success — while: (1) the shell PROCESS keeps running (exe stays LOCKED, defeating the stop-before-adapter-install use that motivated the command); (2) `spt shell list` still `online`; (3) `owlery/<owner>/shells/<id>/info.json` still `status:"online"`. What it DID do is real+invisible: address unregistered — perch address torn out from under a live, still-believed-online shell.
**Reachability:** `spt shell` has NO stop verb (teardown = only exit, destroys perch/repo-binding/tag cursor), so `endpoint stop`'s own help ("stop an endpoint outright, spool preserved") is the door the surface points at, and it ACCEPTS the shell id.
**Class:** endpoint verb reaching a shell perch and half-acting — two surfaces, nothing comparing them (kin: alchemy #24 manifest/verb-table divergence; `spt adapter version` dev-manifest-vs-exe).
**Fix either way (liam, ratifiable):** refuse shell ids outright naming the applicable verb, OR make stop true (process down + record reconciled). What must not persist: success string over a live process + unregistered address.
**NOT the old stale-online trap:** on 0.43.0 pid-derived liveness the recovery is clean (kill pid → relink admitted, same canonical id, binding+cursor intact — liam executed it). Specimen text arrived ready-to-mint via message 2026-07-26 evening (in liam's words; he cannot mint — bound shell may not write to foreign repo, `instantiable` empty for him = rule working as designed).
⚠ Verify in source at mint (ground-don't-assume): endpoint-stop path vs shell-instance records. Receipt owed to liam at liam-close reconcile. Unranked; operator ranks.

**NEW 2026-07-26 — SHELL-RELINK-JOB-INHERIT seed (doyle source-verified answering liam; correction of my own recorded #22 claim):** local `spt shell relink` (and wake) spawns IN-PROCESS from the CLI — `spt_daemon::relink_shell` is a LIBRARY call at cli.rs:12559 → `launch_shell` → `detached_no_inherit` runs breakaway-attempt in the CALLER's process; child inherits the terminal job on denial. Only the cross-node arm (`ref@node`) spawns daemon-side. ⇒ recorded mitigation "cycle through relink → job-free" is FALSE for terminal-invoked local relink; TRUE only for daemon-originated spawns (reconcile/wake-from-daemon, cross-node serve). DETACH_BREAKAWAY_DENIED on CLI stdout = local truth, not relay. Candidate fixes at mint: route local relink spawn through the daemon when one runs (job-neutral), and/or make the diagnostic name WHOSE job. liam's measured datum: his session job LimitFlags=0 (KILL_ON_JOB_CLOSE off) ⇒ "may be reaped" was loaded-not-armed there; historical 17:47 deaths' job flags were INFERRED — cause unaccounted, stays open (no surviving job-flag evidence; box crash-rebooted since). Kin: REQ-SHELL-CLI-SPAWN-JOB-EXPOSURE (liam's, stays as filed), REQ-HAZARD-VIEWER-CLOSE-DETACH ladder. Unranked.

**MODE-2 NEW SAMPLE 2026-07-26 ~19:00 (doyle, discriminating pair):** ONE reply carried TWO tag-send blocks — the SHORT block (deployah, ~450 bytes) delivered intact ([tag-send] confirmed), the LONG block (hertz, ~1100 bytes) arrived at hertz as an EMPTY message (hertz applied the resend rule correctly; resent via `spt send` from file, SENT, intact per protocol). Same mechanism, same reply, size = the only variable ⇒ supports the size-class drop-not-spill hypothesis, and localizes to the HERTZ-inbound path (deployah inbound fine at short length). Note fleet context: box crash-rebooted ~17:45 — hertz's pending adapter adoption may have applied in the bounce; sample is POST-reboot, so the drop survives whatever version hertz now runs — worth asking hertz's adapter version when the probe closes. Standing discipline held (no reconstruction, resend requested).

**NEW 2026-07-26 — WINDOWS-FIXTURE-TMPDIR-LEAK (deployah finding during v0.44.0 cut, ready-to-mint, credit deployah): test fixtures leak their `.tmp*` temp dirs on Windows — 14,319 leaked dirs in %TEMP% accumulated 07-19→07-26, ate hfenduleam to 0.00 GB free; the release-blocking red was spt-daemon::sync two_tier_sync_lands_and_gate_refuses_server_side dying "No space left on device" INSIDE its own leaked-class tmpdir, and the PRIOR red (digest_cross_node brain-IPC deadline elapse) was the SAME root through a timing probe.** Class: resource exhaustion presenting as unrelated timing flakes — burns release windows, invites false environmental discharges (deployah self-corrected his own). TWO-PART SEED: (1) find+fix the leak (which fixture path fails to clean on Windows — tempfile crate dirs should auto-clean, so something holds/leaks them: kill-mid-drop? detached children pinning cwd?); (2) deployah's tripwire: CI preflight FREE-SPACE assertion so the box fails LOUD on the resource, never obscurely on a deadline ([[rule-failed-its-author-needs-a-mechanism]] shape). Second recorded hfenduleam disk-full-CI instance ([[hfenduleam-disk-full-ci]]). Recovery sweep 2026-07-26 (~330 GB freed: doyle 181 GB dead-session gate scratch + hertz-pr75 target + f31849c target + parked worktree targets; deployah 12.57 GB own release-lane target + >6h .tmp* sweep). Unranked; operator ranks.

**MODE-2 ESCALATION 2026-07-26 ~19:3x:** hertz's SECOND and THIRD replies referenced phrases I NEVER sent ("once client disconnects", "black-hole helper", digesthub.rs) — the 07-25 fabrication-from-corrupted-inbound mode RECURRING on the hertz channel, post-reboot, and now on CLI-sent (spt send from file, SENT) bodies too, not just tag-sends. Hard-reset message sent with self-contained task + a verify-first grep + echo-back request (reply with the line numbers you see). ⚠ Until this channel is proven clean: every hertz dispatch must carry a VERIFY-FIRST step and an ECHO-BACK, and any hertz reply referencing content not literally in my message = corruption tell, reset again. Channel-level probe owed (emphasys mode-2 sweep covers omp-spt; hertz's adapter + version = the missing datum — ASK IT in the echo-back round).

**MODE-2 SAMPLES 2026-07-26 ~20:4x (doyle, echo-back round — REFINES the size hypothesis):** (1) SHORT probe (~2 sentences: echo digest_cross_node.rs:443 + version) → reply CLEAN, byte-exact line match, spt 0.44.0. (2) ~4-sentence task dispatch → echo-back CLEAN, all load-bearing elements intact. (3) ~3-sentence yes/no question (servicehost authorship) → reply carried PHANTOM referent "named-pipe handshake timeout fix" (never sent) — answered a question I didn't ask, though it correctly described the real edit. (4) One-word-answer binary re-ask → clean "NO". ⇒ NOT purely size-classed: a mid-length message corrupted while a longer one echoed clean in the same round. Echo-back-before-work remains the only reliable gate; one-word-answer questions survive. **DISPOSITION of hertz's earlier "servicehost repin DONE" claim: hertz answered NO to authorship of the uncommitted provably_gone edit on shared main — the DONE claim was likely fabricated from a corrupted inbound; the edit is AUTHORLESS pending todlando's answer. Never count that claim as work evidence.**

**⚠ CORRECTION 2026-07-26 ~20:15 to ENDPOINT-STOP-ON-SHELL above (flynn self-correcting his co-signed analysis; find attribution unchanged = liam). MECHANISM WAS WRONG — supersedes the class line before minting.** Discriminating repro: `spt endpoint stop zzz-nonexistent-probe-0` → `STOPPED:zzz-nonexistent-probe-0 (no ready marker; address unregistered)` exit 0 — BYTE-IDENTICAL to the alchemy-0 output. So endpoint stop never resolved ANYTHING: it reports STOPPED for any string. **Defect = "endpoint stop reports success for an id it never resolved" — an unconditional-success no-op.** NOT shell-awareness/half-action (shells aren't endpoints; shell ids are owner-scoped and ambiguous by construction — an endpoint verb resolving one would be wrong; it correctly never tried, then answered incorrectly). Original three-surface evidence stays as the SYMPTOM that found it, not the mechanism. The "address unregistered" line needs source-truth at mint: unconditional print vs actual unregister of a nonexistent address (probably a no-op unregister that also cannot fail). Fix shape: resolve first; unknown id → refusal naming what exists; STOPPED only when something stopped. Mint from THIS framing.

## SEED: shell resident cannot read its own instance alias link-authed (perri request 2026-07-27)
Use case: spt-pacer-tool signs sends `--from <instance identity>`; operator's `spt shell rename`
should reflect in that from field, but the resident has no link-authed way to see its current
alias — bind-shell reports canonical id only, `shell list` is owner-session-side. Ask: alias in
bind-shell output, or refreshable over the link (frame or link-authed query). perri ships v1
signing the canonical id (PACER-0), adopts alias whenever this lands. LOW priority, unranked.

## SEED: dual-doc drift class — docs/MANIFEST.md vs docs-site diverge silently (doyle, 2026-07-27, from flynn docs-gap)
b3b2bd5 amended docs/MANIFEST.md but not docs-site; xtask drift gate does not cover the pair.
Second instance same day: fat-archive triples list stale since v0.30.0 (perri read). Candidate:
extend xtask check with a paired-assertion list, or generate one from the other. Unranked.

## SEED: stale deadline-*.json litter in SPT home root (doyle, 2026-07-27)
Hundreds of deadline-<uuid>.json files accumulate in %LOCALAPPDATA%\spt-core\ root (dev sessions,
CI probes, test session-ids). Needs a GC leg (age-based sweep or teardown-owned cleanup). Unranked.

## SEED: supervisor latches startup_fault on the double-daemon clean exit — DEFAULT first boot after [service] adoption (flynn field, 2026-07-27, doyle-banked)
Field sequence (flynn, alchemy on 0.44.0): at boot the supervisor spawned alchemy's daemon while
alchemy's own self-started daemon (detached, survived the spt-core bounce) still held its node
lock → second instance detected lock, exited 0 (alchemy's REQ-HAZARD-DOUBLE-DAEMON invariant,
correct) → supervisor read immediate clean exit as startup fault, latched relaunch OFF.
Three sub-defects: (1) HEADLINE — exit-0-immediately should read "already running, stand down;
retry next tick", not latch; this is the DEFAULT first boot for ANY adapter that had its own
start path before declaring [service] — the old path wins the race once, supervision latches off
on adoption day. (2) latch SURVIVES its cause (incumbent stopped → latch stayed, nothing
relaunched); read-only CLI means no clear verb — the only exit is re-registration (`spt adapter
add <dir>`), undocumented as remedy. (3) `service list` help advertises "captured startup output
behind the latch" but no surface serves it — flynn had to hypothesis-test the node lock instead
of reading it. flynn holds exact pids/timings = acceptance fixture when ranked. flynn NOT
blocked (W25 T5 deletes alchemy's own start path). Unranked.

## SEED: docs server has no boot-race rebind — one 10048 at broker boot = docs dead for the whole run (doyle, 2026-07-27, field on HFENDULEAM)
At the 2026-07-26 23:58 operator bounce the new broker raced the dying one for 5474 →
DOCS_SERVER_BIND_FAIL (os error 10048) → docs surface down for the entire broker run. Bind is
broker-side + one-shot (daemon.rs ~225-245, sole `docshost::start` production call); `daemon
refresh` cycles the BRAIN only, verified ineffective (probe 000, no new DOCS_SERVER line). NET
has exactly this self-heal (REQ-DAEMON-9 net_retry_attach) — docs deserves the same retry-attach
or at least a rebind on refresh. Same broker-served-surface class as flynn's
ADAPTER_SERVICE_NO_ANSWER (ruled 2026-07-27). Interim: full stop+start only — rolled into the
operator bounce window. Blocks blind adapter builders (perri/emphasys/flynn read :5474) whenever
it fires. Unranked, but adoption-visible. UPDATE same night: operator stood up a STOPGAP daemon
(`Temp\spt\docs-host\spt.exe daemon run --detached`, pid 45796) that now serves :5474; fleet
daemon's own binding stays lost until its bounce. Stopgap should be torn down at the real bounce.

## SEED: `adapter add --release` never engages the update hold — two install ceremonies disagree (flynn T7 field, 2026-07-27, doyle ruled-from-source)
flynn installed alchemy 0.5.0 via add --release with the supervised service LIVE: exe swapped
(rename-to-.old + new file), service kept executing the renamed OLD image for minutes, reported
old version confidently; held=false latch=none throughout; kill → supervision relaunched on new
bits in seconds. RULED: not a malfunction — the hold belongs EXCLUSIVELY to the daemon-delegated
adapter-apply ceremony (broker.rs ~6048 quiesce_for_update, ADR-0049: hold→stop→grace→kill→swap→
release-and-reconcile); add --release is the CLI content-hash swap (cli.rs apply_release_crc_swap,
ADR-0025/REQ-ADAPTER-LIVE-UPDATE) whose premise is never-touch-running-processes. flynn's sharper
framing (post docs-read): ServiceStart::boot = desired-state-RUNNING, supervisor documented-correct;
the gap is that NO trigger in the reconcile list is "the binary underneath changed". Interim ruled
contract (flynn documents): install → verify by PROCESS AGE vs exe mtime (never version string) →
kill → desired-state relaunches on new bits. Candidate fix when ranked: add --release engages
quiesce/reconcile when adapter declares [service], or surfaces "service running on displaced
image". Rider: hold has CLI-help-only presence — no prose contract in llms-full (flynn docs-gap a).
Unranked.
**✅ POSITIVE CONTROL 2026-07-27 (flynn, alchemy 0.6.0):** `spt adapter update` ran the holding
path first-use — ADAPTER_UPDATE_LIVE "daemon-coordinated apply" named itself, daemon relaunched
on new bits with NO manual kill (pid started AFTER binary mtime, measured not version-string).
Ruling field-confirmed both directions. **NEW RIDER (measured, unpredicted):** the apply completed
with FOUR live shells holding the exe — no refusal; rename swap absorbs SHELL locks like daemon
locks; shells keep executing the displaced old image, `shell relink` correctly refuses
SHELL_ALREADY_ONLINE (instance IS online), so shell relaunch is the only path onto new bits and
NOTHING signals a shell-on-stale-image. Same "binary underneath changed" blindspot, shell edition.
Coherent with source: quiesce targets [service] only, translations get terminated, shells are in
neither list. Any doc claiming a live shell blocks the update swap = measured FALSE.
**2nd SPECIMEN (doyle PACER-0, 2026-07-27):** pacer 0.5.0 exe swap 05:28; doyle's shell (spawned
03:29) kept serving pre-0.5.0 behavior ~10h — deprecated `extend` guidance, old classify syntax —
with NOTHING signaling stale image; misattributed first to session-context staleness (perri), then
needed pid CreationDate vs exe LastWriteTime to prove. Fix = teardown+respawn (operator: teardown
sufficient, nothing special about pacer). Detection recipe that worked: process start BEFORE binary
mtime ⇒ displaced. Raises the seed's rank: cost two agents a triage cycle on a wrong theory.

## SEED (2026-07-27 ~06:45, hertz full-suite run on #97 rebase rig): servicehost ForceKilled honesty question — 1 sighting
`servicehost::tests::a_service_that_ignores_the_stop_marker_is_force_killed_and_confirmed_dead` assert servicehost.rs:3461 ("ForceKilled must mean child gone") RED under full-suite load after the 150ms cooperative window; immediate isolated exact rerun PASSED. Post-#93 (provably_gone repin) oracle. DISCRIMINATING QUESTION dispatched to hertz (classification = the deliverable): (a) production waits for provable death before minting ForceKilled ⇒ verdict LIED ⇒ REAL product finding (success-claim-without-evidence class), blocks RELEASE not #97; (b) ForceKilled minted at kill-issue and the gone-check is the TEST's oracle ⇒ test-window flake, fix = bounded handle-wait (never sleep-and-peek), hertz thin commit. NOT #97's blocker (suite-inert for its diff). Status: awaiting hertz's (a)/(b) with line numbers.

**UPDATE (2026-07-27 ~06:50): servicehost ForceKilled seed CLOSED as branch (b)-test-oracle.** Production honest (stop_service joins supervision; provably_gone gates verdict). Test asserted `!is_process_alive(pid)` = the KH 7.50 unsound oracle; hertz repinned to provably_gone (same family as #93), rides #97. Also: `brain_resume_conn_deadlock::daemon_cursor_only_resume_keeps_heartbeat_live_respawn_interleave` 10-ticks-in-6s red under load, isolated pass — load-window family, 1 sighting, recorded no-action. Doyle standing order: no local full suites on hfenduleam while CI queue live (starvation class manufactures one timed-window red per run).

## SEED (2026-07-27 ~07:25): hfenduleam disk consumption needs a GC mechanism, not episodic hand-cleanup
Box lost ~66GB TWICE tonight in ~2h windows (80->13.9GB second time). Attribution measured: every full-suite build writes a 20-30GB debug target, and they ACCUMULATE across (a) per-session scratchpad gate targets (4 dead sessions held 48GB), (b) .worktrees rigs (dead rigs of merged PRs held 12GB; hertz active rigs 54GB), (c) runner _work\spt-bs-core 44GB persistent incremental, (d) shared checkout target 111.5GB (!). Preflight (#102) caught both windows as designed — 2 field true-positives night one, converting mystery sub-20ms test reds into named 7s fast-fails. Fix shape: scheduled dead-rig/scratchpad GC (age + no-open-handles + PR-merged predicates), maybe cap/periodic-clean runner _work and shared target. Related: deadline-json GC seed, [[hfenduleam-disk-full-ci]].

## SEED (2026-07-27 ~09:22): adapter shortform tag-send delivered EMPTY body (1 sighting, intermittent)
doyle tag-send to hertz arrived as delivery 22 with empty body; hertz correctly refused to infer (empty-inbound rule) and requested resend; CLI resend worked. Earlier tag-sends same session delivered fine (todlando + hertz, ~5 successes) — intermittent, not systematic. Possible correlates: message contained backtick-quoted test path + `::` + `#`-refs; length ~450 chars (chunking boundary is 400 bytes POST-ESCAPE — suspect: tag body crossing the chunk threshold drops instead of chunking on the tag-send path). Reinforces [[send-body-from-file-not-inline]] for anything near/over 400 bytes. Owner: perri (claude-spt adapter) at rank.

**UPDATE (~09:35): empty-body seed CONFIRMED as length-classed.** Short plain body DELIVERED (hertz "READABLE"); two bodies >400B post-escape arrived empty (one tag-send, one CLI-from-file) ⇒ chunk-REASSEMBLY drop on the receiving adapter path, not tag-send-specific. Repro pair banked; workaround = short bodies. Note: longer sends to hertz worked earlier same session (~08:1x) — onset ~09:20, possibly correlated with his environment change (registered claude-spt reports 0.25.20). FIELD-BLOCKING candidate for perri ranking.

**⚖ ROUTING RULED (doyle 2026-07-27 ~18:3x): emphasys/omp-spt queue, NOT perri's.** Both repros' RECEIVER = hertz's perch = omp-spt-hosted ⇒ receiving-adapter reassembly drop lands in the F-033 EVENT-PART reassembly family emphasys already owns (MODE-2 evidence pack; size-classed shapes fit). perri's ranking hold RELEASED — he re-owns only if a claude-spt receiver reproduces. OPEN RESIDUAL (core, doyle): brain 46476's 0x1800000000 OOM abort proves a SECOND length-corruption site inside core the same morning — one-seam-or-two question unresolved; core seed above tracks it. ⚠ correction to the earlier note: "registered claude-spt reports 0.25.20" was hertz's SENDER-side env; receiver adapter = omp-spt 0.3.30 vintage that morning.
**3rd REPRO 2026-07-27 ~18:3x — ON THE FRESH 18:09 DAEMON (core 0.45.0 both processes):** doyle CLI-from-file ~1.1KB → hertz drained EMPTY ("I received an empty message"); hertz followed empty-inbound rule, requested resend. ⇒ defect NOT tied to the 09:39 sick window or old core vintage — alive on current stack, spooled-then-drained path included. Reinforces omp-spt receiver attribution (hertz still omp-spt-hosted per today's F-035 capture). Workaround remains SHORT bodies to hertz.

**✅ CLOSED — ROOT CAUSE (emphasys, 2026-07-27 ~18:5x, omp-spt 0.3.31 @ef1812d): body loss at TOOL-USE CONTINUATIONS, not reassembly, not size, not core.** The >400B framing was a RED HERRING — size proxies tool-use likelihood. Mechanism: native delivery wakes the turn with the `<msg from=.../>` stub; adapter splices the real body at the context boundary; OMP rebuilds every provider request from its session store where the delivery is only the stub ⇒ body present in provider request #1 ONLY; any toolUse before replying composes the answer from a body-less continuation ⇒ "arrived empty" while wire/digest/request-#1 all carried it. Evidence: doyle's 1.1KB = 4 clean EVENT-PART frames replayed byte-exact to 1112B (reassembly EXONERATED — my "chunk-REASSEMBLY drop" attribution above was WRONG); api poll returns >400B whole; live-instrumented splice (941B in payload #1, absent in continuation); hertz's transcript shows stopReason=toolUse ×2 before each empty-reply. Fix: per-delivery-signature body memory, idempotent re-splice at every boundary, bounded 64/512KB; omp-spt KNOWN-HAZARDS #10 / REQ-HAZARD-DELIVERY-BODY-DURABILITY + 2 regression tests. CORE EXONERATED END-TO-END. **0.3.31 PUBLISHED same evening (tag v0.3.31 @ef1812d, node updated); hertz could not self-bounce (stop kills the OMP context that would run the relaunch — issuer-kill class) so doyle ran the pair 19:1x: graceful stop → run --create CLEAN (no F-035 wedge, third clean-control datum), session 26409caa pid 36060. Dual-nonce ~1.1KB retest sent WITH explicit call-a-tool-first instruction (no-tool reply would pass vacuously on old code); verdict pends hertz's echo.** **✅ RETEST PASS (hertz echo 2026-07-28 ~00:3x, on 0.3.32 / core 0.45.0): 4,898B self-send arrived intact — exact head+tail nonces + full filler visible. Entry fully retired; emphasys exonerated end-to-end, long-body workaround to hertz LIFTED.** ⭐ alchemy usage trap, cost one round-trip: `spt shell send <ref> --file` stages an ATTACHMENT, it does NOT deliver the file as payload — payload goes as the [text] arg (`spt shell send <ref> "$(cat file)"`). ⚠ CONSEQUENCE for the OOM seed above: the "possible single corruption seam" kinship link is DEAD — empty-body was never corruption; the 0x1800000000 abort stands ALONE as a core seed. ⚠ perri hold: fully released, nothing claude-spt-side (mechanism is OMP-session-store-specific), though the stub+boundary-splice pattern is worth a one-question audit in claude-spt at leisure.

## FIELD-BLOCKING (2026-07-27 ~18:5x, perri filing + doyle live probe, doyle owns → todlando dispatched): REQ-RELAY-DEATH-CONVERGENCE misses a live field shape ON 0.45.0 — dead-relay row never converges while the agent stays CLI-active
perri's capture (his daemon log, UTC stamps): doyle's 01:31Z routing-ruling batch — perri's copy injected (610B → translation binary, his line 10632) but **ZERO ENDPOINT_INJECT:emphasys lines ever, not even the loud no-translation-binary arm** ⇒ silent relay-branch skip; emphasys idle 01:16→01:32Z, never woke, manual wake drained. **doyle live probe ~18:58 local, REPRO STILL STANDING:** `owlery\emphasys\info.json` = status=online, controlled=true, driven_by=<node>, rest_state=active, adapter=omp-spt, **pid 44160 DEAD, parent_pid 43192 DEAD**, pid_started_at PRESENT (=oracle CAN judge: absent ⇒ Gone), started=18:14:20 local (row minted at his post-bounce wake), **last_active_ms FRESH (18:57:49 — his CLI sends keep stamping it)**. Sweep plane provably alive same node same window (doyle's own pacer idle-wakes ride the livehost pulse). ⇒ convergence spares a judgeable dead-relay row for 25+ min. ~~PRIME SUSPECT: last_active recency~~ **FALSIFIED (todlando attribution, same evening — last_active appears nowhere in the reconcile path). ROOT ATTRIBUTED @f7ff68f: INHERITED `controllable=true` ROUTES THE LIVENESS MODEL.** Chain: `resolve_controllable` (startup.rs:198) — BrokerPty ⇒ Some(true); ListenerOnly/NonAgent CARRY THE PRIOR FORWARD (REQ-LISTEN-PRESERVES-HOSTING-TOPOLOGY working as designed); emphasys earned Some(true) in an earlier broker-PTY life, his 18:14:20 wake re-bind was listener-only ⇒ stamp survived into a life that never earned it; livehost.rs:883 gates convergence on `controllable != Some(true)` ⇒ converge_dead_relay NEVER CALLED (row reads broker-hosted); broker arm can't heal either — surviving `controlled=true` means has_session=true (CONTROL_REAP_NO_SESSION clears it otherwise) ⇒ EXEMPT FROM BOTH MODELS. Oracle verified right and never asked (both pids absent, birth stamp present ⇒ Gone). CLASS: inherited CAPABILITY stamp routing a LIVENESS proof — kin of is_perch_alive-reads-status-as-topology. **DOYLE RULING (2026-07-27 ~19:2x): (a)+(b), (c) subsumed.** (b) UNCONDITIONAL: Some(true) is topology evidence only while its earning life lives — carry forward only while the earning pid is alive; a wake/re-bind over a dead prior life re-derives, never inherits (amend REQ-LISTEN-PRESERVES-HOSTING-TOPOLOGY title in the build PR; kills the mint at source). (a) CONDITIONAL on todlando's own ⚠ check as build leg 1: what does info.pid hold on a GENUINE broker-PTY row — listener pid ⇒ adopt (a) plain (oracle-first, Gone converges regardless of stamp); broker-child pid ⇒ (a) needs a record-evidence guard, shape back to doyle before build. His process_identity-vs-is_process_alive distinction (livehost.rs:828 hazard is a different predicate) RATIFIED on the record. hertz int leg HELD until shape lands (the shape decides what the int pins). BUILD NOTE: keep emphasys omp-spt F-035 asks (a)/(b)/(c) in view — same inherited-stamp seam (stale controlled/driven_by), plausibly one PR. ⚠ LIVE FIXTURE DESTROYED ~19:25 (emphasys info.json deleted whole, NO_PERCH on send; actor unknown — likely his self-recovery/signoff) — acceptance = SYNTHETIC row from the verbatim snapshot above (inherited Some(true) + dead pids + birth stamp over listener-only re-bind); todlando informed.
**⭐⭐ (a)-CHECK RESULT (todlando ~19:3x) — (a) DROPPED, ruling amended: info.pid = `std::process::id()` OF WHATEVER CLI PERFORMED THE BIND (startup.rs:470), re-stamped per bind. SAME FIELD, TWO MEANINGS, NOTHING RECORD-INTERNAL DISTINGUISHES: claude-spt rows record a transient `api bind` CLI (dead in seconds — measured live: todlando 22588 / doyle 45160 / deployah 29176 all DEAD while all three agents ALIVE AND WORKING); omp-spt rows record the long-lived `api listen` relay (hertz 11216 alive; emphasys 44160 dead = real). Oracle-first-regardless-of-stamp ⇒ mass-offline of every live claude-spt agent. (b) ALONE fixes the emphasys shape THROUGH THE EXISTING GATE: no inherit ⇒ controllable≠Some(true) ⇒ row routes into the shipped convergence branch ⇒ oracle ⇒ Gone; claude-spt rows untouched (BrokerPty wake re-asserts Some(true) FRESH, never inherits).** FINAL RULING (doyle): (b) UNCONDITIONAL, SOLE product leg this PR; (a) dropped not guarded. MIGRATION: next-re-bind, NO boot sweep (mint stops with (b); known stale population = zero, the one specimen self-cleared; manual-wake workaround known; a boot-time rewrite touches the riskiest seam of the day for a population of ~0). PID-ROLE FIELD (his defense-in-depth): SEPARATE SEED, next wave on this seam — record stamps what the pid MEANS at write (relay-holder vs binder), convergence fires only on relay-holder rows; seed CARRIES AN AUDIT QUESTION: which row classes reach the convergence branch today with binder-meaning pids (fresh NonAgent/None rows? shell-instance rows?) — that inference ("≠Some(true) ⇒ pid is relay-holder") is the residual fragility (b) does not close. Separate hertz int leg RETIRED — (b) is a normal product PR, todlando's stages carry impl/unit/int per standing traceability. Fixture note crossed: row already gone; synthetic stands.
**⭐⭐ (b) STOPPED PRE-BUILD (todlando ~19:4x) — SAME MASS-OFFLINE BY A BACK DOOR: on a claude-spt listener-only re-bind the "earning pid" is a dead binder BY CONSTRUCTION ⇒ inheritance drops ⇒ row routes into convergence ⇒ oracle asked about a dead-by-design pid ⇒ live agent converged. Root: "earning pid" is the wrong key for the SAME reason controllable was — the bind CLI is not the hosting life, and for BrokerPty rows the record holds NO pid of the actual hosting life (broker PTY session). Earning-life liveness is UNMEASURABLE from the record as it stands. Empirical: only live `api listen` relays on node = mobile-gw 46152 + hertz 11216; doyle/todlando/deployah have NO listener — controllable=Some(true) is today the ONLY thing keeping live claude-spt agents out of the convergence branch.** **FINAL FINAL RULING (doyle ~19:4x): (b2) ADOPTED — my next-wave deferral of the pid-role field is DEAD, it is load-bearing for the primary fix and no smaller safe subset exists (todlando's boot-sweep alternative also needs the role distinction).** (b2): stamp pid ROLE at write — `relay` (listen path, process genuinely holds the endpoint) vs `binder` (bind path, announcer expected to exit). Inheritance drops ONLY on provably-Gone prior RELAY pid (emphasys-class ⇒ re-derive ⇒ converge); dead BINDER proves nothing, inheritance stands (claude-spt untouched). Convergence re-keys on role=relay (REQ-RELAY-DEATH-CONVERGENCE title addendum: verdict fires only on relay-role pids). LEGACY ROWS (no role field): Unproven-never-kills — inheritance stands, convergence never fires; heal at next re-bind when roles stamp; migration stays next-re-bind. Registry: pid-role REQ mint + REQ-LISTEN-PRESERVES-HOSTING-TOPOLOGY amendment + convergence addendum all ride the build PR. Acceptance: synthetic emphasys template (relay-role dead ⇒ converge) + the three claude-spt-shaped negatives (binder-role dead + listener rebind ⇒ online untouched) — the near-miss IS the pinned negative test. (a) stays dropped.
🔨 BUILD UNDERWAY (todlando ~19:30): branch `build/hosting-stamp-life-scope` off @f7ff68f, worktree `.worktrees/ft-hosting`. Landed: PidRole enum + InfoJson.pid_role (serde default+skip, N-1-safe, absent=legacy=no-knowledge); startup.rs `pid_role_for` + `prior_relay_died()` single role-gated predicate + resolve_controllable re-keyed; livehost.rs ROLE GATE BEFORE ORACLE; REQ-PID-ROLE-EVIDENCE minted (audit rider in doc stage) + both title amendments as ruled; units incl. pinned negative (real doyle/todlando/deployah pids as reason) + legacy never-convergeable. Next: int (synthetic emphasys template, endpoint_lifecycle.rs) + STORAGE.md doc stage. He gates isolated-worktree/throwaway-target, reports pre-push. DOYLE GATE when PR opens: seam suites = livehost/liveness/startup units, endpoint_lifecycle, create_bind_rest_active_e2e; verify negative-test names on CI leg; check title amendments against ruling text. Distinguishing data available: perri's pinned log-line refs + this record snapshot. Consequences while open: any endpoint in this state is silently unreachable for idle wake (messages spool, drain only on manual/self wake) — the 09:39 outage's mechanism ALIVE in miniature on current core. Kin: emphasys omp-spt F-035 (stale controlled/driven_by left behind when convergence DOES fire — adjacent arm, same seam). DISPATCH: todlando (product, he built #107); hertz int for restart-resume/CLI-active shapes upgraded from optional to REQUIRED.

## SEED (flynn routing hand-off 2026-07-27, minted spt-bs-releases#2, doyle owes DESIGN RULING): shared-exe service upgrade requires node-wide stand-down
All instances of a service (field case: alchemy) execute one installed exe; Windows refuses overwrite-while-running ⇒ upgrade needs every instance down at once + teardown loses each perch (repo binding, tag cursor re-baselined, new canonical id). Operator: outage acceptable, SYNCHRONIZED stand-down is the defect. Three shapes on the Request (versioned install dirs / rename-then-replace / upgrade-on-relaunch handshake), none ruled. Full text: https://github.com/BigscreenVR/spt-bs-releases/issues/2. Kin: [[adapter-add-release-archive]], SHELL-STALE-ONLINE (perch-loss cost coupling), Win update-exe class ([[win-update-exe-uac740]]).

## FIELD-BLOCKING (2026-07-27 15:1x, perri isolation, doyle owns): idle-only ephemeral delivery DEAD node-wide after daemon restart
Since 09:39 bounce (pid 24092, 0.44.0): pacer base-pings silently dropped for EVERY endpoint on node. perri clean repro 15:05 (healthy session: latch raised, ping due 60s, 2m38s idle, nothing; active-only payload delivered on wake fine). Worked 05:33 same day (pre-bounce). NOT tonight's code (0.44.0 installed build). Suspect class: DAEMON_RESTART_RESUME path leaves idle-edge/ephemeral machinery dead (boot-race/resting-gate state?). Evidence preserved: scratchpad/evidence-daemon-stderr-0939-bounce.log (153,952 lines; DAEMON_RESTART_RESUME markers ~:31218+), perri probe timeline, doyle state file. ⚠ do NOT bounce daemon before RCA capture decision — bounce likely clears+destroys state. Related mystery: doyle 13:42-14:57 silence = THIS (delivery outage, not session hang).

## SEED (same isolation, doyle owns): turn digest entries not committed during stall windows
doyle inline classify codes emitted during the two outage windows never acted — their turns' digest entries never committed (perri: watermark fine, parsing fine; 14:57 classify acted at 15:01 on commit). Question: digest/session continuity across daemon bounce — where do committed-turn digests go when daemon is mid-restart / session unbound?

**OPERATOR EYEWITNESS (2026-07-27 ~16:35, banked verbatim-substance):** before the force-reset,
the daemon state was worse than delivery-dead: ALL endpoints received no idle-state messages (no
waking); `spt daemon stop --force` would NOT bring the spt binaries down; Task Manager kill FAILED
on them (unkillable-process class — kernel-pended, kin of corpse-handle seed's held-handle theme);
only CLI force-kill of all simultaneously worked. Operator hypothesis on record: this state may
be involved in the g6 delivery-attempt ghost (todlando's sole red ran in the sick window;
non-repro after reset is then EXPECTED — defective state destroyed). Adds to RCA scope: why
stop --force is a no-op against this state + why the processes were unkillable from Task Manager.
**CORRECTION (perri, 15:5x, revising his own report): idle pings were NOT dropped — they QUEUED at the endpoint and only drained at session wake.** His 15:11-15:37 window received the full backoff curve (5 pings) in inbound; the dead leg was WAKE/RE-PROVOCATION, not delivery. Suspect list narrows to: core live-push vs claude-spt relay wake-injection (perri owns the latter; ownership transfers to him if RCA lands there — he offered, accepted-in-principle pending RCA). Operator has since bounced the daemon (defective state destroyed — expected); remaining evidence = doyle's stderr snapshot + perri's timestamped drain files, sufficient to distinguish queued-vs-dropped. perri verifying ping-wake works post-bounce.

**⚖ RULING (doyle, 2026-07-27 ~18:2x, from stderr snapshot): CORE — perri's relay EXONERATED; #12 ownership stays core.** Section-mapped the snapshot (`=== ===` headers): sick pair = broker 24092 (9 stderr lines) + brain 19412, born 09:39:38 local after brain gen2 pid 46476 **ABORTED on `memory allocation of 103079215104 bytes failed`** (= 0x18_0000_0000 exactly — corrupt length-prefix class; kinship candidate: >400B empty-body reassembly drop onset ~09:20 SAME morning, pre-crash). Brain 19412 captured 09:39:38→15:14:27 (~5.6h, ~122k lines, alive + logging CONN_LIFECYCLE/DISPATCH/PUMP throughout): **ZERO inject-class lines entire life — no ENDPOINT_INJECT in EITHER shape (`→ translation binary` inject OR `ACTIVE -> spool (deferred hint)` send-time decision), no IDLE_PARKED_DRAIN; 0 case-insensitive matches for inject|spool|idle|translation|evaporate|parked in the whole post-crash section vs 362 in same-build pre-crash sections.** Demand proven in-window (perri's queued backoff pings 15:11+ inside capture end 15:14; doyle 13:42-14:57 outage). BOTH the send-time delivery decision AND the idle belt silent ⇒ core never initiated wake/re-provocation; nothing was ever handed to the relay to inject. Discriminating sibling: **WAKE_RESUME:hertz fired 13:36:32 (bind-driven resume WORKED)** — only the inject/provocation plane was dead, not bind. Mechanism OPEN (post-DAEMON_RESTART_RESUME state makes delivery-decision/inject machinery unreachable node-wide; candidates: belt task never spawned on crash-resume boot / all endpoints stuck live-bound "online at bind" so inject path never engages / rest-state sticky node-wide, REQ-CREATE-BIND-REST-ACTIVE kin). Related-DEMOTED (todlando correction, same day): g6 axis 3 is NOT established as this class — g6's rig runs its OWN broker in a per-test temp SPT_HOME, so fleet-daemon age has no shared-state route into it; only candidate coupling = resource contention from the fleet daemon's post-restart resume storm ([[quiet-window-predicate]] blind spot). His curve discriminates: duration tracks CPU-delta ⇒ boring contention (separate phenomenon); duration tracks age with flat CPU ⇒ genuinely this class. This ruling stands independently either way (marker-absence evidence, never leaned on g6).

**✅ #12 CLOSED (perri, 2026-07-27 ~18:28, ruling adopted verbatim; relay + pacer exonerated).** Fresh-daemon verify NEGATIVE for repro: 18:09 daemon (broker pid 1732 / brain 14764, **broker AND coordinator both report 0.45.0** — the 18:09 bounce was the full bounce) has a HEALTHY inject plane — perri deliberate-idled 18:27:06, PACER-0 idle ping provoked his session live ~60s later, no queue lag; doyle's own pacer wake same window confirms. ⭐ MECHANISM NARROWING: the 18:09 restart went through the SAME DAEMON_RESTART_RESUME path and the belt lives ⇒ the defect is NOT generic to crash-restart/resume — it was instance-specific state in the 09:39 daemon, whose boot context was the corrupt-length OOM abort of brain 46476. Suspect narrows toward corruption-adjacent boot state, away from the resume path per se. No live repro window; RCA rests on the snapshot (sufficient — ruling stands). perri keeps drain files.

**⭐⭐ MECHANISM (doyle source-read 2026-07-27 ~18:3x, CANDIDATE-STRONG — structurally complete, no direct registry-row evidence since state destroyed): STALE RELAY ADDRESSES ON A PRE-CONVERGENCE CORE.** Source facts: ENDPOINT_INJECT (all 3 shapes) emits ONLY on the inject-target path (broker.rs:5203/5228/5234); a send to a `relay_present` endpoint takes the relay route with NO marker; the belt skips on `relay_present` (livehost.rs:545, BELT-1) where `relay_present = spt_store::registry::resolve_address(id, owlery).is_some()` (livehost.rs:580) — **a registry ROW, not a liveness check**; `is_spt_hosted_no_relay` gates every inject entry point (inject.rs:82/109/163). Chain: 09:36 mass session drop + 09:39 DAEMON_RESTART_RESUME "online at bind" left/re-registered relay address rows for all 8 resumed endpoints; those relay processes died/detached but rows persisted; **the sick daemon ran 0.44.0 — BEFORE relay-death convergence shipped (#107, v0.45.0)** ⇒ nothing ever cleared the rows ⇒ node-wide `relay_present=true` forever ⇒ belt skips everyone AND senders route to dead relays with messages landing in spool ⇒ zero ENDPOINT_INJECT lines BY DESIGN (the silent path is the relay path), zero provocation, drain only at session-wake re-bind. Explains: marker absence without capture-gap; queued-not-dropped; node-wide scope; permanence on 0.44.0; non-repro on 0.45.0 (convergence sweep now clears dead relays — the 18:09 health check is the field acceptance). ⇒ **fix for the outage class ALREADY SHIPPED as #107/REQ-RELAY-DEATH-CONVERGENCE; this incident = its canonical field case — fold into #101-wave acceptance evidence.** RESIDUAL still real: belt-liveness observability seed stands (a healthy-marker absence took 6h to notice); emphasys's omp-spt F-035 shows convergence leaves stale controlled/driven_by (tail defect on the same seam); SPAWN_DEDUP:hertz 13:36 shows the broker wake-plane logging into the sick stream while inject stayed silent — the sibling probe that killed the capture-gap reading.

## SEED (doyle, 2026-07-27, from idle-delivery RCA): inject belt has NO liveness observability — 6h dead, zero evidence of absence
BRAIN_NET_CONSUMERS_UP announces dispatcher + peer pump; NOTHING announces the idle-inject belt booting or ticking. The 09:39 brain ran ~5.6h with the belt dead and the only detection was field silence + a post-hoc grep for marker ABSENCE. Fix shape: belt boot marker + first-tick line (cheap), so absence becomes a greppable defect. Kin [[absence-needs-sibling-probe]], [[verdict-from-exit-not-from-silence]].

## SEED (doyle, 2026-07-27, same RCA): brain gen2 pid 46476 OOM-abort on 0x1800000000 alloc — corrupt length-prefix class
`memory allocation of 103079215104 bytes failed` = exactly 0x18_0000_0000. Reads as Vec::with_capacity from a corrupted wire/stored length. Timeline: >400B empty-body reassembly drops onset ~09:20 → 09:36 mass session drop → this abort → 09:39 daemon set replaced. Possible single corruption seam behind all three; the empty-body seed may be core-side, not adapter — hold perri's ranking of it until this is looked at. Unranked.

## SEED (todlando, 2026-07-27 quiet-box base leg, doyle-ruled split-off): g6 respool claim disagrees with spool truth — pre-existing on main
`inject_control_wedge::g6_faulted_inflight_envelope_is_respooled_not_lost` RED at BASE 3d9ec73 on
QUIET hfenduleam (18/19 pass): fault choreography completed, daemon logged "envelope respooled
once", gate line reads respooled=false — perch spool disagrees with the daemon's claim. NOT load:
quiet window. NOT #104's: test body identical at 3d9ec73..2aae246 (diff never touches the file);
ruled split-off, #104 merged on its green CI. NOTE: same test GREEN on #104's CI runs incl.
hfenduleam Windows leg — local-quiet red vs CI green = env/rig discriminator unowned yet.
todlando's framing: the v0.14.3 fault-transient carve-out is NOT closed. Characterization vehicle:
his owed back-to-back base+2aae246 pair in one drained window (now seed evidence, not a merge
gate). Success-claim-vs-evidence class (kin: servicehost ForceKilled seed). Unranked.
**MECHANISM HYPOTHESIS (todlando 2026-07-27, doyle-ratified plausible, confirmation pending):**
respool WRITE succeeds (failure branch never printed, same-process same resolve_perch_path) — row
then EATEN by the daemon's own idle belt: test sets endpoint IDLE ⇒ drain_idle_spool claims the
non-deferred row ⇒ inject fails (binary faulted) ⇒ release ⇒ `evaporate_ephemeral_non_deferred_at`
DELETES the ephemeral row. Defect = respool racing evaporation policy, not broken respool.
**AXIS CORRECTION (todlando 3-leg result, 2026-07-27): quiet-vs-loaded framing WITHDRAWN** — all
three SHAs (3d9ec73 / 2aae246 / 002ab1b) GREEN running g6 SOLO in a drained window (respool lands
t≈480-520ms, respooled=true). SHA is not the variable; earlier red ran the FULL 19-test file -j2,
green legs ran g6 alone. Red = SIBLING-CONTENTION-dependent. Competing-consumer mechanism still
open but must explain sibling load. In flight: base full-file probe runs ×2 — discriminator =
row lands LATE (4s deadline too tight under load ⇒ test-budget fix) vs lands-and-VANISHES
(consumer race ⇒ product fix). Known probe artifact: pending_all read before non_deferred ⇒
transient pending_all=0/non_deferred=1 is instrument skew, ignore. Pre-exists #104 either way
(base-sha red; #104's narrowing touches deferred rows only, g6 envelope non-deferred).
**TIMESTAMP VERDICT (todlando, 2026-07-27): red is OUTSIDE the sick-daemon window — do NOT fold
into the daemon-wedge RCA.** Red's CONN_LIFECYCLE stamp 15:38:44 local; fleet daemon set restarted
15:34:25-32 (operator reset pinned by process start times) ⇒ red ran ~4 min AFTER reset against
the fresh daemon. Non-repro tonight NOT expected-by-construction. Doyle-recorded alternative axis
(unchased, post-release): red ran in the daemon's first ~4 min post-restart (restart-transient
adjacency — DAEMON_RESTART_RESUME class), all greens ran hours later. Stock-cadence rounds stand.
Clock discipline: gh prints UTC, box local = UTC-7. RIDER: his rounds LEAKED 2 orphaned spt.exe
fixture trees (4 pids under dead parents) = leaked-fixture class reproduced, EVIDENCE FOR
JOB-OBJECT mechanism over name-keyed sweep; scoped kill deferred to his own window (CI live, disk
fine, ownership inferred-not-proven).

**⭐ NEW SEED 2026-07-27 (todlando, #104 wedge pair — G6 RESPOOL RACE; doyle BANKED it as success-claim-vs-evidence class, kin of servicehost ForceKilled; does NOT block #104, which merged @002ab1b).** `spt-daemon::inject_control_wedge g6_faulted_inflight_envelope_is_respooled_not_lost` FAILS on base **3d9ec73** on a quiet HFENDULEAM (19 tests, 18 pass) while the SAME test is GREEN on CI including the hfenduleam Windows leg. Not attributable to #104: `inject_control_wedge.rs` is untouched by `3d9ec73..2aae246`, identical body at both SHAs. **Not a lost write** — broker `respool_envelope` (broker.rs:3553) and the test both resolve `resolve_perch_path(endpoint, ParentHint::Infer)` in the same process, and the failure branch `TRANSLATION_FAULT_RESPOOL` never printed, so `spool_message_at` SUCCEEDED. Gate line reads `respooled=false` while the daemon logs `envelope respooled once` — the row was written and then went away. **HYPOTHESIS (unconfirmed, needs one instrumented run): a COMPETING CONSUMER.** The test sets the endpoint IDLE, so the daemon's idle belt `drain_idle_spool` (inject.rs:108) claims non-deferred rows, fails the inject (binary just faulted), releases, then calls `evaporate_ephemeral_non_deferred_at` — which DELETES ephemeral non-deferred rows with no carrier at window-open. **⭐ THE DIRECTION IS INVERTED FROM THE USUAL WINDOW-ASSERTION RULE: a QUIET box ticks the belt promptly (belt wins the race → RED), a LOADED CI box delays it past the test's first 100ms peek (test wins → GREEN). So CI green is the LUCKY side and the local red is the more truthful observation** — the local-quiet-red/CI-green discriminator doyle flagged as unowned. Confirmation rig: dump resolved perch path + ALL rows with delivered/deferred/ephemeral flags on each poll, alongside `IDLE_PARKED_DRAIN` lines, base and 2aae246 back-to-back in one drained window. If it holds, the defect is NOT "respool is broken" but respool racing the evaporation policy. Kin [[window-assertion-load-direction]], [[verdict-from-exit-not-from-silence]].

**⚠ G6 SEED CORRECTED SAME DAY 2026-07-27 (todlando, three rounds of evidence against my own first framing; doyle ratified each correction).** The quiet-vs-loaded axis in the entry above is **WITHDRAWN** — it was wrong. What actually happened: the sole red ran the FULL 19-test file at `-j 2`; every green since ran g6 with siblings filtered out. **NON-REPRO IS TOTAL: green at all three SHAs solo (base 3d9ec73 / 2aae246 / head 002ab1b, respool visible t≈480-520ms, box stamped nonterminal=0 before and after each leg), AND green 19/19 on two full-file rounds at base.** Three live axes remain, none yet discriminated: (1) **SIBLING CONTENTION** — red only ever seen among concurrent siblings; (2) **⭐ OBSERVER EFFECT / CADENCE** — stock polls the spool at 100ms, my probe at 10ms, so if the respooled row is TRANSIENT the instrument CURES the defect it was built to observe (that inversion is the vanish arm's signature; the discriminating run is stock-cadence full-file × 3 on a genuinely quiet box, looking for a ~1-in-N red); (3) **RESTART-TRANSIENT ADJACENCY** (doyle, recorded not chased, `DAEMON_RESTART_RESUME` class) — the red ran in the fresh daemon's first ~4 min, every green hours post-restart. **TIMESTAMP RULING (kills the operator's sick-window fold):** red's own CONN_LIFECYCLE stamp = **15:38:44 local**, fleet daemon restart visible in process start times at **15:34:25-15:34:32**, so the red is ~4 min AFTER the force-reset, OUTSIDE the 09:39-~15:35 sick window — not explained by destroyed defective state. **⭐ CLOCK TRAP, cost two rounds of confusion: `gh` prints UTC, HFENDULEAM is UTC-7** — "22:38 quiet window" and "15:38 red" are the SAME MOMENT. Always convert before reasoning about run adjacency. **INSTRUMENT ARTIFACT, self-reported:** the probe reads `pending_count_at` BEFORE `peek_non_deferred_at`, so a row landing between the two calls reads `pending_all=0` with `non_deferred=1` — that combination is measurement skew, NOT a spool counting defect. **LEAK REPRODUCED BY ME:** the rounds orphaned two `spt.exe` trees (18880+30692 under dead 20596; 19136+43128 under dead 44700) — fresh evidence for the JOB-OBJECT mechanism over the name-keyed sweep, since a sweep keyed on live-parent ownership would not have claimed these either. Kin [[gate-rig-mechanisms-not-remembered-steps]], [[rule-failed-its-author-needs-a-mechanism]], [[measure-the-box-before-the-instrument]].

## SEED (operator field report, 2026-07-27, first hour of v0.45.0): coordinator-image "not reported" text omits the old-broker cause — misattributes age to the coordinator
Mixed-vintage window (brain refreshed to 0.45.0, broker stays 0.44.0 for daemon life): status
renders "coordinator image: not reported (the running coordinator predates version reporting, or
has not reported yet)" — but the coordinator is NEW; the RECORDER is old (0.44.0 broker has no
announce-recording and no KIND_COORDINATOR_IMAGE). Behavior correct per #105 ruling (None on query
failure); the CAUSE LIST is wrong for the commonest upgrade path (refresh-then-bounce-later = every
node, first hours of every release). Cost operator a bug report within the hour. Fix shape: CLI has
the broker image in hand at render — broker < feature-vintage selects an honest third arm ("the
network layer predates coordinator reporting; full restart brings it current"). Three causes =
three diagnostics (the #106 gate discipline). Unranked, small.

**G6 SEED — DAY-END STATE 2026-07-27 (todlando; cadence axis FALSIFIED, one axis left, experiment ARMED not run).** Stock-cadence rounds came back **3/3 GREEN, 19/19 each** on a genuinely quiet window (`nonterminal=0` before AND after each round, blob verified `db671472` = shipped 100ms poll). **So the observer/cadence hypothesis is FALSIFIED — the instrument was not curing the defect.** Day tally: **8 GREEN vs 1 RED** (3 solo across base/2aae246/head, 2 probed full-file, 3 stock full-file). Axis status: SHA falsified · sibling contention unsupported (5 full-file greens) · cadence falsified · quiet-vs-load withdrawn. **⭐ SOLE SURVIVING AXIS = RESTART-TRANSIENT ADJACENCY (doyle's axis 3, `DAEMON_RESTART_RESUME` class): the red ran ~4 min into a freshly force-restarted daemon; all 8 greens ran hours post-restart. That is now the ONLY condition distinguishing red from green.** ⚡ **ARMED EXPERIMENT — FIRE ON THE NEXT DAEMON RESTART, whatever causes it, operator-driven (agent-driven stop is FORBIDDEN on this box: stop kills the issuer):** `pwsh -File C:\Users\decid\Documents\projects\spt-core\.worktrees\g6-postbounce.ps1` — runs the full wedge file, stock cadence, base sha 3d9ec73, and stamps DAEMON_AGE_AT_START so a sample outside the ~4-min window self-labels as a control. Protocol doyle ratified: run inside 4 min, then a control run an hour later; **red-then-green = axis 3 CONFIRMED with a repro recipe; green = file it honestly as 1-in-N unreproduced and STOP spending windows on it.** The 0.45.0 broker bounce that would have been the natural trigger is PARKED (operator proved quiet-delivery is coordinator-side, so it lost urgency) — the trigger is now any restart, not that one.

**G6 UPDATE (todlando, 2026-07-27 ~18:1x bounce; doyle RATIFIED design change): experiment fired on the 18:09 restart (fresh brain pid 14764), sample landed at DAEMON_AGE≈365s (outside 4-min window — his own wake through DAEMON_RESTART_RESUME ate it; script self-labeled CONTROL). GREEN 19/19 — but g6 DURATION = 2.162s vs 0.686-0.847s across all nine prior samples (~3x prior max; gate wall = 4s).** Direction matches axis 3 (closer to restart ⇒ slower respool ⇒ nearer wall). **DESIGN CHANGE ADOPTED: discriminating quantity = g6 duration vs daemon age (dose-response curve, samples ~1/2/4/8 min post-restart), NOT pass/fail** — falsifiable without a lucky red; flat curve kills axis 3 cleanly, monotone rise establishes it on measurement. Constraint: ~~sub-4-min samples need OPERATOR bounce~~ **RETIRED (operator ruling 2026-07-27 ~19:19): use a DUMMY SPT_HOME-AUGMENTED DAEMON** — private daemon under throwaway SPT_HOME (home-hashed sock, scoped off fleet), home SEEDED for a realistic resume storm, bounced agent-driven (issuer-safe: todlando's session rides the fleet daemon). Exact 1/2/4/8-min sampling, repeatable, no operator window. Fidelity caveat on record: synthetic storm ≠ fleet storm (no live-session reconnects / iroh pairing burst) — rising curve = contention confirmed; flat curve + real CPU-delta = contention dead broadly; flat + weak CPU-delta = inconclusive, justifies ONE fleet-bounce sample later. One-sample caveat held: 3x is not a rate. ⚠ CONVERGENCE CLAIM RETRACTED same day (todlando's own correction, doyle-ratified): **the wedge rig never touches the fleet daemon** — g6 spawns its own broker under a per-test temp SPT_HOME (`init_wedge_home`/TestHome; probe path was `...\.tmpXXXX\owlery\xlate-g6-ep`), so fleet-daemon AGE has no shared-state route into the test. Only available coupling = RESOURCE CONTENTION from the daemon's post-restart resume storm — which also reconciles his withdrawn quiet-vs-load axis (load was real, source was the daemon itself, invisible to the quiet predicate — blind spot now banked in [[quiet-window-predicate]]). Instrument updated: script samples fleet spt CPU-seconds before/after each run, reports delta beside DAEMON_AGE. Curve discriminates: duration tracks CPU-delta ⇒ contention (4s deadline too tight under restart storm — test-budget fix, hertz lane); duration tracks AGE with flat CPU ⇒ genuinely the belt-death class. doyle's core ruling unaffected (independent evidence).

## SEED (emphasys filing, 2026-07-27, omp-spt F-035 — NOT claude-spt's F-035; core v0.45.0): --create spawn granted resume custody of prior sid, then refused its own bind — self-conflict wedges endpoint UNBOUND for the failed tree's lifetime
hertz relaunch: perch pid 35636/parent 28396 both dead+freed, stale `controlled:true`+`driven_by:<HFENDULEAM>` from a prior `spt rc drive` SURVIVED relay-death convergence; resume-custody.json named the NEW launch shim pid 41396 whose argv = fresh template ([session.self], no --resume) ⇒ OMP minted fresh sid. Log order: HOSTING_AUTHORITY_DEMOTED → RELAY_DEATH_CONVERGED (35636 provably gone) → WAKE_RESUME resuming PRIOR sid under pid 41396 → extension bind with fresh sid REFUSED `CONFLICT: live under session <prior>`. Self-sustaining ~17min until failed tree died (CONTROL_REAP_NO_SESSION → DRIVEN_BY_SELFHEAL_OFFLINE → LIVENESS_RECONCILE_OFFLINE). Negative controls (same core/adapter/node, throwaway endpoint): graceful stop→rebind clean; taskkill /T /F→rebind clean; bare api bind w/ dead owner → dead-owner re-pin WORKS on 0.45.0. Differentiator = stale controlled/driven_by. Asks on record: (a) --create/[session.self] spawn must not inherit resume custody of stored sid; (b) or bind from custody-holder pid = owner, re-pin to incoming sid; (c) reap stale controlled/driven_by AT convergence, not later sweep. Full writeup omp-spt docs/SPT-CORE-FINDINGS.md F-035. **Sits exactly on registry PR #101's seam (REQ-RELAY-DEATH-CONVERGENCE + REQ-CREATE-BIND-REST-ACTIVE, builder todlando queued) — fold as acceptance evidence when that wave opens.** No adapter-side workaround (workaround would kill the process being refused).

**⭐ G6 AXIS-3 FIRST QUANTITATIVE SIGNAL 2026-07-27 18:15 (todlando — GREEN sample, but the DURATION is the finding).** Daemon bounced 18:09:04; session resumed through the DAEMON_RESTART_RESUME path under test and the wake ate the window, so the run landed at **DAEMON_AGE_AT_START 364.9s** — ~2 min PAST the agreed ~4-min bound, self-labeled a CONTROL by the script's own stamp (that self-labeling is why the log can't be misread later — keep that pattern). Result: 19/19 green, predicate-clean (`nonterminal_ci=0`, no local builds, blob `db671472` verified stock). **BUT g6's own duration was 2.162s against 0.686-0.847s across ALL NINE prior samples — ~3x the previous maximum, far outside the observed spread — and the gate's deadline is 4s.** So: closer to restart ⇒ slower respool ⇒ nearer the wall, exactly the direction axis 3 predicts, and at ~4 min it plausibly crosses. **This converts axis 3 from "last surviving guess" into a hypothesis with a MEASURABLE DOSE-RESPONSE: the discriminating quantity is g6's duration vs daemon age, not merely pass/fail.** Next restart, capture BOTH — and prefer several samples across ages (1, 2, 4, 8 min) over one in-window pass/fail, since a curve is falsifiable where a single red is not. ⚠ Single sample, no repeat yet; do not bank the 3x as a rate. ⚡ Still armed: `pwsh -File C:\Users\decid\Documents\projects\spt-core\.worktrees\g6-postbounce.ps1` (any restart, any cause). ⭐ Standing constraint learned the hard way: an agent CANNOT manufacture this trigger — agent-driven daemon stop is forbidden on this box (stop kills the issuer), and resuming through the bounce costs ~2 min of the window, so a genuine sub-4-min sample needs the operator bouncing while the agent is ALREADY AWAKE with the command staged.

**📌 TODLANDO NEXT-WAVE FOLD 2026-07-27 (doyle dispatch, for the #101 W0-survivor wave).** The 09:36-15:35 node-wide idle-delivery outage is **REQ-RELAY-DEATH-CONVERGENCE's canonical field case** — fold it as ACCEPTANCE EVIDENCE when that leg opens, with the 18:09 daemon-health verify (perri's + doyle's) as the field leg. doyle's mechanism (source-read, candidate-strong): `relay_present` = registry `resolve_address().is_some()` — **a ROW, not liveness** (livehost.rs:580); belt skips on it (BELT-1 :545); every inject entry gates on `is_spt_hosted_no_relay`; `ENDPOINT_INJECT` prints only on the inject path so **the relay path is silent BY DESIGN** (that silence is why the sick brain logged zero inject-class lines — it was skipping, not failing). The 09:36 drop + resume-at-bind left dead-relay rows for all 8 endpoints, and 0.44.0 had NO relay-death convergence (shipped in #107/0.45.0), so rows never cleared ⇒ node-wide belt-skip + sends-to-dead-relays-spool ⇒ perri's queued-not-dropped + drain-at-wake. **⚠ SCOPE QUESTION TO RESOLVE BEFORE BUILDING THE LEG: if the impl already shipped in #107/0.45.0, then this leg is NOT new impl — it is activation + int evidence pinning the convergence against this exact field shape (dead-relay row survives a resume-at-bind ⇒ must clear ⇒ belt must not skip). Confirm with doyle rather than building impl that exists.** Kin: the g6 axis-3 curve (same restart-adjacent territory, different mechanism — do not merge them).

**✅ SCOPE QUESTION ABOVE — ANSWERED 2026-07-27, AND THE PREMISE WAS STALE IN THE GOOD DIRECTION (doyle, ground-truthed against origin/main).** There is **NO build leg on #101 — do not scope one.** BOTH W0-survivor REQs are already BUILT AND ACTIVATED, by me, in **PR #107** (my own ft-w1w0 branch, merged in the sweep): `REQ-RELAY-DEATH-CONVERGENCE` + `REQ-CREATE-BIND-REST-ACTIVE` sit in traceable-reqs.toml with `required_stages ["impl","unit","int"]`, tags landed at livehost.rs:739 · liveness.rs:217 · info.rs:270/439 · startup.rs:231, units incl. the verdict table at liveness.rs:412 + proc.rs:1143, ints at endpoint_lifecycle.rs:268 + create_bind_rest_active_e2e.rs. **⭐ So the 09:36-15:35 outage was fixed by my build BEFORE doyle finished diagnosing it — the shipped 0.45.0 convergence IS the remedy for the field case he was reconstructing.** The "two survivors stacked on #101" note is RETIRED as stale. What remains on this seam, **none of it mine**: (1) emphasys's omp-spt F-035 tail (convergence leaves stale `controlled:true`/`driven_by`; grants resume custody of the stored sid to a fresh `--create` spawn then self-conflicts its bind) — genuine NEW defect on the shipped seam, doyle mints at wave-open; (2) OPTIONAL int pinning convergence against the RESTART-RESUME shape specifically — existing int covers relay-child-killed-under-live-owner, NOT resume-at-bind; test-only ⇒ **hertz's lane** per the dispatch split; (3) belt-liveness observability seed, unminted. **⭐ LESSON: I nearly scoped a build leg from a queue note instead of from the registry. Ground the work item against traceable-reqs.toml + origin/main BEFORE scoping — a stale queue entry reads exactly like an open leg.**

**⭐⭐ CONVERGENCE GAP ATTRIBUTED 2026-07-27 (todlando, source-read + LIVE record on 0.45.0 — doyle's prime suspect FALSIFIED, real root found).** doyle filed: emphasys renders alive 25+ min with recorded relay pid 44160 DEAD, parent 43192 DEAD, `status=online`, birth stamp present. **ROOT: `controllable=true` is INHERITED ACROSS LIVES, and the reconcile sweep uses it to ROUTE WHICH LIVENESS MODEL APPLIES.** Chain, all cites origin/main @f7ff68f: (1) `resolve_controllable` (spt/src/api/startup.rs:198) — `BrokerPty ⇒ Some(true)`, while `ListenerOnly`/`NonAgent` assert nothing and CARRY THE PRIOR VALUE FORWARD (that is REQ-LISTEN-PRESERVES-HOSTING-TOPOLOGY working as DESIGNED); (2) emphasys earned `Some(true)` in an earlier broker-PTY life, and its 18:14:20 wake re-bind was listener-only, so **the stamp survived into a life that never earned it**; (3) the sweep gates convergence on `if !is_unbound && info.controllable != Some(true)` (spt-daemon/src/livehost.rs:883) ⇒ `converge_dead_relay` IS NEVER CALLED for this row; (4) the broker-session arm cannot heal it either — surviving `controlled=true` PROVES `has_session` was true, since `CONTROL_REAP_NO_SESSION` clears that field otherwise, so `if !has_session` never fires. **Row is exempt from BOTH models.** The REQ's own oracle would have been right: both pids `Absent` + birth stamp present ⇒ `relay_liveness ⇒ Gone` (spt-store/src/liveness.rs:217). It was never asked. **FALSIFIED: last_active recency** — `last_active` appears NOWHERE in the reconcile path (only the pulse driver + tests), so the CLI-active theory is dead; emphasys is singled out because it is the one endpoint that lived as broker-PTY BEFORE becoming listener-hosted. **⭐ CLASS: a claim keyed on the wrong thing — same family as the HARNESS-HOST-LIVENESS root (`is_perch_alive` treating a status field as topology). Here an INHERITED CAPABILITY STAMP routes a LIVENESS PROOF.** FIX SHAPES for doyle to rule: **(a) NARROWEST — ask the oracle FIRST, independent of the routing key**: a numeric recorded pid + birth stamp reading `Gone` converges regardless of `controllable`. Safe *because* `relay_liveness` routes through `process_identity` (process TABLE, handle-immune), NOT `is_process_alive` — the livehost.rs:828 warning about relaxing the gate applies to the `is_process_alive` probe in `hybrid_self_heal_due`, a DIFFERENT predicate. ⚠ CHECK BEFORE ADOPTING (a): for a genuine broker-PTY row, is `info.pid` the listener pid or a broker-spawned child? If the latter, a dead child could converge a row whose session is still live. **(b) SCOPE THE CARRY-FORWARD** — `Some(true)` should not outlive the life that earned it (carry forward only while the earning pid lives). **(c)** route on current-life evidence rather than the stamp. Kin [[unbounded-brain-carrier-cannot-be-bounded]] (fix the constructor, not the caller) — (b) is the constructor-side fix, (a) the caller-side.

## Seed queue additions 2026-07-27 ~20:3x (doyle, post-emphasys-recovery drain)
- **SPT_HOST_PID scrub on resume-at-bind respawn** (perri ask 2026-07-27): resume re-applies saved env verbatim ⇒ every resumed session carries a stale dead SPT_HOST_PID (bit perri's foreign-host gate node-wide after the 18:09 bounce; adapter no longer depends on it, residue worth killing at source).
- **psyche-download conformance warning** (deployah seed, ACCEPTED): core sees non-empty tracked mind + no psyche-download on the bound sid ⇒ one-line bind-time stderr notice (preferred) and/or `spt adapter doctor` check. Detects the silent-amnesia class that cost hertz weeks (omp-spt never called the verb; fixed in omp-spt 0.3.32).
- **adapter-update orphan GC** (deployah seed, ACCEPTED): update replaces in place, never removes de-shipped files — emphasys's install dir held 3 generations + a foreign claude-spt.exe INSIDE the {adapter_dir} resolution surface (SHELL-LAUNCH-TRUTH trap class).
- **pre-push repeat-proof guard needs a mechanism** (deployah self-report: pushed onto #114 mid-leg, cancelled his own repeat-proof leg 1 hours after naming that exact failure in my lane): "nothing pushes to a ref while a repeat-proof leg runs on that ref" belongs in a check before `git push`, not in memory.
- **#114 repeat-proof state**: leg 1 = run 30325300905 @7978158 (substituted after the cancelled original); red ⇒ 2nd sighting of registry_lifecycle oneway_rounds_plateau... on a #107-touched seam ⇒ hertz as defect; green ⇒ one green + one lost leg, not flake-closed.

## Ring-fix leg rulings 2026-07-27 ~21:0x (doyle; builder todlando, next after #116)
- Refusal predicate RULED (todlando counter-shape accepted): "dir exists AND carries a record or spool" — NOT bare create_new (a crashed ring's stale EMPTY dir must not become a permanent silent ring-refusal). Riders: unreadable/corrupt record = OCCUPIED (fail-safe; deletion irreversible, refusal recoverable; unit-pin garbage info.json ⇒ RING_PERCH_EXISTS untouched); stale-EMPTY dir may self-heal (only shape provably ring's own residue). Byte-identical survival unit includes spool.db explicitly.
- ⭐ deployah corollary RATIFIED: ONE wrong liveness question asked TWICE — claude-spt NO-PERCH brief selection uses the same ready-marker-class predicate and served him the "use spt ring" brief while his perch was ONLINE (field specimen, his transcript). The agent most likely handed the ring instruction is the one ring destroys; advisories can't reach fresh sessions whose start-up brief says ring. Routed: perri owns consumer interim (de-advertise ring in no-perch brief or inline advisory) — asked 21:0x; brief-selection predicate deserves the same record-or-spool probe (non-urgent, perri's).
- #114 GATE PASS given (leg-1 green + consumer-proof: emphasys built 0.3.32 from those pages); repeat-proof accounting stays 1-green-1-lost, sighting 2 → hertz.
- #114 MERGED @e165f71 (2026-07-27 ~21:1x). deployah board CLEAR (c80 + #113 + #114 done). Sole outstanding operator action: hertz `spt adapter update omp-spt` + endpoint restart for 0.3.32 (first resume thin = pipe working). perri specimen detail forwarded (same-session ONLINE perch served no-perch ring brief; deployah's transcript, citing authorized).
- RING RULING AMENDED (2026-07-27 ~21:2x, emphasys counter-shape ADOPTED): self-heal rider REVOKED — ring deletes NOTHING it did not create this invocation (empty dir ≠ provably ring residue: endpoint-run mid-create window). Refuse ALL pre-existing dirs, two loud diagnostics: RING_PERCH_EXISTS (record/spool) vs RING_STALE_DIR (empty; names path+remedy). Unit: mid-create race (empty dir ⇒ refuse ⇒ dir survives). Rationale upgrade: hosted-OMP marker-down = NORMAL steady state (extension owns listener, busy/idle via api state) ⇒ marker-first misjudges ROUTINELY. Third predicate face: docs/CI.md acceptance told operator to ring "from a second terminal" — perchless load-bearing unstated; emphasys warned it @7fe7aa7 (docs-only), remove post-fix.
- SEED (emphasys 2026-07-27 ~21:2x, psyche-download cwd-divergence): project tier keys off perch cwd; hertz's perch recorded bare Documents/projects ⇒ tier resolved to empty "projects" key while real github-com-bigscreenvr-spt-bs-core tier sat unread; session minted divergent wrong-key tier silently. FIXED operationally (operator relaunched hertz from repo). MINT SHAPE: core warns when an endpoint's cwd resolves to a non-repo project key WITH no prior context WHILE a repo-keyed tier for the same agent exists — that's the silent shape. Kin: [[omp-spt-psyche-download-gap]].
- **#116 MERGED @bfb555f (2026-07-27 ~21:3x)** — pid-role stamping (fixes inherited-controllable liveness misrouting). Gate: 6/6 green + both negative tests name-verified both OSes. **#117 OPEN (ring perch-adoption, todlando @52b4d70)** — REQ-HAZARD-RING-PERCH-ADOPTION minted in-PR + KH 3.4; ⭐ red-first proof exposed SECOND defect face: ring's reply-wait drain_one_at STEALS the victim's spooled mail into the ringer's reply render BEFORE deletion (two-part loss). ⭐ emphasys self-camouflage rationale: damage mimics the ghost-roster condition ring is used to diagnose ⇒ liveness debuggers are its likeliest victims. Gate holds behind #116's main-baseline run; my gate = CI green + by-name on the 4 new units.
- perri closures: claude-spt **0.25.24** de-advertises ring (advisory inline; reinstates post-#117); brief-misfire root = REQ-HAZARD-STALE-ANCHOR-REFUSAL fixed **0.25.22 @19:45** (deployah specimens 19:40/19:41 predate; zero refusals since 19:46:13). Convergent shape: anchor-pid liveness = same stale-signal-read-as-absence class as ring's predicate.
- **#117 MERGED @9d7af01 (2026-07-27 ~22:3x)** — ring perch-adoption fix ON MAIN (REQ-HAZARD-RING-PERCH-ADOPTION + KH 3.4). Gate: 5 units by name both OSes; g2 wedge red closed as load-family (1st g2 sighting, at-sha green, todlando load-direction corroboration; ledgered distinct from g6). ⏳ RING BAN STAYS until next RELEASE ships the binary (installed CLI = 0.45.0 pre-fix); perri holds 0.25.24 ring-withdrawal until then (reinstate condition = shipped binary, ping him release number at publish); emphasys's CI.md warning 7fe7aa7 comes out same release. Incident arc: perch eaten ~19:15 → recovered 19:49 → root cause ~20:5x → fix merged ~22:3x, same evening.
- 📌 WATCH (2026-07-27 ~23:2x): `resume_no_control_steal_e2e::brain_respawn_keeps_every_session_controller_and_still_promotes` Win/hfenduleam red 2x-in-run at IDENTICAL 1.258s on #117's merge run, then GREEN at-sha (leg 1). NOT flake-closed — 1 sighting stands. Signature = PROCESS-LEVEL DEATH (bare exit, no panic banner, dies ~1.3s in after 3 controller-attaches; before any test deadline) — external-termination family, pid-reuse cross-test kill on suspect list; todlando's static read exonerates #116 mechanism (role gate = strict narrowing; startup.rs not in path). 2nd sighting anywhere ⇒ todlando bench, discriminator = child exit status + panic-banner-existence FIRST, seam second. Main verified @9d7af01 (fix pair #116+#117 both on green main).

## [root-merge 2026-08-23] lines present only in the .claude copy (union-merged at alt-profile migration; placement lost, content verbatim)

**⭐⭐ FAMILY RE-ROOTED 2026-07-22 (deployah third-run analysis, doyle-ratified): NOT N flaky tests — ONE environmental cause picking a RANDOM victim per run: CI executes on the host that runs the live agent fleet.** Evidence: #56 runs 1/2/3 killed a DIFFERENT single daemon-spawning test each time (brain_decouple ×2 starved-disk → adapter_translate → adapter_digest at 105.9 GB free) while sibling tests in the same families passed alongside; victims die PROCESS-LEVEL (bare exit 1, no assert output — same signature as the fork + broker-reap watch-items below); box census during runs: 43 live spt-family processes (29 spt / 12 claude-spt / omp-spt / spt-mobile-host), 6486 handles, vs 1881 tests Phase-A full-parallel many spawning daemons/binding endpoints. Kin hazards realized: [[e2e-leaked-daemons-shared-box]], [[seedmap-test-collides-live-daemon]], [[hfenduleam-hosts-flynn]]. WAVE SHAPE REORDERED (cause-side first): (1) leaked-test-daemon sweep mechanism (scoped to test/temp exe paths — never machine-wide) + census tooling; (2) Phase-A parallelism cut on the Windows leg (ci.yml/nextest — deployah option c, ratified); (3) OPERATOR DECISION REQUEST: CI runner off the agent-fleet host (option d — census + run table attached; same host also just took the disk escalation); (4) member hardening (bounded-poll rigs etc.) only for members that STILL red after cause-side legs. Member-by-member hardening alone = chasing casualties, family never closes. Acceptance stays looped-repro per member. RELEASE-CYCLE MITIGATION used for v0.40.0: quiesce-partial window (scoped leaked-daemon sweep + all-agents-hold + single watched rerun) — doyle-ruled, reusable shape. Individual member entries below stand as evidence records.** The four: (1) fork_forks_homes (Win, bare exit-1, no body); (2) broker::a_reap_clears_control_stamps (Win, no body captured); (3) shell_e2e teardown Directory-not-empty (Linux, os 39); (4) endpoint_autostart_e2e::saved_endpoint_replays (Win CI, session-id freshness assert at 44s — replay's fresh-session stamp lost a timing race under Phase A full-parallel; #55 merge run 29890856839). All: green isolated/rerun, none in the wave's changed seam, all under saturated parallel load. Read: heavy e2e rigs (and possibly product paths) carry timing assumptions that only hold on an unloaded box. Wave shape when activated: per-rig bounded-poll instead of fixed-window reads (the registry_lifecycle 2026-07-19 hardening shape), teardown reap-writers-first, and a triage pass distinguishing rig-race from product-race (autostart #4 needs that discrimination FIRST — a session-id stamp racing a reader could be a real product ordering hole). ACCEPTANCE (deployah rider 2026-07-22, doyle-ratified, = the v0.36.0 lesson): each family member closes on LOOPED-under-load repro-then-green, never on a single rerun-green. Operator decides queue placement.**
