## Completed (7)

### bg_2 [bash] — completed
Label: target/debug/xtask.exe pool-release --pool target
Delivery: already delivered or recovered.

### bg_3 [bash] — completed
Label: rm -r .worktrees/docs-nits-0672/target
Delivery: already delivered or recovered.

### bg_4 [bash] — failed
Label: git -C .worktrees/docs-nits-0672 symbolic-ref --short HEAD && git worktree remove .worktrees/docs-nits-0672
Delivery: already delivered or recovered.

### bg_5 [bash] — completed
Label: scp -r reavus@kitsubito:/home/reavus/spt-w1/.worktrees/relay-msg-in-280/.spt/gate .worktrees/relay-msg-in-280/.spt/li...
Delivery: already delivered or recovered.

### bg_6 [bash] — completed
Label: git worktree list --porcelain
Delivery: not auto-delivered; recovered by this snapshot.
```
worktree C:/Users/decid/Documents/projects/spt-core
HEAD bb25787aee5e809b1ab00581c4e990b158af05f3
branch refs/heads/main

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/212-er-briefing-session-repin
HEAD 1648b103039d4b33428b3b285d51bb97b128359f
branch refs/heads/test/212-er-briefing-session-repin

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/212-firewall-runtime-skip
HEAD 5b108ce91c9b96bd5e6eedea971d1c9899e4307c
branch refs/heads/test/212-firewall-runtime-skip

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/240-twohost-rig-pids
HEAD 70c1a303ec38a0714e90353351d9d7cf96700285
branch refs/heads/fix/240-twohost-rig-pids

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/access-model
HEAD 59348ef62cd5502341d3e038023ebc0a439fca7b
branch refs/heads/spec/access-model

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/assembly-212
HEAD 4eea8051d091d8e85aa6b1a9cd3585799ad990db
detached

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/autostart-emit-carrier
HEAD 0ebe0fbde798cc602eed5479033c3a97bf56e381
branch refs/heads/feat/autostart-emit-carrier

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/bounded-output-500ms
HEAD 7c785802330ab1a942d8af8eb54f8e93557ebf91
branch refs/heads/test/bounded-output-500ms

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/conduit-w1
HEAD 0770ae134dda85328d2ae4ec9b69337094e8a10d
branch refs/heads/build/conduit-w1

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/conduit-w2
HEAD e4c122cccbcbf31766147a63cc18a356a2cfb103
branch refs/heads/fix/228-owner-online-restore

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/conduit-w3
HEAD 487f361679add71ab0153b853cc1ef1218a60e81
branch refs/heads/fix/234-adapter-io-poll

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/docs-attr-passthrough
HEAD f713729382b56046982bfdda70515c4a5004f26d
branch refs/heads/docs/event-attr-passthrough

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/docs-reply-exemption
HEAD 0c1de40a18ec4711a0977826316e3bc8f2031eee
branch refs/heads/docs/reply-exemption-general

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/echo-276
HEAD 914805d112b82088595e6b0e70dde7c6dd9327c6
branch refs/heads/fix/276-echo-direct-route

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/emit-single-write
HEAD d0fdd58d44d8fb1994be70f30d442289f476980c
branch refs/heads/feat/emit-single-write

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/er-fix
HEAD 4ba27d35ed16894a0bacd59a3354c6ecfcfaa93c
branch refs/heads/fix/er-driven-by-stale-reader

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/er-instrument
HEAD bd942f639c83a77341d9c0c16dc1d35e37e8e356
branch refs/heads/test/er-bringup-instrument

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/exit-waiter-miss
HEAD 80834e2d20659630486a0d372714e615798beef0
branch refs/heads/fix/exit-waiter-miss

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/fix-153
HEAD f7d26dd5ad45755d06c870639bc41a3547882670
branch refs/heads/fix/153-update-refusal-exit

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/fix-159
HEAD e46d94c5c3d0c6d3a1f7f0ec9d9623de6402304c
branch refs/heads/fix/159-adapter-floor-staged-core

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/fix-173
HEAD 7204a47f775723de79fc4cfa5a885c542811113e
branch refs/heads/fix/173-firewall-rule-reconcile

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/fix-190
HEAD e50a1d639a2de46c9ebb15405f8f0c16869c5eb3
branch refs/heads/fix/190-read-frame-deadline

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/fix-197
HEAD 5eb6a3bdf0614b6bc917b051e107a9f4373c1b1d
branch refs/heads/fix/197-absent-code-uncounted

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/fix-203
HEAD 8e8392cb005e031fd7b906fe3ccd1bdd5e6a7dcc
branch refs/heads/fix/203-ticket-exemption

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/fix-206
HEAD c56c99144dd3d3a554e9f09aec10bd2faa58e7c6
branch refs/heads/fix/206-is-locked-posture

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/fix-208
HEAD 9d0e9cb62e30c43a3356c2d57eeee2727de97e16
branch refs/heads/fix/208-session-scoped-briefing

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/fix-209
HEAD 3421ebbaa0acbcadbe44688978d48fcfc32023a7
branch refs/heads/fix/209-er-inbound-local-bypass

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/fix-210
HEAD 6fa75953e8c67f2153aed79e5c31638a454acbba
branch refs/heads/fix/210-ruleset-presentation

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/fix-222
HEAD 6a55eb6f67224d0a571f41cbc6b798001fa60669
branch refs/heads/fix/222-seal-kcm-backend

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/fixture-prebuild-hardening
HEAD f24e732849d208d258707c1313c1c5a766dfa68d
branch refs/heads/test/fixture-prebuild-hardening

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/gate-222-ca30a79e
HEAD 561d5c5d5d536eab18767ce7ab3e24b5f49e8a4b
detached

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/gate-w4l1-1c0d435c
HEAD 7e208529ec54c806ee897bfbc3f75d67aa641947
branch refs/heads/fix/spacerun-test-module-latch

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/golden-head-intake
HEAD 4669460e1d495d8668edcff9ba46e6f42c9f972f
branch refs/heads/docs/golden-head-intake

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/hertz-census-iter
HEAD 5e7803ba2e35078a87ac3b8376c8e30d0edb6a73
branch refs/heads/test/census-enum-iter

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/hertz-liveresolve-diag
HEAD 4ede2e01f63c156f730af4e7a8745dff37a3a3f3
branch refs/heads/test/live-resolve-diag

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/hertz-owlery-noun
HEAD 0d1f3e4e5f33f2f3677ce759725a382d71291282
branch refs/heads/docs/owlery-noun

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/hertz-psyche-bound
HEAD 6da6e7e08bc33faab5322459f3ff19e4b640f125
branch refs/heads/test/psyche-soft-budget-bound

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/hertz-teardown-bound
HEAD 915cd24858e7decaa20c4d09025bff8f694d983a
branch refs/heads/test/teardown-bound-shape

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/input-ack-viewer-oracle
HEAD 561d5c5d5d536eab18767ce7ab3e24b5f49e8a4b
branch refs/heads/fix/input-ack-viewer-oracle

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/ir21-instruments
HEAD 061ddad18f8c100e10e0fe1a408d72023a11cea2
branch refs/heads/docs/ir21-instruments

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/ir21-samepkg
HEAD 6fbea74bf5e5ef8c3d1f6f46a889553e2ebb2302
branch refs/heads/fix/ir21-samepkg-bin-edges

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/ir50-stderr-sink-fixup
HEAD 2ac954356ad82f942b1d20956fc856d84a536a27
branch refs/heads/fix/ir50-stderr-sink-census

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/ir54-porter-close
HEAD bee1ab947faae6e9d6e6799c03ea8b5c21171821
branch refs/heads/docs/ir54-porter-close

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/ir56-pool-claim-cwd
HEAD 12910d2f6b1fc71aa799681ca1072cf407742e73
branch refs/heads/fix/ir56-pool-claim-cwd

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/ir62-rig-docs-port
HEAD 33724cfb81ea54a372e2861e97a71f52aa5ee1f7
branch refs/heads/fix/ir62-rig-docs-port

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/ir66-later-attach-needles
HEAD d04b922dfcae0b2d663e4a33b25446e2a241dbe1
branch refs/heads/test/ir66-later-attach-needles

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/keystone-182-family-b
HEAD 5c1a1302e6cdeadbf7ffe223e342b009f53eec85
branch refs/heads/test/keystone-182-family-b

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/keystone-182-hygiene
HEAD 3fe7717696376198d8336d5115bd1fd40a0410eb
branch refs/heads/test/keystone-182-hygiene

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/keystone-182-w0
HEAD 728e1e2afd81d61afa83757db2e7a5b9bd2af387
branch refs/heads/build/keystone-182-w0

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/keystone-w1
HEAD ba2d99841d9a3c9d56b31016d0ecdb1ae6954cfb
branch refs/heads/build/keystone-182-w2-sealed-multi

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/now-signal-inproc-daemon
HEAD fed965f808cdec4236a42ed83e2345b24ea7c021
branch refs/heads/test/now-signal-inproc-daemon

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/pilot-rebase
HEAD fdb4b42a07d8a10372a861af722ff2894db2cc4b
branch refs/heads/spec/brain-handoff-pilot-rebase

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/post65-infra-register
HEAD 9af399202a6d0ee0871fed1ae0248ca39ac88781
branch refs/heads/docs/post65-infra-register

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/post65-register
HEAD 4b63de275f37458086f301dd2018b80460c59381
branch refs/heads/docs/post65-register

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/projindex-external-cwds
HEAD aa219657314cb5cb0d1898bce16b576eb42638d3
branch refs/heads/test/projindex-external-cwds

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/register-followups
HEAD 1fdbf084c8b1b9a836ea898a3e5352ef0faeb113
branch refs/heads/docs/register-locksmith-followups

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/register-sweep
HEAD 80f3a227e64f3531590d1e188761e2bd25715549
branch refs/heads/docs/register-concierge-intake

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/release-v0630
HEAD de91ee62cbf5195600de5f5bfe4f097d2c533b52
branch refs/heads/release/v0.63.0-shape

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/resume-spawn-needle-race
HEAD dbe3daad57fa021986006414edf8f3dc20a696e4
branch refs/heads/fix/resume-spawn-needle-race

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/rig-stop-identity-scrub
HEAD a3d87279f97e16ed740cac90877cf8d1b8a970b9
branch refs/heads/test/rig-stop-identity-scrub

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/schema-internal-codes
HEAD bba0ac0053a35afb3ae1020af51d41ec5a40572f
branch refs/heads/fix/schema-internal-codes

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/servicehost-retryable-kill
HEAD 827a3b772ef7723ffed195a0c363f0864354d926
branch refs/heads/test/servicehost-retryable-kill

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/spec-pilot
HEAD cfd97a8e076e1d4fd96e32f0e9c40b2f17504a53
branch refs/heads/spec/brain-handoff-pilot

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/spec-sealed-code
HEAD e1cb99053bd696265443a64bb6c1863b4bdbd2b9
branch refs/heads/spec/sealed-code-grill

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/spt-home-guard-race
HEAD 40bf625f56a69ac08eb8dc866eb326a677dba8c3
branch refs/heads/test/spt-home-guard-race

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/traceable-reqs-v0.4
HEAD 89526be37a2f2ec8788ed269eda1084de9b9e10b
branch refs/heads/ci/traceable-reqs-v0.4

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/twohost-seal-barrier
HEAD 32b0d2e96928d5a34b4892f2751e4dd719bc5d00
branch refs/heads/test/twohost-seal-barrier

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/w2-rig-fixups
HEAD afa5af354d5f4524934c3e2a4ea499ee0fe99052
branch refs/heads/test/w2-rig-fixups

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/w2-seal-ux
HEAD afed25fc24f5cb8d82d8283295300fa512f65c65
branch refs/heads/fix/w2-seal-ux

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/w3-ingest
HEAD 33434ef1c9902b6c3f5d7b588a0ba13a97b35463
branch refs/heads/fix/w3-ingest-serialize

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/w4-brief-once
HEAD 66df4de8eec9e788cd9d94acc3a1c3dfdcfad978
branch refs/heads/fix/w4-er-brief-once

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/w4-exit-subject
HEAD d82a2fed4fe38eea1ab7c1be5e6b562247e9be87
branch refs/heads/fix/w4-exit-subject

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/w4-lane2
HEAD 79462367bc14583875f10f63dbc7c80aef3f5ca6
branch refs/heads/fix/168-taught-monic-command

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/w4-lane3
HEAD cd115d4d28908b1eefe2d617d1157b7114e55a48
branch refs/heads/fix/74-interior-space-runs

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/w4-linesafe
HEAD 6d39939100bda905cc2a7f2b319649a4a15ac251
branch refs/heads/fix/w3-line-safety-attr

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/w5-lane
HEAD 4eea8051d091d8e85aa6b1a9cd3585799ad990db
detached

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/wax-seal-w1
HEAD dce9a753302185eadc2b33d2133c2ec4708ea47e
branch refs/heads/assembly/wax-seal-21

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/wax-seal-w4
HEAD 145f3dffe321c2036596b0fa0f6e72ed3a18eda9
branch refs/heads/build/wax-seal-w4

worktree C:/Users/decid/Documents/projects/spt-core/.worktrees/ws272-w0
HEAD 884b9124e360bf656fa8c3dc19d97129b56b4877
branch refs/heads/build/ws272-w0

worktree C:\Users\decid\Documents\projects\spt-core\.worktrees\docs-nits-0672\.git
HEAD bb25787aee5e809b1ab00581c4e990b158af05f3
branch refs/heads/docs/nits-0672

worktree C:\Users\decid\Documents\projects\spt-core\.worktrees\iolog-277\.git
HEAD 7689dc33b97379a523048f1cc97dc57015ac66de
branch refs/heads/fix/277-iolog-seq-reset

worktree C:\Users\decid\Documents\projects\spt-core\.worktrees\relay-msg-in-280\.git
HEAD 17815c9c04be73bfb63a3649071d6101dbd131e5
branch refs/heads/fix/280-relay-msg-in

worktree C:\Users\decid\Documents\projects\spt-core\.worktrees\webserve-floor-riders\.git
HEAD 70db2c9f085918054cd24f673e0dbe417d2955ee
branch refs/heads/ci/webserve-floor-riders



Wall time: 0.31 seconds
```

