=== REQUIREMENTS REFERENCED IN PAIRS === REQ-ACTIVITY-INFO-PULL TITLE: The endpoint's current activity state (busy|idle) is readable via `spt api endpoint-info` — a point-in-time read of the perch idle sentinel, for consumers that need a check rather than a stream (ADR DOC: 1. Activity observation is a first-class surface with two avenues — and the digest is not one of them: REQ-ADAPTER-FLOOR-ENFORCE TITLE: F-5 (REMOTE-TRUTH triage §F-5 + doyle rulings 2026-07-05): BOTH adapter acquisition verbs (spt adapter add + spt adapter update) REFUSE when the installed spt-core is BELOW the adapter's declared [ad DOC: `[adapter]` — header: `min_spt_core_version` is the **enforced** compatibility floor. Both acquisition verbs — `spt adapter add` and `spt adapter update` — REFUSE when the installed spt-core is below this version, naming the installed core, the floor, and the next action (update spt-c REQ-ADAPTER-GH-TRANSPORT TITLE: The `gh_release` avenue (and `spt adapter add --release`) gain a fetch `transport`: `https` (current reqwest direct, public), `gh` (shell the pre-authorized `gh` CLI — the private-repo path; `gh` ho DOC: Runtime model: **adapter packaging & live update** (v0.13.2; ADR-0024, ADR-0025): A `.spt` may be **multi-platform**: shared `manifest.toml` + `strings/` at the root, role binaries under per-target-triple subdirectories (`x86_64-pc-windows-msvc/`, …); install/update extracts the shared ro REQ-ADAPTER-MULTIPLATFORM-SPT TITLE: A `.spt` adapter archive may pack multiple platforms in one signed asset: shared `manifest.toml` + `strings/` at the root, role binaries under per-Rust-target-triple subdirectories (ADR-0016 triple vo DOC: Multi-platform adapter `.spt` packaging: REQ-ADAPTER-UPDATE-MESSAGE TITLE: An adapter manifest may declare `[update].message` — a plain (multi-line) human notice surfaced to stdout, markdown-rendered (the v0.13.0 helpfmt prose path), ONLY when `spt adapter update` actually DOC: Runtime model: **adapter packaging & live update** (v0.13.2; ADR-0024, ADR-0025): A `.spt` may be **multi-platform**: shared `manifest.toml` + `strings/` at the root, role binaries under per-target-triple subdirectories (`x86_64-pc-windows-msvc/`, …); install/update extracts the shared ro REQ-API-3 TITLE: commune/signoff are file-drops, not commands REQ-ARCH-1 TITLE: Many small acyclically-layered crates REQ-ARCH-2 TITLE: Public SDK surface is spt-proto, spt-runtime, spt-msg REQ-ARCH-3 TITLE: Wire-protocol version independent of crate semver, N-1 compat window REQ-ATTACH-IDEMPOTENT-REPLAY TITLE: The equal-generation lease rung is idempotent for the same connection. (ADR-0047 decision 3, AMENDING ADR-0044's ladder inside the equal-gen rung; hertz v0.39.4 field bug 4, PINNED via OBS breadcrumbs DOC: 3. The equal-generation rung is idempotent for the same connection: REQ-BIND-HONEST-SELF-STAMP TITLE: C2-ROOT (F028, doyle RCA 2026-07-03): the identity-attribution ROOT behind REQ-SESSIONS-LOG-ENDPOINT-ATTRIBUTION — three composing defects let a psyche-hosted SessionStart hook stamp a FOREIGN perch REQ-BOUNDARY-ROTATION-CREDENTIAL TITLE: api boundary's rotation credential is designed, documented, and eventually anchor-proven (ADR-0032): the proof is the DEPARTED session's (prior sid / token) — --to-session-id is payload, never proof DOC: `api boundary --to-session-id --session-id `: // Boundary rotation credential: the departed-session catch-22 and the parent_pid anchor: REQ-CARRIER-CLAIM-EXCLUSIVE TITLE: MSG-IDENTITY W4 / F-033 + operator self-send probe 2026-07-09 (dup-delivery cluster, RCA-FIRST): a spooled message row is delivered by EXACTLY ONE carrier — the first carrier to take a row (hook-pol REQ-CLI-2 TITLE: spt daemon noun: run|stop|status (hidden daemon verb becomes daemon run; agent-endpoint shutdown keeps its name under endpoint); daemon status renders the pump heartbeat (last-tick recency) so a half- REQ-CLI-3 TITLE: Agent hot path stays flat across the M8 reorg: send/ring/ready/whoami/how-to unchanged; notify moves to subnet notify while notif stays top-level; breaking renames land clean with no deprecation shims REQ-CONN-POISON-ATTRIBUTION TITLE: MSG-IDENTITY W6 / F-039 legs b-d (doyle W6 LOCK 2026-07-10, minted per amendment 3): every broker-conn lifecycle record is ATTRIBUTABLE — the W6 RCA's terminal undecidability (per-line 1:1 CONN_WRIT REQ-CONTROL-STAMP-CONVERGENCE TITLE: REGISTRY-LIFECYCLE W2 (ADR-0041 decision 4, emphasys C3 P1): control-stamp writes are session/generation-VALIDATED (or per-endpoint stamp transitions serialized) so a pre-reap KIND_SESSIONS snapshot c DOC: Decision: 1. **Online is earned, not declared.** A creator may stamp `status=online` only from actual persisted state + hosting authority — never from manifest capability alone. Legacy hybrid rows self-heal at reconcile, but only after a SUCCESSFUL broker query: a broker failure is never REQ-CONTROLLER-LEASE-IDENTITY TITLE: RC-RENDER-TRUTH W2 (ADR-0044 decisions 1+2, hertz same-machine --take split-brain RCA P0-A/B, doyle seam-verified broker.rs resolve_subscribe 1296-1318 + 1334-1347): each rc invocation/attach stream m DOC: Decisions: 1. **Distinct viewport/lease identity.** Each rc invocation/attach stream mints a unique controller lease id, carried through SubscribeReq, the controller slot, and Input/Resize. Node identity is kept separately for display/access policy. The ONLY silent successor/replay case is REQ-CONTROLLER-LIVENESS-REAP TITLE: B-2 (REMOTE-TRUTH triage §B-2, REDUCED @bdc1242): a stale ONLINE+CONTROLLED stamp on a live-session perch self-heals — the info.json driven_by/controlled RECORD is made to match the broker's SINK-T REQ-CONV-2 TITLE: Event-driven advertisement: endpoint online/offline transitions (ready-listener start/stop, rest-state transition, perch death) trigger an immediate advertise_local + peer push as a WAKE of the existi REQ-DAEMON-2 TITLE: Broker/brain split for seamless self-update DOC: Restoration field-run evidence (D7-4) — the seamless-update acceptance: REQ-DAEMON-9 TITLE: Net-bind boot-race resilience: a daemon that comes up net-less (NetHost::start failed — e.g. the systemd unit autostarted before the network/DNS stack was ready, `Failed to create an address lookup REQ-DAEMON-BITS-AMBIGUITY TITLE: SEED (inactive, RCA-first — do NOT close on agreement): nothing on a node surfaces WHICH BITS ARE SERVING, and the same silent wrong-state shape bit twice in one day (2026-07-25). Case 1 (adapter-si REQ-DAEMON-REFRESH TITLE: THE-FORKENING W4 (operator add 2026-07-14): `spt daemon refresh` — restart the daemon BRAIN without a binary swap and WITHOUT touching the broker: exactly the apply_staged brain-cycle path (brain st DOC: Self-update: **daemon refresh (`spt daemon refresh`)** — restart the **brain** in place, no binary swap, broker and every held PTY untouched: the routine-update handoff path minus the swap. The recovery verb for wedged brain-held state (broken endpoint bringup, a downed hosted agent) that previous REQ-DOCS-6 TITLE: spt how-to : in-binary task-oriented agent instructions (anti-drift; quickstart prompts point agents at it) DOC: Quickstart: two agents exchange a message: ### v0.38.1 consequence note — `driven_by` own-node truth (ruling v3) REQ-ENDPOINT-AUTOSTART TITLE: MSG-IDENTITY W5 / F-038 (flynn operator-directed ask 2026-07-10, SPT-CORE-NEEDS #7 + deployah field-confirm same day: mobile-gw alive=false after the v0.30.6 full daemon restart = this feature's absen DOC: Startup defaults (`endpoint run --save`): Infrastructure endpoints (a gateway the phone treats as always-there) should not need hands-on bringup after a box reboot or daemon restart. `spt endpoint run … --save` persists the run — endpoint id, adapter option, and working directory — as REQ-ENDPOINT-CYCLE-HONEST TITLE: REGISTRY-LIFECYCLE W3 (ADR-0041 decision 6, operator deployah stop/run wedge): cycle verbs share ONE liveness authority — the ALREADY_LIVE dup-guard liveness-probes the claimed session client tree b DOC: Decision: 1. **Online is earned, not declared.** A creator may stamp `status=online` only from actual persisted state + hosting authority — never from manifest capability alone. Legacy hybrid rows self-heal at reconcile, but only after a SUCCESSFUL broker query: a broker failure is never REQ-ENDPOINT-LIST-MERGE-LOCAL TITLE: `spt endpoint list` always merges this node's LOCAL (unadvertised) perches into the view; the `--local` flag is REMOVED (operator decision 2026-06-17). Rationale: `spt whoami` is a thin alias of `endp DOC: **endpoint list always merges local perches**: `spt endpoint list` (and therefore `whoami`) **always** appends this node's **LOCAL perch roster** as a trailing section, in addition to the SELF pin and the subnet groups. The subnet groups are the WAN registry snapshot, which lags a just-boun REQ-ENDPOINT-LIST-RENDER-POLISH TITLE: A6 (F028, operator, 4 asks): `spt endpoint list` render polish. (a) the 'Shared subnets' line is NOT dim — LIGHT_GRAY = "37" (cli.rs:3019) is standard-palette WHITE, indistinguishable from row text; REQ-ENDPOINT-ONLINE-TRUTH TITLE: REGISTRY-LIFECYCLE W2 (ADR-0041 decisions 1+2, emphasys C1 P0): ONLINE is earned, not declared — cmd_listen stamps status=online only from actual persisted state + hosting authority, never from mani DOC: Decision: 1. **Online is earned, not declared.** A creator may stamp `status=online` only from actual persisted state + hosting authority — never from manifest capability alone. Legacy hybrid rows self-heal at reconcile, but only after a SUCCESSFUL broker query: a broker failure is never REQ-ENDPOINT-STOP-OFFLINE TITLE: H3: `spt endpoint stop ` marks the endpoint OFFLINE (alive=false), not merely de-readied. cmd_stop (cli.rs:2994-3010) removes the ready marker + unregisters the address but does NOT set status off REQ-ENDPOINT-UNBOUND-ATTACH TITLE: An spt-hosted endpoint is ATTACHABLE between spawn and bind: gate the attach on the broker SESSION being attachable (session+PTY+OutputLog exist at spawn, before bind), not on perch STATUS_ONLINE (bin DOC: Pieces the Instances model requires: **Unbound endpoint**: The lifecycle point between *spawn* and *bind*: an spt-hosted endpoint whose broker **session + PTY are live** but whose harness has **not yet bound** its perch (the *post-spawn seam* hasn't fired — e.g. the harness is waiting on REQ-EP-1 TITLE: Day-one endpoint types; open type system REQ-EP-2 TITLE: Agent endpoints vs Shells distinction in the type model REQ-EP-5 TITLE: Concrete shell instantiation model: spawn-mints-instance (vs relink/online), registered-on-node permission + broadcast-is-discovery, per-shell require_approval gate, max_instances_per_owner + over_cap REQ-EP-6 TITLE: Gateway type acceptance: a Gateway-typed perch binds (api bind --type, open type system — un-hardcode the live_agent default), advertises/addressable like any endpoint, owns shells (owner validation DOC: Endpoint types: **Gateway** (concept ratified 2026-06-11; registered via the open type system, first instance downstream): A **human-backed endpoint** — a user's specialized window into the subnet from a device or surface with no conventional-harness compatibility. Nothing LLM-shaped runs REQ-EP-7 TITLE: Durable live-role.md: a per-agent broad-purpose statement in tracked/agents// beside live-context.md (replicates with the mind on the same a- branch); renders FIRST at start-transition context DOC: Cross-node Psyche sync: **live role** (`live-role.md`, ratified 2026-06-12 — core milestone A): A durable statement of an agent's **broad purpose** — rarely modified, and only at deliberate user instruction. Lives in `tracked/` (the mind) beside `live-context.md`, so it replicates with REQ-GOSSIP-CONTROLLED-ANY TITLE: Bug #3: a locally-controlled endpoint gossips controller_node = None so remote viewers show it free to control. Root: driven_by is stamped Some(node) only for a REMOTE WAN attach (attach.rs:337); a lo REQ-HAZARD-ADAPTER-APPLY-SILENT-NOOP TITLE: A DELEGATED live adapter apply MUST NEVER report success without performing the swap, and the live-update seam MUST use ONE parent-aware adapter matcher across all its comparators. TWO defects made th DOC: 7.23 A message that has REACHED a node's spool must NEVER depend on an adapter hook-poll cadence to reach an spt-hosted (relay-less) endpoint — the daemon drives delivery on the events it owns `[REQ-HAZARD-DELIVERY-STARVATION]`: ### 7.24 A delegated live adapter apply must NEVER report success wit REQ-HAZARD-BIND-REST-STATE-CARRY TITLE: GATEWAY-LIVENESS DEFECT A (flynn field bug 2026-07-09, confirmed independent): a re-bind MUST preserve the daemon-owned resting intent (rest_state, D9-2/REQ-INST-3) — the same carry-forward discipli REQ-HAZARD-BRAIN-RESPAWN-PATH TITLE: The broker respawns the brain onto the APPLIED bytes, not the renamed old binary: the candidate-binary default is the canonical exe path captured ONCE at broker start, never a per-spawn std::env::curr DOC: 6.10 Phase-significant loop timing must be a durable absolute-deadline grid, not phase-relative sleep `[REQ-HAZARD-BROKER-PROCESS-ISOLATION]`: ### 6.11 Brain respawn must exec the APPLIED bytes, not the renamed old binary (Linux `current_exe` follows the apply-rename; readiness ≠ new-bytes) `[REQ- REQ-HAZARD-BRAIN-RESTART-LIFECYCLE-REHYDRATE TITLE: B4 (deepest): a bare brain restart (broker survives) REHYDRATES the live-agent lifecycle so post-restart endpoints are hosted + attachable. Today resume_sessions (brainproc.rs:186, brain.rs:797-809) r REQ-HAZARD-BRAIN-RESTART-PSYCHE-DUP TITLE: A bare brain restart leaves EXACTLY ONE `{id}-psyche` process per endpoint — no duplicate. On an abrupt brain death stop_host never runs (the LiveSet + owned child handles die with the brain) and Br REQ-HAZARD-BROKER-QUIC-DEADLINE TITLE: The broker bounds every brain-waiting QUIC op (dial / open_stream / send_stream) so a black-holed or dead peer fails PROMPTLY with an ORDINARY error the broker REPLIES, never an unbounded await. The b DOC: 7.7 A slow/dead/hostile remote VIEWER must never stall the controller, child, or drain `[REQ-HAZARD-VIEWER-ISOLATION]`: ### 7.8 The broker must never make a brain wait UNBOUNDED on a QUIC op (the pump-IPC-deadline B-half) `[REQ-HAZARD-BROKER-QUIC-DEADLINE]` - **Failure:** the broker's brain REQ-HAZARD-BROKER-SEED-WIRE-SKEW TITLE: A daemon-state wire-format change (e.g. the v0.9.0 adapter-agnostic Seed) does NOT take effect until a DELIBERATE full broker restart: the broker serves the seed-control channel and is RESIDENT across DOC: 7.8 The broker must never make a brain wait UNBOUNDED on a QUIC op (the pump-IPC-deadline B-half) `[REQ-HAZARD-BROKER-QUIC-DEADLINE]`: ### 7.9 A daemon-state wire change needs a deliberate BROKER restart (the broker is resident across a brain self-update) `[REQ-HAZARD-BROKER-SEED-WIRE-SKEW]` ### 5.8 Console children of the console-less daemon flash visible windows `[REQ-HAZARD-CHILD-CONSOLE-FLASH]` - **Failure:** the daemon runs DETACHED (no console, 5.6/`detached_no_inherit`). Any REQ-HAZARD-CONPTY-DSR TITLE: ConPTY reader must auto-answer DSR (ESC[6n) or all child output stalls (5.5) REQ-HAZARD-CONTROL-STAMP-CONVERGENCE TITLE: Control/viewer stamps must CONVERGE to broker session-table truth for every session-backed endpoint, not merely edge-trigger — the UPWARD companion to the DOWNWARD edge-clear REQ-HAZARD-CONTROL-STAM DOC: 7.28 A relative manifest path resolves against the ENDPOINT, never the daemon `[REQ-STORE-CONTEXT-BRANCH-FILL]`: ### 7.29 Control/viewer stamps CONVERGE to broker session-table truth, not merely edge-trigger `[REQ-HAZARD-CONTROL-STAMP-CONVERGENCE]` - **Failure (F-026 stamp-gap, hall-b + the REQ-HAZARD-CONTROL-STAMP-LIFETIME TITLE: #2: a control/viewer stamp never outlives its session — every teardown path clears what attach stamped. The broker exit-waiter (broker.rs ~:1844) sends the exit frame + sessions.remove(&id) but does DOC: 7.26 Concurrent first-touch of ONE fresh BranchStore must ALL succeed — a non-atomic `git init` race must never strand a first-toucher `[REQ-HAZARD-STORE-INIT-RACE]`: ### 7.27 A control/viewer stamp must NEVER outlive its session — every teardown path clears what attach stamped `[REQ-HA REQ-HAZARD-CONTROLLER-GAP-RESUME TITLE: A serving CONTROLLER whose serve-brain hits a b4 drop-don't-block FORWARD output gap must RESUME-FROM-FLOOR (re-subscribe from delivered_through and re-fetch the dropped frames from the ring), NOT sna REQ-HAZARD-CONTROLLER-LEASE TITLE: RC-RENDER-TRUTH W2 (KNOWN-HAZARDS 7.48 — umbrella conformance seam for ADR-0044): at most one input-capable controller lease per PTY session; takeover revokes atomically and loudly; input is fenced DOC: 7.47 The physical terminal is never mutated or terminated outside its renderer's ordered state model — output before exit, owned baselines, unconditional teardown `[REQ-HAZARD-RENDER-LIFECYCLE]`: ### 7.48 At most one input-capable controller lease per PTY session — takeover revokes atomically an REQ-HAZARD-DAEMON-STOP-BARRIER TITLE: B3: `spt daemon stop` then an immediate `spt daemon start` does NOT race — stop fully completes before it returns. Today request_stop (seedmap.rs:240-255) returns on the KIND_STOPPING ack (sent seed REQ-HAZARD-DEFERRED-DRAIN TITLE: Deferred spool rows excluded from the event-stream drain (1.4) REQ-HAZARD-DEFERRED-MANIFEST TITLE: A pointer-mode (delegated / GhReleaseManaged) adapter whose binary/manifest is not yet extracted is reported with a CLEAR diagnostic, never silently dropped. Today such an adapter reads its manifest L REQ-HAZARD-DEFERRED-SURVIVE-DRAIN TITLE: Deferred rows survive poll drain (4.4) REQ-HAZARD-DELIVERY-STARVATION TITLE: A message that has REACHED a node's spool (WAN-arrived or locally spooled-while-active) is NEVER dependent on an adapter HOOK-POLL cadence for its eventual delivery to an spt-hosted (relay-less) endpo DOC: 7.22 An idle delivery with no working translation binary must SPOOL, never raw-inject a pseudo-delivery reported as delivered `[REQ-HAZARD-IDLE-SILENT-NONDELIVERY]`: ### 7.23 A message that has REACHED a node's spool must NEVER depend on an adapter hook-poll cadence to reach an spt-hosted (relay-les REQ-HAZARD-DETACHED-DAEMON-STDIO TITLE: A daemon DETACHED-IN-FACT (no interactive console, or an inherited stderr PIPE nobody drains) that never nulled its std handles will BLOCK on stdio writes when the pipe fills, and/or pop a visible con REQ-HAZARD-DIRECT-WRITE-PRECEDENCE TITLE: Direct-write precedence marker (with node id) guards stale overwrite (6.5) REQ-HAZARD-DRIVEN-BY-IDLE-REMOTE-EVICT TITLE: An spt-hosted endpoint driven by a REMOTE controller whose remote is gone but whose broker connection stays OPEN (a wedged/lost pump that never delivers the detach) AND whose session is IDLE (no outpu DOC: Amendment 1 (2026-07-22, DAEMON-LIFECYCLE W2) — teardown authority is opener-declared class PLUS transport liveness, enforced at the three places decision 6 could not see: REQ-HAZARD-DRIVEN-BY-SELFHEAL TITLE: An spt-hosted endpoint's ONLINE+CONTROLLED state (`driven_by`) must CLEAR even when the detach IPC is lost — do NOT rely on the detach signal (same lesson as REQ-HAZARD-HOSTED-LIVENESS-RECONCILE B2) REQ-HAZARD-DROP-FILE-SINGLE-WRITER TITLE: Drop files are daemon-owned single-writer (6.4) REQ-HAZARD-EBUSY-RENAME TITLE: tmp-write + atomic-rename + retry on Windows EBUSY (5.2) REQ-HAZARD-ECHO-BEFORE-SIGNOFF TITLE: Echo-commune fires before INIT_SIGNOFF on orphan teardown (3.3) REQ-HAZARD-ELEVATED-DAEMON-SPAWN TITLE: The daemon always runs unelevated in the invoking user's universe, regardless of which command spawns it: an elevated spawner de-elevates (Windows: UAC linked token via CreateProcessWithTokenW; Linux: DOC: 5.6 Windows detached children inherit a captured caller's pipe `[REQ-HAZARD-DETACHED-PIPE-INHERIT]`: ### 5.7 Elevated commands spawn the daemon with the wrong token `[REQ-HAZARD-ELEVATED-DAEMON-SPAWN]` - **Failure:** membership-implies-reachability made *every* `spt` invocation a potential REQ-HAZARD-ENVELOPE-CR-LINESAFE TITLE: Envelope CR-linesafety (4.1): the line-framed EVENT codec must neutralize raw carriage returns — `event_body_escape` folds CRLF/lone-CR to the codec's representable linebreak (`\n`→`
`) BEFORE DOC: Body and attribute encoding: **Carriage returns are unrepresentable.** The encoder normalizes `\r\n` and lone `\r` to `\n` *before* the `
` encoding, so no frame ever carries a raw CR and a decoder always receives `\n` newlines. Do not expect `\r` to round-trip — content that needs CRs REQ-HAZARD-ENVELOPE-PARSER-SAFE TITLE: Two-slice envelope parser is panic-free and tolerant (4.2) REQ-HAZARD-EPHEMERAL-CLEANUP TITLE: Ephemeral perch cleanup on every ring exit path (3.1) REQ-HAZARD-GRACE-BEFORE-SIGNOFF TITLE: Grace-period wait completes before composing INIT_SIGNOFF (1.1) REQ-HAZARD-HANDOFF-ARGV-COMPAT TITLE: Broker/brain IPC + handoff argv version-tolerant (2.3) REQ-HAZARD-HOSTED-LIVENESS-RECONCILE TITLE: B2 KEYSTONE: a daemon-hosted (spt-hosted) endpoint's info.json status is RECONCILED to real liveness, not left latched online. The broker exit-waiter (broker.rs:889-910) reaps its in-mem session table REQ-HAZARD-INBOX-NO-DOUBLE TITLE: No double-delivery via legacy inbox (4.5) REQ-HAZARD-LIVEHOST-BOOT-RACE TITLE: The brain's daemon-hosted Psyche lifecycle surfaces a host-FAILURE on the live perch (harness-diagnosable) and runs net-INDEPENDENTLY. When reconcile_once→host_one→spawn_psyche fails for a state=l REQ-HAZARD-LOCAL-API-AUTH TITLE: Every local `api` mutation authenticated to an endpoint/session (codex #13) REQ-HAZARD-PAIR-SEED-ROTATION TITLE: Removing a node rotates the subnet seed (epoch bump) so an old node/old seed cannot rejoin; trust-store delete alone is NOT revocation because the seed is replicated to every trusted node (ADR-0005 #1 REQ-HAZARD-PSYCHE-OUTBOUND-PROXY TITLE: Psyche outbound captured + sanitized: the live-Psyche turn driver captures stdout (never Stdio::null), and the daemon strips/re-stamps Psyche-supplied from=/target and constrains routing (reply→__RE REQ-HAZARD-RC-ATTACH-FAILFAST TITLE: B1: `spt rc ` to a DEAD or non-streaming session fails fast with a clear message, never an INFINITE blank screen. Today rc.rs run_attach (209-231) + pump spawns PUMP_IPC_READER and blocks: the pol REQ-HAZARD-RC-ATTACH-TRUTH TITLE: RC-RENDER-TRUTH W1 (KNOWN-HAZARDS 7.46 — umbrella conformance seam for ADR-0042): an rc surface answers from live session authority, never a stale persisted projection; a resuming perch is UNBOUND, DOC: 7.45 Endpoint lifecycle state converges to truth from every death path — no optimistic online without authority, no surviving control stamps, no immortal wake intent, no untruthful create `[REQ-HAZARD-ENDPOINT-LIFECYCLE]`: ### 7.46 An rc surface answers from live session authority, never a stale p REQ-HAZARD-RC-EOF TITLE: A severed broker stream during a live rc session surfaces GRACEFULLY, never as a raw io error that crashes the PTY. The rc read-loop (rc.rs:352-362) continues only on WouldBlock/TimedOut; ANY other re REQ-HAZARD-REGISTRY-EPOCH-LEASE TITLE: Registry merge ordered by per-node monotonic epoch, never wall-clock — a stale Active can't clobber a newer Offline (4.8, red-team #8) DOC: 4.7 Concurrent SQLite openers must not fail with "database is locked": ### 4.8 Registry merge ordered by epoch, never wall-clock (red-team #8) - **Failure:** the per-subnet registry replicates `endpoint_id → [instances]` eventually-consistently across nodes. Under a partition or clock ske REQ-HAZARD-REGISTRY-STALE-CLEAN TITLE: Stale registry entries degrade to fallback, never hard-fail (4.3) REQ-HAZARD-RENDER-LIFECYCLE TITLE: RC-RENDER-TRUTH W3 (KNOWN-HAZARDS 7.47 — umbrella conformance seam for ADR-0043): the physical terminal is never mutated or terminated outside its renderer's ordered state model. Regression matrix f DOC: 7.46 An rc surface answers from live session authority, never a stale persisted projection — and a resuming perch is UNBOUND, not offline `[REQ-HAZARD-RC-ATTACH-TRUTH]`: ### 7.47 The physical terminal is never mutated or terminated outside its renderer's ordered state model — output before exit, REQ-HAZARD-RESTART-IDEMPOTENT TITLE: Idempotent/exactly-once delivery across brain restart at every broker boundary (codex #14) REQ-HAZARD-ROSTER-GHOST TITLE: A LOCAL subnet roster entry whose backing perch is erased does NOT keep advertising Active (no phantom perch-less endpoint). `api session-end --erase` removes the perch (owlery dir gone) but the REQ-HAZARD-SEEDMAP-CONNECT-UNBOUNDED TITLE: SEED (doyle-filed, 2026-07-05, from the REQ-HAZARD-DAEMON-STOP-BARRIER B2 fix): the PRODUCTION seedmap connect callers (put / take / is_running) inherit the SAME interprocess WaitNamedPipeW-forever ha REQ-HAZARD-SESSION-PIN-WEDGE TITLE: A perch PINNED to a DEAD session-id self-heals instead of wedging forever. authenticate() (spt/src/api/auth.rs:78) gates api poll/state/boundary on proof-sid == info.json.session_id; if ONE boundary r DOC: F-019 diagnosis lesson — confirm an adapter binary actually SPAWNED before behavioral diagnosis `[REQ-INSTALL-11]`: ### 7.25 A perch PINNED to a DEAD session self-heals (dead-owner re-pin) instead of wedging forever; a LIVE-owner rotation still refuses `[REQ-HAZARD-SESSION-PIN-WEDGE]` - **Failure REQ-HAZARD-SHELL-STALE-ONLINE TITLE: A shell instance's ONLINE-ness is DERIVED (recorded status AND its recorded `shell.pid` not provably dead), never the recorded `status` field alone — an abruptly-dead binary (force-kill, crash, OOM: DOC: Conformance checklist (condensed): | # | Invariant | spt-core surface | |---|---|---| | 1.1 | Grace wait precedes INIT_SIGNOFF | daemon teardown | | 1.4/4.4 | Deferred rows excluded from event-stream drain | daemon spool drain | | 2.1/5.1 | Stable PID/broker-handle over ephemeral PID | liveness dete REQ-HAZARD-SINGLE-PATH-SOURCE TITLE: Single path/registry source of truth; no layout ambiguity (6.1) REQ-HAZARD-SOFT-CLEANUP TITLE: Soft-cleanup preserves state, removes only the ready marker (6.2) REQ-HAZARD-STALE-INDEX-LOCK TITLE: Sweep stale lockfiles on daemon boot (1.3) REQ-HAZARD-STDIN-SESSION-ID TITLE: Stdin session_id precedence over env (2.2) REQ-HAZARD-STOP-PATH-PSYCHE-ORPHAN-REAP TITLE: Endpoint-stop and brain-death reconcile MUST reap a brain-less perch's orphan detached Psyche via the cmdline-scoped guard (`psyche_orphan_should_reap`) — the handle-reap (`LiveSet::stop_host`, REQ- DOC: Conformance checklist (condensed): | # | Invariant | spt-core surface | |---|---|---| | 1.1 | Grace wait precedes INIT_SIGNOFF | daemon teardown | | 1.4/4.4 | Deferred rows excluded from event-stream drain | daemon spool drain | | 2.1/5.1 | Stable PID/broker-handle over ephemeral PID | liveness dete REQ-HAZARD-STOP-RESPAWN-CONVOY TITLE: KNOWN-HAZARDS 7.52: an operator stop outranks every implicit ensure — no convenience path resurrects what the operator just killed. The hazard-conformance twin of REQ-ENSURE-DAEMON-STOP-INHIBIT: its DOC: 7.52 An operator stop outranks every implicit ensure — no convenience path resurrects what the operator just killed `[REQ-HAZARD-STOP-RESPAWN-CONVOY]`: - **Failure (paid-for, hertz v0.39.4 field RCA 2026-07-22, doyle code-verified same day):** `spt daemon stop --force` is non-terminal on REQ-HAZARD-TEARDOWN-DEADEND TITLE: TEARDOWN-AUTHORITY W1 HAZARD (ADR-0045 decision 8; hertz RCA 2 — hit doyle's OWN live production endpoint, recoverable only by out-of-band scoped kill): `endpoint stop` followed by `endpoint run --i DOC: 7.48 At most one input-capable controller lease per PTY session — takeover revokes atomically and loudly, input is fenced to the active lease, node identity is never a lease `[REQ-HAZARD-CONTROLLER-LEASE]`: ### 7.49 A teardown verb never stamps a terminal or resting state it has not caused — and REQ-HAZARD-UPDATE-ROLLBACK TITLE: Self-update rejects version rollback; metadata expiry + adapter content signing (codex #5) REQ-HAZARD-VIEWER-CLOSE-DETACH TITLE: A VIEW is independent from the endpoint: closing the tab/window where `spt endpoint run` was invoked must detach ONLY the `spt rc` attach pump — the daemon-hosted harness keeps running and stays re- DOC: Terminal wrapper: **A view is independent from the endpoint** (invariant): An spt-hosted endpoint runs in a **daemon-owned PTY, decoupled from whatever terminal launched it**. Closing the tab/window where `spt endpoint run` was invoked detaches only the `spt rc` attach pump — the endpoint REQ-HAZARD-VIEWER-RING-ROLL-SNAP TITLE: A read-only rc --view VIEWER whose serving brain falls behind the live ring under a hard flood and receives a FORWARD Output seq gap (the ring rolled frames out between reads, BEFORE any channel-overf DOC: Shell sleep/wake (offline ↔ online): **BUILT (M12 W2.5).** The controller/viewer model is implemented end-to-end. Attach intent is **three-valued** (`AttachIntent = Viewer | Control | Take`, wire-default `Control`): `Control` to a FREE endpoint becomes controller; `Control` to a CONTROLLE REQ-HAZARD-WAN-ORIGIN-AUTH TITLE: WAN-inbound origin is transport truth, never payload: the access gate's subject (ADR-0009 origin-node whitelist) is the QUIC handshake-proven remote node id from the broker's conn/stream table — a f DOC: 7.4 Per-agent pulse/psyche/echo scheduling must not serialize across agents `[REQ-HAZARD-DAEMON-SCHED-NONBLOCKING]`: ### 7.5 WAN-inbound origin is transport truth, never payload `[REQ-HAZARD-WAN-ORIGIN-AUTH]` - **Failure:** the ADR-0009 access whitelist gates **unsolicited wire inbound by o REQ-HAZARD-WINDOWS-PID-RECYCLE TITLE: Windows PID-recycling false positives guarded (5.1) REQ-HOST-RUN-1 TITLE: spt-hosted harness bringup: `spt endpoint run` spawns an adapter's `[session.self]` command template into a broker-held PTY (the spawn-session seam, brain.rs spawn_session_pid — same broker path she REQ-IDLE-PARKED-DELIVERY TITLE: W5 (LIFECYCLE-TRUTH): a message QUEUED to an ALREADY-idle spt-hosted endpoint is delivered without an operator poke. ROOT (live during the milestone dispatch 2026-07-07): the idle-edge drain (F-023 le REQ-INFRA-1 TITLE: GitHub issue tracking for v1; tangled.org as migration target REQ-INST-13 TITLE: Subnet-exclusive sync + per-endpoint subnet-membership list REQ-INST-6 TITLE: Deferred messages not delivered to dormant/suspended instances DOC: Deferred Features: | Feature | Cut from | Why deferred | Trigger to revisit | |---|---|---|---| | Scrollback on-disk spillover | terminal wrapper v1 | In-memory ring covers the common case; spillover adds a persistence/rotation story | First long-running session that overflows the ring usefully, or REQ-INST-7 TITLE: Subnet registry + bare-id resolution policy REQ-INSTALL-13 TITLE: Adapter add is non-destructive & idempotent-safe (F-018): `spt adapter add --github|--release` REFUSES when the target `_github/` home already backs an ACTIVE registered record — emitting an a DOC: Installation: **adapter registration (`spt adapter add`)**: How a node comes to *know* an adapter — harness or shell. An explicit **`spt adapter add `** (or **`--github `**) validates the manifest against the published JSON Schema and writes a registration record under `{SPT_HOME} REQ-INSTALL-3 TITLE: Idempotent + interactive-optional first run REQ-INSTALL-9 TITLE: Adapter add from a GitHub release archive: `spt adapter add --release [--tag ] [--asset ]` fetches a `.spt` tar asset over HTTPS+GitHub trust, extracts it to the durable adapter DOC: Installation: **adapter registration (`spt adapter add`)**: How a node comes to *know* an adapter — harness or shell. An explicit **`spt adapter add `** (or **`--github `**) validates the manifest against the published JSON Schema and writes a registration record under `{SPT_HOME} REQ-INSTALL-BOOTSTRAP-VERB TITLE: THE-FORKENING W1 (ADR-0036 §3, bootstrap shape b operator-ruled): virgin-box install = `gh release download` the platform binary + ONE self-install verb in the binary itself — the verb places the b DOC: Installation: **Installer form (gh bootstrap, ADR-0036):** install gh → `gh auth login` (org membership) → `gh release download` the platform binary from the private channel → one **self-install verb** in the binary places it at the canonical install path and registers the *user* PATH (so adap REQ-JOIN-DEFERRED-ELEVATION TITLE: W2 (JOIN-TRUTH, operator UX ruling verbatim): 'if --code was not supplied, don't spawn the elevated subnet-join window until a target machine is discovered → just in time for the code prompt.' When DOC: Deferred-elevation amendment (2026-07-06 — JOIN-TRUTH W2): REQ-LIST-JSON-LIVENESS-PARITY TITLE: GATEWAY-LIVENESS (flynn field bug 2026-07-09, RCA reader-divergence root): `spt endpoint list` (human) and `endpoint list --json` MUST report an IDENTICAL status for a locally-hosted endpoint — espe REQ-LISTEN-PRESERVES-HOSTING-TOPOLOGY TITLE: `api listen` must not ASSERT hosting topology it does not know. (hertz v0.39.0 field RCA 2026-07-21, doyle re-grounded at source.) OBSERVED: the published adapter sequence `api bind` then identity-pre REQ-LIVEHOST-RECONCILE-TRIAL-SILENT TITLE: SEED (DEFERRED investigation, doyle 2026-07-09 — UPDATE-WEDGE follow-up): determine WHY the trial/rollback brain's livehost reconcile loop did NOT drive the broker controller-reap (nor re-host the l REQ-MANIFEST-4 TITLE: Keyword hints — [[hints]] {keywords (literal/regex), text}; spt api hint --session emits at most one matched hint per message, once per session (seen-set), declaration-order first match; profiles ov DOC: Runtime model: **keyword hints** (ratified 2026-06-12 — core milestone A): Once-per-session usage/syntax hints, a first-class adapter feature: the manifest's `[hints]` section declares entries of `{keywords (literal default, regex opt-in), text}`; the adapter's user-prompt hook pipes the REQ-MANIFEST-5 TITLE: File-backed adapter [strings] (M12-W3-T3.1): a [strings] dot-path value MAY be an inline-table FILE POINTER `key = { file = "rel/path" }` resolved to the file's contents at get-string time, keeping la DOC: Runtime model: **adapter strings** (ratified 2026-06-11, Gateway grill): A `[strings]` manifest section — an adapter-authored JSON/TOML KV tree, dot-path-readable by anything on the node via `spt adapter get-string ` (e.g. a harness hook fetching per-profile `ad REQ-MESH-1 TITLE: Membership proof (seed-proof): symmetric current-epoch seed-knowledge replaces is_trusted at EVERY inbound gate (registry apply, WAN receive, sync, notif, connection accept). MK = HKDF(seed, domain †REQ-MESH-3 TITLE: Mesh row fan-out: registry rows stay OWN-AUTHORED; the only change is the push target widens from directly-paired peers to ALL roster members (a wider DIRECT fan-out, never a third-party relay). Every REQ-MESH-4 TITLE: Revoke + timeboxed seed rotation + re-seed grace: `spt subnet revoke ...` (list, elevation-gated, revoke-only) writes roster tombstones immediately, then schedules ONE seed rotation (re-mint see REQ-MSG-3 TITLE: Ready-agent lifecycle: register perch (info.json + listener + registry address) on ready, drain spooled backlog on startup, clean teardown REQ-MSG-4 TITLE: Listener stream stdout emits EVENT envelope lines (sister-format, ADR-0001): parse the __REPLY_TO__ frame, pass pre-formed typed envelopes through verbatim (no double-wrap), compose _Implemented posture_: the **local** user-backed origins are honored end-to-end — a locally-hosted Gateway endpoint (info.json `state="gateway"`) and the local user's CLI (M9-T4/T5). The **cross-node WAN** path is being completed (trust posture **ratified 2026-06-13**): th REQ-MSG-CLI-ORIGIN TITLE: A bare non-perch CLI `spt send` (no owning perch to name as origin) stamps from = `cli@` at compose time (bare `cli` when no node label is known — never a dangling `cli@`), and WAN ingre REQ-MSG-DELIVERY-AXES TITLE: Activity-gated inbound delivery + per-message send control as THREE ORTHOGONAL AXES plus opaque metadata (ADR-0028; grilled w/ operator 2026-06-23). SUBSTRATE (the legacy-SPT parity gap, scaffolded-bu DOC: Activity-gated message delivery + send-modifier axes: REQ-MSG-ENVELOPE TITLE: The body envelope (spt-proto::event, the ADR-0001 grammar) is the SOLE canonical arriving-message format at EVERY harness arriving-message surface on an AGENT perch DOC: Decision: REQ-MSG-IDLE-TRANSLATION-BINARY TITLE: spt-hosted idle message delivery via an adapter TRANSLATION BINARY (ADR-0022). New opt-in manifest section `[message-idle-translation-binary]` = a TABLE carrying a `path` scalar (doyle OPT-B ruling: m DOC: `[message-idle-translation-binary]` — spt-hosted idle delivery: // `[inject]` — inject-input methods: ### `[message-idle-translation-binary]` — spt-hosted idle delivery (ADR-0022) Opt-in. The adapter's **idle-delivery translation binary**: a pure stdin→stdout JSON-lines fil REQ-MSG-SELF-DETECT-ANCESTRY TITLE: #9 (F026, operator field bug): a perch-owned `spt send` from an endpoint's OWN session must self-identify, not mis-stamp `cli@` (whose replies bounce NO_PERCH). ROOT: roster::detect_self_id (ros REQ-NET-3 TITLE: Cross-node Psyche sync over P2P replaces gh-repo-sync REQ-NOTIF-1 TITLE: Notification primitive: per-subnet replicated spool, seen/dismissed, resurface-at-boundary, subsumes update+consent prompts REQ-NOTIF-SCOPE TITLE: Notif scope is a per-row producer-chosen attribute node|subnet: node-scoped rows (update/consent/rollback kinds) live and die on their node and NEVER enter a replication feed; subnet-scoped rows keep DOC: 1. Scope is a per-row, producer-chosen attribute: `node` | `subnet`: REQ-NOTIF-SEAM-DISMISS TITLE: Staleness is dismissed at the seam that knows, never evaluated at surface: a successful update apply dismisses spt-core:update-staged; the update worker's next check, seeing running >= staged, dismiss DOC: 3. Staleness is dismissed at the seam that knows, never evaluated at surface: REQ-NOTIF-UPDATE-ROW-VERSION-RETIRE TITLE: An update-available notif row minted by a node running PRE-0.40.0 spt is retired on the version the running node has ALREADY reached — because the keyed catch-up dismissal is structurally blind to i REQ-ONEWAY-STREAM-TERMINAL TITLE: REGISTRY-LIFECYCLE W1 (ADR-0040 decision 1, hertz defect B leg 1): a one-way fire-and-forget stream family is TERMINAL at successful FIN, sender-side — the registry pump retires its OWN feed row aft DOC: Decision: 1. **One-way (fire-and-forget) stream families are terminal at FIN, sender-side.** The registry feed pump retires its own row after successful write+FIN via the existing `net-stream-retire` verb (best-effort on N-1 brokers, per ADR-0038 A). A one-way family's exchange is definitio REQ-PAIR-5 TITLE: Multi-subnet pairing: subnet-name discovery input, create-new-names-up-front, rendezvous-token hashing REQ-PAIR-8 TITLE: NTP TOTP offset: the pairing ceremony queries NTP at ceremony time (both sides) and applies the derived offset to the TOTP calculation in-process only; system-clock fallback when NTP is unreachable (o REQ-PEERADDR-INVARIANT TITLE: MESH-RECOVERY W1 (ADR-0039, RCA wave 2): the peer-addrs cache INVARIANT — outer peer key == address.id — is ENFORCED on load and on write: invalid rows are repaired from the current roster when po DOC: Context: ## Decision REQ-PICKER-2 TITLE: The picker's project-history loader reads the git-backed context store, not the bare working tree: data.rs project_history_for enumerates an endpoint's projects via the BranchStore branch set (the con REQ-PICKER-3 TITLE: A self-owned subnet row reconciles its status to the LIVE roster: a Subnet-category row whose endpoint_id overlaps a local (is_local) roster id is self-owned (this node hosts it), so its status square REQ-PICKER-BACK-NAV TITLE: C-4 (REMOTE-TRUTH triage §C-4 #9): Backspace is a back() ALIAS across the picker — one keypress backs out one screen along the SAME reverse map Esc walks (model back(), complete for all screens inc REQ-PICKER-CHANGE-ADAPTER-FLOW TITLE: B-2 (F029, operator; LARGEST item): `ConfirmOption::ChangeAdapter` wrongly routes into the CREATE flow (Screen::CreateAdapter → CreateId → CreateHome → START, reenter_create(true)) — it re-pro REQ-PICKER-CONTROLLED-LOCAL TITLE: #3 local half: a LOCALLY-controlled endpoint renders CONTROLLED in its own node's picker. display_status() (crates/spt/src/picker/model.rs:415) derives Controlled ONLY from driven_by.is_some(), but dr REQ-PICKER-CURRENT-DIR-LABEL TITLE: A-2/A-3 (F029, operator, semantic pair): the Choose-project rows must self-identify the CURRENT DIR. build_project_choices (picker/model.rs:322-352). A-2: when the run cwd IS already a history dir the REQ-PICKER-HISTORY-FRESH TITLE: The `spt endpoint run` picker shows project history for FRESH endpoints (operator-raised v0.12.0 real-harness finding). Symptom: a fresh endpoint shows no project history in the picker. ROOT TBD — i REQ-PICKER-ONLINE-ACTION TITLE: The `spt endpoint run` picker shows the correct action for an ALREADY-ONLINE endpoint — Attach, NOT 'Start now' (operator-raised v0.12.0 real-harness finding). Symptom: the picker offers 'Start now' REQ-PICKER-PURGE-STRUCTURED TITLE: RC-RENDER-TRUTH W3 (ADR-0043 decision 3, hertz stale-glyphs RCA leg 3 P0): core verbs invoked from inside an active TUI return STRUCTURED outcomes and write NOTHING to the terminal — the picker purg DOC: Decisions: 1. **One FIFO sequencer per attach sink.** The PTY drain/output writer is the sole sequencer for terminal Output and Exit: Exit is enqueued behind all prior output for each sink (drain EOF/completion first, then Exit). A mutex alone is insufficient — producer order is the contr REQ-PICKER-WINDOW-TITLE TITLE: B-5 (F029, operator): `spt endpoint run`'s interactive picker window/tab is untitled — hard to find among many terminals. Set the window/tab title to `SPT Endpoint Picker`. Anchor picker/mod.rs:88 s REQ-PROJECT-INDEX-INVALIDATION TITLE: PROJECT-INDEX W2 (ADR-0037): event-driven index invalidation, debounced + coalesced: new session/cwd -> refresh that endpoint + the shared cwd cache; context-store mutation -> ONE debounced global mem DOC: Self-update: **index writer duty (daemon)** — the brain hosts ONE writer thread (`projwriter`, spawned beside the live host; single-flight by construction). Batched complexity is contract, `O(P+B+F+C)`: ONE branch enumeration per cycle (`for-each-ref` carries recency + tips), ≤1 tree scan per ** REQ-PSYCHE-LEGACY-RESIDENT-SWEEP TITLE: W5 (F030; doyle+perri 2026-07-04): a dirty daemon upgrade from <=v0.24.0 strands a RESIDENT psyche wrapper the OLD daemon spawned — and F-030 W4's nested-`ready` resolution fix CONVERTED that wrappe REQ-PSYCHE-ROLE-OPTIONAL-SKIP TITLE: W1 (LIFECYCLE-TRUTH): a manifest with NO [session.echo_commune] role SKIPS commune-sync (debug-level note, no strike) instead of hard-failing the turn. ROOT (perri filing, recovered): missing role -> REQ-PSYCHE-STAMP-CLEAR-ANY-SUCCESS TITLE: W1 (LIFECYCLE-TRUTH): EVERY successful psyche operation clears psyche_host_error — not just the pulse-loop leg. ROOT (three field confirmations, perri): the stamp clears only via note_turn_outcome's REQ-PUMP-PEER-ISOLATION TITLE: PUMP-TRUTH W2 (architectural, operator ruling 2026-07-08): one peer must NOT block or poison all others -- peer discovery is async / per-peer-independent. Two coupled defects in run_peer_pump: (1) SEQ REQ-PUMP-STAGE-TRUTH TITLE: MESH-RECOVERY W1 (ADR-0039, RCA wave 3 — the acceptance surface, same contract): peer-failure telemetry is STAGE-SPLIT and health is USER-MEANINGFUL. The single 10s PUMP_PEER_FAIL token splits into DOC: Context: ## Decision REQ-RC-1 TITLE: `spt rc ` — user CLI attaching a local terminal to a broker-held PTY, reusing the cross-node attach machinery (attach.rs request_attach → send_attach_input pump, spt-net AttachRecord codec); l REQ-RC-HARNESS-ONLY-REFUSAL TITLE: RC-RENDER-TRUTH W1 (ADR-0042 decision 3, hertz elevated-endpoints RCA core leg 1): direct `spt rc ` preflights the already-known harness_only/controllable=Some(false) fact (local + gossiped rows b DOC: Decisions: 1. **`spt rc` consults the honest-session authority before the offline fast-fail.** Normal `spt rc ` runs the same bounded `SessionProbe::has_live_session_honest` gate `endpoint run` uses (ADR-0041 single liveness authority). An honest session exists → attach via the sessio REQ-RC-HONEST-SESSION-AUTHORITY TITLE: RC-RENDER-TRUTH W1 (ADR-0042 decision 1, hertz perri-contradiction RCA): normal `spt rc` consults the ADR-0041 single honest-session authority BEFORE the persisted-offline fast-fail — run the bounde DOC: Decisions: 1. **`spt rc` consults the honest-session authority before the offline fast-fail.** Normal `spt rc ` runs the same bounded `SessionProbe::has_live_session_honest` gate `endpoint run` uses (ADR-0041 single liveness authority). An honest session exists → attach via the sessio REQ-RC-RECONNECT TITLE: B-3 (REMOTE-TRUTH triage §B-3, the operator-asked UX): the rc attach viewport RECONNECTS on a severed transport instead of print-and-exit. Pre-fix rc was one-shot (resolve→dial→attach→pump→pa DOC: Proven rows (injection evidence in-tree): | # | Fault injected | Blast radius (by design) | Survives untouched | Recovery | Evidence | |---|---|---|---|---|---| | 1 | **Brain killed mid-PTY-stream** (logic crash / routine self-update) | Logic halts until restart | Broker, PTY child (pid stable), out REQ-RC-RESIZE-PRESENTATION-BARRIER TITLE: During a resize transition, LIVE DELIVERY is barriered along with the grid parse: no attached sink (controller or viewer) ever receives mixed-geometry raw bytes; commit substitutes ONE synthesized syn DOC: The bringup core is **type-agnostic** — the endpoint TYPE is the adapter manifest's concern, not a separate bringup mode. A manifest declaring `[session.psyche_init]` brings up a **LiveAgent** (the daemon REQ-REGISTRY-REPLAY-BOUNDED TITLE: REGISTRY-LIFECYCLE W1 (ADR-0040 decision 4, hertz defect B leg 4, defense-in-depth behind REQ-ONEWAY-STREAM-TERMINAL): a deadline-poisoned one-way (Registry) replay carries a per-stream strike budget; REQ-RELAY-NO-BUSY-DELIVER TITLE: MSG-IDENTITY W4 (operator self-send probe 2026-07-09, companion leg): the relay/idle-inject carrier MUST NOT fire for an ACTIVE endpoint — the daemon already guards send-time (daemon.stderr.log: 'EN REQ-REST-VERB-ROUTING TITLE: A-3 (REMOTE-TRUTH triage §A + Q3 operator-law): a BARE-id rest verb (spt wake/suspend ) routes across the subnet like send's fallback instead of failing local-only. ROOT (certain): cmd_rest (cli. REQ-RESUME-ADAPTER-FOLLOWS-SESSION TITLE: D-2 (REMOTE-TRUTH triage §D-2 + operator Q5 @c248afc): a resume-from-history restores the RECORDED session adapter (REQ-SESSION-ADAPTER-RECORDED) — the resumed harness is the one the session ran un REQ-RESUME-HARNESS-SESSION-ID TITLE: B2 (F028, hall-b diagnosis, verified 0.22.0): respawn/`--resume` feeds the SPT session id to `claude -r`. After the 02:05 daemon bounce respawn built `claude.exe -r 70b5bfa40901b7d4` — an spt sessio REQ-RESUME-REAP-PRIOR-HARNESS TITLE: B4 (F028, hall-b diagnosis, verified 0.22.0): `--resume` respawns a SECOND harness onto the SAME session without reaping the first. Observed live: resume of b4421cf9 spawned pid 34432 while gen1 (2503 REQ-RESUME-UNBOUND-STAMP TITLE: RC-RENDER-TRUTH W1 (ADR-0042 decision 2, operator-spotted second root seam): resume launch transitions an existing offline perch to UNBOUND before/with the broker spawn — UNBOUND semantics are fresh DOC: Decisions: 1. **`spt rc` consults the honest-session authority before the offline fast-fail.** Normal `spt rc ` runs the same bounded `SessionProbe::has_live_session_honest` gate `endpoint run` uses (ADR-0041 single liveness authority). An honest session exists → attach via the sessio REQ-RUN-ID-REUSES-ADAPTER TITLE: D-1 (REMOTE-TRUTH triage §D-1): `spt endpoint run --id ` with NO --adapter, when names an EXISTING perch, REUSES that perch's recorded info.adapter and runs NON-INTERACTIVELY — instead of REQ-RUN-PICKER TITLE: Interactive `spt endpoint run` picker (ratatui TUI): bare `spt endpoint run` (no --adapter/--id) enters an in-process picker (flags-present = the REQ-HOST-RUN-1 non-interactive path, untouched). Layer DOC: Shell sleep/wake (offline ↔ online): **spt-hosted bringup picker (`spt endpoint run`)** (M12-W2): The user-facing bringup flow for spt-hosted endpoints. **Bare `spt endpoint run`** (no `--adapter`/`--id`) opens an in-process **ratatui picker**; the **flagged** form is the non-interactive REQ-SCREENGRID-REPAINT-MODE-REPLAY TITLE: RC-RENDER-TRUTH W3 (ADR-0043 decision 4, hertz stale-glyphs RCA leg 4 P1): ScreenGrid cold repaint replays EVERY tracked render-affecting mode — DECSTBM scroll margins at minimum — before final cu DOC: Decisions: 1. **One FIFO sequencer per attach sink.** The PTY drain/output writer is the sole sequencer for terminal Output and Exit: Exit is enqueued behind all prior output for each sink (drain EOF/completion first, then Exit). A mutex alone is insufficient — producer order is the contr REQ-SEAT-LIFETIME-BOUNDED TITLE: REGISTRY-LIFECYCLE W1 (ADR-0040 decision 5, hertz defect B leg 5 CROSS-FAMILY per the final attribution correction — my_stream_subs releases only at conn-loop exit, NO unsubscribe verb existed, ~546 DOC: Decision: 1. **One-way (fire-and-forget) stream families are terminal at FIN, sender-side.** The registry feed pump retires its own row after successful write+FIN via the existing `net-stream-retire` verb (best-effort on N-1 brokers, per ADR-0038 A). A one-way family's exchange is definitio REQ-SELF-DETECT-PARENT-PID TITLE: E-1 (REMOTE-TRUTH triage §E-1 #7): self-detect leg (c) — the pid-ancestry fallback — ALSO candidates on `rec.parent_pid` (the harness pid, CONTEXT's 'stable session-binding anchor', stamped at bi REQ-SELF-ID-TRUST-INJECTED-ENV TITLE: DEFERRED to a followup vX.X.n sprint (post-LIFECYCLE-TRUTH, operator-ruled 2026-07-07): self-identity resolution must trust the harness-injected authoritative id and detect a stomped perch instead of REQ-SEND-STAMP-AGENT-ID TITLE: MSG-IDENTITY W4 / endpoint-identity (operator-flagged 2026-07-09 + live-confirmed on flynn's F-038 ask arriving 'cli@HFENDULEAM'): a live agent's own CLI `spt send ` MUST stamp from_id with th REQ-SEND-WINDOW-DRAIN-HONOR TITLE: F-035 (field finding 2026-07-09): active_only = POLL-ONLY for a relay-bearing live agent -- it must NEVER be RELAY-delivered (its contract is 'active hook window only, never wakes' per spool.rs WINDOW DOC: # F-035 RCA — idle-edge parked-drain ignores the delivery-window tag REQ-SESSION-RESUME-TEMPLATE TITLE: Resuming an endpoint session that HAS conversation history brings up a BLANK session. ROOT (doyle, code-grounded + CONTEXT — case-3 spt-core MISSING feature, NOT a perri docs-miss): CONTEXT L127-129 DOC: `[session.]` — outbound templates: **Resuming an existing harness session (since v0.13.0).** `[session.self]` is the *fresh* bringup; `[session.resume]` is the **native-resume** sibling. spt-core selects `[session.resume]` over `[session.self]` only when a bringup carries a prior se REQ-SESSIONS-LOG-ENDPOINT-ATTRIBUTION TITLE: C2 (F028, infra; ROOT-CAUSED + severity-upgraded doyle RCA 2026-07-03): cross-endpoint perch contamination — a foreign psyche's SessionStart hook REBINDS a victim perch's IDENTITY, not merely its le REQ-SHELL-3 TITLE: Drive channel (owner->shell, REST-only, never-spooled, latest-wins): the owner->shell mirror of sensory for continuous real-time control (scroll/crank/stick/avatar) — a [shell.drive] manifest vocab REQ-SHELL-5 TITLE: Shell ownership is owner-type-agnostic: any non-Shell endpoint type may own/spawn/drive/command/link a shell (Gateway the named first) — control-exclusivity keys on the owner endpoint_id, NEVER on t DOC: Shell model (detailed): **Owner-linked, exclusive.** Spawned by an **owning endpoint**; both linked; **only that owner `endpoint_id` may control it**. Agent endpoints are the common owner REQ-SHELL-ADAPTER-OWNED-DETACHED-SERVICE TITLE: RULING OWED (unratified — do NOT satisfy without one): may a shell adapter own a DETACHED process that deliberately OUTLIVES its shell's link-break? Today the answer is 'no, silently, on Windows onl REQ-SHELL-FRAME-VOCAB TITLE: The shell relay frame vocabulary is a PUBLISHED contract, not a reverse-engineered one. (flynn spt-alchemy clean-room audit 2026-07-21, doyle code-verified, seed pair item 1.) TODAY: shellchan.rs comp DOC: The frame contract: what a shell binary parses: REQ-SOFT-END-PRESERVES-LIVE-LISTENER TITLE: F-2 (REMOTE-TRUTH triage §F-2, field-repro'd hall-bf 2026-07-04): a /clear must not sever a SURVIVING poll listener's relay address — post-clear owl-path send hit NO_PERCH while ready was present a REQ-SPOOL-TAKE-AUDIT TITLE: W5 (LIFECYCLE-TRUTH, RCA cost: proving WHO took delivered=1 rows burned an hour): the spool records the taker per row — leg enum (relay-backlog / hook-poll / idle-inject / psyche) + sid/pid + taken_ REQ-STREAM-INFOS-SERVER-FILTER TITLE: REGISTRY-LIFECYCLE W1 (ADR-0040 decision 2, hertz defect B leg 2): broker stream_infos excludes initiated_locally rows SERVER-SIDE (retired already excluded) before cloning/serializing to the dispatch REQ-STREAM-LEASE-CLASSES TITLE: REGISTRY-LIFECYCLE W2 (ADR-0040 decision 6 + ADR-0041, emphasys C2 P0): streams declare a lifetime class at open — RC attach/view streams are ConnectionBound (opener conn EOF means the target sees F DOC: Decision: 1. **One-way (fire-and-forget) stream families are terminal at FIN, sender-side.** The registry feed pump retires its own row after successful write+FIN via the existing `net-stream-retire` verb (best-effort on N-1 brokers, per ADR-0038 A). A one-way family's exchange is definitio REQ-STREAM-LIFETIME-CLASS TITLE: RESCOPED at W2 activation 2026-07-22 (doyle verify-first, C3-retirement precedent): the CLEAN-CASE chain this REQ was minted for is ALREADY SHIPPED under REQ-STREAM-LEASE-CLASSES / ADR-0040 decision 6 DOC: Amendment 1 (2026-07-22, DAEMON-LIFECYCLE W2) — teardown authority is opener-declared class PLUS transport liveness, enforced at the three places decision 6 could not see: REQ-SUBNET-3 TITLE: Node labels: hostname-default, gossiped, addressable in @node qualifiers (refuse-on-ambiguity) REQ-SUBNET-4 TITLE: Subnet membership mutations elevation-gated (create = seed reveal; join = trust-boundary enrollment) DOC: Product-surface amendment (2026-06-05 — M7 D3): REQ-SUBNET-7 TITLE: Per-machine re-pair trust overwrite: registry rows carry a hashed stable machine identifier (OS machine id /etc/machine-id|MachineGuid, domain-separated SHA-256 before gossip, spt-minted persisted UUI REQ-SUBNET-8 TITLE: Status render honesty: zero-subnet text is daemon-aware ('No subnets registered — this node is standalone.' + daemon-running-dependent blurb, never implying messaging works while the daemon is down) REQ-TERM-2 TITLE: session-surface abstraction; send-keys + send-line injection REQ-TRANSLATE-BINARY-LIVENESS-DECAY TITLE: SUPERSEDED by REQ-TRANSLATE-COMMIT-MISS-TOLERANCE (F029 C-1). B6 (F028, perri F-e) was ROOT-PINNED as the commit-deadline-miss fault: at a checkpoint clear boundary the clear-only inject's {commit} wa REQ-TRANSLATE-COMMIT-MISS-TOLERANCE TITLE: C-1 (F029, B6 ROOT — rescope of REQ-TRANSLATE-BINARY-LIVENESS-DECAY, now PINNED): at a checkpoint clear boundary the clear-only inject drives `/clear`; its `{commit}` is never observed within INJECT DOC: Amendment (2026-07-03, F029 C-1) — a commit-miss is NOT a fault; real faults respawn: REQ-UPD-7 TITLE: Origin-source update bootstrap (`spt update fetch`): pull the latest signed release directly from the GitHub release origin (`SaberMage/spt-releases`) — the per-platform artifact + its `.rele REQ-UPD-8 TITLE: Platform-safe `spt update fetch` + apply platform-guard (v0.3.1 cross-OS brick fix): `spt update fetch` stages the signed multi-platform `SignedUpdateSet` (`update-set.json` + every platform artifact REQ-UPD-9 TITLE: `gh_release` adapter [update] avenue (optional signing): an adapter declares `[update] avenue = "gh_release", repo = "user/repo"` (+ optional `asset`, default `adapter.spt`; + optional Ed25519 `signin DOC: Runtime model: **adapter update declaration** (manifest field): Each adapter manifest declares how spt-core should *ripple-update the adapter itself* (see Self-update). One of: **file-pull** (a plugin-directory lookup regex + a gh repo for the adapter's latest files — spt-core fetches + s REQ-UPDATE-ADAPTERS-VERB TITLE: THE-FORKENING W4 (operator-grilled 2026-07-14): `spt update adapters [[,...]]` = thin ALIAS over the existing `spt adapter update` engine (cli.rs:748 gh_release avenue; the old verb STAYS — pu DOC: Self-update: **update composite (`spt update`)** — the plain verb is the primary form: `update fetch --apply` then `update adapters` (core-first order); with core already current, only adapters update. `--core-only`/`-c` skips adapters; `spt update adapters [[,…]]` is the adapters leg alon REQ-UPDATE-APPLY-ALREADY-APPLIED TITLE: `spt update apply` classifies an already-staged / already-applied state as a friendly exit-0 no-op instead of dying at the binary-aside rename with 'Access is denied (os error 5)'. ROOT (F-025): a sec REQ-UPDATE-APPLY-RESTART-NOTICE TITLE: `spt update apply` prints a LOUD restart-required notice whenever the surviving broker will keep running the pre-apply image (which, until broker-restart choreography exists, is ALWAYS on a successful REQ-UPDATE-DEFAULT-COMPOSITE TITLE: THE-FORKENING W4 (operator-grilled 2026-07-14): plain `spt update` = `update fetch --apply` THEN `update adapters` (core-first doctrine order); when core is already current the core leg no-ops and ONL DOC: Self-update: **update composite (`spt update`)** — the plain verb is the primary form: `update fetch --apply` then `update adapters` (core-first order); with core already current, only adapters update. `--core-only`/`-c` skips adapters; `spt update adapters [[,…]]` is the adapters leg alon REQ-UPDATE-FETCH-CURRENT-UX TITLE: `spt update fetch` reports an already-staged / already-applied latest as an ACTIONABLE human outcome (exit 0), not a Debug-formatted error. ROOT: cmd_update_fetch (cli.rs) sets the rollback floor = st REQ-UPDATE-FINISH-ENDPOINT-SURVIVAL TITLE: W3 (LIFECYCLE-TRUTH): daemon restart no longer massacres hosted endpoints — daemon start RE-RUNS previously-online spt-hosted endpoints. ROOT rig-proven: daemon stop+start (the apply notice's OWN in REQ-UPDATE-GH-TRANSPORT TITLE: THE-FORKENING W1 (ADR-0036, operator-ruled 2026-07-14): the release channel is PRIVATE (`BigscreenVR/spt-bs-releases`) and the gh CLI is the mandated carrier — release discovery (`releases/latest`, DOC: Self-update: **release channel (private, gh-carried)** — the release channel is a **private** GitHub repo (`BigscreenVR/spt-bs-releases`, ADR-0036); the **gh CLI is the mandated carrier** for release discovery and asset download (each node authenticates via org membership). A node without an authe REQ-UPDATE-ONE-SHOT-FINISH TITLE: W3 (LIFECYCLE-TRUTH): update apply works daemonless and one command finishes the cycle. ROOT (operator wart): update fetch/apply run ensure_daemon_announced (cli.rs:4386) -> on a stopped box they BOOT REQ-UPDATE-RESTART-SAFE-SWAP TITLE: THE-FORKENING W4 (operator-grilled 2026-07-14; RETIRES findings-backlog seed #12 REQ-UPDATE-ONE-STEP-SAFE-SWAP): `spt update --restart` = the one-step ergonomic path to the SAFE full-cycle swap — fe DOC: Self-update: **update composite (`spt update`)** — the plain verb is the primary form: `update fetch --apply` then `update adapters` (core-first order); with core already current, only adapters update. `--core-only`/`-c` skips adapters; `spt update adapters [[,…]]` is the adapters leg alon REQ-UPDATE-RUNNING-IMAGE-SURFACE TITLE: `spt` surfaces the RUNNING broker image version beside the on-disk version so an updated-looking node reveals broker-side dormancy. ROOT (F-025): `spt update apply` restarts the BRAIN only (ADR-0018 D REQ-UPDATE-TRIAL-DRAIN-DRIVE TITLE: UPDATE-WEDGE (counter-54, doyle-ruled 2026-07-09 — regression of the v0.29.0 seamless brain-swap): a brain generation DRIVES the broker's controller-liveness reap (a KIND_SESSIONS poll) each heartbe DOC: Self-update: **brain-trial promotion (readiness + drained)** — the broker supervises the swapped-in brain through a bounded readiness **trial** and *promotes* the new binary only when it both signals ready for its own generation **and** the OUTGOING generation's control plane has **drained** — t REQ-VIEWER-SKIP-TO-LIVE-ON-EVICT TITLE: A `rc --view` VIEWER that overflows its broker subscription queue and is EVICTED (OutputLog::append try_send Full → viewers.remove, REQ-HAZARD-VIEWER-ISOLATION session-protection) must SKIP TO LIVE, DOC: Shell sleep/wake (offline ↔ online): **BUILT (M12 W2.5).** The controller/viewer model is implemented end-to-end. Attach intent is **three-valued** (`AttachIntent = Viewer | Control | Take`, wire-default `Control`): `Control` to a FREE endpoint becomes controller; `Control` to a CONTROLLE REQ-WAKE-WAIT TITLE: A-2 rider (REMOTE-TRUTH triage §A-2): `spt endpoint wake --wait` blocks on the REAL bind (status reaches online) after the daemon wake-resume lift (REQ-WAKE-RESUME-LEG), instead of the DEFAULT accept REQ-WAN-SPT-HOSTED-DELIVERY TITLE: A WAN-ARRIVED `spt send` is DELIVERED to an spt-hosted endpoint (broker holds its PTY, NO api-listen relay), not spooled-forever. Today receive_wan (spt-daemon/wan.rs:271-276) tries deliver_tcp (the h REQ-WHOAMI-1 TITLE: The `endpoint list` SELF pin carries the Self endpoint's authored `endpoint description` (info::read_info(...).resources) when present, inline after the liveness state; whoami stays a top-level hot-pa DOC: **whoami** (alias for endpoint list): `spt whoami` is a thin **alias for `spt endpoint list`** — it prints the full view with the session's own endpoint **SELF-pinned first**, that pin carrying the endpoint's id, liveness state, and its authored **endpoint description** (the "who am I" an REQ-WORKER-LIST-VISIBILITY TITLE: V-1 (WORKER-TRUTH triage, operator rider): worker perches leave the DEFAULT `spt endpoint list` view — they are process-local machinery, not subnet citizens; leaked-or-live worker rows rendering as REQ-WORKER-PICKER-EXCLUDED TITLE: V-2 (WORKER-TRUTH triage, operator rider): non-drivable endpoint classes never render as `spt endpoint run` picker rows — a worker perch cannot be driven, instantiated, or controlled; offering it is REQ-WORKER-REAP TITLE: W-3 (WORKER-TRUTH triage): worker records must not persist indefinitely past their useful life — 6 dead-pid workers leaked OFFLINE on flynn (kill-paths where SubagentStop never fires: parent killed, REQ-WORKER-SID-SYMMETRIC-AUTH TITLE: W-2 (WORKER-TRUTH triage, operator-ruled 2026-07-06): worker verbs go sid-symmetric with every sibling id-scoped verb — worker-start mints NO token and worker-stop takes NONE (token custody is undue DOC: `api worker-start [--agent-id ] [--agent-type ]`: ### `api worker-stop --session-id ` · `api worker-poll --session-id `