# PR #23690 evidence capture (AgentSessionScanner `cat` reads)

HEAD `b2948332e22490d654b31a70a95767ee6baa7e5e` (~/wt/pr-23690), MERGE-BASE `60b35a1ee02d717009ff4a3de34de285db9e8a60` (~/wt/pr-23690-before). Linux x86_64, Node 24.22.1 (drivers) / 26.12.1 (dev server). Drivers build the scanner exactly like `layerScannerTest` in `AgentSessionScanner.test.ts` (ServerSettings.layerTest + ServerConfig.layerTest + mocked ProjectStore), with fixture `homePath`s for Claude and Codex. No tracked files were edited.

| Row | Verdict | Result |
|---|---|---|
| R1 identity parity | PROVEN | Covers 8 cwds: normal, a linked worktree of a non-bare repo, the linked worktree of a bare repo, a submodule-style pointer, a `.git` with no config, a garbage pointer, a regular file and a plain dir. Base and head JSON are identical (`diff` exit 0). |
| R2 >1 MiB config | PROVEN | `early` (origin at byte 19 of 1,440,067) gives `acme/early` on both. `late` (origin at byte 1,440,027) gives `acme/late` on base and `remoteKey:null` on head. Under truncation, cat exits with **code 0** (not killed or SIGPIPE'd), `stdoutTruncated:true`, 1,048,576 chars, so head parses the **1 MiB prefix**, not "". |
| R3 memo | PROVEN | Same scanner instance: scan 1 took 2115 ms, scan 2 83 ms, scan 3 69 ms. `fifo-repo/.git/config` was cat-exec'd once in scan 1 and 0 times in scans 2–3 (strace execve). |
| R4 dedupe | PROVEN | Two linked worktrees (`wt-a`, `wt-b`) of one bare repo whose config is a FIFO: `shared.git/config` was cat-exec'd **once** in scan 1. |
| R5 spawn error | PROVEN | With PATH=empty dir, every `cat` execve fails ENOENT, the scan exits 0 in 115 ms with no crash, and repos degrade to `remoteKey:null`. Side effect: pointer-file cwds degrade to `git:null`, so the **linked worktree `normal-wt` becomes a candidate** (it is hidden when cat works). |
| R6 dev server | PROVEN | `vp run dev --home-dir …/home-head --no-seed`, driven over a real `/ws` connection (dev-cookie auth, `agentSessions.scan` RPC). Conn 1, 5 scans: 2050 / 23 / 21 / 39 / 24 ms. Each FIFO config was cat-exec'd once in total. `/.well-known/t3/environment` returned 200 in 4 ms (server port and via vite). The fs-backed static handler (non-loopback Host → `resolveStaticDir` fs checks) returned 503 "waiting for build" in 1.5 ms. There were 0 `cat` children of server PID 1503130 about 5 s after the last scan. Stopped the recorded process group; ports 14187 and 6147 are closed. |

## R6 addition: memo lifetime and recovery

- **The memo is shared for the server's lifetime, not per connection.** A NEW WebSocket (conn2) scan ran in 21 ms with **0** cat execs for `fifo-a`/`fifo-b` config. Only `normal/.git/config` was read. `ws.ts` provides `AgentSessionScanner.layer` inside the per-connection `layerWsRpc`, but the instance (and its `blockedGitFilePaths` set) is reused across connections. Layer memoization is the likely cause; this capture did not check that mechanism.
- **A released path does not recover without a server restart.** We replaced `fifo-a/.git/config` with a regular config containing `origin = https://github.com/acme/fifo-a.git` at the same path. Scans on two fresh connections (conn3, conn3b) both made **0** cat execs for it and still reported `fifo-a` with `remoteKey:null`. The memo has no expiry or retry, so a path that blocked once (for example a macOS privacy prompt that was later granted) keeps its remote hidden until the server restarts.

## Artifacts
- Transcripts: `r1-transcript.txt`, `r2-transcript.txt`, `r3r4-transcript.txt`, `r5-transcript.txt`, `r6-transcript.txt`, `r6-shutdown.txt`, `r6-transcript.attempt1-protocol-426.txt`. The first R6 attempt failed the WS handshake with 426 because `?orchestrationProtocol=2` was missing; no scans ran in it.
- Raw: `r3-strace.log`, `r6-cat.log` (PATH-shim log of `cat -- <path>`), and the JSON results.
- `r6-server.log` is not uploaded because it contains the dev auth token.

## Driver sha256
See `drivers.sha256`.