### bg_1 [bash] — failed
Label: git worktree repair .worktrees/docs-nits-0672 && git worktree remove .worktrees/docs-nits-0672
Delivery: already delivered or recovered.

### bg_7 [bash] — completed
Label: traceable-reqs check
Delivery: not auto-delivered; recovered by this snapshot.
```
876 requirements: 876 complete, 0 incomplete, 0 findings
  [OK] REQ-ACCESS-RETIRED-VERB-REFUSAL  required: [impl, unit]  stages: -doc +impl +unit -int
       A RETIRED SUBCOMMAND OF `spt endpoint access` REFUSES BY NAME RATHER THAN FALLING THROUGH ITS OWN OPTIONAL POSITIONAL AND ANSWERING PLAUSIBLY. `access` takes an optional endpoint id positionally, so once `list` and `rules` stopped being subcommands (retired when the roster views replaced them) clap handed those tokens to the POSITIONAL, and the view reported `no access entities ruled for 'list'` at exit 0 -- a well-formed, confident report about an entity nobody has ever created. Found by flynn in the v0.49.0 field verify (releases#67). THE DEFECT IS NOT A MISSING ERROR MESSAGE, IT IS AN ANSWER: the sentence is TRUE of any name nobody has ruled, so it is indistinguishable from the real result for a real endpoint, and an operator or agent still carr…
  [OK] REQ-ACCESS-VERDICT-REASON  required: [impl, unit]  stages: -doc +impl +unit -int
       The endpoint access gate reports WHY a pass passed, not merely THAT it passed: the gate's verdict carries, on its allow arm, the reason the chain admitted the interaction — the same-node short-circuit, the reply exemption, an entry whose subject NAMED the peer (a proven sender endpoint or the origin node), an entry that matched only by SUBNET WILDCARD (an entry, but one that never named this peer), or a posture pass (an endpoint / node / captured-subnet mode, or the implicit-open bottom of the chain). The reason is computed AT THE GATE, in the one place that holds the whole chain, and travels with the decision. The alternative — a downstream consumer re-deriving it — means RE-OPENING the access store after the gate has closed it, which is bot…
  [OK] REQ-ACL-ACCESS-REFRESH-ER-ONLY  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       spt api access-refresh stops refusing and becomes real, gated to the engine room, updating ONLY the node's captured subnet-level fallbacks (ADR-0052 decision 6; the W2 refusal REQ-ACL-ACCESS-REFRESH-VERB was minted precisely so this wave changes one behavior rather than adding a surface and its gate). The refresh is the CONSENTED half of advisory gossip: a subnet-mode change reaches a member as a notification, the engine room is briefed with the exact new posture, and a human decides whether this node adopts it — which is why the verb writes the captured fallbacks and never the node's own rules, and why no remote actor can invoke it. Its authentication is the same shared engine-room function empower uses. The W2 refusal test is repinned to the ne…
  [OK] REQ-ACL-ACCESS-REFRESH-VERB  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       `spt api access-refresh` is MINTED THIS WAVE BUT REFUSES — 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 adapters and the engine-room brief will be built against, and it makes the wave that implements enforcement a change to ONE behavior rather than a new surface plus its gate. A refusal that merely says 'unknown command' would invite an adapter to route around it. When it does light up it updates ONLY the node's captured subnet-level fallbacks — never the node's own rules, which are the operator's, not the subnet's. Gate: doc — the CONTEXT.md capture…
  [OK] REQ-ACL-DISCOVER-DEFAULT-ON  required: [doc, impl, unit, int]  stages: +doc +impl +unit +int
       DISCOVER IS ON BY DEFAULT: a `closed` posture at ANY mode tier -- endpoint mode, node mode, or the join-time-captured subnet mode -- no longer implies a DISCOVER deny, and the ONLY thing that closes DISCOVER is a deny that NAMES it: an access rule row, or a `per_surface` mode entry (engine-room-set at the node tier). Operator-ruled 2026-08-17 (releases#180/#181): being findable is what makes a knock -- the ask to be admitted -- possible at all, so a node that closed its posture to say 'do not talk to me' had also silently said 'and you may not ask', which was never the choice being made; the messaging-first majority pays for a discovery decision they never took. THE DEFAULT LIVES IN THE SURFACE VOCABULARY, NOT BESIDE THE CHAIN: the `surface::TABLE`…
  [OK] REQ-ACL-DISCOVER-GATE  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       DISCOVER is a real gated surface: registry resolve/advertise and the resources blurb are filtered per viewer, so discovery leaks nothing a viewer could not reach. ADR-0009 NAMED this leg — 'discovery (resource advertisement) is gated by the first two gates' — and CONTEXT.md's resource-advertisement entry promises that an endpoint whose access rules exclude the viewer's node by naming DISCOVER in a deny never appears in that view; a legacy grant plus blanket-closed posture does not imply that exclusion because DISCOVER is default-on. Only the VISIBILITY half was ever built; the access half has been an unbuilt promise since M4. Un-gated discovery on a shared subnet is an inventory of every agent on every member node, including the ones an operato…
  [OK] REQ-ACL-ER-DISCOVER-CONJUNCTION-NOTICE  required: [doc, impl, unit, int]  stages: +doc +impl +unit +int
       AN ACCEPTED RULE THAT CANNOT CURRENTLY TAKE EFFECT SAYS SO: an endpoint-scoped access mutation naming the ENGINE ROOM is accepted and, when its `DISCOVER` half cannot presently disclose anything, the accept site prints a LOUD CONJUNCTION NOTICE naming the engine room's advertisement whitelist as the other lever and its current posture. Disclosure of the engine room is an AND across two records: `DiscoverGate` checks the ER advertisement filter BEFORE the access chain (REQ-ER-NOT-ADVERTISED, ratified and unchanged by this requirement), so a rule accepted against an empty whitelist discloses NOTHING while reading as policy in force. Field case: ENLYZEAM's sole `DISCOVER` allow was ER-scoped `any-of SPT_DEV` with an empty whitelist, and every SPT_DEV …
  [OK] REQ-ACL-FAIL-CLOSED  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       A corrupt or unreadable access store degrades CLOSED, loudly (ADR-0053 — an ADR-level flip of ADR-0009's deliberate fail-open ruling). ADR-0009 justified fail-open explicitly: the whitelist was 'a same-subnet convenience boundary layered inside subnet membership, not the system's outer wall', because every member node was the one user's own machine. The SHARED SUBNET ruling breaks that premise — member nodes now belong to different human operators and the access layer gates agents — and a boundary that evaporates when its store file corrupts is not a boundary an operator can reason about. So a store that CANNOT BE READ refuses unlisted-subject traffic on every surface rather than admitting it, and says so on the refusing node naming the store…
  [OK] REQ-ACL-FORK-WITHOUT-DISCOVER-CONSEQUENCE  required: [doc, impl, unit, int]  stages: +doc +impl +unit +int
       A `FORK` GRANT WHOSE SUBJECT CANNOT RESOLVE THE ENDPOINT SAYS SO AT WRITE TIME -- a stated consequence, never a refusal: the rule lands exactly as typed and the operator is told that as written the subject cannot resolve the endpoint it may now fork, so the attempt fails later as an unresolvable subject. Forking a remote endpoint takes TWO surfaces and only one is obvious: `FORK` authorizes the operation, `DISCOVER` is what lets the grantee resolve the row at all. Field origin (releases#76, from the releases#29 cross-node rung): node B granted node A `FORK` alone, A could never fork, and granting the pair fixed it -- diagnosed empirically, not by reading. The operator-facing defect was never that the pair is required; it is that the requirement was…
  [OK] REQ-ACL-GRANT-NODES-POLICY  required: [doc, impl, unit]  stages: +doc +impl +unit +int
       ENDPOINTS_CAN_GRANT_NODES is a node-tier policy toggle, settable only via the engine-room, gating whether an ordinary endpoint may write a NODE-SUBJECT entry into its own whitelist — the widened grant a non-attributable-surface approval produces. Explicitly set it is true or false; UNSET DERIVES PER-DECISION from the effective posture of the REQUESTED SURFACE at the target node: open => endpoints may self-approve (an allow entry on an open surface punches no hole), closed => engine-room only (a node-subject allow would punch a hole in a closed posture). The gate applies in BOTH POLARITIES — adding a node allow and removing a node deny are the same widening act — and it is enforced at the STORE MUTATION SEAM rather than in any one caller, so n…
  [OK] REQ-ACL-INTRA-NODE-SELF  required: [doc, impl, unit, int]  stages: +doc +impl +unit +int
       INTRA-NODE GOVERNANCE IS A SELF-REFERENTIAL NODE SUBJECT AT THE EXISTING TIERS, NOT A NEW TIER. Operator-rephrased 2026-08-22, superseding in full the v1 reading (a slot-3.5 rules tier with a mode twin at 6.5): #211 adds NO tier, NO Subject kind and NO schema change. A rule whose subject is THIS NODE'S OWN id governs traffic authored on this node, and it does so through machinery that already shipped. Two effects, both operator-confirmed: a NODE-SCOPE own-node rule governs intra-node actions for every endpoint hosted here, and a PER-ENDPOINT own-node rule governs incoming actions from other same-node endpoints. The third -- endpoint-targeted rules evaluate before node-targeted -- is the chain's existing order and nothing moves. THE MECHANISM AND TH…
  [OK] REQ-ACL-LOCAL-ORIGIN-TIERS  required: [impl, unit]  stages: -doc +impl +unit -int
       WHERE AN INVOCATION CAME FROM IS DATA THE CHAIN REASONS ABOUT, NOT A SHORT-CIRCUIT BEFORE IT. Until releases#209 the chain's step 1 was `if local, return Allow(SameNode)`, so locally-authored traffic never reached `AccessStore::decide` at all. That was invisible while local traffic was ungated, and it is exactly what would have foreclosed the operator's intra-node governance surface (releases#211) — which under the ruled shape is NOT a new tier between the per-endpoint entries and the node tier, but SELF-REFERENTIAL Node subjects at the EXISTING tiers (v1's slot-3.5 reading withdrawn in full, operator-rephrased 2026-08-22). A tier the local path short-circuits past is not a tier. So `AccessRequest` carries an `Origin` SET AT EXACTLY ONE CONSTRUCT…
  [OK] REQ-ACL-LOCAL-SUBJECT-ONE-SHAPE  required: [impl, unit]  stages: -doc +impl +unit -int
       EVERY LOCAL FEEDER OF THE ADMISSION GATE HANDS IT A PROVEN ENDPOINT ID OR NOTHING — ONE MEANING, ONE SPELLING (releases#215): `gate::admit_local_delivery`'s `sender` is a SUBJECT (`Subject::SenderEndpoint` matches it by equality), and its three local feeders disagreed on what they put there — `spt send` passed the session-proven bare id, `spt ring` passed `resolve_from(--from)` (where an EXPLICIT `--from` BEATS session detection), and `notify` passed `NotifRow.from_id`, the COMPOSITE `{issuer}@{node_hex}`. A tier-1 rule an operator wrote for endpoint `ling`, that the CLI accepted and the view renders, therefore covered two of three local delivery verbs and COULD NEVER MATCH ON NOTIFY: it failed in the SILENT direction. `access_check_with_sender…
  [OK] REQ-ACL-LOCKED-POSTURE  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       The **locked** claim is one predicate, and it asks the CHAIN. `ACCESS_LOCKED` (the `revoke` arm) and the access view's `locked` field are two renderings of a single fact — this endpoint refuses ALL unsolicited remote inbound — and both take that fact from ONE predicate, `AccessStore::is_locked(endpoint)`. It is CHAIN-SCOPED by necessity, not by preference: the superseded `EndpointAcl::is_locked` was record-scoped and therefore structurally unable to answer, because an endpoint that names no posture of its own inherits one from the node mode and from captured subnet modes, neither of which a record can see; it counted node-subject allows (`allowed_nodes().is_empty()`) and never read a mode at all, so a `revoke` on a default-open endpoint told th…
  [OK] REQ-ACL-MODE-ADVISORY-GOSSIP  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       A subnet-mode change gossips ADVISORILY — 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 can reach into a member node and re-posture its gate. This is the difference between a subnet owner ADVISING members of a policy change and COMMANDING their enforcement — on a shared subnet whose members are different humans, only the former is defensible, and a producer that quietly applied would be a remote write to security material. Gate: doc — the CONTEXT.md control-surface-modes advisory-gossip sentence; impl — the notif producer on subnet-m…
  [OK] REQ-ACL-MUTATION-HUSK-REFUSAL  required: [impl, unit]  stages: -doc +impl +unit -int
       ADR-0053'S FAIL-CLOSED HAS A WRITE SIDE, AND IT IS ENFORCED AT THE SAVE SEAM RATHER THAN AT THE MUTATION CALL SITES. `load_checked` split NotFound from corrupt and the gate refused a husk correctly -- but the store is READ-MODIFY-WRITE at every path that edits it, and `AccessStore::load` is `load_checked_from(..).unwrap_or_default()`, so a degrade was swallowed into an EMPTY document. The consequence inverted the guarantee (releases#57): the gate refused unsolicited traffic, and then the first `spt endpoint access` command an operator ran to investigate the refusal saved that empty document over the damaged file -- permanent rule loss, and a posture that flipped from degraded-closed to open-with-one-rule. The boundary held exactly until someone tou…
  [OK] REQ-ACL-NODE-MODE-SET  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       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' — 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 agent cannot reach without passing a human-held TOTP; every other candidate — a plain CLI verb, an elevation-gated verb, a config file the daemon reads — is reachable by something running as the user. Subnet-scope mode authority is separate and rides empower (REQ-SUBNET-EMPOWER-VERB); this requirement is the node's own posture, which needs no empowerment because the bring-up gate already proved subnet membership. Gate: doc — the CONTEXT.md contr…
  [OK] REQ-ACL-NODE-VIEW  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       `spt daemon access` is the node-tier roster: the entities the node-scope rules name (node and subnet-wildcard subjects — 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 — the tier every hosted endpoint falls through to, in the same item grammar as the per-endpoint view so the two scopes read as one system. There is NO `spt subnet access`: a subnet is a subject tier and a mode source, never a rule-holding target — its mode facts surface on `spt subnet status` (REQ-SUBNET-STATUS-MODES). Gate: doc — the CONTEXT.md access-entity entry; impl — the node roster builder and the daemon verb; unit — the node roster's entities, mode-exception summary,…
  [OK] REQ-ACL-ORIGIN-QUALIFIER  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       An access rule may carry an ORIGIN QUALIFIER (any|user|agent) restricting it to invocations of that origin class, so a rule can say 'the humans on node A, not its agents' and let that node's agents fall through to the mode. TWO TYPES, NOT ONE (doyle-ruled design): the RULE side is a three-valued qualifier defaulting to `any` for N-1 records; the REQUEST side is a TOTAL two-valued class (user|agent) with no unknown arm, because `any` is a rule-side value that no classifier ever emits — a single three-valued type would let a classifier return `any`, which is meaningless. Classification is ambient and ceremony-free, performed by the SENDING daemon over the existing local-origin predicate (interactive terminal with no perch/broker ancestry => user; a…
  [OK] REQ-ACL-POSITIONAL-ALLOW-HONORS-FLAGS  required: [impl, unit, int]  stages: -doc +impl +unit +int
       `access allow`'s POSITIONAL SPELLING REACHES THE SAME MUTATION SEAM ITS FLAG SPELLING DOES -- it is a shorthand for the rule, never a second, ungated way to write one. The v1 arm matched `node: Some(..)` and swallowed every other flag in a `..`, then called `AccessStore::allow` directly, and that cost three things at once, all three RUNTIME-MEASURED before the fix (releases#185; the filing was read-derived and named only the first). (1) `--surfaces MSG` WAS DROPPED, and an empty surface list means EVERY surface -- so the store took a rule strictly WIDER than the operator typed, exit 0, no diagnostic on either stream. The direction matters and was checked rather than assumed: the `is_empty => set_all(Mode::Closed)` at the tail of `allow_surfaces` re…
  [OK] REQ-ACL-PRECISE-ALLOW-WRITE-CONTRACT  required: [impl, unit, int]  stages: -doc +impl +unit +int
       THE PRECISE `access allow` IS A RULE VERB; THE POSITIONAL ONE IS A RULE+POSTURE VERB -- and the precise arm therefore says so at write time rather than leaving the operator to discover it. releases#196 asked whether the flag spelling should also close an endpoint's posture on its first rule (the v1 semantic `restrict_if_unset` carries, which the positional arm re-applies explicitly). RULED HORN B (doyle 2026-08-21, on a census read at b88fab2a): default-open-until-explicit-close IS the shipped T6 semantic, the mutation seam stays POSTURE-BLIND, and what was missing was never the close -- it was any signal that a rule written onto an unrestricted endpoint changes no verdict. TWO STRUCTURAL FACTS DECIDE THIS RATHER THAN A PREFERENCE. (1) A CLOSE CANN…
  [OK] REQ-ACL-RC-VIEW-SPLIT  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       Watching an endpoint's terminal and DRIVING it are separately grantable: attach gates on the request's AttachIntent — Viewer -> RC_VIEW, Control/Take -> RC_ATTACH. Before this, one access_check(endpoint, origin, Unsolicited) covered every attach intent, so admitting a node to view an endpoint necessarily admitted it to take the keyboard (and, with Take, to displace an incumbent controller). On a shared subnet that is the difference between showing a colleague's agent what happened and letting their agent drive yours. The split is keyed on the intent the REQUEST carries, evaluated at the serve side under the handshake-proven origin — never on anything the attaching side can restate after the gate. Kin: ADR-0042 (rc-attach truth) and REQ-ACL-SURF…
  [OK] REQ-ACL-RULE-MUTATION  required: []  stages: -doc +impl +unit -int
       Access rule mutation and revocation are TUPLE-SHAPED, never id-shaped: a removal restates the subject, surfaces and origin qualifier rather than naming a generated rule id, which makes it idempotent and script-safe and removes rule-id bookkeeping from the model entirely (tuples ARE the identity). Every entry records its PROVENANCE — knock-approve, code-redeem, or manual — and the access drill-down view prints the exact removal command beside each rule together with that provenance, so revocation is copy-paste from the view that showed it. Entries born of knocks or codes have no special lifecycle after birth. Authority is threefold: the owner endpoint's agent (narrowing mutations always free, widening node-subject mutations in either polarity ga…
  [OK] REQ-ACL-SUBJECT-CHAIN  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       One FIRST-MATCH-WINS subject chain decides every access question, with an implicit-open bottom that preserves current fleet behavior. Order: per-endpoint sender-endpoint rule -> per-endpoint node rule -> per-endpoint subnet-wildcard rule -> node-scope node rule -> node-scope subnet-wildcard rule -> endpoint mode for the surface -> node mode for the surface -> join-time-captured subnet mode for the surface -> (nothing matched) OPEN. The stateful-firewall reply exemption a
[…1630ln elided…]
oc +impl +unit +int
       Platform-targeted update sets and debug rollout: signed multi-platform update metadata, recipient platform selection, channel-scoped monotonic counters, debug-channel opt-in via release-key overlay, local staging plus pull-based peer propagation, and maintainer-only convergence tooling (ADR-0016)
  [OK] REQ-UPD-7  required: [impl, unit]  stages: -doc +impl +unit -int
       Origin-source update bootstrap (`spt update fetch`): pull the latest signed release directly from the GitHub release origin (`SaberMage/spt-releases`) — the per-platform artifact + its `<asset>.release.json` SignedRelease metadata — and stage it through the EXISTING verify→stage pipeline (the same `plan_verified` gate: two-key signature + channel + monotonic rollback floor + SHA-256), after which the normal consent-notif / `spt update apply` flow is unchanged. Closes the peer-only-discovery gap (REQ-UPD-1): a first-in-fleet / isolated node can update with no peer to pull from. The signed-release anchor keeps the GitHub transport untrusted-but-verified.
  [OK] REQ-UPD-8  required: [impl, unit]  stages: -doc +impl +unit -int
       Platform-safe `spt update fetch` + apply platform-guard (v0.3.1 cross-OS brick fix): `spt update fetch` stages the signed multi-platform `SignedUpdateSet` (`update-set.json` + every platform artifact it names), never a platform-blind single `SignedRelease`, so local apply selects `current_platform()` and P2P re-serve lets each peer select ITS own platform. Defense-in-depth: `apply_staged` REFUSES a staged single-release artifact unless it is platform-stamped for THIS node (an unstamped pre-v0.3.2 single, or a single stamped for another OS, fail-safe refuses — the guard that alone prevents the v0.3.1 brick where a Linux ELF was applied as `spt.exe`). UX: a friendly post-apply message (`Updated spt-core to vX.Y.Z.` + changelog URL) driven by an add…
  [OK] REQ-UPD-9  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       `gh_release` adapter [update] avenue (optional signing): an adapter declares `[update] avenue = "gh_release", repo = "user/repo"` (+ optional `asset`, default `adapter.spt`; + optional Ed25519 `signing_key`); spt-core's ripple compares the repo's LATEST GitHub release version against the installed adapter version and, when newer, auto-updates by fetching the release `.spt` archive (the REQ-INSTALL-9 `--release` fetch primitive) → verifies the `.spt` against `signing_key` if declared, else HTTPS+GitHub first-acquisition trust → re-extracts + re-registers the adapter root. Lets a harness adapter ship updates from its own GitHub releases with NO signing tooling or plugin coupling (removes the perri file_pull/delegated avenue blockers). Acquisition…
  [OK] REQ-UPDATE-ADAPTERS-VERB  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       THE-FORKENING W4 (operator-grilled 2026-07-14): `spt update adapters [<a>[,<b>...]]` = thin ALIAS over the existing `spt adapter update` engine (cli.rs:748 gh_release avenue; the old verb STAYS — published surface) + comma-list accepted on BOTH forms. Semantics: no names -> all gh_release-avenue registrations; names validated FAIL-FAST against the registry BEFORE any update starts (a typo must not leave a half-updated set); per-adapter failure ISOLATION (one failure doesn't stop the rest) with a per-adapter summary line; nonzero exit if any failed; local-path/dev registrations SKIP loud (not error). Gate: unit — name validation, list parsing, isolation + exit-code aggregation, local-path skip; doc — reference regen (drift-gated). Kin REQ-UPDA…
  [OK] REQ-UPDATE-APPLY-ALREADY-APPLIED  required: [impl, unit]  stages: -doc +impl +unit -int
       `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 os-error-5, reading as a hard failure when the machine is simply up to date. FIX: apply gains the same pure classifier `fetch` got in v0.18.0 (REQ-UPDATE-FETCH-CURRENT-UX) — already-applied → clear message + exit 0, and the flow MUST short-circuit BEFORE the binary-aside rename in that state; mirror the classifier at ALL apply reject/entry sites the way the fetch fix covered its three. Genuine errors (bad signature, wrong platform, true downgrade, net…
  [OK] REQ-UPDATE-APPLY-RESTART-NOTICE  required: [impl, unit]  stages: -doc +impl +unit -int
       `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 / the update-apply-confident-message rule) — name the user-visible CONSEQUENCE ('daemon-coordinated features run the previous version until the daemon restarts'), not the broker/brain internals. Composes with REQ-UPDATE-RUNNING-IMAGE-SURFACE (the notice tells the user what the version-surface will then show, and how to clear it). (F-025)
  [OK] REQ-UPDATE-COMPOSITE-EXIT-PRECEDENCE  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       THE COMPOSITE UPDATE'S EXIT IS FOLDED BY PRECEDENCE, NEVER BY WRITE ORDER (releases#216): `cmd_update_composite` aggregated leg exits with `worst = code` — the LAST nonzero, not the worst — so under `--restart` (the only plan where a leg runs AFTER the isolated adapters leg) an Adapters FAILURE of 1 followed by a Finish REFUSAL of 3 reported 3, and a refusal MASKED a failure. That inverts REQ-UPDATE-REFUSAL-EXIT-DISTINCT's contract, whose 3 means refusal present AND no failure — the same class of misread as the releases#153 field report where a refused fleet roll recorded itself as rolled. THE TOTAL ORDER IS 0 < 3 < EVERY OTHER NONZERO, classed BY VALUE and never by which constant minted it (the tree holds TWO distinct 3s — `EXIT_NOT_ELEVAT…
  [OK] REQ-UPDATE-DEFAULT-COMPOSITE  required: [doc, impl, unit, int]  stages: +doc +impl +unit +int
       THE-FORKENING W4 (operator-grilled 2026-07-14): plain `spt update` = `update fetch --apply` THEN `update adapters` (core-first doctrine order); when core is already current the core leg no-ops and ONLY adapters update; `--core-only`/`-c` skips the adapters leg. GROUNDING (operator-corrected, code-confirmed): fetch --apply cycles the BRAIN only — broker + PTYs survive (apply_staged applyhost.rs:303; the restart-required text is a NOTICE, cli.rs:4615, not behavior) — so the composite's invoking process survives by construction and NO re-run machinery is needed; on a broker-side release the existing F-025 notice remains the composite's closing output. Gate: unit — composite sequencing incl. already-current -> adapters-only and --core-only skip; …
  [OK] REQ-UPDATE-FETCH-APPLY-FLAG  required: [impl, unit]  stages: -doc +impl +unit -int
       `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 — so the brittle `fetch && apply` chain (which broke when fetch no-oped / exited nonzero on an already-staged latest, skipping the chained apply) is unnecessary. Composes with REQ-UPDATE-FETCH-CURRENT-UX: the end state is 'installed latest', reached idempotently from new-staged -> apply / already-staged (applied<candidate) -> STILL apply / already-applied -> noop+exit0 / genuine error (bad signature, no artifact for platform, true downgrade, network) -> do NOT apply, propagate the error + nonzero. Reuses the existing cmd_update_apply core (its own verify + two-phase + auto-rollback own correctn…
  [OK] REQ-UPDATE-FETCH-CURRENT-UX  required: [impl, unit]  stages: -doc +impl +unit -int
       `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_metadata returns Err(RejectReason::Rollback{current,candidate}) — printed as {reason:?} (Debug) at exit 1, reading as a FAILURE when the update is merely already downloaded and just needs `spt update apply` (this bit the operator: fetch kept 'failing', apply was the missing step). FIX: a PURE classifier (reason, applied, staged) -> {AlreadyStaged (latest downloaded, not yet installed) / AlreadyApplied (up to date) / GenuineError}; already-staged + already-a…
  [OK] REQ-UPDATE-FINISH-COMMUNE-FLUSH  required: []  stages: -doc -impl -unit -int
       DEFERRED (post-LIFECYCLE-TRUTH, operator-ruled 2026-07-07 — 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` = daemonless swap -> daemon RESTART; the graceful `daemon stop` path (daemon.rs:316-325) raises brain_stop then reaper.reap() KILLS the brain subtree (brain + shellwake watchers + detached Psyches) as one unit — there is NO per-endpoint final commune before the kill. ENDPOINT-SURVIVAL (REQ-UPDATE-FINISH-ENDPOINT-SURVIVAL) then RESPAWNS each orphaned online spt-hosted endpoint, but from its LAST commune (whatever the ongoing per-event echo-commune cadence…
  [OK] REQ-UPDATE-FINISH-ENDPOINT-SURVIVAL  required: [impl, unit, int]  stages: -doc +impl +unit +int
       W3 (LIFECYCLE-TRUTH): daemon restart no longer massacres hosted endpoints — daemon start RE-RUNS previously-online spt-hosted endpoints. ROOT rig-proven: daemon stop+start (the apply notice's OWN instruction) kills every hosted endpoint; they stay OFFLINE after start (no resurrection) though records exist (info.json status + adapter + cwd). SCOPE RULING (doyle): re-run-on-start, marked start-reason=daemon-restart; agents' minds ride psyche re-host as today. Int: endpoint online -> daemon stop -> start -> endpoint back ONLINE, same id, harness respawned.
  [OK] REQ-UPDATE-GH-TRANSPORT  required: [doc, impl, unit, int]  stages: +doc +impl +unit +int
       THE-FORKENING W1 (ADR-0036, operator-ruled 2026-07-14): the release channel is PRIVATE (`BigscreenVR/spt-bs-releases`) and the gh CLI is the mandated carrier — release discovery (`releases/latest`, cli.rs:9717) and asset download (cli.rs:4861 public browser URLs) move to deadline-wrapped `gh` subprocess calls (`gh api`, `gh release download`; run_git pattern). WHY gh not token+HTTP: private-repo `browser_download_url` 404s even with a valid token — the API asset-id dance is gh's job. Default repo flips via the existing SPT_INSTALL_REPO seam (cli.rs:5363) + xtask REPO const (main.rs:729) + notif.rs consent-changelog URL rider. Loud failure classes: gh missing -> UPDATE_FETCH_REJECTED:GhCliRequired with OS-SPECIFIC install hints (winget/apt/brew)…
  [OK] REQ-UPDATE-ONE-SHOT-FINISH  required: [impl, unit]  stages: -doc +impl +unit -int
       W3 (LIFECYCLE-TRUTH): update apply works daemonless and one command finishes the cycle. ROOT (operator wart): update fetch/apply run ensure_daemon_announced (cli.rs:4386) -> on a stopped box they BOOT THE OLD broker pre-swap, guaranteeing the mixed old-broker/new-brain pair + a manual bounce. FIX: apply works daemonless (swap + record, next start runs new bytes); `update apply --finish` (name subject to docs-token gate) completes the cycle: swap -> brain cycle -> broker restart onto new bytes (rides REQ-UPDATE-FINISH-ENDPOINT-SURVIVAL so the restart is not a massacre). CLI change -> xtask docs gen, no internal codes in clap ///.
  [OK] REQ-UPDATE-PROMOTE-DRAINED  required: [impl, unit, int]  stages: -doc +impl +unit +int
       W3 (LIFECYCLE-TRUTH, mechanic-d MOVED FROM W2 per doyle gate verdict @e5ae7a9 — binding): the update-apply brain-generation promotion completes only when the OLD generation's broker subscriber connection is CLOSED or stall-EVICTED — never while blocked writes still pend on it. ROOT: `brain.ready` != subscribers drained; W2's stall-evict (REQ-HAZARD-BROKER-VIEWER-BRAIN-DECOUPLE) only BOUNDS the false-promote window to BRAIN_WRITE_DEADLINE (15s), it does NOT close it — a new brain can signal ready inside that window while the old gen's conn is still wedged, so the apply 'promotes' onto a still-frozen control plane (the 22:47 incident-night false-promote). FIX: the promotion gate (ADR-0018 brain-trial, brainproc.rs) adds an explicit DRAINED prec…
  [OK] REQ-UPDATE-REFUSAL-EXIT-DISTINCT  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       A REFUSAL AND A FAILURE ARE DIFFERENT ANSWERS AND MUST NOT SHARE AN EXIT CODE OR A SUMMARY WORD (releases#153, doyle ruling 2026-08-21). A guard that DECLINED and did no work leaves the box exactly as it was; a failure means something broke and may have left work half-done. A caller gating on exit status therefore needs THREE answers: applied (0), refused-with-nothing-done (3), failed (1). CODIFICATION, NOT A NEW CONTRACT — the tree already answered refusals with 3 at three sites (EXIT_NOT_ELEVATED, DAEMON_STOP_REFUSED, UPDATE_FINISH_REFUSED) while cli.rs's own module doc called 1 a 'runtime refusal'; there is no migration to look for, and a fourth code would fork a convention that already reads consistently. WHAT THIS REQUIREMENT COVERS is the p…
  [OK] REQ-UPDATE-RESTART-SAFE-SWAP  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       THE-FORKENING W4 (operator-grilled 2026-07-14; RETIRES findings-backlog seed #12 REQ-UPDATE-ONE-STEP-SAFE-SWAP): `spt update --restart` = the one-step ergonomic path to the SAFE full-cycle swap — fetch -> `update adapters` -> `apply --finish` LAST (lethal-leg-last, ruled: apply --finish restarts the whole daemon incl. broker/PTYs, so it must be the final act — everything completes from ANY invoking context including an spt-hosted session whose PTY dies at that step; accepted cost: a finish FAILURE leaves updated adapters on old-activated core briefly — loud + operator-attended by nature of the flag). Composes with `-c/--core-only` (skip adapters leg). The 0.28.0 wedge lesson closes: the ergonomic one-step no longer picks the riskier path by d…
  [OK] REQ-UPDATE-RUNNING-IMAGE-SURFACE  required: [impl, unit, int]  stages: -doc +impl +unit +int
       `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) — the BROKER process survives and keeps running its pre-apply compiled image, so every broker-side surface of a freshly-applied release (the F015B live-apply matcher, dispatch inject legs, etc.) is silently dormant until a full daemon bounce, with nothing in the CLI revealing the split. FIX: the running broker SELF-REPORTS its compiled image version over IPC (a new request KIND answered by the live broker process from its own compiled build constant) — HARD CONSTRAINT: the version comes FROM the running broker process, NEVER inferred from disk…
  [OK] REQ-UPDATE-TRIAL-DRAIN-DRIVE  required: [doc, impl, int]  stages: +doc +impl -unit +int
       UPDATE-WEDGE (counter-54, doyle-ruled 2026-07-09 — regression of the v0.29.0 seamless brain-swap): a brain generation DRIVES the broker's controller-liveness reap (a KIND_SESSIONS poll) each heartbeat throughout its boot/trial loop, so a hard-KILLED prior generation's black-holed LOCAL controller conn (by:None) is stall-evicted within the trial window and can never permanently strand the promotion DRAINED gate. ROOT (2026-07-09 field freeze, `spt update fetch --apply` v0.30.0->v0.30.2 froze all 7 live PTYs ~30s then rolled back): the promote gate (run_trial, brainproc.rs:657-661) needs BOTH `ready_generation==gen` AND `old_gen_drained()`; `old_gen_drained()` = `!any_local_controller_wedged()` (brainproc.rs:534) is a PURE READ of `write_blocked_si…
  [OK] REQ-USHER-LIFECYCLE-VERBS  required: [doc, impl, unit]  stages: +doc +impl +unit +int
       THE ENDPOINT LIFECYCLE READS AS VERBS, AND `endpoint run` RETIRES WITHOUT A SHIM. One overloaded verb carried the whole lifecycle: `spt endpoint run` minted an endpoint, started a new session on an existing one, resumed a prior session, opened the interactive picker, and (with `--save`) set a startup default — the invocation's MEANING sat in which of nine flags were present, so the CLI could not be read and the picker's doors could not be named. The ratified surface (releases#5 bag grill, 2026-08-04) is: `endpoint create <new-id> [--subnet S] [--adapter A] [--cwd DIR]` = the ONLY mint, subnet immutable after it; `endpoint start <id> [--adapter A] [--cwd DIR]` = a NEW session on the endpoint's most-recent adapter in its most-recent project folder,…
  [OK] REQ-VIEWER-SKIP-TO-LIVE-ON-EVICT  required: [doc, impl, unit, int]  stages: +doc +impl +unit +int
       A `rc --view` VIEWER that overflows its broker subscription queue and is EVICTED (OutputLog::append try_send Full → viewers.remove, REQ-HAZARD-VIEWER-ISOLATION session-protection) must SKIP TO LIVE, not die silently. ROOT (v0.13.0, b4 JIT item 2 = p0_paste + post-b4 a_journaled-Linux, ONE root): serve_attach forwards each frame (read_event→b64decode→re-encode AttachRecord→net_stream_send) SLOWER than the drain fans out under flood → its VIEWER_CHANNEL_DEPTH(256) channel overflows → the drain evicts (viewers.remove drops the ViewerSink → drops tx → viewer_writer's rx.recv() Err → the writer returns WRITING NOTHING) → serve_attach's brain.read_event() just STOPS getting Output (no EOF, no error) → serve_attach blocks forever →…
  [OK] REQ-VIS-REMOTE-NOT-HIDE-NEW  required: [doc, impl, unit, int]  stages: +doc +impl +unit +int
       A REMOTE ENDPOINT'S VISIBILITY IS ITS OWN NODE'S BUSINESS, AND THE ASKING NODE'S `hide_new_endpoints` POSTURE GOVERNS ITS OWN ENDPOINTS ONLY. `VisibilityStore::hidden` resolves an explicit per-(endpoint, subnet) override first and otherwise falls through to `subnet_hide_new || default_hide`; a REMOTE id never has an override or a default-hide row in the ASKING node's local store, so on any node whose subnet has `hide_new_endpoints` ON that fall-through evaluates true for EVERY remote id and the resolve-side exclusion vetoes them all -- `resolve_across_visible` returns NotFound and every remote wan target is refused on that node. IT IS NOT CONSERVATIVE, IT IS BACKWARDS: `hide_new_endpoints` is the OWNING node's advertisement policy, captured at join…
  [OK] REQ-VOCAB-ANCHOR-SUBNET  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       THE UBIQUITOUS LANGUAGE FOR AN ENDPOINT'S DEFAULT-SCOPE SUBNET IS `anchor subnet`, NOT `home subnet`. Operator-requested (discord:reavo) and GREENLIT as releases#176: `home` reads as a place the endpoint lives, which is precisely the reading the concept must not carry — identity is node-global and advertised into EVERY subnet the node belongs to, and the subnet in question anchors DEFAULTS (sync scope, bare-name qualification) rather than bounding where the endpoint exists. The glossary body already used the word `anchor` to explain what `home` meant, which is the tell: the definition needed a second word to undo the first. THIS INVERTS A RATIFIED GLOSSARY AVOID AND MUST SAY SO INLINE. CONTEXT.md carried an `_Avoid_` line forbidding the term `anc…
  [OK] REQ-WAKE-RESUME-LEG  required: [impl, unit, int]  stages: -doc +impl +unit +int
       A-2 (REMOTE-TRUTH triage §A-2 + ADR-0033): the daemon reconcile gains a WAKE-RESUME LEG — 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 wake <id>` on a suspended live agent actually brings it back (today: reconcile_once start-arm hosts ONLY status==online (livehost.rs:199), so a woken-but-unbound endpoint is skipped forever — neither status reaches online nor does reconcile re-host). This is the ADR-0033 LIFT: the thin `spt wake` edge writes rest intent, the DAEMON does the work. Mirrors shellwake::resolve_wake (read rest state, live-pid double-launch guard, launch, NEVER flip stat…
  [OK] REQ-WAKE-WAIT  required: []  stages: -doc -impl -unit -int
       A-2 rider (REMOTE-TRUTH triage §A-2): `spt endpoint wake --wait` blocks on the REAL bind (status reaches online) after the daemon wake-resume lift (REQ-WAKE-RESUME-LEG), instead of the DEFAULT accepted-not-bound print (thin edge writes intent, daemon lifts async — ADR-0033). Reuses the F-027 bind-await machinery if/when it lands, else a bounded poll on status==online with a plain-language timeout (no core lingo, F-1). Default wake is UNCHANGED (accepted-not-bound truth). Separate chunk from the core leg (doyle A-2 ruling: C-2 needs the core leg, not --wait); F-027 bind-await stays design-only until this activates.
  [OK] REQ-WAN-DENY-PRECEDES-EXISTENCE  required: [impl, unit]  stages: -doc +impl +unit -int
       At the WAN ingress, an ACCESS DENIAL and an ABSENT PERCH are DISTINCT OUTCOMES, and the denial arm runs FIRST. `receive_wan` consults the gate before it asks whether the target's perch exists, so a refused arrival returns `WanOutcome::Refused` whether or not the target is there, and `WanOutcome::NoPerch` is reserved for an ADMITTED arrival with nothing to deliver to. The ordering is the load-bearing half and it is not an accident of layout: reversed, a denied message to an absent perch would report absence, which both mislabels the refusal AND is the precise shape that would make a later `DENIED`-style reword of the NO_PERCH line leak the existence of an endpoint deliberately hidden from the asker (the DISCOVER-denial seam, where `Existence is not …
  [OK] REQ-WAN-SEND-DELIVERY  required: [impl, unit, int]  stages: -doc +impl +unit +int
       Bug #9/#10: cross-node spt send reports SENT(WAN) but does not deliver, even on stable-IP pairs. Real root: spt send resolves the dial with id-only addr_for_node_hex (endpoint.rs:538) which forces a fresh iroh discovery round-trip every send, while the gossip pump uses cached direct addresses (dial_seeded/PeerAddrStore) so gossip stays green but send rides a marginal discovery path that cannot carry the fire-and-forget payload; the handshake completes so SENT(WAN) prints falsely. Fix: (1) route the WAN dial through the pump seeded-direct-address resolution (PeerAddrStore first, id-only fallback); (2) receiver writes its WanOutcome back so the sender confirms delivery under the QUIC deadline and only reports SENT on confirmed delivery, honest failur…
  [OK] REQ-WAN-SPT-HOSTED-DELIVERY  required: [impl, unit, int]  stages: -doc +impl +unit +int
       A WAN-ARRIVED `spt send` is DELIVERED to an spt-hosted endpoint (broker holds its PTY, NO api-listen relay), not spooled-forever. Today receive_wan (spt-daemon/wan.rs:271-276) tries deliver_tcp (the harness-hosted relay leg) then falls to spool — it has NO spt-hosted broker-inject leg, which exists ONLY in local cmd_send (REQ-SEND-SPT-HOSTED, Brain::inject_endpoint → KIND_ENDPOINT_INPUT → broker dispatch_endpoint_input → translation-binary idle-inject). So a WAN arrival to an idle spt-hosted perch with a live translation binary ALWAYS sleeps in spool until an adapter hook polls (F-023: perch verifiably idle 7min, binary healthy, zero injection). FIX: factor cmd_send's spt-hosted delivery leg into a SHARED fn; receive_wan calls it after the …
  [OK] REQ-WHOAMI-1  required: [doc, impl, unit]  stages: +doc +impl +unit -int
       The `endpoint list` SELF pin carries the Self endpoint's authored `endpoint description` (info::read_info(...).resources) when present, inline after the liveness state; whoami stays a top-level hot-path verb (parse unchanged, REQ-MSG-9) and renders the same description-carrying SELF pin. HISTORY: originally minted whoami as a thin ALIAS of `spt endpoint list` — that alias premise is SUPERSEDED by REQ-WHOAMI-IDENTITY-ONLY (PROJECT-INDEX W1, 2026-07-15): the alias inherited the list's O(perches x branches) git fanout onto hook paths (the 2026-07-15 message-delivery incident), so whoami is now identity-only over the shared render_self_pin. The pin render + parse evidence here stands; the full-roster surface lives solely on `endpoint list`.
  [OK] REQ-WHOAMI-EXPLICIT-SID-REFUSAL  required: []  stages: -doc -impl -unit -int
       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 — today `detect_self_id` (roster.rs, legs a→b→b2→c) treats sid-UNMATCHED identically to sid-ABSENT, so the fallback chain re-adopts precisely the identity a sharper claim just failed to prove. MEASURED (perri, this node, 2026-07-26, three read-only whoami calls from a genuine descendant of the perri host process): (1) all SPT_*/OWL_* scrubbed → id null, exit 1 — ancestry resolved nothing (caveat honored from the probe: the perch's recorded pid was not in the c…
  [OK] REQ-WHOAMI-IDENTITY-ONLY  required: [doc, impl, unit, int]  stages: +doc +impl +unit +int
       PROJECT-INDEX W1 (F-040, perri filing claude-spt docs/SPT-CORE-FINDINGS.md @d775b38; correctness-critical opener — the 2026-07-15 message-bodies incident root): a core IDENTITY-ONLY resolution — session -> endpoint|null — that touches NO list/registry/project/git/network path, and `spt whoami` DE-ALIASED from cmd_endpoint_list (cli.rs ~6609 aliases the full list = 100+ git children under hook deadlines). endpoint-info is DISQUALIFIED as the carrier (runs latest_project_ref). Adapters/hooks get a bounded-time identity verb; the harness-hosted adapter fallback stays deadline-vulnerable until this ships. Gate: impl — the resolver + whoami de-alias; unit — resolver returns endpoint|null with zero project derivation (assert no git spawn seam);…
  [OK] REQ-WORKER-LIST-VISIBILITY  required: [impl, int]  stages: -doc +impl -unit +int
       V-1 (WORKER-TRUTH triage, operator rider): worker perches leave the DEFAULT `spt endpoint list` view — they are process-local machinery, not subnet citizens; leaked-or-live worker rows rendering as permanent OFFLINE endpoints is the operator-visible symptom root. A dedicated flag (--workers) reveals them (one command + flag per the --all/--detail precedent, NOT a separate list-working command — sister divergence deliberate). Applies to the human render, --json (additive default-absent filter), and the registry/projection legs; verify-and-stop any worker gossip into the subnet registry as peer endpoints.
  [OK] REQ-WORKER-MINTED-NAME  required: [doc, impl, unit, int]  stages: +doc +impl +unit +int
       N-1 (WORKER-TRUTH triage, operator rider): worker perch identity is CORE-MINTED and parent-derived — `{parent}-w{N}` with a per-parent counter at registration (sister shape: claude_skill_owl hook_subagent_start.rs) — never the adapter-presented agent id (CC Task ids render as random-named rows). worker-start mints + echoes the id (WORKER_STARTED:{parent}-w{N}); the adapter's agent_id/agent_type ride the record as correlation METADATA, not identity. Verb-shape contract change — freeze with W-2 in ONE coordination with perri.
  [OK] REQ-WORKER-PICKER-EXCLUDED  required: [impl, unit]  stages: -doc +impl +unit -int
       V-2 (WORKER-TRUTH triage, operator rider): non-drivable endpoint classes never render as picker rows — 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 — same non-drivable family) at every picker source leg, extend-not-multiply for future non-drivable classes.
  [OK] REQ-WORKER-REAP  required: [impl, unit, int]  stages: -doc +impl +unit +int
       W-3 (WORKER-TRUTH triage): worker records must not persist indefinitely past their useful life — 6 dead-pid workers leaked OFFLINE on flynn (kill-paths where SubagentStop never fires: parent killed, abort, timeout). The stored rec.pid is the ephemeral worker-start hook process (dead by design — the REQ-HAZARD-DEAD-REC-PID class; NEVER an alive-gate signal). Honest reap signals: (a) parent-session lifecycle — reap the parent's soft-stopped + orphaned workers at parent session-end/boundary and on parent-death detection (a worker cannot outlive its parent's live session); (b) a generous TTL floor since `created` as belt-and-braces. Soft-stop preservation semantics (REQ-HAZARD-SOFT-CLEANUP: results drain before reap) stay honored — reap after d…
  [OK] REQ-WORKER-SID-SYMMETRIC-AUTH  required: [doc, impl, unit, int]  stages: +doc +impl +unit +int
       W-2 (WORKER-TRUTH triage, operator-ruled 2026-07-06): worker verbs go sid-symmetric with every sibling id-scoped verb — worker-start mints NO token and worker-stop takes NONE (token custody is undue adapter burden, ruling via perri). Registration STORES the sid it authenticated (the parent's sid at start; today cmd_worker_start hardcodes session_id="" — worker.rs:44 — so a sid-authed stop compares against empty and refuses 100%). Stop accepts the parent's CURRENT sid OR the stored registration sid (a /clear between start and stop rotates the parent's sid; either rotation endpoint is honest custody — the REQ-PSYCHE-SID-CUSTODY rotation reasoning). Under the ruling the field adapter's existing emission (worker-stop <id> --session-id <parent s…
  [OK] REQ-XTASK-SPT-BIN-TARGET-DIR  required: [impl, unit]  stages: -doc +impl +unit -int
       #13 (F026 micro, tooling): xtask `spt_bin()` (crates/xtask/src/main.rs) BUILDS `spt` via cargo (which honors CARGO_TARGET_DIR) but returns a HARDCODED `<root>/target/debug/spt` path — so under a redirected target dir (CI / isolated-gate rigs that set CARGO_TARGET_DIR to a throwaway) the binary lands in `$CARGO_TARGET_DIR/debug` while xtask looks in `<root>/target/debug` -> NotFound -> `xtask check` (docs-drift gate) spuriously fails. Workaround was running `xtask check` with CARGO_TARGET_DIR unset. FIX: a pure `target_debug_dir(root, CARGO_TARGET_DIR)` seam mirroring cargo's resolution — absolute override as-is, relative resolved against `root` (the dir cargo is invoked in), default `<root>/target` — join `debug`; `spt_bin` returns from it. S…


Wall time: 6.08 seconds
```