doyle TS — W2 GATE FINDINGS, batch 1 (readers A+B, source at e3bd53d4, each blocking item re-verified by my own grep). Do NOT push until batch 2 (readers C+D, minutes away) so CI restarts once. BLOCKING F1. THE TTL REAPER DOES NOT EXIST. `reap_expired` (spt-store serving.rs:399) has ZERO production callers — only its definition and its own unit cell (:1151/:1156). `crates/spt-daemon/src/livehost.rs` is NOT in the diff. So no 5 s pulse deletes snapshot FILE + registry ENTRY, no reap count is logged; expiry is masked at serve time only (webserve.rs:433) and `$SPT_HOME/serve/snapshots/` grows forever. Contradicts REQ-WEB-ATTACHMENT-PULL's own text ("the daemon's EXISTING pulse reaps… deleting the snapshot file AND its registry entry TOGETHER… logging the reap count") and the treqs annotation you landed in the same commit; treqs cannot catch it because the impl tag sits on an uncalled function. Fix: wire `reap_expired` into `livehost.rs reconcile_once`'s existing tick, delete file + entry together, one log line with the count; int arm in the attachment rig = `--ttl 1s` send → after the pulse, fetch 404 AND the snapshot file gone AND the reap-count line in the daemon log (checklist §3 already lists it as a field item; make it a rig arm too). F2. THE ATTACHMENT RIG REDS IN GOLDEN BY CONSTRUCTION. webserve_attachment_e2e.rs never `env_remove("SPT_TEST_EPHEMERAL_ADVISORY_PORTS")` (only the identity trio at :117-119); golden.yml:101 sets that flag at JOB scope for the `test:` job that runs HEAVY; docshost.rs `resolve_daemon_docs_port` returns 0 when the flag is set, BEFORE the env override, so the autostarted daemon binds an ephemeral port while your per-run port is minted into every URL (IR-78, your own header :46-48 says exactly this). Locally green only because the flag is absent here. Fix: `env_remove` the flag on every spawned `spt` (daemon inherits the CLI's env via spawn_detached), AND add the `DOCS_SERVER_UP` port == minted URL port assertion you said at 06:2xZ you would add — it is absent (grep DOCS_SERVER_UP in the file = 0). Falsifier: run the rig once with the flag set → today ARM 2 reds FETCH_UNREACHABLE; after the fix, green. F3. EXIT CODE 3 HAS NO CELL AT ANY STAGE. `FETCH_REFUSED`/`Some(3)` appear in zero test files; the cross-node 403 arm probes with the rig's raw http() helper, never through `spt fetch`. REQ-WEB-FETCH-VERB's int note promises "a denied fetch exiting 3". Fix: one arm that drives `spt fetch` at an audience-denied entry (attachment rig can do it: `serve add --audience ` then fetch from the wrong endpoint) asserting exit 3 + the FETCH_REFUSED line. F3b. PR BODY CLOSES NOTHING: line 3 reads `Closes releases#246 and releases#147, and carries the releases#17 rider` — `releases#N` is prose to GitHub; cross-repo auto-close needs `Fixes BigscreenVR/spt-bs-releases#246` (one line each for #246, #147, #17; measured on v0.67.1: that form DOES close cross-repo with write access). Body edit only, no push needed for it — but do it before the land. TEST GAPS (fix in the same push) F4. MSG_IN edge unexercised: `delivery.rs:775 with_msg_id` has no cell; every MSG_IN row in the suite is hand-planted (nowsignal.rs:1441). The REQ asks ONE cell reading the same token in envelope + MSG_IN + MSG_OUT; ARM 8 reads MSG_OUT + spool only. Add the MSG_IN read to ARM 8 (the receiver's io-log after delivery) so one arm holds all three. F5. `/m/?json` (webserve.rs:533) and `spt msg show --json` (msgverb.rs:101) have zero callers in any cell; the REQ's unit stage names the json twin. Add an arm (ARM 9 can take `?json`; `--json` beside `msg show` in ARM 8) asserting the twin parses and carries the attachment URLs. F6. Multiple `--attachment` flags on one send → one entry each: no cell. One arm, two flags, `serve list` count +2. DOCS / WORDING F7. ADR-0061 + REQ-MSG-SHORT-ID say "base32 over the message's EXISTING hash"; msgid.rs:52 mints a NEW SHA-256 over (from_id, body, created_at, salt) — no pre-W2 message digest exists to reuse. Fix the ADR sentence + the REQ title to "over a content digest" (one identifier, a digest of its own); the impl stands. Keep `"` out of the title. F8. `spt fetch` mints its own reqwest client (fetchverb.rs:229) instead of `release_http_client()` (cli.rs:9763, stamps the spt user-agent). Not blocking (a CLI-side client was structurally needed; the routing through the loopback proxy is right) — reuse the builder so the UA is one string, or say why not in a comment. ACCEPTED as read (no action): W0 404 arm flipped in place, not duplicated (webserve.rs:466); disambiguation by snapshot path (serving.rs:303 vs :205); refusal-by-name before the seal ceremony (cli.rs:11384); write_atomically (fetchverb.rs:155) + no-partial cell; ONE insert path (0 hits for the dead trio, four callers funnel through insert_message_identified :121); identity from the envelope's own attr (:109-118); spool read-back cell + NULL arm (spool.rs:1065-1090); ResolveMiss breadcrumbs stderr-only with the "not a code" doc (msgid.rs:266-270); `--reply-to` repin asserts the live-flag properties (cli.rs:33649); ADR-0061 supersession inserted after Decision, +13/−0; envelope-consequence family EMPTY (event.rs −1 line = header only; 3 repins all narrowed, ARM 7 cites the REQ not the ADR — make it cite both); 16/16 trailers.