# PR #23610 evidence matrix (fs-29, Linux; synthetic profile via SHELL=/tmp/ev-23610/shellwrap)

BEFORE = main 8d3b061121, AFTER = 7acf9a905a. Same driver.ts against each server; profile.sh edited after server start.

| Row | Before | After | Verdict |
|---|---|---|---|
| R2 page open, single discovery (Settings mount == Rescan: both call the same `discovery` query; Rescan = `discovery.refresh()`) | 235 ms; 0 shell spawns; glab `missing`; terminal PATH unchanged | 278 ms; 1 shell spawn; glab `available` "glab 9.9.9-FAKE-glab-from-profile-a"; terminal PATH now starts with fakebin-a, `which glab` → fakebin-a | Fixed. Note: opening Settings alone re-reads the profile (no Rescan-only gating server-side) |
| R3 slow profile (`trap '' TERM; sleep 60`) | 151 ms, no shell | 6600 ms; WARN "Timed out reading PATH from login shell /tmp/ev-23610/shellwrap after 5s."; then fallback `/bin/bash` candidate ran (~0.3 s) and its PATH was merged (added /usr/local/nvm/.../bin from system /etc/profile) | Bounded, but >5 s: timeout 5 s + forceKill ~1 s + fallback shell. Fallback shell silently changes PATH when $SHELL is slow |
| R4 failing profile (`exit 3`) | 162 ms, no shell | 409 ms; no log line (non-zero exit is silent); fakebin-fail NOT in PATH; fallback `/bin/bash` candidate ran | Correct (failure ignored); fallback runs, no warning logged |
| R5 reorder (fake git/claude/codex prepended) | git "2.43.0"; `which` → /usr/bin/git, /usr/local/bin/claude,codex | git "0.0.0-FAKE"; terminal `which -a` → fakebin-r/git, fakebin-r/claude, fakebin-r/codex first | Expected consequence: login-profile order now wins at runtime. New Claude/Codex sessions resolve bare `claude`/`codex` via process.env at spawn (ClaudeProvider.ts:442, CodexProvider.ts:712 `environment ?? process.env`) → would spawn the fakebin-r binaries (not started) |
| R6 overlap (3 concurrent, `sleep 2` profile) | 322/366/417 ms, 0 spawns | 2339/2377/2408 ms, 1 spawn (shared via cachedWithTTL(0)); cancel A at 500 ms → B finished 2237 ms, 1 spawn | Dedup works; cancelling one caller does not break the other |

Startup: both servers ran the profile once at start (fixPath), as before.
