[
  {
    "index": 1,
    "id_a": "REQ-ACL-ACCESS-REFRESH-VERB",
    "id_b": "REQ-ACL-NODE-VIEW",
    "title_a": "`spt api access-refresh` is MINTED THIS WAVE BUT REFUSES \u2014 the verb exists, parses and is documented, and its refusal names why: the capture-refresh is engine-room-only, and engine-room enforcement (ADR-0052) does not land until W3. Minting the refusing verb now is deliberate: it fixes the contract ",
    "title_b": "`spt daemon access` is the node-tier roster: the entities the node-scope rules name (node and subnet-wildcard subjects \u2014 a node-scope sender-endpoint rule cannot exist by schema), this machine's own mode with its per-surface exceptions, and the captured subnet modes \u2014 the tier every hosted endpoint ",
    "doc_a": "control-surface modes (`open` / `closed`)** (ratified 2026-07-29, access-control grill): Per-surface default posture for unlisted subjects \u2014 `open` = allowed (no forced whitelisting), `closed` = blocked. Defined at three levels: **subnet** (a universal all-surfaces mode chosen at `subnet create` \u2014 p",
    "doc_b": "access entity** (ratified 2026-07-30, fast-follow grill): Anything that can be granted (or denied) control via access rules \u2014 a **subnet**, **node**, or **endpoint**. A **ruled access entity**, relative to a given target, is an access entity that at least one of the target's rules names. Access view"
  },
  {
    "index": 2,
    "id_a": "REQ-ACL-NODE-MODE-SET",
    "id_b": "REQ-ACL-VIEW-ROSTER",
    "title_a": "The node's control-surface modes are settable through the engine room and nowhere else (ADR-0052 decisions 1 and 3, CONTEXT.md 'control-surface modes' \u2014 the node level of the three). Modes are exactly what a confused or adversarial agent would loosen, so the mutation surface must be the one place an",
    "title_b": "Access views are roster-first (CONTEXT.md 'access entity', FF grill 2026-07-30): `spt endpoint access [<endpoint>]` lists each ruled target's access entities \u2014 the subnets, nodes, and endpoints its own rules name \u2014 grouped by type in that order, each with its rule count; a subnet or the home node al",
    "doc_a": "A locked-down **agent endpoint** (harness-adapter-backed, spt-hosted, has a mind \u2014 it can be briefed on and reason about the node's access posture). It is the designated way to set the **node's** control-surface modes.",
    "doc_b": "access entity** (ratified 2026-07-30, fast-follow grill): Anything that can be granted (or denied) control via access rules \u2014 a **subnet**, **node**, or **endpoint**. A **ruled access entity**, relative to a given target, is an access entity that at least one of the target's rules names. Access view"
  },
  {
    "index": 3,
    "id_a": "REQ-ACL-SURFACE-VOCAB",
    "id_b": "REQ-MSG-6",
    "title_a": "Access control is granular at the CONTROL SURFACE, not at the endpoint. A rule is (target endpoint x surface x subject) -> allow/deny, where a surface is a named remote-reachable operation class with an OPEN CONSTANT_CASE string vocabulary \u2014 new surfaces mint ids without a schema change, and an unre",
    "title_b": "cross-node Gateway user-msg honored via advertised endpoint_type: a user-msg from a Gateway-typed origin survives the receive_wan funnel as user-msg (vs the fail-closed re-stamp), keyed on the QUIC-handshake-proven origin node (never wire `from`). Trust boundary = subnet membership (operator-ratifie",
    "doc_a": "control surface** (ratified 2026-07-28, access-control grill): The unit of access-control granularity: a named remote-reachable operation class on an endpoint. **Open string vocabulary, CONSTANT_CASE ids** (like capability ids \u2014 new surfaces mint ids without schema change). v1 set = the existing gat",
    "doc_b": "_Implemented posture_: the **local** user-backed origins are honored end-to-end \u2014 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**): the **subnet membership bound"
  },
  {
    "index": 4,
    "id_a": "REQ-MSG-6",
    "id_b": "REQ-PRES-1",
    "title_a": "cross-node Gateway user-msg honored via advertised endpoint_type: a user-msg from a Gateway-typed origin survives the receive_wan funnel as user-msg (vs the fail-closed re-stamp), keyed on the QUIC-handshake-proven origin node (never wire `from`). Trust boundary = subnet membership (operator-ratifie",
    "title_b": "Presence resolution: the presence datum (last_active_node, last_active_endpoint, ts) gossiped subnet-wide via the agent-interaction heartbeat (rides registry distribution, visibility-gated) + one first-class most-recently-active resolution API consumed by notif first-fire, update-consent delivery, c",
    "doc_a": "_Implemented posture_: the **local** user-backed origins are honored end-to-end \u2014 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**): the **subnet membership bound",
    "doc_b": "| 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 any \"scroll back fu"
  },
  {
    "index": 5,
    "id_a": "REQ-ADAPTER-FLOOR-ENFORCE",
    "id_b": "REQ-HAZARD-ADAPTER-APPLY-SILENT-NOOP",
    "title_a": "F-5 (REMOTE-TRUTH triage \u00a7F-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 [adapter].min_spt_core_version floor \u2014 with an F-1 operator refusal naming the installed core, the floor",
    "title_b": "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 the field repro (BUILD-F015B-APPLYMATCH: `--adapter cc:ccs` live update silently no-ops): (D1, matcher",
    "doc_a": "`min_spt_core_version` is the **enforced** compatibility floor. Both acquisition verbs \u2014 `spt adapter add` and `spt adapter update` \u2014 REFUSE when the installed spt-core is below this version, naming the installed core, the floor, and the next action (update spt-core first). The check is a numeric pe",
    "doc_b": "7.24 A delegated live adapter apply must NEVER report success without swapping, and the live-update seam must use ONE parent-aware adapter matcher `[REQ-HAZARD-ADAPTER-APPLY-SILENT-NOOP]` Failure (F015B / BUILD-F015B-APPLYMATCH):** a live adapter update to a PROFILE-COMPOSITE endpoint (`--adapter cc"
  },
  {
    "index": 6,
    "id_a": "REQ-ADAPTER-PROOF-DIR-OVERRIDE",
    "id_b": "REQ-HAZARD-COMMUNE-INGEST-BLACKHOLE",
    "title_a": "The author-time proof commands (`spt adapter digest-proof`, `spt adapter translate-proof`) gain a `--dir <path>` / `--manifest <file>` override so an author proofs a DEV binary against an on-disk manifest+install dir WITHOUT staging a full extracted GhReleaseManaged install (mirrors digest-proof's `",
    "title_b": "F-032 (perri field finding 2026-07-08, LEGACY-SPT-PARITY-GAP, data-loss): commune/signoff ingest MUST NOT delete a drop until its content is DURABLY COMMITTED to every APPLICABLE tier \u2014 a slice that cannot be committed this ingest must leave the drop in place for a later ingest (retry when the preco",
    "doc_a": "Proof a DEV build off disk \u2014 `--dir` / `--manifest`.** Both `digest-proof` and `translate-proof` accept `--dir <install-dir>` (binaries resolve there, just like a registered install) or `--manifest <file>` (pins the manifest its parent is the install dir) to proof an adapter that is **not registered",
    "doc_b": "7.40 A commune/signoff drop is deleted ONLY after every applicable tier is durably committed \u2014 an un-committable slice preserves the drop, never delete-then-lose `[REQ-HAZARD-COMMUNE-INGEST-BLACKHOLE]` Failure (paid-for, perri field finding 2026-07-08 \u2014 F-032, data-loss):** `ingest_drops` unconditio"
  },
  {
    "index": 7,
    "id_a": "REQ-ADAPTER-UNRESOLVED-HINT-FORM",
    "id_b": "REQ-MANIFEST-6",
    "title_a": "F-034 leg a (perri/hertz field finding 2026-07-09): the ADAPTER_UNRESOLVED refusal hint must print a WORKING command form. It currently says 'pass --adapter <name[:profile]>', but --adapter is a `spt api` GROUP flag, NOT a `listen` flag \u2014 following the hint literally (`spt api listen <id> --adapter ",
    "title_b": "Cross-adapter fallback target addressing (M12-W3-T3.2): a cross-adapter fallback target is addressed as `<adapter>:<profile>` (not just a bare adapter_name), resolved through the one composite-addressing resolver (registry::resolve_option) at every adapter-option read site so a fallback may select a",
    "doc_a": "",
    "doc_b": "Command templates are opaque.** spt-core never parses out a model/tool/flag \u2014 the adapter writes the whole command line; spt-core fills substitution keys and runs it. A command template's program token resolves against the adapter install dir before PATH (since v0.8.0).** A `.spt` adapter ships its "
  },
  {
    "index": 8,
    "id_a": "REQ-API-1",
    "id_b": "REQ-RUN-ID-REUSES-ADAPTER",
    "title_a": "api prefix and adapter_name on every machinery invocation",
    "title_b": "D-1 (REMOTE-TRUTH triage \u00a7D-1): `spt endpoint run --id <id>` with NO --adapter, when <id> names an EXISTING perch, REUSES that perch's recorded info.adapter and runs NON-INTERACTIVELY \u2014 instead of always falling to the picker as a create-new prefill (an existing endpoint retyping its own adapter, or",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 9,
    "id_a": "REQ-DIGEST-FETCHER-STRATEGY",
    "id_b": "REQ-DOC-ENDPOINT-DROP-RESOLUTION",
    "title_a": "Bug #17 (W6b, closes eel-a end-to-end): [digest] gains a `fetcher` strategy mirroring [history]'s locate/normalize split (CONTEXT \u00a7history: [digest] mirrors history's two strategies \u2014 locate ownership). ROOT: the pre-W6b [digest] had only the locate_normalize analog (spt-core resolves ONE `source` t",
    "title_b": "D1 (F028, perri F-c; docs/truth): SI-1's resolution rule \u2014 a RELATIVE watched drop dir resolves against the ENDPOINT's cwd, never the daemon's (KH 7.28, shipped v0.22.0) \u2014 is documented NOWHERE public. Add it to harness-contract/manifest.md + the manifest schema field descriptions so an adapter auth",
    "doc_a": "`[digest]` supports the same two locate strategies as `[history]` \u2014 pick with `strategy`: / `[digest]` \u2014 session-digest extractor (ADR-0019) The session digest's own seam \u2014 **distinct from `[history]`** (which stays opaque and single-session, feeding the echo-commune verbatim). Declares an **imperat",
    "doc_b": ""
  },
  {
    "index": 10,
    "id_a": "REQ-DOC-ECHO-COMMUNE-CONTRACT",
    "id_b": "REQ-RESUME-ADAPTER-FOLLOWS-SESSION",
    "title_a": "W6 (LIFECYCLE-TRUTH, docs \u2014 this gap cost a full outage night, priority slot): publish the [session.echo_commune] I/O contract on the docs-site: key catalog core fills; core does NOT stdin-feed [history] (field-proven); self-locate guidance incl. CLAUDE_CONFIG_DIR / read_env; drop-file protocol (sin",
    "title_b": "D-2 (REMOTE-TRUTH triage \u00a7D-2 + operator Q5 @c248afc): a resume-from-history restores the RECORDED session adapter (REQ-SESSION-ADAPTER-RECORDED) \u2014 the resumed harness is the one the session ran under, re-stamped onto the endpoint PRE-SPAWN, and an unregistered recorded adapter refuses LOUDLY before",
    "doc_a": "the full echo-commune I/O contract: the role + fields, the key catalog spt-core fills, the no-history-on-stdin rule, read-env self-locate, the single-writer/per-endpoint-resolver/ingest-deletes drop-file protocol, and stdout ingestion",
    "doc_b": ""
  },
  {
    "index": 11,
    "id_a": "REQ-EP-7",
    "id_b": "REQ-LISTEN-SEED-CONSUME-AFTER-BIND",
    "title_a": "Durable live-role.md: a per-agent broad-purpose statement in tracked/agents/<id>/ beside live-context.md (replicates with the mind on the same a-<id> branch); renders FIRST at start-transition context injection (role -> live-context -> project-context); SOLE writer `spt endpoint role --overwrite <fi",
    "title_b": "F-034 leg b (perri/hertz field finding 2026-07-09, hertz's HEADLINE): `api listen` must NOT consume the consume-once ephemeral seed on a PRE-BIND refusal \u2014 validate (adapter resolvable, home/subnet) and BIND first, THEN consume the seed. ROOT: today `api listen` burns the consume-once seed BEFORE it",
    "doc_a": "live role** (`live-role.md`, ratified 2026-06-12 \u2014 core milestone A): A durable statement of an agent's **broad purpose** \u2014 rarely modified, and only at deliberate user instruction. Lives in `tracked/` (the mind) beside `live-context.md`, so it replicates with the mind and follows the agent across n",
    "doc_b": "Recoverable refusals do not consume the seed.** The seed is consumed by a successful bind** \u2014 or by a refusal that proves the seed itself dead (see spend-vs-restore below). A recoverable refusal that never bound \u2014 `HOME_REFUSED` on a multi-subnet node without `--subnet`, `ADAPTER_UNRESOLVED`, a live"
  },
  {
    "index": 12,
    "id_a": "REQ-HAZARD-BROKER-SEED-WIRE-SKEW",
    "id_b": "REQ-LISTEN-SEED-CONSUME-AFTER-BIND",
    "title_a": "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 a brain-only self-update (ADR-0004 no-terminate-during-update forbids auto-killing it), so a NEW-ve",
    "title_b": "F-034 leg b (perri/hertz field finding 2026-07-09, hertz's HEADLINE): `api listen` must NOT consume the consume-once ephemeral seed on a PRE-BIND refusal \u2014 validate (adapter resolvable, home/subnet) and BIND first, THEN consume the seed. ROOT: today `api listen` burns the consume-once seed BEFORE it",
    "doc_a": "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]` Failure:** the broker serves the seed-control channel and is RESIDENT across a brain-only self-update (ADR-0004's no-terminate-during-update pilla",
    "doc_b": "Recoverable refusals do not consume the seed.** The seed is consumed by a successful bind** \u2014 or by a refusal that proves the seed itself dead (see spend-vs-restore below). A recoverable refusal that never bound \u2014 `HOME_REFUSED` on a multi-subnet node without `--subnet`, `ADAPTER_UNRESOLVED`, a live"
  },
  {
    "index": 13,
    "id_a": "REQ-HAZARD-ECHO-BEFORE-SIGNOFF",
    "id_b": "REQ-RESUME-ADAPTER-FOLLOWS-SESSION",
    "title_a": "Echo-commune fires before INIT_SIGNOFF on orphan teardown (3.3)",
    "title_b": "D-2 (REMOTE-TRUTH triage \u00a7D-2 + operator Q5 @c248afc): a resume-from-history restores the RECORDED session adapter (REQ-SESSION-ADAPTER-RECORDED) \u2014 the resumed harness is the one the session ran under, re-stamped onto the endpoint PRE-SPAWN, and an unregistered recorded adapter refuses LOUDLY before",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 14,
    "id_a": "REQ-LISTEN-SEED-CONSUME-AFTER-BIND",
    "id_b": "REQ-MANIFEST-8",
    "title_a": "F-034 leg b (perri/hertz field finding 2026-07-09, hertz's HEADLINE): `api listen` must NOT consume the consume-once ephemeral seed on a PRE-BIND refusal \u2014 validate (adapter resolvable, home/subnet) and BIND first, THEN consume the seed. ROOT: today `api listen` burns the consume-once seed BEFORE it",
    "title_b": "[adapter] host_binaries declares the harness executable basenames a kind=\"harness\" adapter hosts agents inside (e.g. host_binaries = [\"claude\"]); bind-time pid\u2192exe-basename match (case-insensitive, .exe-stripped) over the seed's parent_pid selects the candidate adapter set; zero matches \u2192 a friendly",
    "doc_a": "Recoverable refusals do not consume the seed.** The seed is consumed by a successful bind** \u2014 or by a refusal that proves the seed itself dead (see spend-vs-restore below). A recoverable refusal that never bound \u2014 `HOME_REFUSED` on a multi-subnet node without `--subnet`, `ADAPTER_UNRESOLVED`, a live",
    "doc_b": "Bind-time adapter/profile resolution (ADR-0021).** Because the seed is adapter-agnostic, `listen`/`poll` resolve the owning adapter/profile when they bind, as a pure read \u2014 never a seed-time snapshot that could drift. `--adapter <name[:profile]>` is an **optional override** on the `api` group (an ex"
  },
  {
    "index": 15,
    "id_a": "REQ-MANIFEST-NODE-KEY",
    "id_b": "REQ-SEAM-CAPABILITY",
    "title_a": "A new session-scoped manifest fill key `{node}` resolves to THIS node's advertised label \u2014 available wherever the session-scoped keys ({id}/{session_id}/{session_name}) populate: BOTH topologies' spawn-prep catalogs (harnesshost.rs:111-118 self-spawn guaranteed-fill + lifecycle.rs:280 base lifecycle",
    "title_b": "Hostable endpoint-types capability declaration",
    "doc_a": "```toml [session.self] {node} fills as one argv token \u2014 the node's advertised label (its hostname). command = \"claude --session-id {session_id} --remote-control {id}--{node}\" keys = [\"session_id\", \"id\", \"node\"] ```",
    "doc_b": ""
  },
  {
    "index": 16,
    "id_a": "REQ-RESUME-ADAPTER-FOLLOWS-SESSION",
    "id_b": "REQ-WORKER-MINTED-NAME",
    "title_a": "D-2 (REMOTE-TRUTH triage \u00a7D-2 + operator Q5 @c248afc): a resume-from-history restores the RECORDED session adapter (REQ-SESSION-ADAPTER-RECORDED) \u2014 the resumed harness is the one the session ran under, re-stamped onto the endpoint PRE-SPAWN, and an unregistered recorded adapter refuses LOUDLY before",
    "title_b": "N-1 (WORKER-TRUTH triage, operator rider): worker perch identity is CORE-MINTED and parent-derived \u2014 `{parent}-w{N}` with a per-parent counter at registration (sister shape: claude_skill_owl hook_subagent_start.rs) \u2014 never the adapter-presented agent id (CC Task ids render as random-named rows). wor",
    "doc_a": "",
    "doc_b": "`api worker-start <parent> [--agent-id <id>] [--agent-type <type>]`"
  },
  {
    "index": 17,
    "id_a": "REQ-UPDATE-APPLY-RESTART-NOTICE",
    "id_b": "REQ-UPDATE-FINISH-COMMUNE-FLUSH",
    "title_a": "`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 apply). Public wording, no internal CODE:RESULT markers (composes with REQ-ADAPTER-UPDATE-MESSAGE /",
    "title_b": "DEFERRED (post-LIFECYCLE-TRUTH, operator-ruled 2026-07-07 \u2014 mint now, impl a FUTURE milestone): make the update swap LOSSLESS for live hosted endpoints by flushing a final echo-commune per endpoint BEFORE the brain-subtree reap. ROOT (operator-surfaced probing --finish): `update apply --finish` = da",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 18,
    "id_a": "REQ-WAKE-RESUME-LEG",
    "id_b": "REQ-WAKE-WAIT",
    "title_a": "A-2 (REMOTE-TRUTH triage \u00a7A-2 + ADR-0033): the daemon reconcile gains a WAKE-RESUME LEG \u2014 an endpoint whose rest INTENT is Active but whose harness session is COLD (status != online) is resumed by the daemon via the adapter's [session.resume] template using the LAST LEDGER session id, so a bare `spt",
    "title_b": "A-2 rider (REMOTE-TRUTH triage \u00a7A-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 accepted-not-bound print (thin edge writes intent, daemon lifts async \u2014 ADR-0033). Reuses the F-027 bind-aw",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 19,
    "id_a": "REQ-CLI-1",
    "id_b": "REQ-MSG-INJECT-LEG-DROP-VISIBLE",
    "title_a": "spt endpoint noun namespace: absorbs fork/suspend/wake/shutdown/rename/stop/digest + access (ported 1:1: allow|revoke|open|list, decision 21) + description (ex-resources blurb; bare=show, set=author); merged endpoint list [--local|--subnet <name>] grouped by subnet with SELF pinned, --detail adding ",
    "title_b": "SEED (inactive \u2014 observability): a silently-dropped delivery leg must be DISTINGUISHABLE from an honestly-offline endpoint on a status surface. The spt-hosted inject leg (spt-daemon inject.rs `try_spt_hosted_inject` \u2014 the ONE shared implementation behind local cmd_send, the WAN ingress, the idle-edg",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 20,
    "id_a": "REQ-CLI-4",
    "id_b": "REQ-DAEMON-5",
    "title_a": "User-facing CLI output is human-readable: DIRECT-USER commands (e.g. adapter update/list/use) render friendly prose instead of raw CODE:RESULT markers \u2014 \"claude-spt is up to date (0.2.0).\" not \"ADAPTER_UPDATE_UPTODATE:claude-spt: installed 0.2.0, latest 0.2.0\". Strictly bounded to the direct-user su",
    "title_b": "Pump liveness: the peer pump writes a last-tick heartbeat consumed by daemon status / subnet status (decision 23 render legs in REQ-CLI-2/REQ-SUBNET-8); the daemon supervises the pump task \u2014 a panic is caught, logged loudly, and the pump restarts with capped backoff (\u22645 min), so a 5.9-class death se",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 21,
    "id_a": "REQ-CLI-HELP-MARKDOWN",
    "id_b": "REQ-SHELL-3",
    "title_a": "`spt --help` (and every subcommand --help) renders the inline Markdown authored in the clap doc-comments as terminal styling, never as literal markers: `**bold**` \u2192 ANSI bold, `` `code` `` \u2192 ANSI cyan, `[text](url)` \u2192 `text`. The markers are STRIPPED either way \u2014 a raw `**` or backtick must NEVER re",
    "title_b": "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) \u2014 a [shell.drive] manifest vocab + EVENT_TYPE_DRIVE frame, delivered to the ONLINE binary only via a single live slot (a new frame supe",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 22,
    "id_a": "REQ-CLI-WIN-VT-ENABLE",
    "id_b": "REQ-RESIDENT-SERVICE",
    "title_a": "A7 (F028, operator, Win10 conhost): ANSI emitted without VT enable \u2192 garbled console. Evidence (raw PowerShell 7, Win10 conhost): literal `\u2190[36m` in `endpoint list` + `--help`. ROOT: ENABLE_VIRTUAL_TERMINAL_PROCESSING is enabled ONLY on the rc attach path (rc.rs:746, REQ-RC-WIN-VT-OUTPUT) \u2014 plain CL",
    "title_b": "ResidentService substrate (ADR-0049, design ratified 2026-07-26): a daemon-supervised binary an adapter declares via a `[service]` manifest section \u2014 core-owned from birth, NO perch/identity/address. SPAWN: the daemon launches it job-neutrally (detached_no_inherit + the cold-start ladder posture), s",
    "doc_a": "",
    "doc_b": "`command`** \u2014 an **opaque** command string (program token plus args), like every other command seam. Its program token resolves against the adapter install dir** before PATH (REQ-INSTALL-11), and args support adapter-static `{adapter_dir}` / `{adapter_name}` substitution only. Must be non-empty: a d"
  },
  {
    "index": 23,
    "id_a": "REQ-DIGEST-JSON-SELF-CONTAINED",
    "id_b": "REQ-SHELL-ADAPTER-OWNED-DETACHED-SERVICE",
    "title_a": "TEARDOWN-AUTHORITY W4 (perri adapter-surface finding 2026-07-19, doyle-grounded and RE-SCOPED; title AMENDED at gate 2026-07-19 \u2014 the original welded version to --after polling, todlando falsified it from digesthub.rs/cli.rs and doyle ruled the amendment rides the wave: fifth instance of the claim-k",
    "title_b": "RULING OWED (unratified \u2014 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 only'. `shellhost::kill_shell_pid` force-kills with `taskkill /PID <pid> /T /F` \u2014 /T is a TREE kill, so `",
    "doc_a": "the self-contained --json contract: top-level integer version cursor, stderr-clean under --json, the complete entry-kind enum with per-kind agent-produced vs spt-injected provenance, and the seq/cursor asymmetry",
    "doc_b": ""
  },
  {
    "index": 24,
    "id_a": "REQ-ENDPOINT-LIST-NODE-IDENT",
    "id_b": "REQ-MSG-INJECT-LEG-DROP-VISIBLE",
    "title_a": "Bug #5: spt endpoint list local section header is the hardcoded literal LOCAL (this node) (render_local_section cli.rs:4359). Change to 'This node: <node-id>' using the existing node-ident idiom (os_hostname + nodeid public-key prefix, cli.rs:5531 \u2014 factor a node_ident_display helper); compute in th",
    "title_b": "SEED (inactive \u2014 observability): a silently-dropped delivery leg must be DISTINGUISHABLE from an honestly-offline endpoint on a status surface. The spt-hosted inject leg (spt-daemon inject.rs `try_spt_hosted_inject` \u2014 the ONE shared implementation behind local cmd_send, the WAN ingress, the idle-edg",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 25,
    "id_a": "REQ-ER-RULESET-TABLE",
    "id_b": "REQ-SHELL-1",
    "title_a": "The engine room presents access rulesets as TABLES (ADR-0052 decision 3). The rendering is a requirement rather than a nicety because the operator decision this surface exists to support \u2014 is this node's posture what I think it is \u2014 is a comparison across subjects, surfaces and tiers, and prose forc",
    "title_b": "Shell hosting machinery: shell perch under the owner (type/owner/adapter_name/status/alias), broker-launched binary + api bind local-link handshake, the three channels (command durable, text+file durable + progress-queryable, sensory REST-only never spooled + dropped-unless-owner-live), owner exclus",
    "doc_a": "Refuses all inbound except replies to its own outbound (knocks and knock-codes ARE accepted); online **only while a controller is attached** \u2014 detach drops it offline and every empowerment dies with it; `rc --view` denied even locally; remote attach denied; **local `rc --take` allowed** precisely be",
    "doc_b": ""
  },
  {
    "index": 26,
    "id_a": "REQ-HAZARD-TEMPLATE-ARGV-FILL",
    "id_b": "REQ-WHOAMI-EXPLICIT-SID-REFUSAL",
    "title_a": "Command-template substitution fills argv ELEMENTS, not a re-tokenized string: spt-core currently `fill_template`s {key} values INTO the command STRING and THEN `tokenize`s the filled string (runtime.rs:94/122), so a multi-word {key} value whitespace-SPLITS into multiple argv tokens unless the adapte",
    "title_b": "RULED DESIGN, delivery unowned (doyle 2026-07-26): when a caller hands identity resolution an EXPLICIT non-empty $OWL_SESSION_ID that resolves to NO perch, core must REFUSE identity (unresolved, exit 1, loud distinct diagnostic) rather than fall through to an ambient/inherited one \u2014 today `detect_se",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 27,
    "id_a": "REQ-SHELL-1",
    "id_b": "REQ-SHELL-ADAPTER-OWNED-DETACHED-SERVICE",
    "title_a": "Shell hosting machinery: shell perch under the owner (type/owner/adapter_name/status/alias), broker-launched binary + api bind local-link handshake, the three channels (command durable, text+file durable + progress-queryable, sensory REST-only never spooled + dropped-unless-owner-live), owner exclus",
    "title_b": "RULING OWED (unratified \u2014 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 only'. `shellhost::kill_shell_pid` force-kills with `taskkill /PID <pid> /T /F` \u2014 /T is a TREE kill, so `",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 28,
    "id_a": "REQ-DAEMON-REFRESH",
    "id_b": "REQ-HAZARD-CONTROLLER-IRRECOVERABLE-BEHIND",
    "title_a": "THE-FORKENING W4 (operator add 2026-07-14): `spt daemon refresh` \u2014 restart the daemon BRAIN without a binary swap and WITHOUT touching the broker: exactly the apply_staged brain-cycle path (brain stop -> respawn -> readiness trial -> promote, incl. the trial-drain drive REQ-UPDATE-TRIAL-DRAIN-DRIVE ",
    "title_b": "DEFERRED EDGE of REQ-HAZARD-CONTROLLER-GAP-RESUME: when a serving controller falls behind the live ring FURTHER than the ring holds (tail - delivered_through > cap_chunks, the ring trim being delivered_through-blind, broker.rs:327-330), the dropped frames have rolled OUT of the ring and an exactly-o",
    "doc_a": "daemon refresh (`spt daemon refresh`)** \u2014 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 previously required a ful",
    "doc_b": ""
  },
  {
    "index": 29,
    "id_a": "REQ-HAZARD-INJECT-CONTROL-COEXIST",
    "id_b": "REQ-SERVE-OWNERSHIP-GENERATION",
    "title_a": "SPINE INVARIANT (v0.13.0 keystone): the broker must accept INJECTED keystrokes into an spt-hosted PTY (the v0.11.0 raw direct-inject today; the ADR-0022 translation-binary choreography tomorrow) WHILE a live `spt rc` controller is attached to the SAME PTY, without (a) the operator losing control, (b",
    "title_b": "REDISPATCH-STALL W1 (ADR-0038 Amendment, fix 6): terminal-exclusion enforced PRE-SERVE + ownership/generation validation on attach/detach \u2014 a stale worker can never detach or displace a REPLACEMENT controller (today detach_if compares Arc ptr identity only; the serve path re-checks nothing at comple",
    "doc_a": "",
    "doc_b": "Amendment \u2014 REDISPATCH-STALL (2026-07-16)"
  },
  {
    "index": 30,
    "id_a": "REQ-DAEMON-4",
    "id_b": "REQ-UPDATE-FINISH-ENDPOINT-SURVIVAL",
    "title_a": "Honor every KNOWN-HAZARDS invariant",
    "title_b": "W3 (LIFECYCLE-TRUTH): daemon restart no longer massacres hosted endpoints \u2014 daemon start RE-RUNS previously-online spt-hosted endpoints. ROOT rig-proven: daemon stop+start (the apply notice's OWN instruction) kills every hosted endpoint; they stay OFFLINE after start (no resurrection) though records",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 31,
    "id_a": "REQ-ENSURE-DAEMON-STOP-INHIBIT",
    "id_b": "REQ-HAZARD-DAEMON-STOP-REAP",
    "title_a": "An operator stop outranks every implicit daemon ensure. (ADR-0047 decision 2, AMENDING REQ-DAEMON-3's anchor; hertz v0.39.4 field bug 2, RCA accepted 2026-07-22.) TODAY: every `spt api` invocation runs unconditional ensure_daemon() (api/mod.rs run()), so on a box with live adapter sessions a `daemon",
    "title_b": "Breap: `spt daemon stop` REAPS the spt-hosted children it spawned \u2014 no orphaned psyche/harness processes. Today a stop leaves ~8 orphaned claude-spt-psyche.exe + spt.exe: Psyches are spawned DETACHED (runtime.rs:342-356, the Child is dropped \u2014 'Detached' ~349) and the livehost stop flag Arc<AtomicBo",
    "doc_a": "\u2026with one exception, because you are allowed to mean it: **`spt daemon stop` sticks.** Auto-start is a convenience, and a convenience never overrules an explicit instruction. Once you stop the daemon, the implicit auto-start that every `spt` invocation performs *declines* to bring it back, printing ",
    "doc_b": ""
  },
  {
    "index": 32,
    "id_a": "REQ-DISPATCH-HYGIENE-TELEMETRY",
    "id_b": "REQ-STREAMLOG-SUBSCRIBER-DISCIPLINE",
    "title_a": "REDISPATCH-STALL W1 (ADR-0038 Amendment, fixes 7+8+9): dispatcher hygiene + keyed observability \u2014 (a) bounded redispatch worker pool with batched cold enumeration, NO claim locks held during I/O (today thread::spawn per stream, unbounded on a cold table); (b) sessions-lock discipline: clone-then-dro",
    "title_b": "REDISPATCH-STALL W1 (ADR-0038 Amendment, fixes 2+3+4): StreamLog subscriber write discipline \u2014 (a) replay and live fan-out HALT at the first failed subscriber write and the failed subscriber is REMOVED, at ALL sites (attach replay, append, finish; PresenceLog mirrors ride the same change \u2014 today let",
    "doc_a": "Amendment \u2014 REDISPATCH-STALL (2026-07-16)",
    "doc_b": "Amendment \u2014 REDISPATCH-STALL (2026-07-16)"
  },
  {
    "index": 33,
    "id_a": "REQ-DOCS-1",
    "id_b": "REQ-EP-6",
    "title_a": "Dual-audience docs (human + AI dev-agent), markdown once / two depths",
    "title_b": "Gateway type acceptance: a Gateway-typed perch binds (api bind --type, open type system \u2014 un-hardcode the live_agent default), advertises/addressable like any endpoint, owns shells (owner validation not agent-family-gated), subscribes to digests, and is the user-msg identity gate's user-backed origi",
    "doc_a": "the dual-audience contract surfaced to the second audience: agent exports, .md negotiation, schema, CLI-help-as-docs For AI agents reading this",
    "doc_b": "Gateway** (concept ratified 2026-06-11; registered via the open type system, first instance downstream): A **human-backed endpoint** \u2014 a user's specialized window into the subnet from a device or surface with no conventional-harness compatibility. Nothing LLM-shaped runs there; the intelligence at t"
  },
  {
    "index": 34,
    "id_a": "REQ-DOCS-5",
    "id_b": "REQ-WORKER-SID-SYMMETRIC-AUTH",
    "title_a": "Anti-drift: rustdoc/schema/exports/CLI-help generated + CI-checked",
    "title_b": "W-2 (WORKER-TRUTH triage, operator-ruled 2026-07-06): worker verbs go sid-symmetric with every sibling id-scoped verb \u2014 worker-start mints NO token and worker-stop takes NONE (token custody is undue adapter burden, ruling via perri). Registration STORES the sid it authenticated (the parent's sid at ",
    "doc_a": "",
    "doc_b": "`api worker-stop <id> --session-id <sid>` \u00b7 `api worker-poll <id> --session-id <sid>`"
  },
  {
    "index": 35,
    "id_a": "REQ-HAZARD-DEFERRED-SURVIVE-DRAIN",
    "id_b": "REQ-HAZARD-EPOCH-RESET",
    "title_a": "Deferred rows survive poll drain (4.4)",
    "title_b": "Advertisement-epoch reset strands a node: peers' higher last-seen epoch drops the reset node's fresh advertisements as Stale until the counter outruns history. Common case (full reinstall/re-pair) is mitigated by REQ-SUBNET-7's ceremony eviction (peer-side epoch memory dies with the deleted row \u2014 ac",
    "doc_a": "",
    "doc_b": "4.11 Advertisement-epoch reset strands a node `[REQ-HAZARD-EPOCH-RESET]` Failure:** a node whose advertisement-epoch counter resets (the durable `EpochSource` file lost/recreated) re-advertises with LOW epochs; peers hold a higher last-seen epoch for that `(endpoint, node)` lease and drop every fres"
  },
  {
    "index": 36,
    "id_a": "REQ-CONN-POISON-ATTRIBUTION",
    "id_b": "REQ-HAZARD-DAEMON-HOSTED-LIVENESS",
    "title_a": "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 \u2014 the W6 RCA's terminal undecidability (per-line 1:1 CONN_WRITE_POISONED churn = fresh-carrier churn OR stderr interleave artifact) exists because records carry no ",
    "title_b": "Daemon-hosted perches (Psyche, spt-hosted Self) derive liveness from the daemon endpoint table + info.json status, never is_process_alive(info.pid) (2.5)",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 37,
    "id_a": "REQ-DAEMON-5",
    "id_b": "REQ-WAKE-RESUME-LEG",
    "title_a": "Pump liveness: the peer pump writes a last-tick heartbeat consumed by daemon status / subnet status (decision 23 render legs in REQ-CLI-2/REQ-SUBNET-8); the daemon supervises the pump task \u2014 a panic is caught, logged loudly, and the pump restarts with capped backoff (\u22645 min), so a 5.9-class death se",
    "title_b": "A-2 (REMOTE-TRUTH triage \u00a7A-2 + ADR-0033): the daemon reconcile gains a WAKE-RESUME LEG \u2014 an endpoint whose rest INTENT is Active but whose harness session is COLD (status != online) is resumed by the daemon via the adapter's [session.resume] template using the LAST LEDGER session id, so a bare `spt",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 38,
    "id_a": "REQ-DAEMON-BITS-AMBIGUITY",
    "id_b": "REQ-PICKER-NODE-GROUPING",
    "title_a": "SEED (inactive, RCA-first \u2014 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-side echo): a post-reboot ensure race left a dev-build alchemy Hub Daemon serving release shells \u2014 versi",
    "title_b": "Bug #13: the endpoint run Subnet tab shows a machine once PER shared subnet (subnet_rows data.rs:253 iterates per-subnet, groups by subnet:node, no cross-subnet dedup). Fix: dedup by (node, endpoint_id) across the subnet loop, collect the set of shared subnet names per endpoint, emit one group per M",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 39,
    "id_a": "REQ-ENDPOINT-AUTOSTART",
    "id_b": "REQ-HAZARD-CORRUPT-PERCH-COHERENCE",
    "title_a": "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 absence, live): an endpoint can be marked a STARTUP DEFAULT so the daemon brings it back up at daemon sta",
    "title_b": "Corrupt (present-but-unparseable) info.json is NOT absent: liveness/status readers agree a destroyed record is neither alive nor Active (counter-39 #2)",
    "doc_a": "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 \u2026 --save` persists the run \u2014 endpoint id, adapter option, and working directory \u2014 as a **startup default** in `daemon.json`; the daemon **rep",
    "doc_b": "5.14 Corrupt info.json read as ABSENT \u2192 fail-open readers gossip a wiped perch ONLINE `[REQ-HAZARD-CORRUPT-PERCH-COHERENCE]` Failure:** three readers each collapsed a **corrupt** (present-but-unparseable) `info.json` into their fail-open ABSENT default, so a NUL-wiped perch (5.13) read as permanentl"
  },
  {
    "index": 40,
    "id_a": "REQ-ENDPOINT-CYCLE-HONEST",
    "id_b": "REQ-UPDATE-TRIAL-DRAIN-DRIVE",
    "title_a": "REGISTRY-LIFECYCLE W3 (ADR-0041 decision 6, operator deployah stop/run wedge): cycle verbs share ONE liveness authority \u2014 the ALREADY_LIVE dup-guard liveness-probes the claimed session client tree before refusing (dead tree means reap + respawn honestly, never a refusal citing a zombie); the shutdow",
    "title_b": "UPDATE-WEDGE (counter-54, doyle-ruled 2026-07-09 \u2014 regression of the v0.29.0 seamless brain-swap): a brain generation DRIVES the broker's controller-liveness reap (a KIND_SESSIONS poll) each heartbeat throughout its boot/trial loop, so a hard-KILLED prior generation's black-holed LOCAL controller co",
    "doc_a": "1. **Online is earned, not declared.** A creator may stamp `status=online` only from actual persisted state + hosting authority \u2014 never from manifest capability alone. Legacy hybrid rows self-heal at reconcile, but only after a SUCCESSFUL broker query: a broker failure is never interpreted as an emp",
    "doc_b": "brain-trial promotion (readiness + drained)** \u2014 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** \u2014 the old brain's loca"
  },
  {
    "index": 41,
    "id_a": "REQ-ENDPOINT-LIST-RENDER-POLISH",
    "id_b": "REQ-SHELL-2",
    "title_a": "A6 (F028, operator, 4 asks): `spt endpoint list` render polish. (a) the 'Shared subnets' line is NOT dim \u2014 LIGHT_GRAY = \"37\" (cli.rs:3019) is standard-palette WHITE, indistinguishable from row text; use SGR 90 (bright-black/gray) for the dim intent. (b) the `Total:` line takes the same dim color. (c",
    "title_b": "Shell sleep/wake: link-break always closes the binary (pre-close instruction + termination timeout), ephemeral teardown vs persistent offline/relink, wake_command wake-watcher (offline-only, exit-opcode supervision, exponential backoff + give-up), state-keyed wake resolution (dormant/suspended/activ",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 42,
    "id_a": "REQ-ENDPOINT-MESSAGE-ONLY-DISPLAY",
    "id_b": "REQ-RELAY-DEATH-CONVERGENCE",
    "title_a": "An online agent-family endpoint with NO session surface reads as message-reachable, not as a harness-hosted live agent and not as a plain ONLINE. (hertz v0.39.0 field report 2026-07-21; doyle PRODUCT RULING \u2014 deliberately NEITHER of the two options offered.) OBSERVED: an adapterless `spt ready` perc",
    "title_b": "A dead harness relay MUST converge the endpoint's projection \u2014 an endpoint whose relay process is provably gone cannot keep rendering `ONLINE - HARNESS ONLY` with ready=true alive=true and a registered address merely because the owner parent is still alive. RE-PROVEN PRESENT on 0.44.0 (hertz W0 item",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 43,
    "id_a": "REQ-ENDPOINT-STOP-OFFLINE",
    "id_b": "REQ-PID-ROLE-EVIDENCE",
    "title_a": "H3: `spt endpoint stop <id>` 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 offline, so a stopped daemon-hosted endpoint still reports alive=true (status=online latch). FIX: add s",
    "title_b": "THE RECORDED PID MUST CARRY WHAT IT MEANS. `info.pid` has two incompatible meanings decided by write path, and every reader has been guessing: the `api listen` path records a process that GENUINELY HOLDS the endpoint (its death IS the endpoint's relay death), while the `api bind` path records the an",
    "doc_a": "",
    "doc_b": "`info.json` \u2014 what the recorded `pid` MEANS (`pid_role`)"
  },
  {
    "index": 44,
    "id_a": "REQ-EP-4",
    "id_b": "REQ-PICKER-NODE-GROUPING",
    "title_a": "PresenceChannel broker endpoint (seam day-one)",
    "title_b": "Bug #13: the endpoint run Subnet tab shows a machine once PER shared subnet (subnet_rows data.rs:253 iterates per-subnet, groups by subnet:node, no cross-subnet dedup). Fix: dedup by (node, endpoint_id) across the subnet loop, collect the set of shared subnet names per endpoint, emit one group per M",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 45,
    "id_a": "REQ-HAZARD-ATTACH-WEDGE",
    "id_b": "REQ-PRESENCE-LIVENESS-TRUTH",
    "title_a": "A legitimately dead PTY child (real crash/kill) + an undrained operator pump must NOT wedge the broker for all other clients. ROOT (v0.12.0 real-harness defect): loopback attach output is a blocking write_all into a bounded 64KB tokio duplex (nethost.rs:1040,1090); when the operator's rc pump stops ",
    "title_b": "A node's gossiped per-endpoint registry Status reflects real liveness, so a remote viewer never paints a DEAD endpoint as ONLINE. ROOT (confirmed + gated vs CONTEXT.md): registryhost.rs:397-405 advertises a NOT-alive perch as Status::Dormant (the `else` of is_perch_alive), re-stamped every gossip ro",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 46,
    "id_a": "REQ-HAZARD-BOUNDARY-READY-STRAND",
    "id_b": "REQ-SELF-DETECT-PARENT-PID",
    "title_a": "C-2 (F029, SEAM-2 pinned \u2014 B6's SECOND HALF, the live-wake blocker; perri wakep9 vs wakep4 gate-state dump + doyle code trace): at a /clear, CC fires SessionEnd(reason=clear) for the DEPARTING session BEFORE SessionStart; the departing sid STILL matches the perch pin at that instant, so the adapter'",
    "title_b": "E-1 (REMOTE-TRUTH triage \u00a7E-1 #7): self-detect leg (c) \u2014 the pid-ancestry fallback \u2014 ALSO candidates on `rec.parent_pid` (the harness pid, CONTEXT's 'stable session-binding anchor', stamped at bind), not `rec.pid` alone. ROOT: for an spt-hosted endpoint (broker PTY, headless) `rec.pid` is the epheme",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 47,
    "id_a": "REQ-HAZARD-CORRUPT-PERCH-COHERENCE",
    "id_b": "REQ-UPDATE-TRIAL-DRAIN-DRIVE",
    "title_a": "Corrupt (present-but-unparseable) info.json is NOT absent: liveness/status readers agree a destroyed record is neither alive nor Active (counter-39 #2)",
    "title_b": "UPDATE-WEDGE (counter-54, doyle-ruled 2026-07-09 \u2014 regression of the v0.29.0 seamless brain-swap): a brain generation DRIVES the broker's controller-liveness reap (a KIND_SESSIONS poll) each heartbeat throughout its boot/trial loop, so a hard-KILLED prior generation's black-holed LOCAL controller co",
    "doc_a": "5.14 Corrupt info.json read as ABSENT \u2192 fail-open readers gossip a wiped perch ONLINE `[REQ-HAZARD-CORRUPT-PERCH-COHERENCE]` Failure:** three readers each collapsed a **corrupt** (present-but-unparseable) `info.json` into their fail-open ABSENT default, so a NUL-wiped perch (5.13) read as permanentl",
    "doc_b": "brain-trial promotion (readiness + drained)** \u2014 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** \u2014 the old brain's loca"
  },
  {
    "index": 48,
    "id_a": "REQ-HAZARD-DRIVEN-BY-SELFHEAL",
    "id_b": "REQ-MSG-INJECT-LEG-DROP-VISIBLE",
    "title_a": "An spt-hosted endpoint's ONLINE+CONTROLLED state (`driven_by`) must CLEAR even when the detach IPC is lost \u2014 do NOT rely on the detach signal (same lesson as REQ-HAZARD-HOSTED-LIVENESS-RECONCILE B2): the reconcile loop clears `driven_by` when the endpoint has no live controller/session. Today a wedg",
    "title_b": "SEED (inactive \u2014 observability): a silently-dropped delivery leg must be DISTINGUISHABLE from an honestly-offline endpoint on a status surface. The spt-hosted inject leg (spt-daemon inject.rs `try_spt_hosted_inject` \u2014 the ONE shared implementation behind local cmd_send, the WAN ingress, the idle-edg",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 49,
    "id_a": "REQ-HAZARD-HOSTED-LIVENESS-RECONCILE",
    "id_b": "REQ-TRANSLATE-COMMIT-MISS-TOLERANCE",
    "title_a": "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 + emits ExitEvent but NEVER touches info.json; lifecycle::mark_offline only fires on Psyche teardow",
    "title_b": "C-1 (F029, B6 ROOT \u2014 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_COMMIT_DEADLINE (5s, broker.rs:158) so the inject worker FAULTS + TERMINATES a HEALTHY translate bina",
    "doc_a": "",
    "doc_b": "Amendment (2026-07-03, F029 C-1) \u2014 a commit-miss is NOT a fault; real faults respawn"
  },
  {
    "index": 50,
    "id_a": "REQ-HAZARD-SHELL-STALE-ONLINE",
    "id_b": "REQ-RUN-PICKER",
    "title_a": "A shell instance's ONLINE-ness is DERIVED (recorded status AND its recorded `shell.pid` not provably dead), never the recorded `status` field alone \u2014 an abruptly-dead binary (force-kill, crash, OOM: no link-break, so `close_shell`'s offline flip never runs) must not read online forever. The shell-si",
    "title_b": "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 1 picks kind (Create new | Pick existing). Create-new: choose a registered kind=\"harness\" adapter w",
    "doc_a": "| # | 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 detection | | 2.3 | Handoff argv/IPC ve",
    "doc_b": "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 bringup path (`--adapter <a[:profile]> --id <id> -"
  },
  {
    "index": 51,
    "id_a": "REQ-INST-4",
    "id_b": "REQ-RUN-PICKER",
    "title_a": "active to dormant/suspended fires a transition echo commune",
    "title_b": "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 1 picks kind (Create new | Pick existing). Create-new: choose a registered kind=\"harness\" adapter w",
    "doc_a": "",
    "doc_b": "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 bringup path (`--adapter <a[:profile]> --id <id> -"
  },
  {
    "index": 52,
    "id_a": "REQ-LISTEN-PRESERVES-HOSTING-TOPOLOGY",
    "id_b": "REQ-TRANSLATE-COMMIT-MISS-TOLERANCE",
    "title_a": "`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-preserving `api listen --session-id` produces a self-contradictory live record \u2014 controlled=true AND co",
    "title_b": "C-1 (F029, B6 ROOT \u2014 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_COMMIT_DEADLINE (5s, broker.rs:158) so the inject worker FAULTS + TERMINATES a HEALTHY translate bina",
    "doc_a": "",
    "doc_b": "Amendment (2026-07-03, F029 C-1) \u2014 a commit-miss is NOT a fault; real faults respawn"
  },
  {
    "index": 53,
    "id_a": "REQ-PICKER-CONTROL-LINE-STATUS-GATE",
    "id_b": "REQ-SPAWN-COLLISION-GUARD-LIVE-DUP",
    "title_a": "A2 (F028, operator #2): the picker confirm-panel 'controlled locally' line renders for OFFLINE endpoints. view.rs:425-436 builds control_line from ep.controlled with NO status gate; an offline endpoint with a stale controlled stamp shows 'controlled locally' (operator screenshot: hall-a offline + co",
    "title_b": "W4 (LIFECYCLE-TRUTH): single-flight wake per endpoint \u2014 the WAKE/RESUME respawn seam must not launch twice for one wake. ROOT (perri parentage + recovered filing): one wake processed TWICE within 1s \u2014 broker (306368) spawned two identical `launch --cli ccs --id flynn --resume <sid>` 1s apart, both s",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 54,
    "id_a": "REQ-PSYCHE-LEGACY-RESIDENT-SWEEP",
    "id_b": "REQ-PUMP-PEER-ISOLATION",
    "title_a": "W5 (F030; doyle+perri 2026-07-04): a dirty daemon upgrade from <=v0.24.0 strands a RESIDENT psyche wrapper the OLD daemon spawned \u2014 and F-030 W4's nested-`ready` resolution fix CONVERTED that wrapper's accidental self-reap into a permanent HANG. The pre-W3 wrapper's only spt IPC is `spt ready <paren",
    "title_b": "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) SEQUENTIAL fan-out (for peer in fan_targets dials one-at-a-time, each up to the bound -> peer N+1 waits",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 55,
    "id_a": "REQ-RUN-PICKER",
    "id_b": "REQ-WAKE-RESUME-LEG",
    "title_a": "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 1 picks kind (Create new | Pick existing). Create-new: choose a registered kind=\"harness\" adapter w",
    "title_b": "A-2 (REMOTE-TRUTH triage \u00a7A-2 + ADR-0033): the daemon reconcile gains a WAKE-RESUME LEG \u2014 an endpoint whose rest INTENT is Active but whose harness session is COLD (status != online) is resumed by the daemon via the adapter's [session.resume] template using the LAST LEDGER session id, so a bare `spt",
    "doc_a": "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 bringup path (`--adapter <a[:profile]> --id <id> -",
    "doc_b": ""
  },
  {
    "index": 56,
    "id_a": "REQ-API-2",
    "id_b": "REQ-EP-5",
    "title_a": "The api subcommand surface (bind/listen/poll/state/worker/boundary/...)",
    "title_b": "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, instance aliasing, discovery scope",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 57,
    "id_a": "REQ-ER-RESERVED-ENDPOINT",
    "id_b": "REQ-SEAM-SPAWN",
    "title_a": "A node has exactly ONE engine-room endpoint, and 'exactly one' is STRUCTURAL rather than policed: the engine room lives at a reserved per-node endpoint id, so a second one cannot be created any more than a directory can hold two entries of the same name (ADR-0052 decision 1). It is an ordinary agent",
    "title_b": "spawn-session seam",
    "doc_a": "A locked-down **agent endpoint** (harness-adapter-backed, spt-hosted, has a mind \u2014 it can be briefed on and reason about the node's access posture). It is the designated way to set the **node's** control-surface modes.",
    "doc_b": ""
  },
  {
    "index": 58,
    "id_a": "REQ-SEAM-POSTSPAWN",
    "id_b": "REQ-SELF-ID-TRUST-INJECTED-ENV",
    "title_a": "post-spawn / api bind seam with boot nonce",
    "title_b": "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 silently mis-attributing. ROOT (doyle /diagnose 2026-07-07, field: agent sends stamped `cli@HFENDULE",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 59,
    "id_a": "REQ-ENDPOINT-STOP-RESOLVES",
    "id_b": "REQ-HAZARD-SEEDMAP-CONNECT-UNBOUNDED",
    "title_a": "`spt endpoint stop <id>` REFUSES an id that nothing on the node knows, instead of stamping success on a no-op \u2014 an unconditional-success verb is a lying instrument (find: liam via flynn's discriminating repro, mechanism corrected by flynn 2026-07-26 superseding the original shell-half-action framing",
    "title_b": "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 hazard the stop path just bounded \u2014 a Windows named-pipe connect to a name that EXISTS but has NO acce",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 60,
    "id_a": "REQ-HAZARD-SEEDMAP-CONNECT-UNBOUNDED",
    "id_b": "REQ-RC-DISPLAY-SOLE-WRITER",
    "title_a": "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 hazard the stop path just bounded \u2014 a Windows named-pipe connect to a name that EXISTS but has NO acce",
    "title_b": "TEARDOWN-AUTHORITY W5 (hertz RCA 3 bug 1, 2026-07-19 \u2014 REPRODUCED on 0.38.1 CLI + 0.38.1 broker; doyle ruled, and it CORRECTS an incomplete v0.38.1 call of doyle's own): while `spt rc` owns the terminal (raw / alternate screen), rc is the SOLE writer to that display \u2014 no background thread may write ",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 61,
    "id_a": "REQ-ACL-NODE-MODE-SET",
    "id_b": "REQ-ER-RESERVED-ENDPOINT",
    "title_a": "The node's control-surface modes are settable through the engine room and nowhere else (ADR-0052 decisions 1 and 3, CONTEXT.md 'control-surface modes' \u2014 the node level of the three). Modes are exactly what a confused or adversarial agent would loosen, so the mutation surface must be the one place an",
    "title_b": "A node has exactly ONE engine-room endpoint, and 'exactly one' is STRUCTURAL rather than policed: the engine room lives at a reserved per-node endpoint id, so a second one cannot be created any more than a directory can hold two entries of the same name (ADR-0052 decision 1). It is an ordinary agent",
    "doc_a": "A locked-down **agent endpoint** (harness-adapter-backed, spt-hosted, has a mind \u2014 it can be briefed on and reason about the node's access posture). It is the designated way to set the **node's** control-surface modes.",
    "doc_b": "A locked-down **agent endpoint** (harness-adapter-backed, spt-hosted, has a mind \u2014 it can be briefed on and reason about the node's access posture). It is the designated way to set the **node's** control-surface modes."
  },
  {
    "index": 62,
    "id_a": "REQ-ER-INBOUND-LOCK",
    "id_b": "REQ-ER-RC-INTENT-LOCKS",
    "title_a": "The engine room refuses ALL inbound except replies to its own outbound, with a dormant knock exemption landed in the same seam (ADR-0052 decision 3; doyle ruling (f) 2026-07-29). The lock is what keeps a minded governance surface from being reachable \u2014 and therefore promptable \u2014 by the very agents w",
    "title_b": "The engine room's attach surface is locked by INTENT: rc --view is denied even same-node, remote attach of any intent is denied, and local --take is allowed (ADR-0052 decision 3). Viewing is denied because a read-only spectator on the surface that renders access rulesets is an information leak with ",
    "doc_a": "Refuses all inbound except replies to its own outbound (knocks and knock-codes ARE accepted); online **only while a controller is attached** \u2014 detach drops it offline and every empowerment dies with it; `rc --view` denied even locally; remote attach denied; **local `rc --take` allowed** precisely be",
    "doc_b": "Decision 3 was written in the language of the ceremony, and two of its clauses do not survive contact with the daemon's lifecycle invariants. Both are amended here rather than built literally."
  },
  {
    "index": 63,
    "id_a": "REQ-ACTIVITY-LIST-JSON",
    "id_b": "REQ-HAZARD-STALE-SIGNOFF-SENTINEL",
    "title_a": "`spt endpoint list --json` carries a per-endpoint `activity` (busy|idle) key, for consumers surveying the idle/busy state of many endpoints at once (ADR-0048 decision 1, roster pull avenue; operator addition 2026-07-24). Additive key, N-1-safe; kin the flynn 2026-07-06 last-active/description/adapte",
    "title_b": "Stale signoff sentinel does not kill a fresh start (3.2)",
    "doc_a": "| Command | Top-level shape | |---|---| | `endpoint list` | `{ self, subnets[], local[] }` \u2014 `self`: `{id, status, ready, alive, unbound, description, psyche_host_error, translation_fault?}`; `subnets[]`: `{name, endpoints[]}` where each endpoint is `{id, node, node_label, status, resources, endpoin",
    "doc_b": ""
  },
  {
    "index": 64,
    "id_a": "REQ-ADAPTER-ADD-SURFACE-ERRORS",
    "id_b": "REQ-EP-9",
    "title_a": "Bug #1: adapter add runs the install-as-first-update via conduct (cli.rs:6963) which on a non-zero exit prints only the exit code and DISCARDS the subprocess stdout/stderr, so the real error is invisible (the failure itself does propagate). Fix: include out.stderr/stdout in the ADAPTER_INSTALL_FAIL ",
    "title_b": "`#` always-on address sigil: a reserved LEADING sigil marking an AlwaysOnEndpoint, extending the REQ-INST-10 grammar to `[subnet:]#id[@node]`. Mandatory + bijective \u2014 `#name` \u27fa always-on endpoint, bare `name` \u27fa agent endpoint \u2014 so the router resolves endpoint class from the address alone, before any",
    "doc_a": "",
    "doc_b": "Status: accepted (2026-06-21)"
  },
  {
    "index": 65,
    "id_a": "REQ-ADAPTER-GH-TRANSPORT",
    "id_b": "REQ-ADAPTER-UPDATE-MESSAGE",
    "title_a": "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 \u2014 the private-repo path; `gh` honors OAuth and `GH_TOKEN`, so spt custodies no token), or `auto` (default: prefer `gh` when installed+",
    "title_b": "An adapter manifest may declare `[update].message` \u2014 a plain (multi-line) human notice surfaced to stdout, markdown-rendered (the v0.13.0 helpfmt prose path), ONLY when `spt adapter update` actually APPLIES an update (version changed), not on a no-op. Read from the newly-installed manifest; avenue-a",
    "doc_a": "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/`, \u2026); install/update extracts the shared root plus only the current nod",
    "doc_b": "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/`, \u2026); install/update extracts the shared root plus only the current nod"
  },
  {
    "index": 66,
    "id_a": "REQ-ADAPTER-MULTIPLATFORM-SPT",
    "id_b": "REQ-UPDATE-FETCH-APPLY-FLAG",
    "title_a": "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 vocabulary, e.g. `x86_64-pc-windows-msvc/`); install/update extracts the shared root plus ONLY `curren",
    "title_b": "`spt update fetch --apply` is the one-shot get-to-latest: fetch, then INSTALL the staged update REGARDLESS of whether the fetch itself staged anything new \u2014 so the brittle `fetch && apply` chain (which broke when fetch no-oped / exited nonzero on an already-staged latest, skipping the chained apply)",
    "doc_a": "Multi-platform adapter `.spt` packaging",
    "doc_b": ""
  },
  {
    "index": 67,
    "id_a": "REQ-ADAPTER-UPDATE-MESSAGE",
    "id_b": "REQ-RELEASE-MUSL-ARTIFACT",
    "title_a": "An adapter manifest may declare `[update].message` \u2014 a plain (multi-line) human notice surfaced to stdout, markdown-rendered (the v0.13.0 helpfmt prose path), ONLY when `spt adapter update` actually APPLIES an update (version changed), not on a no-op. Read from the newly-installed manifest; avenue-a",
    "title_b": "MUSL-TIER W3 (CI build + signed release + update-set publish + self-update E2E): release.yml gains a musl matrix entry (build on kitsubito; install musl-tools+cmake+target in-job, CC_x86_64_unknown_linux_musl=musl-gcc); the assemble job includes spt-x86_64-linux-musl in SHA256SUMS + the release uplo",
    "doc_a": "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/`, \u2026); install/update extracts the shared root plus only the current nod",
    "doc_b": ""
  },
  {
    "index": 68,
    "id_a": "REQ-CI-POSTJOB-DAEMON-REAP",
    "id_b": "REQ-RUN-SHORTCUT",
    "title_a": "A CI job REAPS ITS OWN test-spawned daemons at battery end, in-job, and logs a process census at job start AND job end so contamination and reap effectiveness are visible in every run's log. (Load-flake family leg 1, doyle-ratified 2026-07-22 from deployah's third-run analysis.) THE SIGNATURE THIS C",
    "title_b": "`<basename>-<id>` launcher shortcut generation (picker `s` keybind, M12-W2-T2.4): from any pre-start options set the picker writes/updates a `<basename>-<id>` launcher at the project root baking the current selection's non-interactive `spt endpoint run` flags (terminal actions only: adapter[:profile",
    "doc_a": "",
    "doc_b": "`spt-<id>` shortcut** (picker `s` keybind, M12-W2): From any pre-start options set, `s` writes (or updates) a **`<basename>-<id>` launcher** at the project root that bakes the current selection's **non-interactive** flags (terminal actions only: adapter[:profile] + id + create|resume + start|attach|"
  },
  {
    "index": 69,
    "id_a": "REQ-DAEMON-9",
    "id_b": "REQ-UPDATE-RUNNING-IMAGE-SURFACE",
    "title_a": "Net-bind boot-race resilience: a daemon that comes up net-less (NetHost::start failed \u2014 e.g. the systemd unit autostarted before the network/DNS stack was ready, `Failed to create an address lookup service`) must SELF-HEAL \u2014 retry the net bring-up in the background with capped backoff and, on succes",
    "title_b": "`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 D3-3) \u2014 the BROKER process survives and keeps running its pre-apply compiled image, so every broker-s",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 70,
    "id_a": "REQ-HAZARD-DEFERRED-MANIFEST",
    "id_b": "REQ-INST-15",
    "title_a": "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 LIVE from source_dir (registry.rs manifest_dir ~146/149); a deferred / un-extracted install makes loa",
    "title_b": "Immutable home subnet (assigned at creation: auto-if-one/ask-if-many) + spt fork (cross-subnet clone to a new identity, copy-then-diverge, not re-home); adapter chosen at creation from registered hostable adapters, changed only via launch/resume-under-new (ADR-0010)",
    "doc_a": "",
    "doc_b": "Delivered (M4-D9-5, 2026-06-04):** home assignment at creation (`spt_store::home` \u2014 auto-if-one / ask-if-many / local-only-until-first-join, carried forward across re-binds, no setter) + `sync_subnets = [home]` creation seeding + `spt fork <src> <new_id> --subnet <target [--delete-source]` (one-time"
  },
  {
    "index": 71,
    "id_a": "REQ-HAZARD-WMI-DAEMON-WINDOW",
    "id_b": "REQ-INSTALL-3",
    "title_a": "`spt daemon start` launches the daemon with NO visible console window. REGRESSION (v0.12.1 L1.5): the WMI job-neutral launch (spawn_daemon_via_wmi) set CREATE_NO_WINDOW on the launching powershell but NOT on the Win32_Process.Create call \u2014 Win32_Process.Create does not inherit it, so the spawned cmd",
    "title_b": "Idempotent + interactive-optional first run",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 72,
    "id_a": "REQ-INST-11",
    "id_b": "REQ-INST-12",
    "title_a": "spt rename <id> rippled to all instances (collision-checked, 6.5-reconciled)",
    "title_b": "Endpoint visibility per-(endpoint,subnet): excluded semantics, OR-of-defaults + override, gates sync",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 73,
    "id_a": "REQ-INST-13",
    "id_b": "REQ-PLATFORM-REGISTRY",
    "title_a": "Subnet-exclusive sync + per-endpoint subnet-membership list",
    "title_b": "MUSL-TIER W1 (target-triple centralization, behaviour-NEUTRAL refactor): ONE authoritative platform registry from which current_platform(), KNOWN_TARGET_TRIPLES, the applyhost cross-platform 'other' logic, and the asset-name<->triple map all derive. ROOT: the target triple x86_64-unknown-linux-gnu +",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 74,
    "id_a": "REQ-INST-2",
    "id_b": "REQ-MIGRATE-1",
    "title_a": "Per-node files, synced Psyche mind",
    "title_b": "Auto-detect and migrate a legacy claude_skill_owl install",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 75,
    "id_a": "REQ-INST-6",
    "id_b": "REQ-INST-7",
    "title_a": "Deferred messages not delivered to dormant/suspended instances",
    "title_b": "Subnet registry + bare-id resolution policy",
    "doc_a": "| 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 any \"scroll back fu",
    "doc_b": ""
  },
  {
    "index": 76,
    "id_a": "REQ-INST-9",
    "id_b": "REQ-PLATFORM-MUSL",
    "title_a": "Multi-subnet membership (same-user N subnets; cross-user seam)",
    "title_b": "MUSL-TIER W2 (register the musl platform, self-IDENTIFY): add x86_64-unknown-linux-musl to the W1 registry \u2014 a current_platform() cfg arm (target_arch=x86_64, target_os=linux, target_env=musl -> the musl triple, NO more 'unknown' fallback), asset name spt-x86_64-linux-musl, triple-map entry. PROVEN ",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 77,
    "id_a": "REQ-INSTALL-12",
    "id_b": "REQ-UPDATE-FETCH-CURRENT-UX",
    "title_a": "Durable active-profile pointer for bind-time profile selection (ADR-0021): adapters/active-profiles.toml at the registry ROOT (sibling to the per-adapter <name>/ dirs, so adapter add/update/remove \u2014 which only rewrite a <name>/ subdir \u2014 can never clobber it), a flat host_binary \u2192 \"adapter[:profile]\"",
    "title_b": "`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 = staged_version, so when the published candidate == the already-staged version, verify_update_set_metad",
    "doc_a": "Bind-time adapter/profile resolution (ADR-0021).** Because the seed is adapter-agnostic, `listen`/`poll` resolve the owning adapter/profile when they bind, as a pure read \u2014 never a seed-time snapshot that could drift. `--adapter <name[:profile]>` is an **optional override** on the `api` group (an ex",
    "doc_b": ""
  },
  {
    "index": 78,
    "id_a": "REQ-INSTALL-7",
    "id_b": "REQ-MANIFEST-SUBST",
    "title_a": "Windows inbound reachability: the elevated install leg registers the inbound-UDP firewall rule (New-NetFirewallRule); the daemon self-detects blocked inbound and renders it as the no-connection state in subnet status + the coming-online banner (covers user-scope installs that skip the elevated leg \u2014",
    "title_b": "Manifest substitution primitives for resolve-not-execute (ADR-0029, supersedes a rejected `spt api run-hook`): (1) two adapter-static substitution keys `{adapter_dir}` (the registry record's precise source_dir \u2014 install dir, survives updates, the dir bare-program resolution uses) and `{adapter_name}",
    "doc_a": "",
    "doc_b": "Adapter-static keys \u2014 `{adapter_dir}` and `{adapter_name}` (since v0.16.0).** Two of the catalog keys are *adapter-static* \u2014 they depend only on the resolved adapter, never on a session or event, so they are available **wherever** command/string substitution runs (every `[session.*]` template, the `"
  },
  {
    "index": 79,
    "id_a": "REQ-RELEASE-MUSL-ARTIFACT",
    "id_b": "REQ-RUN-SHORTCUT",
    "title_a": "MUSL-TIER W3 (CI build + signed release + update-set publish + self-update E2E): release.yml gains a musl matrix entry (build on kitsubito; install musl-tools+cmake+target in-job, CC_x86_64_unknown_linux_musl=musl-gcc); the assemble job includes spt-x86_64-linux-musl in SHA256SUMS + the release uplo",
    "title_b": "`<basename>-<id>` launcher shortcut generation (picker `s` keybind, M12-W2-T2.4): from any pre-start options set the picker writes/updates a `<basename>-<id>` launcher at the project root baking the current selection's non-interactive `spt endpoint run` flags (terminal actions only: adapter[:profile",
    "doc_a": "",
    "doc_b": "`spt-<id>` shortcut** (picker `s` keybind, M12-W2): From any pre-start options set, `s` writes (or updates) a **`<basename>-<id>` launcher** at the project root that bakes the current selection's **non-interactive** flags (terminal actions only: adapter[:profile] + id + create|resume + start|attach|"
  },
  {
    "index": 80,
    "id_a": "REQ-BROKER-OUTPUT-BEFORE-EXIT",
    "id_b": "REQ-MANIFEST-2",
    "title_a": "RC-RENDER-TRUTH W3 (ADR-0043 decision 1, hertz stale-glyphs RCA leg 1 P0): the PTY drain/output writer is the SOLE FIFO sequencer for terminal Output + Exit per attach sink \u2014 Exit is enqueued BEHIND all prior output (drain EOF/completion first, then Exit); the exit waiter never direct-writes KIND_EX",
    "title_b": "Adapter profiles \u2014 sparse leaf-replace overlays (shipped + local), composite <adapter>:<profile> addressing, shadow-refusal, tighten-only consent floors",
    "doc_a": "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 \u2014 producer order is the contract. Output-before-Exi",
    "doc_b": "adapter profile** (ratified 2026-06-11, Gateway grill; future spt-core milestone \u2014 first beneficiaries `spt-claude-code` and the usbip shell): A named **sparse overlay** on its parent adapter manifest. Merge semantics are **leaf-replace**: a profile key replaces the whole value at that path (arrays "
  },
  {
    "index": 81,
    "id_a": "REQ-HAZARD-DIRECT-WRITE-PRECEDENCE",
    "id_b": "REQ-PROJECT-INDEX-READER-CUTOVER",
    "title_a": "Direct-write precedence marker (with node id) guards stale overwrite (6.5)",
    "title_b": "PROJECT-INDEX W3 (ADR-0037): endpoint list, the picker, and endpoint-info consume the materialized index \u2014 NO git work in any user-facing read path (the O(PxB+C) fanout at cli.rs ~2954 / picker/data.rs ~456-518 dies). BEHAVIORAL PARITY is binding: precedence session-cwd -> origin-cwd -> context-rece",
    "doc_a": "",
    "doc_b": "project index** \u2014 a node's endpoint\u2192project attribution is DERIVED state, held as a **persistent materialized index** (ADR-0037): `spt-store` owns the versioned format + read path (daemon-offline reads = last persisted snapshot); the **daemon is the sole single-flight writer** (load-at-start, ready-"
  },
  {
    "index": 82,
    "id_a": "REQ-HAZARD-SINGLE-PATH-SOURCE",
    "id_b": "REQ-MANIFEST-6",
    "title_a": "Single path/registry source of truth; no layout ambiguity (6.1)",
    "title_b": "Cross-adapter fallback target addressing (M12-W3-T3.2): a cross-adapter fallback target is addressed as `<adapter>:<profile>` (not just a bare adapter_name), resolved through the one composite-addressing resolver (registry::resolve_option) at every adapter-option read site so a fallback may select a",
    "doc_a": "",
    "doc_b": "Command templates are opaque.** spt-core never parses out a model/tool/flag \u2014 the adapter writes the whole command line; spt-core fills substitution keys and runs it. A command template's program token resolves against the adapter install dir before PATH (since v0.8.0).** A `.spt` adapter ships its "
  },
  {
    "index": 83,
    "id_a": "REQ-INSTALL-4",
    "id_b": "REQ-START-5",
    "title_a": "Adapter registration lifecycle: spt adapter add (--github, manifest-first, install-is-first-update) + soft-deregister remove + optional manifest uninstall template; node-local registered-adapter set self-update ripples over",
    "title_b": "Adapter-agnostic harness-hosted seed + bind-time adapter/profile resolution (ADR-0021): `api seed` carries only parent_pid + session_id (+ optional cwd), no --adapter \u2014 a pure \"a harness session exists at this pid\" record; --adapter becomes an OPTIONAL override across the whole api group (an explici",
    "doc_a": "",
    "doc_b": "Harness-hosted (e.g. spt-plugin; the harness binary is user-launched, harness is the parent).** Key constraint: the SPT *live agent* does not exist until the agent invokes start \u2014 the `live_id` isn't chosen at session boot, and `$LIVE start` is itself invoked *behind the Monitor tool*, so it becomes"
  },
  {
    "index": 84,
    "id_a": "REQ-MANIFEST-6",
    "id_b": "REQ-STORE-1",
    "title_a": "Cross-adapter fallback target addressing (M12-W3-T3.2): a cross-adapter fallback target is addressed as `<adapter>:<profile>` (not just a bare adapter_name), resolved through the one composite-addressing resolver (registry::resolve_option) at every adapter-option read site so a fallback may select a",
    "title_b": "spt-store::BranchStore (git branch as versioned KV; commit=checkpoint/tip=resume, atomic multi-key, merge-native sync) is the substrate for coarse/durable/audited state (context, registry snapshot+distribution, daemon checkpoint); hot paths (B5 fsync journal) + indexed queries (SQLite spool) exclude",
    "doc_a": "Command templates are opaque.** spt-core never parses out a model/tool/flag \u2014 the adapter writes the whole command line; spt-core fills substitution keys and runs it. A command template's program token resolves against the adapter install dir before PATH (since v0.8.0).** A `.spt` adapter ships its ",
    "doc_b": ""
  },
  {
    "index": 85,
    "id_a": "REQ-CARRIER-CLAIM-EXCLUSIVE",
    "id_b": "REQ-TERM-2",
    "title_a": "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 \u2014 the first carrier to take a row (hook-poll drain, relay idle-inject, relay-backlog, psyche) atomically CLAIMS it so no other carrier can re-del",
    "title_b": "session-surface abstraction; send-keys + send-line injection",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 86,
    "id_a": "REQ-HAZARD-INBOX-NO-DOUBLE",
    "id_b": "REQ-SEND-WINDOW-DRAIN-HONOR",
    "title_a": "No double-delivery via legacy inbox (4.5)",
    "title_b": "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_ACTIVE_ONLY doc + cli.rs:85; `spt send --active-only` / the hidden `--deferred` alias and `send_def",
    "doc_a": "",
    "doc_b": "F-035 RCA \u2014 report-before-fix. F-035 RCA \u2014 idle-edge parked-drain ignores the delivery-window tag"
  },
  {
    "index": 87,
    "id_a": "REQ-CONN-BLACKHOLE-LIFECYCLE-HARNESS",
    "id_b": "REQ-CONN-POISON-DIAL-SCOPE",
    "title_a": "MSG-IDENTITY W6 / F-039 leg e (doyle W6 LOCK 2026-07-10, minted per amendment 3 \u2014 hertz's five invariants VERBATIM from his RCA fix-shape item 5): 'Build a deterministic black-holed-controller harness against current v0.30.6 semantics and assert: unrelated sessions continue; the bad physical connect",
    "title_b": "MSG-IDENTITY W6 / F-039 (deployah field-acceptance follow-up 2026-07-10, RCA-FIRST \u2014 mint per the v0.30.6 PASS handoff): ambient CONN_WRITE_POISONED log-churn correlates 1:1 with PUMP_PEER_FAIL submit-dials to OFFLINE peers (enlyzeam/kitsubito/gravity) with NO wedge and NO freeze \u2014 pre-existed the b",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 88,
    "id_a": "REQ-EP-9",
    "id_b": "REQ-SHELL-4",
    "title_a": "`#` always-on address sigil: a reserved LEADING sigil marking an AlwaysOnEndpoint, extending the REQ-INST-10 grammar to `[subnet:]#id[@node]`. Mandatory + bijective \u2014 `#name` \u27fa always-on endpoint, bare `name` \u27fa agent endpoint \u2014 so the router resolves endpoint class from the address alone, before any",
    "title_b": "Shell tunnel (reliable-ordered opaque byte stream): an owner<->shell link may hold a long-lived, reliable-ordered, link-bound QUIC stream pair carrying opaque wire protocol traffic the channel taxonomy must NOT reinterpret (first consumer usbip URB) \u2014 manifest opt-in, not enveloped, not MAC-framed, ",
    "doc_a": "Status: accepted (2026-06-21)",
    "doc_b": "shell tunnel: a long-lived reliable-ordered link-bound QUIC stream pair carrying opaque bytes the taxonomy never reinterprets; manifest opt-in, not enveloped/MAC-framed/spooled; link-break closes it; reliable-ordered \u21d2 on-LAN posture Channels carry typed, taxonomy-interpreted payloads. Distinct from"
  },
  {
    "index": 89,
    "id_a": "REQ-NOTIF-1",
    "id_b": "REQ-NOTIF-QUIET-DELIVERY",
    "title_a": "Notification primitive: per-subnet replicated spool, seen/dismissed, resurface-at-boundary, subsumes update+consent prompts",
    "title_b": "The notify kind rides the active_only window UNCONDITIONALLY, rollback included: spool-only, never live TCP, never a wake, for EVERY producer; loudness = resurface-until-dismissed persistence, never PTY interruption; boundary resurface (clear/compact/new-session/wake) + the adapter safe-point drain ",
    "doc_a": "",
    "doc_b": "4. Delivery: the notify kind rides `active_only`, unconditionally"
  },
  {
    "index": 90,
    "id_a": "REQ-ER-BRINGUP-TOTP-GATE",
    "id_b": "REQ-PAIR-NTP-LOUD-FAIL",
    "title_a": "Bringing the engine room online \u2014 and attaching a controller to it \u2014 requires a same-node CLI call PLUS a member-or-admin TOTP for its home subnet, and never OS elevation (ADR-0052 decision 2). The gate proves 'a human holding this subnet's material is at the controls', which is the question that ma",
    "title_b": "W1/D2 (JOIN-TRUTH): total NTP failure (no server on any family answered) is LOUD, not silent \u2014 a node running the ceremony on its raw skewed system clock must be visible. ROOT: current_offset_secs (ntp.rs) does `query_offset_secs().unwrap_or(0)` and eprintln's ONLY on a nonzero success, so an all-se",
    "doc_a": "Bring-online + controller-attach requires a **same-node CLI call plus a member-or-admin TOTP** for the engine-room's home subnet. The gate proves a human holding subnet material is at the controls; agents cannot pass it.",
    "doc_b": ""
  },
  {
    "index": 91,
    "id_a": "REQ-JOIN-DIAGNOSTICS",
    "id_b": "REQ-PAIR-3",
    "title_a": "`spt subnet join` never fails SILENTLY (ADR-0030; the field incident showed no output at all). (a) LIVE progress during the meet (replace the one-shot \"Searching\u2026\" cli.rs:6268 with periodic elapsed/deadline) so silence \u2260 hang; (b) DETAILED failure on meet-exhaustion \u2014 rendezvous candidates + familie",
    "title_b": "Fetch current pairing code from any paired node",
    "doc_a": "Robust WAN subnet join: meet-before-code + per-family bind gate",
    "doc_b": ""
  },
  {
    "index": 92,
    "id_a": "REQ-PAIR-2",
    "id_b": "REQ-SUBNET-ADMIN-SEED-REPLICATION",
    "title_a": "Local trust store with TOFU + warn-on-change",
    "title_b": "Every member node holds BOTH subnet seeds \u2014 the admin seed replicates at join exactly as the member seed does \u2014 because empower verification and admin-code joins are LOCAL operations any member node must be able to serve without consulting a privileged peer (ADR-0051 decision 2; the mesh stays symme",
    "doc_a": "",
    "doc_b": "2. Held everywhere, revealable nowhere / 3. Irrecoverable by design"
  },
  {
    "index": 93,
    "id_a": "REQ-ENDPOINT-LIST-PALETTE",
    "id_b": "REQ-STORE-CONTEXT-BRANCH-FILL",
    "title_a": "Bugs #11 + #15 (display): spt endpoint list renders status as plain text while the picker turns the same ResourceRow into the W5 colored EpDisplay palette. Fix: extract one shared ResourceRow-to-EpDisplay builder + make the picker display enums/helpers public, and have endpoint list render the same ",
    "title_b": "#1 SI-1 (RCA, operator-promoted 2026-07-03): the context store (tracked/.seed.git) holds ZERO p-* branches on a box with months of live-agent use, while kitsubito/enlyzeam stores carry them. Context commits never land -> picker history has no store source (REQ-PICKER-PROJECT-HISTORY-TRUTH's fallback",
    "doc_a": "",
    "doc_b": "7.28 A relative manifest path resolves against the ENDPOINT, never the daemon `[REQ-STORE-CONTEXT-BRANCH-FILL]` Class rule:** a relative manifest path naming a filesystem location the ENDPOINT reads or writes MUST resolve against the endpoint's own cwd (its `info.json.cwd`, read at USE time), never "
  },
  {
    "index": 94,
    "id_a": "REQ-PICKER-1",
    "id_b": "REQ-PICKER-5",
    "title_a": "The picker renders a FOUR-state endpoint status (extending the W2 online/offline duality): the list-item square AND a color-coded STATUS line at the top of the pick-existing right-side details both show \u2014 gray OFFLINE; green ONLINE (online + PTY-controllable spt-hosted, not controlled); amber 'ONLIN",
    "title_b": "`spt endpoint list` (bare/subnet view) renders an ALIGNED table with canonical node labels: cmd_endpoint_list prints subnet rows with `\\t` TAB separators (cli.rs:~1651-1662) so variable-width endpoint_ids snap fields to different tab-stops \u2192 a RAGGED status column (operator screenshot: X/help status",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 95,
    "id_a": "REQ-PICKER-4",
    "id_b": "REQ-PICKER-START-PROJECT-CHOICE",
    "title_a": "The picker's Subnet category renders the canonical node LABEL, not bare key-hex: a subnet row's node renders as 'LABEL (keyprefix\u2026)' (e.g. 'HFENDULEAM (bcead52b\u2026)') per CONTEXT.md:650 + Instance.node_label, NOT the raw node key-hex (SPT_DEV:14efb80cb\u2026 \u2014 a picker-only regression because resource_proj",
    "title_b": "#5: after 'Start now' in the endpoint picker, swap the bottom Options panel to a 'Choose project' list: (1) the endpoint's most recent project dir, (2) 'Here: <dir>' \u2014 the spt endpoint run cwd (only if different), (3) all other project-history dirs newest->oldest. Fire the step ONLY when (A) the run",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 96,
    "id_a": "REQ-PICKER-CHOOSE-DEDUP-ALL",
    "id_b": "REQ-PICKER-CURRENT-DIR-LABEL",
    "title_a": "A4 (F028, operator #5): choose-project duplicate rows. model.rs:314-337 build_project_choices dedups the `Here: <run_cwd>` row only against the HEAD ref's dir (line 324) \u2014 an OLDER history ref with the SAME dir still renders, giving `Here: C:\\...\\projects` + `projects` as two rows for one project (o",
    "title_b": "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 `Here:` row is (correctly) suppressed by the dedup (REQ-PICKER-CHOOSE-DEDUP-ALL), but the matching ",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 97,
    "id_a": "REQ-PICKER-NODE-GROUPING",
    "id_b": "REQ-PICKER-REMOTE-WAKE",
    "title_a": "Bug #13: the endpoint run Subnet tab shows a machine once PER shared subnet (subnet_rows data.rs:253 iterates per-subnet, groups by subnet:node, no cross-subnet dedup). Fix: dedup by (node, endpoint_id) across the subnet loop, collect the set of shared subnet names per endpoint, emit one group per M",
    "title_b": "C-2 (REMOTE-TRUTH triage \u00a7C-2 #4 + addendum @3442ce5): a REMOTE suspended picker row offers `Wake now` \u2014 waking the endpoint THROUGH its owning node's rest edge (the A-2 daemon resume leg) \u2014 instead of a bare `Start now` that silently cold-starts a COLLIDING LOCAL instance of a remote id (node-ancho",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 98,
    "id_a": "REQ-PICKER-SHORTCUT-LABEL-FILENAME",
    "id_b": "REQ-STORE-CONTEXT-BRANCH-FILL",
    "title_a": "B-4 (F029, operator): the confirm-panel shortcut option label is a static `New/Update spt-<id> shortcut (s)` placeholder \u2014 it should name the REAL file it writes: `Set shortcut here --> <current dir>/<shortcut-name>` where <shortcut-name> is the EXACT on-disk filename (incl. extension). The name mus",
    "title_b": "#1 SI-1 (RCA, operator-promoted 2026-07-03): the context store (tracked/.seed.git) holds ZERO p-* branches on a box with months of live-agent use, while kitsubito/enlyzeam stores carry them. Context commits never land -> picker history has no store source (REQ-PICKER-PROJECT-HISTORY-TRUTH's fallback",
    "doc_a": "",
    "doc_b": "7.28 A relative manifest path resolves against the ENDPOINT, never the daemon `[REQ-STORE-CONTEXT-BRANCH-FILL]` Class rule:** a relative manifest path naming a filesystem location the ENDPOINT reads or writes MUST resolve against the endpoint's own cwd (its `info.json.cwd`, read at USE time), never "
  },
  {
    "index": 99,
    "id_a": "REQ-HAZARD-DAEMON-IDENTITY-ENV-SANITIZE",
    "id_b": "REQ-HAZARD-PARENT-PID-PREFER",
    "title_a": "MSG-IDENTITY W1 / F-036 leg a (perri field RCA 2026-07-09/10, psyche seat-theft \u2014 doyle ACCEPTED primary fix): the daemon MUST sanitize inherited per-session identity env (SPT_ENDPOINT_ID / OWL_SESSION_ID / SPT_AGENT_ID) at startup AND before EVERY role spawn \u2014 these are per-session identity and are",
    "title_b": "Prefer stable parent PID / broker handle over ephemeral PID (2.1)",
    "doc_a": "7.39 Per-session identity env (`SPT_ENDPOINT_ID`/`OWL_SESSION_ID`/`SPT_AGENT_ID`) is NEVER inherited \u2014 the daemon scrubs it at startup AND on every role spawn, regardless of any role's declared `env_remove` `[REQ-HAZARD-DAEMON-IDENTITY-ENV-SANITIZE]` Failure (paid-for, perri field RCA 2026-07-09/10 ",
    "doc_b": ""
  },
  {
    "index": 100,
    "id_a": "REQ-API-4",
    "id_b": "REQ-HAZARD-ENDPOINT-RUN-ATTACH-OUTPUT",
    "title_a": "api resolves the adapter manifest (+ profile + install dir) from `--adapter name:profile` via the registry when `--manifest` is omitted; `--manifest` becomes an optional OVERRIDE (unregistered / local-dev manifests). Removes the require-both-flags redundancy \u2014 a registered adapter's live bringup / d",
    "title_b": "A clean `spt rc` attach to a LIVE spt-hosted (`endpoint run`) harness must DELIVER the harness's PTY output. KEYSTONE \u2014 the operator's central 'attach shows no output' symptom, reproduced on the real dummy-harness fixture (v0.12.1 Wave 1) with NO death and NO wedge: bringup succeeds (online, harness",
    "doc_a": "Manifest resolution from `--adapter` (since v0.8.0).** `spt api <cmd> --adapter <name[:profile]>` resolves the registered adapter's manifest, `:profile` overlay, and install dir from the registry when `--manifest` is omitted \u2014 a registered adapter's `api` calls need only `--adapter`. `--manifest <pa",
    "doc_b": ""
  },
  {
    "index": 101,
    "id_a": "REQ-BIND-PSYCHE-CUSTODY-SQUAT-GUARD",
    "id_b": "REQ-HAZARD-BRAIN-RESTART-LIFECYCLE-REHYDRATE",
    "title_a": "MSG-IDENTITY W1 / F-036 leg c (perri field RCA, doyle ACCEPTED defense-in-depth): a bind whose --set-session-id equals a NESTED psyche perch's own custody sid is definitionally wrong and MUST be refused \u2014 core owns psyche-custody.json and can see the collision at bind time. ROOT CONTEXT: with the F-",
    "title_b": "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) re-subscribes to the broker's PTY sessions but ALL BrainLifecycle instances (lifecycle.rs:58-130; the",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 102,
    "id_a": "REQ-DAEMON-9",
    "id_b": "REQ-ECHO-DROP-DIR-RESOLVE",
    "title_a": "Net-bind boot-race resilience: a daemon that comes up net-less (NetHost::start failed \u2014 e.g. the systemd unit autostarted before the network/DNS stack was ready, `Failed to create an address lookup service`) must SELF-HEAL \u2014 retry the net bring-up in the background with capped backoff and, on succes",
    "title_b": "W1 (LIFECYCLE-TRUTH): fire_echo resolves the manifest commune_dir through the SAME resolver its siblings use before any write. ROOT (pinned): fire_echo (spt-daemon lifecycle.rs:790) passes the RAW manifest commune_dir into run_echo_commune -> echo.rs:115-117 create_dir_all+join; a relative `.claude`",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 103,
    "id_a": "REQ-ECHO-DROP-DIR-RESOLVE",
    "id_b": "REQ-HAZARD-ENDPOINT-RUN-ATTACH-OUTPUT",
    "title_a": "W1 (LIFECYCLE-TRUTH): fire_echo resolves the manifest commune_dir through the SAME resolver its siblings use before any write. ROOT (pinned): fire_echo (spt-daemon lifecycle.rs:790) passes the RAW manifest commune_dir into run_echo_commune -> echo.rs:115-117 create_dir_all+join; a relative `.claude`",
    "title_b": "A clean `spt rc` attach to a LIVE spt-hosted (`endpoint run`) harness must DELIVER the harness's PTY output. KEYSTONE \u2014 the operator's central 'attach shows no output' symptom, reproduced on the real dummy-harness fixture (v0.12.1 Wave 1) with NO death and NO wedge: bringup succeeds (online, harness",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 104,
    "id_a": "REQ-HAZARD-DAEMON-IDENTITY-ENV-SANITIZE",
    "id_b": "REQ-HEAVY-UNIT-CLASSIFICATION",
    "title_a": "MSG-IDENTITY W1 / F-036 leg a (perri field RCA 2026-07-09/10, psyche seat-theft \u2014 doyle ACCEPTED primary fix): the daemon MUST sanitize inherited per-session identity env (SPT_ENDPOINT_ID / OWL_SESSION_ID / SPT_AGENT_ID) at startup AND before EVERY role spawn \u2014 these are per-session identity and are",
    "title_b": "A unit test that stands up a REAL broker inside a lib/bin `#[cfg(test)]` block must sit in the `heavy-broker-pty` nextest group, and the classification must be ENFORCED rather than remembered. FLAKE-LEDGER #14 diagnosed this class in the `spt` binary, wrote the CLASS in prose, then shipped an ENUMER",
    "doc_a": "7.39 Per-session identity env (`SPT_ENDPOINT_ID`/`OWL_SESSION_ID`/`SPT_AGENT_ID`) is NEVER inherited \u2014 the daemon scrubs it at startup AND on every role spawn, regardless of any role's declared `env_remove` `[REQ-HAZARD-DAEMON-IDENTITY-ENV-SANITIZE]` Failure (paid-for, perri field RCA 2026-07-09/10 ",
    "doc_b": ""
  },
  {
    "index": 105,
    "id_a": "REQ-HAZARD-ENDPOINT-RUN-ATTACH-OUTPUT",
    "id_b": "REQ-PSYCHE-EPHEMERAL-DRIVER",
    "title_a": "A clean `spt rc` attach to a LIVE spt-hosted (`endpoint run`) harness must DELIVER the harness's PTY output. KEYSTONE \u2014 the operator's central 'attach shows no output' symptom, reproduced on the real dummy-harness fixture (v0.12.1 Wave 1) with NO death and NO wedge: bringup succeeds (online, harness",
    "title_b": "W1 (F030, design \u00a73): each psyche-relevant event runs exactly ONE bounded per-event turn through the existing driver stack (psyche_turn_and_relay for outbound-intent events / resume_psyche for session-custody transitions / run_psyche_turn for pure merges) \u2014 no resident psyche process exists between ",
    "doc_a": "",
    "doc_b": "Psyche**: The Psyche companion's own perch, distinct from its paired LiveAgent's perch. First-class endpoint type so messages addressed to a LiveAgent's Psyche route directly without ambiguity. **A Psyche is a bounded per-event turn, not a resident process (since v0.25.0).** Each psyche-relevant eve"
  },
  {
    "index": 106,
    "id_a": "REQ-HAZARD-LIVEHOST-BOOT-RACE",
    "id_b": "REQ-TERM-7",
    "title_a": "The brain's daemon-hosted Psyche lifecycle surfaces a host-FAILURE on the live perch (harness-diagnosable) and runs net-INDEPENDENTLY. When reconcile_once\u2192host_one\u2192spawn_psyche fails for a state=live_agent+status=online endpoint (e.g. the adapter's psyche binary absent from its install dir, REQ-INST",
    "title_b": "Two-origin digest merge: spt-owned context-injection entries (psyche_download | echo_mirror | owl_message) appended by spt to the endpoint `digest.log`, timestamp-interleaved with the adapter's extracted activity records into one ordered timeline, via a distinct context-injection record category. Da",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 107,
    "id_a": "REQ-HAZARD-PSYCHE-RESIDENCY-EXPECTATION",
    "id_b": "REQ-PSYCHE-ACCOUNT-REFUSAL-EXIT",
    "title_a": "W3 (F030 hazard; paid-for: hall-bf churn ordinal 6491+ + adapter v0.13.2 bad-ship brick 2026-07-04): a psyche failure of ANY shape must NOT remove or alter the parent endpoint's ready/hosted state, and hosting must NOT churn-respawn. The v0.13.2 shim-exit tripped the residency machinery (confirm_res",
    "title_b": "RESERVED EXIT 96 \u2014 account/credential refusal from a psyche_resume turn: the inner tool refused for account-level reasons (spend/usage cap, expired/revoked credential, org quota) \u2014 session healthy, code healthy, retry correct-but-pointless until a HUMAN acts. Core discriminates on the EXIT CODE ALON",
    "doc_a": "7.30 A Psyche failure of ANY shape must NEVER remove or alter the parent endpoint's ready/hosted state `[REQ-HAZARD-PSYCHE-RESIDENCY-EXPECTATION]` Failure (paid-for, field brick 2026-07-04, adapter v0.13.2):** the pre-F-030 model kept a **resident** Psyche process the daemon supervised, with residen",
    "doc_b": "Reserved exit codes \u2014 how a `psyche_resume` turn tells spt-core *why* it failed.** spt-core classifies a failed turn on the process **exit code alone \u2014 never on output text** (your harness may reword, restructure, or JSON-wrap its errors freely; only the code is contract). Any other nonzero exit is "
  },
  {
    "index": 108,
    "id_a": "REQ-HAZARD-UNHOST-PSYCHE-REAP",
    "id_b": "REQ-HOST-RUN-2",
    "title_a": "On un-host, the detached `{id}-psyche` HARNESS PROCESS is reaped \u2014 not just its in-brain pulse-driver thread. Today stop_host (livehost.rs:203) trips the HostedLife stop flag + JOINS the driver thread, but the Psyche is a detached harness process (spawn_psyche \u2192 ManifestRuntime detached spawn, runti",
    "title_b": "Project-scoped working directory for spt-hosted bringup: `spt endpoint run` lands the broker-spawned harness PTY in the user's PROJECT cwd, not the daemon's, via an additive `SpawnReq.cwd` field carried through the broker PTY spawn (portable-pty CommandBuilder cwd). N-1-safe wire change (additive, d",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 109,
    "id_a": "REQ-HOST-RUN-1",
    "id_b": "REQ-INST-2",
    "title_a": "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 \u2014 same broker path shellhost.rs launch_shell_brokered_in uses for shells, now for kind=\"harness\" self-role), registers the p",
    "title_b": "Per-node files, synced Psyche mind",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 110,
    "id_a": "REQ-INST-2",
    "id_b": "REQ-PSYCHE-CRASHLOOP-BACKOFF-SHUTDOWN",
    "title_a": "Per-node files, synced Psyche mind",
    "title_b": "C3 (F028, perri F-h): psyche wrapper crash-loop has no backoff, and `endpoint shutdown` misses a wedged wrapper. A probe psyche crash-looped ~3 boots/sec for ~30min (CC died instantly on the untrusted owlery cwd; ledger hit ordinal 5358) \u2014 SILENTLY; and `spt endpoint shutdown` did NOT tear the loopi",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 111,
    "id_a": "REQ-NET-3",
    "id_b": "REQ-WORKER-PICKER-EXCLUDED",
    "title_a": "Cross-node Psyche sync over P2P replaces gh-repo-sync",
    "title_b": "V-2 (WORKER-TRUTH triage, operator rider): non-drivable endpoint classes never render as `spt endpoint run` picker rows \u2014 a worker perch cannot be driven, instantiated, or controlled; offering it is a lie the picker then fails on. Filter endpoint_type worker (and the psyche class if it ever surfaces",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 112,
    "id_a": "REQ-PSYCHE-CONTEXT-FILE-INDIRECTION",
    "id_b": "REQ-PSYCHE-STAMP-CLEAR-ANY-SUCCESS",
    "title_a": "W4 (F030; doyle Q2 ruling + perri file-always freeze, 2026-07-04): the composed psyche mind ({psyche_context}) rides the SHIM argv today \u2014 a real ~20KB doyle psyche-download exceeds the win32 CreateProcess lpCommandLine ~32k cap \u2192 the shim spawn BRICKS. FIX (file-always, replaces {psyche_context} ou",
    "title_b": "W1 (LIFECYCLE-TRUTH): EVERY successful psyche operation clears psyche_host_error \u2014 not just the pulse-loop leg. ROOT (three field confirmations, perri): the stamp clears only via note_turn_outcome's Ok leg (lifecycle.rs:1101); a SUCCESSFUL psyche op via checkpoint/wake bypasses it -> stale FAILED st",
    "doc_a": "Psyche-download \u2014 `{psyche_context_file}` (file-always, replaces `{psyche_context}`).** The composed Psyche mind rides a **file**, never the command argv: before each turn spt-core writes the mind into the nested psyche perch dir and fills a single **`{psyche_context_file}` = that path** (argv-cap-i",
    "doc_b": ""
  },
  {
    "index": 113,
    "id_a": "REQ-PSYCHE-ROLE-OPTIONAL-SKIP",
    "id_b": "REQ-WORKER-SID-SYMMETRIC-AUTH",
    "title_a": "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 -> commune-sync hard-fails -> 3-strike stamps the host ('manifest declares no [session.echo_commune] ro",
    "title_b": "W-2 (WORKER-TRUTH triage, operator-ruled 2026-07-06): worker verbs go sid-symmetric with every sibling id-scoped verb \u2014 worker-start mints NO token and worker-stop takes NONE (token custody is undue adapter burden, ruling via perri). Registration STORES the sid it authenticated (the parent's sid at ",
    "doc_a": "",
    "doc_b": "`api worker-stop <id> --session-id <sid>` \u00b7 `api worker-poll <id> --session-id <sid>`"
  },
  {
    "index": 114,
    "id_a": "REQ-START-2",
    "id_b": "REQ-TERM-7",
    "title_a": "Harness-hosted startup: api seed then listen",
    "title_b": "Two-origin digest merge: spt-owned context-injection entries (psyche_download | echo_mirror | owl_message) appended by spt to the endpoint `digest.log`, timestamp-interleaved with the adapter's extracted activity records into one ordered timeline, via a distinct context-injection record category. Da",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 115,
    "id_a": "REQ-REL-1",
    "id_b": "REQ-RELEASE-CHANNEL-PRIVATE",
    "title_a": "HISTORICAL (superseded by ADR-0036 / REQ-RELEASE-CHANNEL-PRIVATE + REQ-DOCS-LOCAL-SERVER): spt-releases publish-target repo \u2014 README public face, licensing split, Pages docs at the ADR-0014 canonical URL. The Pages pipeline retired at THE-FORKENING (docs-publish.yml deleted W2, xtask site() deleted ",
    "title_b": "THE-FORKENING W2 (ADR-0036 \u00a72): the publish pipeline targets `BigscreenVR/spt-bs-releases` \u2014 release.yml assemble/draft/flip retargeted (draft lands on the bs releases repo, untagged, per the existing spt-releases pattern); docs-publish.yml RETIRED (no public docs, ADR-0014 superseded) with the mdbo",
    "doc_a": "delivered M6-D1: SaberMage/spt-releases created (private), README + LICENSE-MIT/LICENSE-BINARY pushed (2debda8); Pages goes live at the D7 flip",
    "doc_b": ""
  },
  {
    "index": 116,
    "id_a": "REQ-ADAPTER-UPDATE-INPLACE",
    "id_b": "REQ-HAZARD-SHAREDSEND-NO-BLOCKING-WRITE-UNDER-LOCK",
    "title_a": "Bug #18: spt adapter update fails at re-register with os error 2 because it derives the install dir from the update repo NAME (_github/<safe>) instead of updating in place at the adapter record source_dir; when the adapter repo is intentionally renamed across releases (spt-claude-code to claude-spt,",
    "title_b": "UPDATE-WEDGE round-4 (hertz RCA, root reproduced + source-pinned on Windows 2026-07-09): EVERY write on a physical broker connection rides ONE bounded + cancelable + poison-on-failure framed-write primitive \u2014 no writer may hold the connection's serialized send gate across an UNBOUNDED OS write. ROOT",
    "doc_a": "",
    "doc_b": "7.38 EVERY write on a physical broker connection is bounded + cancelable + poison-on-failure \u2014 no writer holds the send gate across an UNBOUNDED OS write `[REQ-HAZARD-SHAREDSEND-NO-BLOCKING-WRITE-UNDER-LOCK]` Failure (paid-for, field capture + deterministic Windows repro 2026-07-09 \u2014 hertz RCA, UPDA"
  },
  {
    "index": 117,
    "id_a": "REQ-ADAPTER-UPDATE-POST",
    "id_b": "REQ-UPDATE-GH-TRANSPORT",
    "title_a": "Composite adapter update \u2014 an avenue-agnostic `[update.post]` sub-table `{ command, self_verifies }` run AFTER the primary avenue (gh_release/file_pull/delegated) resolves, in the same `spt adapter update` (ADR-0029). Runs UNCONDITIONALLY (even on an adapter version no-op \u2014 the post-step's own idemp",
    "title_b": "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 \u2014 release discovery (`releases/latest`, cli.rs:9717) and asset download (cli.rs:4861 public browser URLs) move to deadline-wrapped `gh` subpro",
    "doc_a": "`[update.post]` \u2014 the composite post-step (since v0.16.0) / Composite update \u2014 `[update.post]` (since v0.16.0).** An optional **avenue-agnostic** sub-table that runs a delegated **post-step** *after* the primary update avenue resolves, in the same `spt adapter update`. It lets an adapter pull its `.",
    "doc_b": "release channel (private, gh-carried)** \u2014 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 authed `gh` cannot fet"
  },
  {
    "index": 118,
    "id_a": "REQ-BROKER-ATTACH-JOURNAL-RESILIENT",
    "id_b": "REQ-RELEASE-MUSL-ARTIFACT",
    "title_a": "A poisoned EffectJournal mutex or a sick NetHost runtime must NOT permanently brick all future attaches. Bug #16 (URGENT): a live spt-hosted endpoint (eel-a) attach fails with 'brain IPC read deadline elapsed' after a self-update brain-respawn \u2014 the broker survives the respawn and one journaled op (",
    "title_b": "MUSL-TIER W3 (CI build + signed release + update-set publish + self-update E2E): release.yml gains a musl matrix entry (build on kitsubito; install musl-tools+cmake+target in-job, CC_x86_64_unknown_linux_musl=musl-gcc); the assemble job includes spt-x86_64-linux-musl in SHA256SUMS + the release uplo",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 119,
    "id_a": "REQ-DOCS-RELEASE-ASSET",
    "id_b": "REQ-HAZARD-INPUT-ACK-BACKPRESSURE",
    "title_a": "THE-FORKENING W2 (ADR-0036 \u00a74): every release ships a platform-independent docs bundle `spt-docs.tar.gz` (BUILT mdbook output: HTML + llms.txt + llms-full.txt + raw .md + manifest.schema.json) as a release asset WITH an entry in the SIGNED update-set (sha256, same integrity chain as binaries \u2014 docs ",
    "title_b": "A FLOOD of operator input on one brain\u2194broker connection deadlocks the broker PERMANENTLY (entire broker \u2014 no new/existing attach; the controller stays latched because the per-conn handler can't process the detach). ROOT (doyle /diagnose, code-grounded + HITL capture, the v0.13.0 P1 ctrl+V re-open):",
    "doc_a": "docs bundle** \u2014 every release ships a platform-independent archive of the **built docs** (HTML + `llms.txt` + `llms-full.txt` + raw markdown + `manifest.schema.json`) as a **signed update-set asset**; apply lands it at `$SPT_HOME/docs`, so a node's docs always match its installed version. A docs-ass",
    "doc_b": "7.19 An operator input FLOOD must not deadlock the broker via the applied-ack on the same conn `[REQ-HAZARD-INPUT-ACK-BACKPRESSURE]` Failure (operator HITL, the ctrl+V re-open):** a flood of operator input on one brain\u2194broker conn wedged the WHOLE broker PERMANENTLY (no new/existing attach; the cont"
  },
  {
    "index": 120,
    "id_a": "REQ-HAZARD-BROKER-SEED-WIRE-SKEW",
    "id_b": "REQ-HAZARD-INPUT-ACK-BACKPRESSURE",
    "title_a": "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 a brain-only self-update (ADR-0004 no-terminate-during-update forbids auto-killing it), so a NEW-ve",
    "title_b": "A FLOOD of operator input on one brain\u2194broker connection deadlocks the broker PERMANENTLY (entire broker \u2014 no new/existing attach; the controller stays latched because the per-conn handler can't process the detach). ROOT (doyle /diagnose, code-grounded + HITL capture, the v0.13.0 P1 ctrl+V re-open):",
    "doc_a": "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]` Failure:** the broker serves the seed-control channel and is RESIDENT across a brain-only self-update (ADR-0004's no-terminate-during-update pilla",
    "doc_b": "7.19 An operator input FLOOD must not deadlock the broker via the applied-ack on the same conn `[REQ-HAZARD-INPUT-ACK-BACKPRESSURE]` Failure (operator HITL, the ctrl+V re-open):** a flood of operator input on one brain\u2194broker conn wedged the WHOLE broker PERMANENTLY (no new/existing attach; the cont"
  },
  {
    "index": 121,
    "id_a": "REQ-HAZARD-ROLLBACK-STATE-COMPAT",
    "id_b": "REQ-UPD-2",
    "title_a": "A brain must not irreversibly migrate durable state before update ready-promotion: the readiness-gated auto-rollback (ADR-0018 Q7) spawns the N-1 binary against durable state the new brain may have written, so every pre-ready write must stay N-1-readable (schema migrations gated behind ready-promoti",
    "title_b": "All binaries signature-verified before handoff",
    "doc_a": "6.8 No irreversible durable-state migration before update ready-promotion `[REQ-HAZARD-ROLLBACK-STATE-COMPAT]` Failure:** the readiness-gated auto-rollback (ADR-0018 Q7) spawns the *previous* binary against durable state the *new* brain already wrote. The first release that migrates a durable-state ",
    "doc_b": ""
  },
  {
    "index": 122,
    "id_a": "REQ-INSTALL-4",
    "id_b": "REQ-START-1",
    "title_a": "Adapter registration lifecycle: spt adapter add (--github, manifest-first, install-is-first-update) + soft-deregister remove + optional manifest uninstall template; node-local registered-adapter set self-update ripples over",
    "title_b": "Adapters never resolve SPT_HOME; binary on PATH; api bridging only",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 123,
    "id_a": "REQ-RELEASE-MUSL-ARTIFACT",
    "id_b": "REQ-UPDATE-APPLY-ALREADY-APPLIED",
    "title_a": "MUSL-TIER W3 (CI build + signed release + update-set publish + self-update E2E): release.yml gains a musl matrix entry (build on kitsubito; install musl-tools+cmake+target in-job, CC_x86_64_unknown_linux_musl=musl-gcc); the assemble job includes spt-x86_64-linux-musl in SHA256SUMS + the release uplo",
    "title_b": "`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 second apply on an already-applied staged version reaches the two-phase binary-aside rename and fails o",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 124,
    "id_a": "REQ-UPD-4",
    "id_b": "REQ-UPDATE-APPLY-RESTART-NOTICE",
    "title_a": "Update gated on user confirmation by default; opt-in full-auto",
    "title_b": "`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 apply). Public wording, no internal CODE:RESULT markers (composes with REQ-ADAPTER-UPDATE-MESSAGE /",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 125,
    "id_a": "REQ-MSG-6",
    "id_b": "REQ-MSG-SELF-DETECT-ANCESTRY",
    "title_a": "cross-node Gateway user-msg honored via advertised endpoint_type: a user-msg from a Gateway-typed origin survives the receive_wan funnel as user-msg (vs the fail-closed re-stamp), keyed on the QUIC-handshake-proven origin node (never wire `from`). Trust boundary = subnet membership (operator-ratifie",
    "title_b": "#9 (F026, operator field bug): a perch-owned `spt send` from an endpoint's OWN session must self-identify, not mis-stamp `cli@<node>` (whose replies bounce NO_PERCH). ROOT: roster::detect_self_id (roster.rs) was ENV-ONLY \u2014 OWL_SESSION_ID matched to info.session_id, else SPT_AGENT_ID \u2014 but an agent-s",
    "doc_a": "_Implemented posture_: the **local** user-backed origins are honored end-to-end \u2014 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**): the **subnet membership bound",
    "doc_b": ""
  },
  {
    "index": 126,
    "id_a": "REQ-UPDATE-FINISH-COMMUNE-FLUSH",
    "id_b": "REQ-UPDATE-PROMOTE-DRAINED",
    "title_a": "DEFERRED (post-LIFECYCLE-TRUTH, operator-ruled 2026-07-07 \u2014 mint now, impl a FUTURE milestone): make the update swap LOSSLESS for live hosted endpoints by flushing a final echo-commune per endpoint BEFORE the brain-subtree reap. ROOT (operator-surfaced probing --finish): `update apply --finish` = da",
    "title_b": "W3 (LIFECYCLE-TRUTH, mechanic-d MOVED FROM W2 per doyle gate verdict @e5ae7a9 \u2014 binding): the update-apply brain-generation promotion completes only when the OLD generation's broker subscriber connection is CLOSED or stall-EVICTED \u2014 never while blocked writes still pend on it. ROOT: `brain.ready` !=",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 127,
    "id_a": "REQ-HOST-RUN-2",
    "id_b": "REQ-WHOAMI-EXPLICIT-SID-REFUSAL",
    "title_a": "Project-scoped working directory for spt-hosted bringup: `spt endpoint run` lands the broker-spawned harness PTY in the user's PROJECT cwd, not the daemon's, via an additive `SpawnReq.cwd` field carried through the broker PTY spawn (portable-pty CommandBuilder cwd). N-1-safe wire change (additive, d",
    "title_b": "RULED DESIGN, delivery unowned (doyle 2026-07-26): when a caller hands identity resolution an EXPLICIT non-empty $OWL_SESSION_ID that resolves to NO perch, core must REFUSE identity (unresolved, exit 1, loud distinct diagnostic) rather than fall through to an ambient/inherited one \u2014 today `detect_se",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 128,
    "id_a": "REQ-BIND-HONEST-SELF-STAMP",
    "id_b": "REQ-SEAM-RESUME",
    "title_a": "C2-ROOT (F028, doyle RCA 2026-07-03): the identity-attribution ROOT behind REQ-SESSIONS-LOG-ENDPOINT-ATTRIBUTION \u2014 three composing defects let a psyche-hosted SessionStart hook stamp a FOREIGN perch: (1) roster::detect_self_id leg (a) scans the owlery ONE level (roster.rs:107 read_dir(owlery)) so a ",
    "title_b": "resume-session seam (fresh-with-preload / continue-existing)",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 129,
    "id_a": "REQ-ENDPOINT-LIST-MERGE-LOCAL",
    "id_b": "REQ-GOSSIP-ADAPTER-PROJECTS",
    "title_a": "`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 `endpoint list` \u2014 a just-online agent running `whoami` must see its OWN perch, or it gets an omitted-self",
    "title_b": "#4: remote endpoint details (harness + project history) are gossiped, not faked. Today from_resource_row (crates/spt/src/picker/model.rs:340) hardcodes project_history=Vec::new() for every remote row and passes adapter_profile=row.resources (the blurb masquerading as the harness), and Instance/Resou",
    "doc_a": "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-bound perch by ",
    "doc_b": ""
  },
  {
    "index": 130,
    "id_a": "REQ-GOSSIP-CONTROLLED-ANY",
    "id_b": "REQ-PRESENCE-CONTROL-REAP-ON-EXIT",
    "title_a": "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 local controller is by=None by design (broker.rs:1750, KH 7.15 \u2014 a local-only controller must not latc",
    "title_b": "B3 (F028, hall-b diagnosis + deferred #11 seed; BROADENED perri F-b CONFIRMED): dead-pid ONLINE decay window + sticky CONTROLLED stamp. Repro: /exit -> all endpoint processes dead -> `endpoint list` stays \u25a0 ONLINE for a decay window before OFFLINE. Sticky CONTROLLED: perri confirmed controlled=true ",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 131,
    "id_a": "REQ-HAZARD-INJECT-CONTROL-COEXIST",
    "id_b": "REQ-INJECT-MULTILINE-INTEGRITY",
    "title_a": "SPINE INVARIANT (v0.13.0 keystone): the broker must accept INJECTED keystrokes into an spt-hosted PTY (the v0.11.0 raw direct-inject today; the ADR-0022 translation-binary choreography tomorrow) WHILE a live `spt rc` controller is attached to the SAME PTY, without (a) the operator losing control, (b",
    "title_b": "W5 (LIFECYCLE-TRUTH): the idle-inject TYPED delivery leg delivers multi-line bodies byte-complete. ROOT (4 field instances + spool diff): the typed leg eats HEAD bytes nondeterministically \u2014 spool rows complete (1669B) vs ~322B received suffix; mid-turn poll envelopes always intact; a 1854B body lat",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 132,
    "id_a": "REQ-DAEMON-RESTART-SELF-INTERRUPTION",
    "id_b": "REQ-TRANSLATE-COMMIT-MISS-TOLERANCE",
    "title_a": "SEED (inactive \u2014 operator-workflow trap, field-paid 2026-07-25): an spt-hosted context CANNOT restart the daemon, because the restart's STOP phase tears down the very context running the restart command \u2014 the START half never executes and the daemon stays down until an operator starts it by hand. Fi",
    "title_b": "C-1 (F029, B6 ROOT \u2014 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_COMMIT_DEADLINE (5s, broker.rs:158) so the inject worker FAULTS + TERMINATES a HEALTHY translate bina",
    "doc_a": "",
    "doc_b": "Amendment (2026-07-03, F029 C-1) \u2014 a commit-miss is NOT a fault; real faults respawn"
  },
  {
    "index": 133,
    "id_a": "REQ-ACTIVITY-INFO-PULL",
    "id_b": "REQ-PRESENCE-LIVENESS-TRUTH",
    "title_a": "The endpoint's current activity state (busy|idle) is readable via `spt api endpoint-info` \u2014 a point-in-time read of the perch idle sentinel, for consumers that need a check rather than a stream (ADR-0048 decision 1, pull avenue; operator-ruled 2026-07-24). Additive key, N-1-safe per the additive-evo",
    "title_b": "A node's gossiped per-endpoint registry Status reflects real liveness, so a remote viewer never paints a DEAD endpoint as ONLINE. ROOT (confirmed + gated vs CONTEXT.md): registryhost.rs:397-405 advertises a NOT-alive perch as Status::Dormant (the `else` of is_perch_alive), re-stamped every gossip ro",
    "doc_a": "1. Activity observation is a first-class surface with two avenues \u2014 and the digest is not one of them",
    "doc_b": ""
  },
  {
    "index": 134,
    "id_a": "REQ-HAZARD-CORRUPT-PERCH-COHERENCE",
    "id_b": "REQ-LISTEN-SESSION-ID-FALLBACK",
    "title_a": "Corrupt (present-but-unparseable) info.json is NOT absent: liveness/status readers agree a destroyed record is neither alive nor Active (counter-39 #2)",
    "title_b": "F-034 leg c (perri/hertz field finding 2026-07-09): a session that goes live LATE (hours after SessionStart, or after a daemon restart) must still be able to bind \u2014 the ephemeral SessionStart seed ('consumed within seconds') is GONE by then and nothing re-fires it until the NEXT SessionStart, so eve",
    "doc_a": "5.14 Corrupt info.json read as ABSENT \u2192 fail-open readers gossip a wiped perch ONLINE `[REQ-HAZARD-CORRUPT-PERCH-COHERENCE]` Failure:** three readers each collapsed a **corrupt** (present-but-unparseable) `info.json` into their fail-open ABSENT default, so a NUL-wiped perch (5.13) read as permanentl",
    "doc_b": "Seed lifetime.** The seed lives **in the daemon's memory only** \u2014 no file \u2014 and survives until exactly one of: a successful `listen` bind consumes it, a newer `seed` for the same pid overwrites it, or the daemon process restarts (which drops the whole map). Nothing re-fires it until the harness's **"
  },
  {
    "index": 135,
    "id_a": "REQ-ENDPOINT-CYCLE-HONEST",
    "id_b": "REQ-HAZARD-RC-ATTACH-TRUTH",
    "title_a": "REGISTRY-LIFECYCLE W3 (ADR-0041 decision 6, operator deployah stop/run wedge): cycle verbs share ONE liveness authority \u2014 the ALREADY_LIVE dup-guard liveness-probes the claimed session client tree before refusing (dead tree means reap + respawn honestly, never a refusal citing a zombie); the shutdow",
    "title_b": "RC-RENDER-TRUTH W1 (KNOWN-HAZARDS 7.46 \u2014 umbrella conformance seam for ADR-0042): an rc surface answers from live session authority, never a stale persisted projection; a resuming perch is UNBOUND, not offline. Regression matrix from the hertz RCAs + operator field recovery: offline-row-over-honest-",
    "doc_a": "1. **Online is earned, not declared.** A creator may stamp `status=online` only from actual persisted state + hosting authority \u2014 never from manifest capability alone. Legacy hybrid rows self-heal at reconcile, but only after a SUCCESSFUL broker query: a broker failure is never interpreted as an emp",
    "doc_b": "7.46 An rc surface answers from live session authority, never a stale persisted projection \u2014 and a resuming perch is UNBOUND, not offline `[REQ-HAZARD-RC-ATTACH-TRUTH]` Failure (paid-for, hertz perri contradiction RCA 2026-07-17/18 + operator field recovery):** the broker hosted an honest live sessi"
  },
  {
    "index": 136,
    "id_a": "REQ-ELEVATE-1",
    "id_b": "REQ-HAZARD-ELEVATED-DAEMON-SPAWN",
    "title_a": "Cross-platform self-elevating re-launch for privilege-gated commands: a pure decision seam `decide_elevation_path(os, elevation, interactive_tty, has_display, has_pkexec, has_term_emulator) -> ElevatePath{AlreadyElevated, InlineSudo, UacWindow, Pkexec, TerminalEmulator, PrintHint}` selecting how to ",
    "title_b": "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: drop to SUDO_UID/SUDO_GID + the invoker's HOME) \u2014 an elevated daemon's pipes deny unelevated client",
    "doc_a": "self-elevating re-launch (cross-platform)**: When a gated command is run unelevated, spt does not just print \"run as administrator\" \u2014 it **re-launches itself with privilege** so the user reaches the result in one step. The path is chosen by a pure decision seam (`elevation::decide_elevation_path`) f",
    "doc_b": "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 daemon spawner (`ensure_running`), including the elevation-gated ones (`subnet create`/`join`, REQ-SUBNET-4). The spaw"
  },
  {
    "index": 137,
    "id_a": "REQ-INSTALL-11",
    "id_b": "REQ-MANIFEST-8",
    "title_a": "Adapter command templates resolve their program against the adapter's install dir BEFORE PATH: a `.spt`-shipped binary (dropped to adapters/_github/<safe>/ by --release/--github acquisition, or kept in the source_dir under copy-mode where only manifest+strings/ are copied to adapters/<name>) runs wi",
    "title_b": "[adapter] host_binaries declares the harness executable basenames a kind=\"harness\" adapter hosts agents inside (e.g. host_binaries = [\"claude\"]); bind-time pid\u2192exe-basename match (case-insensitive, .exe-stripped) over the seed's parent_pid selects the candidate adapter set; zero matches \u2192 a friendly",
    "doc_a": "Command templates are opaque.** spt-core never parses out a model/tool/flag \u2014 the adapter writes the whole command line; spt-core fills substitution keys and runs it. A command template's program token resolves against the adapter install dir before PATH (since v0.8.0).** A `.spt` adapter ships its ",
    "doc_b": "Bind-time adapter/profile resolution (ADR-0021).** Because the seed is adapter-agnostic, `listen`/`poll` resolve the owning adapter/profile when they bind, as a pure read \u2014 never a seed-time snapshot that could drift. `--adapter <name[:profile]>` is an **optional override** on the `api` group (an ex"
  },
  {
    "index": 138,
    "id_a": "REQ-CONN-POISON-ATTRIBUTION",
    "id_b": "REQ-SESSIONS-LOG-ENDPOINT-ATTRIBUTION",
    "title_a": "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 \u2014 the W6 RCA's terminal undecidability (per-line 1:1 CONN_WRITE_POISONED churn = fresh-carrier churn OR stderr interleave artifact) exists because records carry no ",
    "title_b": "C2 (F028, infra; ROOT-CAUSED + severity-upgraded doyle RCA 2026-07-03): cross-endpoint perch contamination \u2014 a foreign psyche's SessionStart hook REBINDS a victim perch's IDENTITY, not merely its ledger. Evidence: hall-a's info.json.session_id IS f015b-probe-psyche's session (359d7bd7) + hall-a's le",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 139,
    "id_a": "REQ-BROKER-ATTACH-JOURNAL-RESILIENT",
    "id_b": "REQ-HAZARD-BROKER-QUIC-DEADLINE",
    "title_a": "A poisoned EffectJournal mutex or a sick NetHost runtime must NOT permanently brick all future attaches. Bug #16 (URGENT): a live spt-hosted endpoint (eel-a) attach fails with 'brain IPC read deadline elapsed' after a self-update brain-respawn \u2014 the broker survives the respawn and one journaled op (",
    "title_b": "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 bound (< the brain's 30s PUMP_PEER_IO_TIMEOUT so the BROKER fires first) surfaces to the pump as a no",
    "doc_a": "",
    "doc_b": "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-facing QUIC handlers (`dispatch_net_dial` / `dispatch_net_stream_open` / `dispatch_net_stream_send`) call into `NetHost::dial` / `open_s"
  },
  {
    "index": 140,
    "id_a": "REQ-HAZARD-ATTACH-WEDGE",
    "id_b": "REQ-TEST-TMPDIR-HYGIENE",
    "title_a": "A legitimately dead PTY child (real crash/kill) + an undrained operator pump must NOT wedge the broker for all other clients. ROOT (v0.12.0 real-harness defect): loopback attach output is a blocking write_all into a bounded 64KB tokio duplex (nethost.rs:1040,1090); when the operator's rc pump stops ",
    "title_b": "Windows test fixtures MUST NOT leak their temp dirs \u2014 find and fix the leak that accumulated 14,319 `.tmp*` dirs (163 GB) in %TEMP% on hfenduleam over 2026-07-19\u219226 and ate the box to 0.00 GB free during the v0.44.0 cut (find credit: deployah). The class presents as resource exhaustion wearing a tim",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 141,
    "id_a": "REQ-PICKER-1",
    "id_b": "REQ-STREAMLOG-SUBSCRIBER-DISCIPLINE",
    "title_a": "The picker renders a FOUR-state endpoint status (extending the W2 online/offline duality): the list-item square AND a color-coded STATUS line at the top of the pick-existing right-side details both show \u2014 gray OFFLINE; green ONLINE (online + PTY-controllable spt-hosted, not controlled); amber 'ONLIN",
    "title_b": "REDISPATCH-STALL W1 (ADR-0038 Amendment, fixes 2+3+4): StreamLog subscriber write discipline \u2014 (a) replay and live fan-out HALT at the first failed subscriber write and the failed subscriber is REMOVED, at ALL sites (attach replay, append, finish; PresenceLog mirrors ride the same change \u2014 today let",
    "doc_a": "",
    "doc_b": "Amendment \u2014 REDISPATCH-STALL (2026-07-16)"
  },
  {
    "index": 142,
    "id_a": "REQ-BRAIN-HASH-ONCE",
    "id_b": "REQ-SUBNET-CREATE-CAPTURE-PROOF",
    "title_a": "REGISTRY-LIFECYCLE W1 (ADR-0040 rider; dropped THE-FORKENING W4 rider escalated \u2014 hertz re-measured live 2026-07-17: 61.29 MiB/s predicted vs 63.91 observed, 15.5%/core): the brain executable self-hash is captured EXACTLY ONCE per brain process (OnceLock in run_brain before the heartbeat loop); ever",
    "title_b": "`subnet create` proves the admin key was captured before anything persists (ADR-0051 \u00a72b, FF grill 2026-07-30). Ceremony order, binding: the admin material displays FIRST \u2014 labelled otpauth URI + terminal QR, with NO current TOTP code anywhere on screen, because that absence is the proof's soundness",
    "doc_a": "",
    "doc_b": "2b. Capture proof at create (added 2026-07-30, fast-follow grill)"
  },
  {
    "index": 143,
    "id_a": "REQ-REL-3",
    "id_b": "REQ-SUBNET-REVOKE-ADMIN-GATE",
    "title_a": "Two-key release-signing trust anchor: primary + offline never-used recovery, both pubkeys embedded in the binary's trusted set, manual local signing (ADR-0015)",
    "title_b": "`spt subnet revoke` (both forms, --force-rotate-seed included) requires the subnet's CURRENT admin TOTP \u2014 a member code is insufficient, and OS elevation stays on top answering its different question (ADR-0051 \u00a72a, FF grill 2026-07-30). Eviction is a subnet-governance act, and the proof doubles as t",
    "doc_a": "",
    "doc_b": "2a. Surfaced only to a proven admin \u2014 at mint and at rotation (amended 2026-07-30, fast-follow grill)"
  },
  {
    "index": 144,
    "id_a": "REQ-BROKER-SCREEN-GRID",
    "id_b": "REQ-HAZARD-RENDER-LIFECYCLE",
    "title_a": "Bugs #6 + #12 + #7/#8-artifacts: the broker is a raw-byte pump with no screen model \u2014 OutputLog replays the raw ring from seq 0 into a fresh terminal on attach, so an alt-screen TUI (Claude Code) corrupts scrollback (#6) and rc-to-a-pre-running-endpoint garbles (#12 \u2014 rc and endpoint run --attach ar",
    "title_b": "RC-RENDER-TRUTH W3 (KNOWN-HAZARDS 7.47 \u2014 umbrella conformance seam for ADR-0043): the physical terminal is never mutated or terminated outside its renderer's ordered state model. Regression matrix from the hertz RCA: output-before-exit through the production path; unconditional display teardown acro",
    "doc_a": "the server-side render grid + clean repaint on attach: a clean-room `ScreenGrid` (vte::Perform) interprets the byte stream into an authoritative current screen; `become_controller`/`add_viewer` emit one synthesized repaint instead of the raw ring. Companion design: V0.19.0-P6-SCREEN-GRID-DESIGN.md.",
    "doc_b": "7.47 The physical terminal is never mutated or terminated outside its renderer's ordered state model \u2014 output before exit, owned baselines, unconditional teardown `[REQ-HAZARD-RENDER-LIFECYCLE]` Failure (paid-for, hertz stale-glyphs RCA 2026-07-18, all legs doyle seam-verified):** four render-lifecy"
  },
  {
    "index": 145,
    "id_a": "REQ-RC-DISPLAY-SOLE-WRITER",
    "id_b": "REQ-RC-IDENTITY",
    "title_a": "TEARDOWN-AUTHORITY W5 (hertz RCA 3 bug 1, 2026-07-19 \u2014 REPRODUCED on 0.38.1 CLI + 0.38.1 broker; doyle ruled, and it CORRECTS an incomplete v0.38.1 call of doyle's own): while `spt rc` owns the terminal (raw / alternate screen), rc is the SOLE writer to that display \u2014 no background thread may write ",
    "title_b": "`spt rc` overlays a persistent endpoint-identity marker so the operator always groks which endpoint they control: a reserved TOP status row via a DECSTBM scroll-region (shrink the PTY's reported rows by 1, own the row), right-aligned `SUBNET : ENDPOINT_ID @ NODE`, CYAN text. Re-assert the margin + r",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 146,
    "id_a": "REQ-RC-RESIZE-PRESENTATION-BARRIER",
    "id_b": "REQ-TERM-ECHO-CLAMP-WINDOW",
    "title_a": "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 sync frame at the target geometry. (hertz post-fix field RCA 2026-07-21 on a fully-0.39.3 node, doyle-a",
    "title_b": "SEED (DAEMON-LIFECYCLE W3 rideout, field-grounded 2026-07-22): the hosted-TUI echo CLAMP WINDOW \u2014 a Windows pseudoconsole boots with echo/line input ON (in=0x1f7, measured by the 7.55 instrument @0f74bba) and it is the hosted CHILD that clamps them, so any window in which the TUI has not yet (re-)cl",
    "doc_a": "the presentation barrier over live delivery: during a resize transition the ring keeps recording but controller and viewer delivery is suppressed; commit lands the grid at the target geometry and pushes ONE synthesized sync frame (repaint ++ deferred non-grid bytes) to every attached sink under the ",
    "doc_b": ""
  },
  {
    "index": 147,
    "id_a": "REQ-ACL-MODE-ADVISORY-GOSSIP",
    "id_b": "REQ-GOSSIP-PROJECT-DERIVE-ONCE",
    "title_a": "A subnet-mode change gossips ADVISORILY \u2014 it produces a notification and nothing else. An existing member's EFFECTIVE posture never changes remotely: the captured mode (REQ-ACL-SUBNET-MODE-CAPTURE) is immutable except through the node's own refresh (REQ-ACL-ACCESS-REFRESH-VERB), so no remote party c",
    "title_b": "REGISTRY-LIFECYCLE W4 fast-follow (hertz v0.37.0 field-verify CPU-gate FAIL RCA 2026-07-17, doyle seam-verified same day; timing-pinned ~16s burst clusters per 30s Registry pump round): recent-project gossip derives a project id AT MOST ONCE PER DISTINCT CWD per advertisement round \u2014 recent_projects",
    "doc_a": "control-surface modes (`open` / `closed`)** (ratified 2026-07-29, access-control grill): Per-surface default posture for unlisted subjects \u2014 `open` = allowed (no forced whitelisting), `closed` = blocked. Defined at three levels: **subnet** (a universal all-surfaces mode chosen at `subnet create` \u2014 p",
    "doc_b": ""
  },
  {
    "index": 148,
    "id_a": "REQ-ER-NOT-ADVERTISED",
    "id_b": "REQ-PEERADDR-INVARIANT",
    "title_a": "The engine room is NOT registry-advertised by default, and is advertised only to endpoints it has whitelisted (ADR-0052 decision 3). An advertised governance surface is a discoverable one, and discoverability is the first half of every reach attempt the inbound lock then has to refuse; keeping it ou",
    "title_b": "MESH-RECOVERY W1 (ADR-0039, RCA wave 2): the peer-addrs cache INVARIANT \u2014 outer peer key == address.id \u2014 is ENFORCED on load and on write: invalid rows are repaired from the current roster when possible, rejected (dropped loudly) otherwise; never silently kept, never used as a route. MIGRATION = reb",
    "doc_a": "Refuses all inbound except replies to its own outbound (knocks and knock-codes ARE accepted); online **only while a controller is attached** \u2014 detach drops it offline and every empowerment dies with it; `rc --view` denied even locally; remote attach denied; **local `rc --take` allowed** precisely be",
    "doc_b": "Decision"
  },
  {
    "index": 149,
    "id_a": "REQ-MESH-1",
    "id_b": "REQ-PICKER-CONTROLLED-LOCAL",
    "title_a": "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 \u2016 subnet_id \u2016 seed_epoch); mutual channel-bound challenge-response at connect (transcript binds both h",
    "title_b": "#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 driven_by is REMOTE-only by design (KH 7.15) \u2014 a locally-controlled endpoint has driven_by=None + cont",
    "doc_a": "",
    "doc_b": ""
  },
  {
    "index": 150,
    "id_a": "REQ-PEERADDR-INVARIANT",
    "id_b": "REQ-PICKER-CONTROLLED-LOCAL",
    "title_a": "MESH-RECOVERY W1 (ADR-0039, RCA wave 2): the peer-addrs cache INVARIANT \u2014 outer peer key == address.id \u2014 is ENFORCED on load and on write: invalid rows are repaired from the current roster when possible, rejected (dropped loudly) otherwise; never silently kept, never used as a route. MIGRATION = reb",
    "title_b": "#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 driven_by is REMOTE-only by design (KH 7.15) \u2014 a locally-controlled endpoint has driven_by=None + cont",
    "doc_a": "Decision",
    "doc_b": ""
  }
]