{
  "schemaVersion": 1,
  "summary": {
    "requirementCount": 783,
    "completeCount": 783,
    "incompleteCount": 0,
    "findingCount": 0
  },
  "requirements": [
    {
      "id": "REQ-ACCESS-VERDICT-REASON",
      "title": "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, whi…
      "requiredStages": [
        "impl",
        "unit"
      ],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 177
            },
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 183
            },
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 190
            },
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 234
            },
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 386
            }
          ]
        },
        "int": {
          "complete": false,
          "evidence": []
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 1350
            },
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 1483
            }
          ]
        }
      }
    },
    {
      "id": "REQ-ACL-ACCESS-REFRESH-ER-ONLY",
      "title": "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 …
      "requiredStages": [
        "doc",
        "impl",
        "unit"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "docs/adr/0052-engine-room-endpoint-empower.md",
              "line": 379
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-store/src/briefing.rs",
              "line": 369
            },
            {
              "path": "crates/spt-store/src/subnet.rs",
              "line": 417
            },
            {
              "path": "crates/spt/src/api/engineroom.rs",
              "line": 66
            },
            {
              "path": "crates/spt/src/api/engineroom.rs",
              "line": 83
            },
            {
              "path": "crates/spt/src/api/engineroom.rs",
              "line": 440
            },
            {
              "path": "crates/spt/src/api/engineroom.rs",
              "line": 455
            },
            {
              "path": "crates/spt/src/api/engineroom.rs",
              "line": 547
            },
            {
              "path": "crates/spt/src/api/mod.rs",
              "line": 302
            }
          ]
        },
        "int": {
          "complete": false,
          "evidence": []
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-store/src/subnet.rs",
              "line": 611
            },
            {
              "path": "crates/spt/src/api/engineroom.rs",
              "line": 847
            },
            {
              "path": "crates/spt/src/api/engineroom.rs",
              "line": 1013
            },
            {
              "path": "crates/spt/src/api/mod.rs",
              "line": 1036
            }
          ]
        }
      }
    },
    {
      "id": "REQ-ACL-ACCESS-REFRESH-VERB",
      "title": "`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.m…
      "requiredStages": [
        "doc",
        "impl",
        "unit"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "CONTEXT.md",
              "line": 875
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/api/mod.rs",
              "line": 301
            }
          ]
        },
        "int": {
          "complete": false,
          "evidence": []
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/api/mod.rs",
              "line": 1036
            }
          ]
        }
      }
    },
    {
      "id": "REQ-ACL-DISCOVER-DEFAULT-ON",
      "title": "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 `surfac…
      "requiredStages": [
        "doc",
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "CONTEXT.md",
              "line": 875
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 193
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 206
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 303
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 316
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 741
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 1110
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 1602
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 1656
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 1684
            },
            {
              "path": "crates/spt-store/src/erole.rs",
              "line": 154
            },
            {
              "path": "crates/spt/src/accessview.rs",
              "line": 90
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 18302
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 18334
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 18351
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/tests/twohost.rs",
              "line": 2324
            },
            {
              "path": "crates/spt-daemon/tests/twohost.rs",
              "line": 2347
            },
            {
              "path": "crates/spt-daemon/tests/twohost.rs",
              "line": 2371
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 774
            },
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 923
            },
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 973
            },
            {
              "path": "crates/spt-daemon/src/pump/registry.rs",
              "line": 385
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 2820
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 2865
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 2894
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 2938
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 2961
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 2994
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 3038
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 4144
            },
            {
              "path": "crates/spt/src/accessview.rs",
              "line": 520
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 33164
            }
          ]
        }
      }
    },
    {
      "id": "REQ-ACL-DISCOVER-GATE",
      "title": "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 a…
      "requiredStages": [
        "doc",
        "impl",
        "unit"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "CONTEXT.md",
              "line": 792
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 552
            },
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 592
            },
            {
              "path": "crates/spt-daemon/src/pump/registry.rs",
              "line": 172
            },
            {
              "path": "crates/spt-daemon/src/pump/registry.rs",
              "line": 270
            },
            {
              "path": "crates/spt-daemon/src/pump/registry.rs",
              "line": 277
            }
          ]
        },
        "int": {
          "complete": false,
          "evidence": []
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 898
            },
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 956
            },
            {
              "path": "crates/spt-daemon/src/pump/registry.rs",
              "line": 335
            },
            {
              "path": "crates/spt-daemon/src/pump/registry.rs",
              "line": 412
            }
          ]
        }
      }
    },
    {
      "id": "REQ-ACL-ER-DISCOVER-CONJUNCTION-NOTICE",
      "title": "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…
      "requiredStages": [
        "doc",
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "CONTEXT.md",
              "line": 881
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 647
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 14982
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 15021
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 15052
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 15104
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/tests/twohost.rs",
              "line": 2393
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/cli.rs",
              "line": 32948
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 33125
            }
          ]
        }
      }
    },
    {
      "id": "REQ-ACL-FAIL-CLOSED",
      "title": "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 …
      "requiredStages": [
        "doc",
        "impl",
        "unit"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "CONTEXT.md",
              "line": 875
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 553
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 897
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 1368
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 1376
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 1422
            }
          ]
        },
        "int": {
          "complete": false,
          "evidence": []
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 691
            },
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 956
            },
            {
              "path": "crates/spt-daemon/src/access.rs",
              "line": 1005
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 3924
            },
            {
              "path": "crates/spt-store/src/access.rs",
              "line": 3957
            }
          ]
        }
      }
    },
    {
      "id": "REQ-ACL-FORK-WITHOUT-DISCOVER-CONSEQUENCE",
      "title": "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 requir…
      "requiredStages": [
        "doc",
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "CONTEXT.md",
              "line": 879
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/cli.rs",
              "line": 15004
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 15159
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 15186
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 15229
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 18352
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/tests/twohost_cli.rs",
              "lin
[…53693ln elided…]
    {
              "path": "crates/spt-daemon/src/notif.rs",
              "line": 553
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 8875
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 9460
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 9465
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 9485
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 9505
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 9516
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 9528
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 10251
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 10288
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 10371
            },
            {
              "path": "crates/xtask/src/main.rs",
              "line": 1272
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/tests/release_verify_e2e.rs",
              "line": 21
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/cli.rs",
              "line": 31973
            }
          ]
        }
      }
    },
    {
      "id": "REQ-UPDATE-ONE-SHOT-FINISH",
      "title": "W3 (LIFECYCLE-TRUTH): update apply works daemonless and one command finishes the cycle. ROOT (operator wart): update fetch/apply run ensure_daemon_announced (cli.rs:4386) -> on a stopped box they BOOT 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 ///.",
      "requiredStages": [
        "impl",
        "unit"
      ],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/applyhost.rs",
              "line": 97
            },
            {
              "path": "crates/spt-daemon/src/applyhost.rs",
              "line": 382
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 8929
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 8948
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 8966
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 9030
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 9279
            }
          ]
        },
        "int": {
          "complete": false,
          "evidence": []
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/applyhost.rs",
              "line": 925
            },
            {
              "path": "crates/spt-daemon/src/applyhost.rs",
              "line": 966
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 28475
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 32127
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 32160
            }
          ]
        }
      }
    },
    {
      "id": "REQ-UPDATE-PROMOTE-DRAINED",
      "title": "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 DRA…
      "requiredStages": [
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/brainproc.rs",
              "line": 662
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 2393
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 5020
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 5158
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/tests/false_promote.rs",
              "line": 231
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/brainproc.rs",
              "line": 1761
            },
            {
              "path": "crates/spt-daemon/src/brainproc.rs",
              "line": 1809
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 10522
            }
          ]
        }
      }
    },
    {
      "id": "REQ-UPDATE-RESTART-SAFE-SWAP",
      "title": "THE-FORKENING W4 (operator-grilled 2026-07-14; RETIRES findings-backlog seed #12 REQ-UPDATE-ONE-STEP-SAFE-SWAP): `spt update --restart` = the one-step ergonomic path to the SAFE full-cycle swap — 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 …
      "requiredStages": [
        "doc",
        "impl",
        "unit"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "CONTEXT.md",
              "line": 682
            },
            {
              "path": "docs-site/src/self-update/overview.md",
              "line": 41
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/cli.rs",
              "line": 2262
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 9116
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 9150
            }
          ]
        },
        "int": {
          "complete": false,
          "evidence": []
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/cli.rs",
              "line": 23729
            }
          ]
        }
      }
    },
    {
      "id": "REQ-UPDATE-RUNNING-IMAGE-SURFACE",
      "title": "`spt` surfaces the RUNNING broker image version beside the on-disk version so an updated-looking node reveals broker-side dormancy. ROOT (F-025): `spt update apply` restarts the BRAIN only (ADR-0018 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 …
      "requiredStages": [
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/brain.rs",
              "line": 1431
            },
            {
              "path": "crates/spt-daemon/src/brain.rs",
              "line": 1471
            },
            {
              "path": "crates/spt-daemon/src/brain.rs",
              "line": 1503
            },
            {
              "path": "crates/spt-daemon/src/brainproc.rs",
              "line": 70
            },
            {
              "path": "crates/spt-daemon/src/brainproc.rs",
              "line": 77
            },
            {
              "path": "crates/spt-daemon/src/brainproc.rs",
              "line": 86
            },
            {
              "path": "crates/spt-daemon/src/brainproc.rs",
              "line": 225
            },
            {
              "path": "crates/spt-daemon/src/brainproc.rs",
              "line": 916
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 430
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 441
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 4697
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 5318
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 5320
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 6906
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 6933
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 6957
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 8047
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 8076
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 8368
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 8373
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 8511
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 8520
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/applyhost.rs",
              "line": 566
            },
            {
              "path": "crates/spt/tests/coordinator_image_e2e.rs",
              "line": 80
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 7846
            },
            {
              "path": "crates/spt-daemon/tests/pumpdeadline.rs",
              "line": 90
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 32194
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 32240
            }
          ]
        }
      }
    },
    {
      "id": "REQ-UPDATE-TRIAL-DRAIN-DRIVE",
      "title": "UPDATE-WEDGE (counter-54, doyle-ruled 2026-07-09 — regression of the v0.29.0 seamless brain-swap): a brain generation DRIVES the broker's controller-liveness reap (a KIND_SESSIONS poll) each 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_b…
      "requiredStages": [
        "doc",
        "impl",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "CONTEXT.md",
              "line": 695
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/brainproc.rs",
              "line": 361
            },
            {
              "path": "crates/spt-daemon/src/livehost.rs",
              "line": 1269
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/tests/trial_drain_drive_e2e.rs",
              "line": 332
            },
            {
              "path": "crates/spt/tests/trial_drain_drive_e2e.rs",
              "line": 518
            },
            {
              "path": "crates/spt/tests/trial_drain_drive_e2e.rs",
              "line": 540
            }
          ]
        },
        "unit": {
          "complete": false,
          "evidence": []
        }
      }
    },
    {
      "id": "REQ-USHER-LIFECYCLE-VERBS",
      "title": "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 projec…
      "requiredStages": [
        "doc",
        "impl",
        "unit"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "CONTEXT.md",
              "line": 415
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/cli.rs",
              "line": 222
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 422
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 450
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 470
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 482
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 2062
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 2225
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 2237
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 2763
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 2784
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 2817
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3486
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3510
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3706
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3733
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3757
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3843
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3872
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3922
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 4071
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 4122
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 4135
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 4228
            },
            {
              "path": "crates/spt/src/picker/shortcut.rs",
              "line": 96
            },
            {
              "path": "crates/spt/src/picker/shortcut.rs",
              "line": 153
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/tests/cli_stack_smoke.rs",
              "line": 108
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/cli.rs",
              "line": 2897
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3140
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3246
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3330
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3363
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3416
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3553
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 3602
            },
            {
              "path": "crates/spt/src/picker/shortcut.rs",
              "line": 203
            },
            {
              "path": "crates/spt/src/picker/shortcut.rs",
              "line": 241
            },
            {
              "path": "crates/spt/src/picker/shortcut.rs",
              "line": 278
            }
          ]
        }
      }
    },
    {
      "id": "REQ-VIEWER-SKIP-TO-LIVE-ON-EVICT",
      "title": "A `rc --view` VIEWER that overflows its broker subscription queue and is EVICTED (OutputLog::append try_send Full → viewers.remove, REQ-HAZARD-VIEWER-ISOLATION session-protection) must SKIP TO LIVE, 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 fo…
      "requiredStages": [
        "doc",
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "CONTEXT.md",
              "line": 405
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/attach.rs",
              "line": 720
            },
            {
              "path": "crates/spt-daemon/src/brain.rs",
              "line": 997
            },
            {
              "path": "crates/spt-daemon/src/brain.rs",
              "line": 1238
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 3290
            },
            {
              "path": "crates/spt-daemon/src/msg.rs",
              "line": 1498
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/tests/inject_control_wedge.rs",
              "line": 2910
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/brain.rs",
              "line": 2407
            },
            {
              "path": "crates/spt-daemon/src/brain.rs",
              "line": 2698
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 8197
            },
            {
              "path": "crates/spt-daemon/src/broker.rs",
              "line": 8264
            },
            {
              "path": "crates/spt-daemon/src/msg.rs",
              "line": 1816
            }
          ]
        }
      }
    },
    {
      "id": "REQ-VIS-REMOTE-NOT-HIDE-NEW",
      "title": "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, capture…
      "requiredStages": [
        "doc",
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "CONTEXT.md",
              "line": 768
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-store/src/perch.rs",
              "line": 751
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 6233
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 6486
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 6621
            },
            {
              "path": "crates/spt/src/picker/data.rs",
              "line": 315
            },
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 131
            },
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 144
            },
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 170
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/tests/hide_new_remote_rows_e2e.rs",
              "line": 160
            },
            {
              "path": "crates/spt/tests/hide_new_remote_rows_e2e.rs",
              "line": 169
            },
            {
              "path": "crates/spt/tests/hide_new_remote_rows_e2e.rs",
              "line": 190
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 1783
            },
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 1807
            },
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 1826
            },
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 1850
            },
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 1880
            }
          ]
        }
      }
    },
    {
      "id": "REQ-WAKE-RESUME-LEG",
      "title": "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 …
      "requiredStages": [
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/livehost.rs",
              "line": 217
            },
            {
              "path": "crates/spt-daemon/src/livehost.rs",
              "line": 324
            },
            {
              "path": "crates/spt-daemon/src/livehost.rs",
              "line": 361
            },
            {
              "path": "crates/spt-store/src/info.rs",
              "line": 246
            },
            {
              "path": "crates/spt-store/src/info.rs",
              "line": 768
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 7364
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/livehost.rs",
              "line": 2535
            },
            {
              "path": "crates/spt-daemon/src/livehost.rs",
              "line": 2565
            },
            {
              "path": "crates/spt-daemon/src/livehost.rs",
              "line": 2594
            },
            {
              "path": "crates/spt-daemon/src/livehost.rs",
              "line": 2617
            },
            {
              "path": "crates/spt/tests/twohost_cli.rs",
              "line": 735
            },
            {
              "path": "crates/spt/tests/wake_resume_bind_e2e.rs",
              "line": 40
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/livehost.rs",
              "line": 2487
            },
            {
              "path": "crates/spt-daemon/src/registryhost.rs",
              "line": 2297
            },
            {
              "path": "crates/spt-store/src/info.rs",
              "line": 1511
            }
          ]
        }
      }
    },
    {
      "id": "REQ-WAKE-WAIT",
      "title": "A-2 rider (REMOTE-TRUTH triage §A-2): `spt endpoint wake --wait` blocks on the REAL bind (status reaches online) after the daemon wake-resume lift (REQ-WAKE-RESUME-LEG), instead of the DEFAULT 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.",
      "requiredStages": [],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": false,
          "evidence": []
        },
        "int": {
          "complete": false,
          "evidence": []
        },
        "unit": {
          "complete": false,
          "evidence": []
        }
      }
    },
    {
      "id": "REQ-WAN-SEND-DELIVERY",
      "title": "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, hone…
      "requiredStages": [
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/wan.rs",
              "line": 139
            },
            {
              "path": "crates/spt-daemon/src/wan.rs",
              "line": 178
            },
            {
              "path": "crates/spt-daemon/src/wan.rs",
              "line": 263
            },
            {
              "path": "crates/spt-net/src/net/wanmsg.rs",
              "line": 164
            },
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 210
            },
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 808
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 2279
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/wan.rs",
              "line": 1099
            },
            {
              "path": "crates/spt-net/src/net/wanmsg.rs",
              "line": 399
            },
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 2079
            },
            {
              "path": "crates/spt/src/wansend.rs",
              "line": 2178
            }
          ]
        }
      }
    },
    {
      "id": "REQ-WAN-SPT-HOSTED-DELIVERY",
      "title": "A WAN-ARRIVED `spt send` is DELIVERED to an spt-hosted endpoint (broker holds its PTY, NO api-listen relay), not spooled-forever. Today receive_wan (spt-daemon/wan.rs:271-276) tries deliver_tcp (the 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 a…
      "requiredStages": [
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/inject.rs",
              "line": 35
            },
            {
              "path": "crates/spt-daemon/src/inject.rs",
              "line": 73
            },
            {
              "path": "crates/spt-daemon/src/wan.rs",
              "line": 919
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/tests/inject_control_wedge.rs",
              "line": 3006
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/inject.rs",
              "line": 246
            },
            {
              "path": "crates/spt-daemon/src/wan.rs",
              "line": 1391
            }
          ]
        }
      }
    },
    {
      "id": "REQ-WHOAMI-1",
      "title": "The `endpoint list` SELF pin carries the Self endpoint's authored `endpoint description` (info::read_info(...).resources) when present, inline after the liveness state; whoami stays a top-level hot-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`.",
      "requiredStages": [
        "doc",
        "impl",
        "unit"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "CONTEXT.md",
              "line": 1027
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/cli.rs",
              "line": 11444
            }
          ]
        },
        "int": {
          "complete": false,
          "evidence": []
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/cli.rs",
              "line": 26234
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 26449
            }
          ]
        }
      }
    },
    {
      "id": "REQ-WHOAMI-EXPLICIT-SID-REFUSAL",
      "title": "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…
      "requiredStages": [],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": false,
          "evidence": []
        },
        "int": {
          "complete": false,
          "evidence": []
        },
        "unit": {
          "complete": false,
          "evidence": []
        }
      }
    },
    {
      "id": "REQ-WHOAMI-IDENTITY-ONLY",
      "title": "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 spa…
      "requiredStages": [
        "doc",
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "docs-site/src/harness-contract/api.md",
              "line": 413
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/cli.rs",
              "line": 11524
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/tests/whoami_identity_e2e.rs",
              "line": 14
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/cli.rs",
              "line": 26451
            },
            {
              "path": "crates/spt/src/roster.rs",
              "line": 655
            }
          ]
        }
      }
    },
    {
      "id": "REQ-WORKER-LIST-VISIBILITY",
      "title": "V-1 (WORKER-TRUTH triage, operator rider): worker perches leave the DEFAULT `spt endpoint list` view — they are process-local machinery, not subnet citizens; leaked-or-live worker rows rendering as 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.",
      "requiredStages": [
        "impl",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/cli.rs",
              "line": 6140
            },
            {
              "path": "crates/spt/src/cli.rs",
              "line": 6155
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/tests/worker_visibility_e2e.rs",
              "line": 18
            },
            {
              "path": "crates/spt/tests/worker_visibility_e2e.rs",
              "line": 61
            }
          ]
        },
        "unit": {
          "complete": false,
          "evidence": []
        }
      }
    },
    {
      "id": "REQ-WORKER-MINTED-NAME",
      "title": "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.",
      "requiredStages": [
        "doc",
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "docs-site/src/harness-contract/api.md",
              "line": 325
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-store/src/worker_seq.rs",
              "line": 31
            },
            {
              "path": "crates/spt-store/src/worker_seq.rs",
              "line": 39
            },
            {
              "path": "crates/spt/src/api/worker.rs",
              "line": 45
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/tests/worker_lifecycle_e2e.rs",
              "line": 25
            },
            {
              "path": "crates/spt/tests/worker_lifecycle_e2e.rs",
              "line": 194
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-store/src/info.rs",
              "line": 1009
            },
            {
              "path": "crates/spt-store/src/worker_seq.rs",
              "line": 74
            },
            {
              "path": "crates/spt-store/src/worker_seq.rs",
              "line": 88
            },
            {
              "path": "crates/spt-store/src/worker_seq.rs",
              "line": 111
            },
            {
              "path": "crates/spt/src/api/mod.rs",
              "line": 1169
            },
            {
              "path": "crates/spt/src/api/worker.rs",
              "line": 213
            }
          ]
        }
      }
    },
    {
      "id": "REQ-WORKER-PICKER-EXCLUDED",
      "title": "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.",
      "requiredStages": [
        "impl",
        "unit"
      ],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/picker/data.rs",
              "line": 204
            },
            {
              "path": "crates/spt/src/picker/data.rs",
              "line": 336
            }
          ]
        },
        "int": {
          "complete": false,
          "evidence": []
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/picker/data.rs",
              "line": 707
            },
            {
              "path": "crates/spt/src/picker/data.rs",
              "line": 717
            }
          ]
        }
      }
    },
    {
      "id": "REQ-WORKER-REAP",
      "title": "W-3 (WORKER-TRUTH triage): worker records must not persist indefinitely past their useful life — 6 dead-pid workers leaked OFFLINE on flynn (kill-paths where SubagentStop never fires: parent killed, 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 — rea…
      "requiredStages": [
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/livehost.rs",
              "line": 276
            },
            {
              "path": "crates/spt-store/src/worker_reap.rs",
              "line": 59
            },
            {
              "path": "crates/spt-store/src/worker_reap.rs",
              "line": 87
            },
            {
              "path": "crates/spt/src/api/reporting.rs",
              "line": 344
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-daemon/src/livehost.rs",
              "line": 1789
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt-store/src/worker_reap.rs",
              "line": 163
            },
            {
              "path": "crates/spt-store/src/worker_reap.rs",
              "line": 173
            },
            {
              "path": "crates/spt-store/src/worker_reap.rs",
              "line": 191
            },
            {
              "path": "crates/spt-store/src/worker_reap.rs",
              "line": 206
            },
            {
              "path": "crates/spt-store/src/worker_reap.rs",
              "line": 225
            },
            {
              "path": "crates/spt-store/src/worker_reap.rs",
              "line": 241
            },
            {
              "path": "crates/spt/src/api/reporting.rs",
              "line": 1643
            }
          ]
        }
      }
    },
    {
      "id": "REQ-WORKER-SID-SYMMETRIC-AUTH",
      "title": "W-2 (WORKER-TRUTH triage, operator-ruled 2026-07-06): worker verbs go sid-symmetric with every sibling id-scoped verb — worker-start mints NO token and worker-stop takes NONE (token custody is undue 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-i…
      "requiredStages": [
        "doc",
        "impl",
        "unit",
        "int"
      ],
      "stages": {
        "doc": {
          "complete": true,
          "evidence": [
            {
              "path": "docs-site/src/harness-contract/api.md",
              "line": 346
            }
          ]
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/api/auth.rs",
              "line": 236
            },
            {
              "path": "crates/spt/src/api/mod.rs",
              "line": 853
            },
            {
              "path": "crates/spt/src/api/worker.rs",
              "line": 46
            }
          ]
        },
        "int": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/tests/worker_lifecycle_e2e.rs",
              "line": 26
            },
            {
              "path": "crates/spt/tests/worker_lifecycle_e2e.rs",
              "line": 194
            }
          ]
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/spt/src/api/auth.rs",
              "line": 543
            },
            {
              "path": "crates/spt/src/api/auth.rs",
              "line": 553
            },
            {
              "path": "crates/spt/src/api/auth.rs",
              "line": 576
            },
            {
              "path": "crates/spt/src/api/auth.rs",
              "line": 594
            },
            {
              "path": "crates/spt/src/api/worker.rs",
              "line": 213
            },
            {
              "path": "crates/spt/src/api/worker.rs",
              "line": 245
            }
          ]
        }
      }
    },
    {
      "id": "REQ-XTASK-SPT-BIN-TARGET-DIR",
      "title": "#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 f…
      "requiredStages": [
        "impl",
        "unit"
      ],
      "stages": {
        "doc": {
          "complete": false,
          "evidence": []
        },
        "impl": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/xtask/src/main.rs",
              "line": 173
            },
            {
              "path": "crates/xtask/src/main.rs",
              "line": 199
            }
          ]
        },
        "int": {
          "complete": false,
          "evidence": []
        },
        "unit": {
          "complete": true,
          "evidence": [
            {
              "path": "crates/xtask/src/main.rs",
              "line": 2019
            }
          ]
        }
      }
    }
  ],
  "findings": []
}


Wall time: 3.91 seconds