{
  "summary": "Read-only source map for releases#299 completed. Standalone human/JSON endpoint listing reads local perches plus persisted WAN snapshots, then waits for UNLISTED presence probes before finishing its table. The picker shares local/snapshot gathers but not that probe stage. Several independent waits can produce similar elapsed times; no root cause established and no execution performed.",
  "files": [
    {
      "path": ".worktrees/304-product/crates/spt/src/cli.rs:6427-6858",
      "description": "Complete endpoint-list human/JSON gather and render; human UNLISTED barrier at 6826, JSON barrier at 6649."
    },
    {
      "path": ".worktrees/304-product/crates/spt/src/cli.rs:6906-7028,14185-14294",
      "description": "UNLISTED evidence/probe mapping; 10-second outer ceiling, 16-item windows, bounded scratch threads and joining."
    },
    {
      "path": ".worktrees/304-product/crates/spt/src/roster.rs:62-118,158-175,191-287",
      "description": "Local enumeration, per-perch registry lookup/liveness, nested enumeration and environment/PID ancestry identity detection."
    },
    {
      "path": ".worktrees/304-product/crates/spt/src/picker/data.rs:103-134,220-300,310-385",
      "description": "Picker local/snapshot union and self-owned reconciliation; separate from UNLISTED network probing."
    },
    {
      "path": ".worktrees/304-product/crates/spt/src/wansend.rs:223-232,678-733,1230,1458-1480",
      "description": "Snapshot reader, presence probe entry, route selection, 30-second pump carrier and outcome projection."
    },
    {
      "path": ".worktrees/304-product/crates/spt-store/src/registry.rs:20-42,83-91,117-143",
      "description": "SQLite registry connection per address lookup; responder additionally cleans stale rows."
    },
    {
      "path": ".worktrees/304-product/crates/spt-store/src/db.rs:30-77",
      "description": "Five-second default SQLite busy timeout plus manual WAL retries."
    },
    {
      "path": ".worktrees/304-product/crates/spt-daemon/src/brain.rs:480-501,1022-1032,1934-1957,2569-2601",
      "description": "Pump connection setup, fixed call deadline, blocking dial reply and ten-second peer reply budget."
    },
    {
      "path": ".worktrees/304-product/crates/spt-daemon/src/wan.rs:881-930",
      "description": "Presence stream open/send/subscribe and reply loop, with per-data-frame rearming."
    },
    {
      "path": ".worktrees/304-product/crates/spt-daemon/src/broker.rs:6108-6111,9255-9275",
      "description": "Non-journaled presence dial dispatch into NetHost."
    },
    {
      "path": ".worktrees/304-product/crates/spt-daemon/src/nethost.rs:975-1006,1469-1482,1564-1581",
      "description": "Dial semaphore, QUIC connect, membership proof and broker QUIC-operation bound."
    },
    {
      "path": ".worktrees/304-product/crates/spt-daemon/src/dispatch.rs:1987-2030,2114-2195",
      "description": "Remote presence server, access decision, fresh broker sessions query, SQLite resolution and 500ms relay connect."
    },
    {
      "path": ".worktrees/304-product/crates/spt-daemon/src/registryhost.rs:911-925,947-978",
      "description": "Daemon in-memory registry locks and persisted snapshot producer; not a synchronous CLI roster request."
    },
    {
      "path": ".worktrees/304-product/docs/INFRA-REGISTER.md:5566-5635",
      "description": "IR-94 stream-server gate coverage prerequisite and IR-95 elapsed/budget/producer-progress evidence requirements."
    }
  ],
  "architecture": "Three distinct registries must not be conflated: local SQLite address registry, daemon in-memory subnet RegistryHost, and persisted JSON WAN snapshots. List/picker read the first and third; RegistryHost writes snapshots independently. List additionally requests fresh presence for evidence-known UNLISTED rows over CLI→broker→QUIC→remote dispatch→remote broker/local relay. This mixed snapshot/fresh-probe command has no single global wall deadline.",
  "report": "## Scope and accepted measurements\nRead https://github.com/BigscreenVR/spt-bs-releases/issues/299 and its comment https://github.com/BigscreenVR/spt-bs-releases/issues/299#issuecomment-5629569142 (not core). Reporter perri on HFENDULEAM, standalone 0.69.0: unpiped `endpoint list --show-all` took 3822, 10120, 10105ms, rc=0 each, byte-identical complete 2497-byte output. Accept these observations directly. Reported field corpus: 1210 UPS traces over 50.4h/10 endpoints; three live-roster stages 7454/10058/10061ms, total calls 10086/10307/11174ms. Two of seven peers reportedly unreachable at quic-connect. No adapter subprocess timeout; historic 5s versus current 20s hook allowance is mitigation context only. Neither causation nor failure rate follows from these survivor traces.\n\nThis is preparation against the assigned worktree, not reproduced diagnosis. No files changed; no builds, checks, tests, fixtures, production interactions or Rust execution. The assigned d89a655f baseline was not independently verified with git; concurrent product edits may shift line numbers.\n\n## Exact command flow and waits\n1. `main.rs:154-206` launches `cli::run` on its sized CLI stack. `cli.rs:2393-2402` selects `cmd_endpoint_list(subnet, detail, show_all, workers, json)`.\n2. `cli.rs:6442-6448` loads/validates subnet configuration. Human path resolves node identity and caller at 6668-6674. `roster::detect_self_id` (roster.rs:191-287) may read all perch/nested records for session ID, use environment labels, or walk OS process ancestry plus per-perch PID probes. These are filesystem/OS costs, not WAN registry RPCs. If caller resolves, another full roster enumeration builds the self-pin, printed before the later table barrier.\n3. `cli.rs:6730-6748` loads persisted WAN JSON snapshots, visibility and project index, then enumerates local rows. `wansend::load_snapshots` (1458-1480) performs read_dir/read_to_string/JSON parse per snapshot, no request to a daemon. Project-index use is a read, not synchronous git enrichment (ADR-0037:21-40; explicit reader cutover at cli.rs:6739 onward).\n4. `roster.rs:62-118`: per directory, info read, ready existence, liveness/unbound evaluation, then `registry::lookup_address`. Every lookup opens `<owlery>/.registry`, tunes it, executes CREATE TABLE IF NOT EXISTS and SELECT (spt-store/registry.rs:20-42,83-91). `db.rs:30-53` sets a per-connection/per-statement busy handler and tries WAL up to 200 times, sleeping 5+(attempt%10)ms on busy/locked; sleep sum is 1900ms if all 200 retry, before statement execution costs. Default busy timeout is 5s, environment-overridable (`db.rs:55-77`). Multiple rows/enumerations can repeat these waits; no list-wide bound. This is a contention candidate to measure, not a finding of contention. Local info, sentinel, project-index and nested-child reads add unbounded-by-command filesystem cost.\n5. Human path adds caller-owned nested rows (`cli.rs:6773-6793`), projects remote rows with visibility and worker filtering, drops this node's gossip duplicates, groups by node (`6799-6819`). `--show-all` affects later suspended-row filtering (`7432-7445`), not these waits. All wanted suspended/local/remote rows must remain in reproduction and remedy.\n6. `gather_unlisted` (`6906-6943`) excludes already-listed/local/visibility-excluded IDs and calls local evidence gather. `unlisted.rs:278-285` reduces raw evidence; evidence sources include access rules, contact ledger and outbound knocks (`117-200`). These reads may add metadata cost. UNLISTED is not the same as unreachable subnet peers: listed remote rows do NOT themselves enter this worklist. Correlation with two unreachable peers only becomes pertinent if their node keys are actually in the UNLISTED worklist or affect a shared dependency.\n7. `cli.rs:6826-6832` calls `probe_unlisted` before table rendering at 6837 onward. The JSON leg likewise waits at 6649 before its single final JSON print. `probe_unlisted` repeats identity resolution even if the worklist is empty (7024), then calls `probe_unlisted_with`.\n8. `6981-7013`: only evidence rows carrying node keys are probed; node-less rows remain, explicitly not asked. Answers stay in input order and pair to every original row. `PRESENCE_PROBE_CEILING=10s` (6968), `MAX_INFLIGHT=16` (14209). `probe_all_with` (14244-14294) processes windows sequentially, spawns one wrapper per item and joins every wrapper before the next window. Thus <=16 probe items approximately share one outer ceiling; >16 can cost ceil(k/16) ceilings. This is an endpoint worklist, not deduplicated by node: distinct endpoints on the same node are separate probes.\n9. `run_bounded` (14185-14196) spawns an inner worker and `recv_timeout`s. Timeout supplies Unknown to the row; it does not cancel/join the inner operation. The outer cap bounds waited-on wrappers, not necessarily all still-running underlying workers across windows. Preserve this distinction when sizing the experiment and observing drain.\n10. Actual worker (`wansend.rs:678-712`) first calls `ensure_running`. `daemon.rs:603-604` uses seed ping; `seedmap.rs:387-403` connects, writes PING, reads PONG without an explicit deadline in this function. If absent, `daemon.rs:691-750` can wait for the machine spawn lock (`daemon_inhibit.rs:134-149`, blocking lock_exclusive), service discovery/start/manual spawn, and startup polling. `daemon.rs:619-632` counts accumulated START_POLL sleeps up to a 5s START_TIMEOUT, not total wall time including ping. Outer probe ceiling bounds the caller's wait, not all these operations' lifetimes.\n11. `Brain::cold_start_pump` (brain.rs:480-501) connects local IPC and sends hello before storing its io_timeout. The presence caller supplies 30s (`wansend.rs:1230`). Local connect/hello, outgoing writes and scheduling must be timed separately from later read deadlines. `seed_first_addr` (223-232) reads valid peer route or falls back to ID-based discovery.\n12. `Brain::net_dial` (1934-1957) sends KIND_NET_DIAL with op=None and waits for NetDialed/Error under call_deadline. Broker dispatch (`broker.rs:6108-6111,9255-9275`) directly calls `NetHost::dial`, not submit_dial and not its journaled branch. `nethost.rs:1564-1581` waits for shared dial semaphore, then `DialPlan::connect` (975-1006) waits QUIC connection and membership proof; `bounded_block_on` (1469-1482) bounds this combined operation (documented production 10s). Local permit contention and a remote QUIC wait therefore share an outer bound. Source timing constants alone cannot distinguish them.\n13. After dial, `request_presence` (`wan.rs:881-930`) refuses an unbounded carrier, opens stream, sends and finishes request, subscribes, then waits for reply. Each broker operation has its own request/reply work. Peer reply deadline is min(carrier,10s) (`brain.rs:1026-1032,2569-2601`), rearmed on matching data frames; timeout produces PeerSilent, EOF without answer produces Answered(Unknown), and errors propagate. `wansend.rs:725-733` projects PeerSilent to Unknown honestly. The CLI's 10s outer ceiling competes with broker-dial and peer-reply bounds; it can return without proving which internal stage finished.\n14. Remote serving (`dispatch.rs:1987-2030`) subscribes and reads a subscriber-lifetime stream with None deadline. `answer_presence_probe` (`2114-2144`) checks MSG access. It evaluates BOTH broker_session_idle and observe_relay before combining them. Broker query uses a fresh `Brain::cold_start` then sessions (`2158-2170`), not the serving carrier. Relay observation (`2180-2195`) uses resolve_address, which cleans SQLite stale rows then reopens for lookup, followed by a 500ms TCP connect; SQL/OS waits precede that connect ceiling. These remote costs are hidden behind the caller's reply/outer wait, not separately measured in #299.\n15. After all UNLISTED probe wrappers finish, human table and UNLISTED section print (`cli.rs:6837-6858`). Final stdout/terminal backpressure and process teardown are additional elapsed stages. The human self-pin may have printed earlier, so measure first-byte versus complete-output separately without proposing incremental/partial output as a remedy.\n\n## Picker and daemon registry distinction\n`picker/data.rs:103-114` gathers label map→local_rows→subnet_rows→reconcile_self_owned. Label map (121-134) and subnet_rows (310 onward) each reload snapshots; local rows (220 onward) read index, roster, info and offline session history. It does not call probe_unlisted. It is a useful comparison seam, not an equivalent substitute command.\n`RegistryHost::rows/snapshot` (`registryhost.rs:911-925`) lock daemon state for internal consumers. `write_snapshots` (`947-978`) holds regs while serializing/atomic-writing each subnet and separately mirrors heard metadata. CLI readers do not acquire these mutexes or await a fresh registry pump cycle. Therefore a supposed synchronous complete-roster daemon registry RPC is not in this traced list/picker path. Contention could still affect broker servicing, local SQLite or shared filesystem/runtime resources, but must be demonstrated, not inferred from RegistryHost locks.\n\n## Existing seams and limits\n- `cli.rs:28090-28161`: injected probe validates node-less preservation and row-to-answer pairing.\n- `cli.rs:28168-28200`: injected 150ms ceiling with one 1500ms sleeper returns [Listening,Unknown,Listening] in order; this proves wrapper behavior only, not real CLI delay cause.\n- `cli.rs:27908-27928`: show-all suspended retention/status ordering evidence.\n- `roster.rs:437 onward`: corrupt local row retention; `805 onward`: identity zero-git seam.\n- `picker/data.rs:765 onward`: isolated-home snapshot→projection→picker suspended-row path.\n- `spt-store/registry.rs:172-192`: concurrent registration/lookup seam. It does not establish a lock stall for endpoint list.\n- `spt-daemon/tests/wan_reply_bound.rs:76-130,275-371`: two hermetic brokers (relay disabled), live-but-unserving peer, presence included among sibling reply calls; one-second pump budget, caller watchdog, elapsed/verdict recorded. Good seed for accepted-stream silence isolation; not end-to-end list and its timing starts after dial.\n- `spt/tests/worker_visibility_e2e.rs:50 onward`: actual binary endpoint-list command helper in isolated home. Useful consumer-surface composition pattern.\n- `nethost.rs:2673 onward`: injected QUIC-operation bound seam, independent from whole-list output preservation.\n\n## Missing evidence\nNeed correlated elapsed spans for entry/identity, each roster enumeration, SQLite open/tune/query, JSON and project/evidence reads, worklist creation (count plus endpoint/node identities), each probe's queued/start/ensure/IPC-connect/dial-permit/QUIC/membership/open/send/subscribe/reply/timeout completion, and final output. Existing issue provides aggregate timing and output length/equality, not these spans or the 2497-byte roster itself. Need exact UNLISTED rows and whether the two unreachable nodes are queried, resolved route mode, effective timeout settings, daemon/broker startup state, OS/storage contention, and deployed 0.69.0 versus current source correspondence. Need distinguish successful answer, EOF, local failure, peer-silent and outer timeout BEFORE the column projection makes several Unknown. Root cause cannot be selected from three separate 10s timers or unchanged output.\n\n## Smallest bounded executable proposal (not executed)\n1. Obtain a separately authorized isolated Windows allocation matching the observed platform. Use one serial lane, one worktree-owned target pool, temporary SPT_HOME, fixed caller environment, no production credentials/services or production peer dials. Hertz owns regression implementation; Main owns interpretation and product edits.\n2. Seed a tiny but COMPLETE deterministic roster: local live and suspended rows; remote active and suspended snapshot rows; two UNLISTED node-bearing rows with distinct outcomes; one node-less rule row. Keep all rows and identical metadata in every trial. Fix evidence timestamps sufficiently to avoid changing relative-age output within a comparison window. No row dropping and no whoami replacement.\n3. First exercise the existing injected probe seam with one quick answer and one controlled blocked worker released by a bounded gate. Assert exact full row membership/order and truthful Unknown/not-asked, not merely row counts. This is apparatus proof, not reproduction of field cause.\n4. Compose actual unpiped human `endpoint list --show-all` in isolated terminal using an instrumented diagnostic binary. Keep output payload intact; record timings off stdout. Start one local broker and one hermetic peer using existing WAN fixture pattern. Separate serial cases with unchanged roster: responsive presence; accepted stream with no reply; gated local broker/permit wait; deliberate local SQLite lock holder. Gate/release each injected wait independently. Compare full normalized/byte-stable expected output where states are equal, and exact row identities plus only truthful state differences otherwise. JSON can supplement shape checks but cannot replace the reported human scenario.\n5. One blocked operation at a time and <=16 queried rows; retain production timeout values for the faithful path. Predeclare a wall watchdog covering full command plus bounded fixture drain (e.g. 45s command, 15s shutdown) and record rc, complete bytes/hash, all stage elapsed times, counts and producer progress on success AND expiry. Terminate only isolated fixture process trees if drain fails. Do not run a 100x stress loop initially. If field behavior does not appear, report only the stages exercised and obtain the missing field artifact/probe; no fix proposal follows merely from successful timer injection.\n6. Runtime resource prerequisite is currently UNALLOCATED. Allocation must name Windows host, exclusive source/cache ownership, build jobs and memory/disk ceiling, maximum simultaneous broker/CLI processes and dial workers, serial case count, watchdogs, retained diagnostic artifact location and teardown owner. A small unit-seam allocation and the heavier real-binary/two-broker allocation must be sized separately. No build/test command is authorized by this source investigation.\n\n## IR-94 / IR-95\nIR-94 (`INFRA-REGISTER.md:5566-5594`) is an enforcement-coverage prerequisite if later work changes stream-server lifetime/deadline classification or migrates serve_sync onto a bounded carrier. No serve_sync migration is needed to collect this map or time standalone list, so it is not an unconditional blocker for this reproduction. Do not treat the current narrow brainread census as comprehensive proof for presence/registry stream paths.\nIR-95 (`5596-5635`) applies immediately to any new reproduction polling/barrier: actual elapsed, budget type (wall versus accumulated sleeps/iterations), iterations, and producer progress must be retained on passes and failures. Existing daemon startup sleep-count loop and WAN fixture connect-retry loops show why nominal durations are not wall bounds. Gate implementation should not silently inherit those blind retry loops or widen their budgets. No infrastructure edits were made here."
}
