# Proof audit, pass 1 — fixture and transcript matrix

PR [#25970](https://git.cafe/pingdotgg/t3code/pull/25970). Read-only audit in `/home/ubuntu/wt/pr-25970`.
Head [bfd52848f9](https://git.cafe/pingdotgg/t3code/commit/bfd52848f9c02add53ab87e4a7dff31aae12b745), parent/merge-base [e9236274a3](https://git.cafe/pingdotgg/t3code/commit/e9236274a3a6e0c731a7df4092db1e686f039068).

## Findings first

1. The diff is four test files, +24/-8 ignoring whitespace. Seven test registrations gain `it.effect.skipIf(!symlinksSupported)`; three gain the import. No product component, UI caller, layout, theme, viewport, RPC, route, loading state, or client changes. The complete changed input axis is the module-load probe's boolean, crossed with revision and owning package.
2. The probe calls `mkdtempSync`, then `symlinkSync` with an untyped, dangling link, returns true on success, false on any caught creation error, and ignores cleanup errors. The uploaded preload replaces sync, callback, and promise symlink APIs, sets `code: EPERM`, and calls `syncBuiltinESMExports`. Its SHA-256 is `e364864529ef79a816183b75d210f52b7fc134bc220b318de3dcaddf93cecdde`.
3. A small diagnostic imported the actual probe in the current checkout, both in a main Node process and a fork with `execArgv: []`. Normal: probe true, callback/promise creation succeeded. With the downloaded preload supplied through `NODE_OPTIONS=--require=...`: probe false and both async APIs returned EPERM in both processes. This validates the injection mechanism, not any suite outcome. Raw driver, preload, and diagnostic logs: [probe audit evidence](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fa278719f02eb95b/probe-audit-evidence.tar.gz). Diagnostic runtime: Node v24.22.1.
4. Root and server configs do not set `pool`, `execArgv`, or `NODE_OPTIONS`; server inherits root test settings and disables file parallelism. Installed Vitest 5.0.5 resolves an unset pool to `forks` (its later threads fallback is unreachable after this default). Its pool builds worker env from `process.env`, then runtime/project overrides, and calls `child_process.fork` with that env. Root config only overrides VP cache variables, so NODE_OPTIONS reaches workers. These config, package, lockfile, and probe files are identical at parent and head. No `--pool` override is needed. Passing the preload only on the coordinator's command line would be weaker: Vitest filters inherited `process.execArgv`; use the environment mechanism below.
5. Every explicit symlink creation in these four files is guarded at head. There are 14 source call sites: scanner 3 (one site expands to two tests), settings 1, ACP 3, OpenCode 7, plus the shared probe outside those files. Scanner's two existing alias cases already skip on parent. No additional unguarded symlink planter was found in the four files. Static test registration expansion gives settings 47, scanner 53, OpenCode 5, ACP 13, totaling 118. These are expected counts, not newly observed run results.
6. Earlier transcripts and PR-body totals were not accepted as capture evidence in this pass. The normal/failure/skip expectations below follow from source and need fresh run transcripts. Native Windows was not run; the preload models permission denial, not Windows path semantics or all Windows filesystem behavior.

## Named fixture catalog (all labelled harness fixtures)

Each named test seeds its own scoped temporary filesystem using NodeServices/Effect. There is no real-app route/settings/RPC seed for a test-registration skip. Run the owning test file: no server, browser, live database, or user data is required. Dates below are fixed fixture data, not wall-clock waits.

| ID | Full test name / caller | Required data and actions | Diff affected? |
|---|---|---|---|
| S1 | `server settings > saves through a symlinked settings file without replacing the link` | External settings JSON with `responseStreamingMode: turn`; symlink configured settings path to it; update to paragraph; assert link identity and persisted value. | Yes, new guard |
| S2 | `AgentSessionScanner > scan > returns the imported project ID through a realpath alias` | Real workspace, alias link, Claude transcript pointing to alias (2026-01-01), canonical root already imported as project-1; scan returns canonical project and imported flag. | Yes, new guard |
| S3 | `AgentSessionScanner > scan > excludes sandboxes reached through a symlink into the worktrees dir` | Custom base/worktrees/t3code/wt-3 plus innocent external alias, Claude transcript using alias (2026-01-01); scan produces zero candidates. | Yes, new guard |
| E1 | `AgentSessionScanner > recentThreads > rechecks claudeAgent snapshot cwd after replacement with symlink alias` | Original/other workspace, alias to original, Claude session with original prompt; scan, replace transcript at fixed 2026-08-24T12:00Z with alias cwd and Replacement prompt; recentThreads imports replacement. | No, existing guard/control |
| E2 | `AgentSessionScanner > recentThreads > rechecks codex snapshot cwd after replacement with symlink alias` | Same filesystem and replacement sequence as E1, using Codex session_meta/event_msg records. | No, existing guard/control |
| O1 | `readOpenCodeUsage > never follows symlinks in the legacy OpenCode store` | sinceMs=1780000000000; fresh/stale linked messages, directory link, cycle, dangling target, self-loop. Read links-only store: missing true/error false/no files. Add real message: read returns only its path and opencode:msg-real record. | Yes, new guard |
| O2 | `openCodeUsageReader > scans canonical instance roots once, including XDG and home defaults` | Three real roots: default home, explicit instance, XDG. Alias to default. Three instances: unconfigured default; configured comma-separated explicit/alias/default/empty entries; configured XDG. Scan with window and retention zero, awaitRefresh true; exactly three canonical roots. | Yes, new guard |
| A1 | `acpPermissionDisposition > denies mutations through workspace symlinks that escape the writable roots` | Workspace and external existing file/directory links. Full-access/never policy with workspaceWrite and no extra roots. Edit linked file, missing directory descendant, and linked-directory/../escaped-file all denied. | Yes, new guard |
| A2 | `acpPermissionDisposition > allows existing and new files beneath canonical writable roots` | Canonical workspace with src/existing.ts and symlink cwd. Same workspaceWrite policy; existing file and missing src/generated/new-file.ts both allowed. | Yes, new guard |

Counts/lengths/empty/error branches internal to these fixtures remain inside their existing test bodies; this diff guards the whole body, not individual cases. O1's two sequential reads, S1's update, and E1/E2's replacement are interaction-dependent: capture the complete run as **recording (test transcript)**. All rows below use this form, so no still image can substitute for a run. Viewport × theme = N/A × N/A for every row.

## Commands and checkout contract

Only head exists in the supplied checkout. The auditor did not switch it, create a parent checkout, run these suites, or mutate tracked files. The capturer must use a separate parent checkout at the exact full parent SHA; never switch the lead's worktree while it is in use. Package directories below are relative to the named checkout root. Confirm `git rev-parse HEAD`, package cwd, `node --version`, preload hash, full command, verbose named test results, and exit code in each raw transcript. Save each run in a new timestamped directory under the capturer's own scratch subdirectory; do not overwrite earlier runs.

`PRELOAD` below is the absolute path to the downloaded file in the capturer's own scratch directory. The source URL is [no-symlink-preload.cjs](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/891327c2dc0364f0/no-symlink-preload.cjs); verify the hash above. `env NODE_OPTIONS="--require=$PRELOAD"` is a POSIX-shell command with an already assigned absolute PRELOAD path. Normal rows clear all NODE_OPTIONS intentionally to prevent leaked fault injection. No test name filters: the other tests are the regression controls.

| Row | Checkout | Package directory | Exact invocation | Named outcomes and suite totals (expected) | Diff effect | Capture/status |
|---|---|---|---|---|---|---|
| S-P-N | parent e9236274a3 | `apps/server` | `env -u NODE_OPTIONS vp test run src/serverSettings.test.ts src/project/AgentSessionScanner.test.ts --reporter=verbose` | S1/S2/S3/E1/E2 PASS; settings 47P, scanner 53P = 100P. All other named tests PASS. | Baseline control | recording (transcript); Optional normal baseline; source-equivalent to head normal, NOT CAPTURED |
| S-P-E | parent e9236274a3 | `apps/server` | `env NODE_OPTIONS="--require=$PRELOAD" vp test run src/serverSettings.test.ts src/project/AgentSessionScanner.test.ts --reporter=verbose` | S1/S2/S3 FAIL at first fixture symlink with EPERM; E1/E2 SKIP; settings 46P/1F, scanner 49P/2F/2S = 95P/3F/2S. All other named tests PASS. | Baseline control | recording (transcript); REQUIRED, NOT CAPTURED |
| S-H-N | head bfd52848f9 | `apps/server` | `env -u NODE_OPTIONS vp test run src/serverSettings.test.ts src/project/AgentSessionScanner.test.ts --reporter=verbose` | S1/S2/S3/E1/E2 PASS; settings 47P, scanner 53P = 100P. All other named tests PASS. | New guards retain execution | recording (transcript); REQUIRED, NOT CAPTURED |
| S-H-E | head bfd52848f9 | `apps/server` | `env NODE_OPTIONS="--require=$PRELOAD" vp test run src/serverSettings.test.ts src/project/AgentSessionScanner.test.ts --reporter=verbose` | S1/S2/S3/E1/E2 SKIP; settings 46P/1S, scanner 49P/4S = 95P/5S. All other named tests PASS. | New guards take false-capability branch | recording (transcript); REQUIRED, NOT CAPTURED |
| O-P-N | parent e9236274a3 | `packages/provider-opencode` | `env -u NODE_OPTIONS vp test run --config ../../vite.config.ts --dir . src/server/usage.test.ts --reporter=verbose` | O1/O2 PASS; all 5P. All other named tests PASS. | Baseline control | recording (transcript); Optional normal baseline; source-equivalent to head normal, NOT CAPTURED |
| O-P-E | parent e9236274a3 | `packages/provider-opencode` | `env NODE_OPTIONS="--require=$PRELOAD" vp test run --config ../../vite.config.ts --dir . src/server/usage.test.ts --reporter=verbose` | O1/O2 FAIL at first fixture symlink with EPERM; 3P/2F. All other named tests PASS. | Baseline control | recording (transcript); REQUIRED, NOT CAPTURED |
| O-H-N | head bfd52848f9 | `packages/provider-opencode` | `env -u NODE_OPTIONS vp test run --config ../../vite.config.ts --dir . src/server/usage.test.ts --reporter=verbose` | O1/O2 PASS; all 5P. All other named tests PASS. | New guards retain execution | recording (transcript); REQUIRED, NOT CAPTURED |
| O-H-E | head bfd52848f9 | `packages/provider-opencode` | `env NODE_OPTIONS="--require=$PRELOAD" vp test run --config ../../vite.config.ts --dir . src/server/usage.test.ts --reporter=verbose` | O1/O2 SKIP; 3P/2S. All other named tests PASS. | New guards take false-capability branch | recording (transcript); REQUIRED, NOT CAPTURED |
| A-P-N | parent e9236274a3 | `packages/provider-acp` | `env -u NODE_OPTIONS vp test run --config ../../vite.config.ts --dir . src/server/clientPolicy.test.ts --reporter=verbose` | A1/A2 PASS; all 13P. All other named tests PASS. | Baseline control | recording (transcript); Optional normal baseline; source-equivalent to head normal, NOT CAPTURED |
| A-P-E | parent e9236274a3 | `packages/provider-acp` | `env NODE_OPTIONS="--require=$PRELOAD" vp test run --config ../../vite.config.ts --dir . src/server/clientPolicy.test.ts --reporter=verbose` | A1/A2 FAIL at first fixture symlink with EPERM; 11P/2F. All other named tests PASS. | Baseline control | recording (transcript); REQUIRED, NOT CAPTURED |
| A-H-N | head bfd52848f9 | `packages/provider-acp` | `env -u NODE_OPTIONS vp test run --config ../../vite.config.ts --dir . src/server/clientPolicy.test.ts --reporter=verbose` | A1/A2 PASS; all 13P. All other named tests PASS. | New guards retain execution | recording (transcript); REQUIRED, NOT CAPTURED |
| A-H-E | head bfd52848f9 | `packages/provider-acp` | `env NODE_OPTIONS="--require=$PRELOAD" vp test run --config ../../vite.config.ts --dir . src/server/clientPolicy.test.ts --reporter=verbose` | A1/A2 SKIP; 11P/2S. All other named tests PASS. | New guards take false-capability branch | recording (transcript); REQUIRED, NOT CAPTURED |
| W | Native Windows, symlinks denied; parent and head | All three package directories above | Clear NODE_OPTIONS and use each corresponding `vp test run … --reporter=verbose` invocation above in the owning package on actual Windows without Developer Mode/elevation. | Required behavior: parent S1-S3/O1-O2/A1-A2 fail from fixture EPERM; head skips those seven; E1/E2 skip on both. Do not assert Linux aggregate totals for native Windows without a run. | Actual target platform | **cannot-verify windows**; no Windows host available in this VM. |

P=pass, F=fail, S=skip. N=normal symlink-capable Linux host; E=all Node symlink APIs forced to EPERM. The injected probe is false before registration. Parent S-P-E/O-P-E/A-P-E should exit nonzero; every required head row should exit zero and report no unhandled errors. Any other failing/skipped named test contradicts the expected row and needs explanation, not silently updated totals.

**Minimum capture set: nine transcripts** — S-P-E, S-H-E, S-H-N, O-P-E, O-H-E, O-H-N, A-P-E, A-H-E, A-H-N. These cover the fault on parent, guard effect on head, and retained normal execution for all suites. Optional S-P-N/O-P-N/A-P-N explicitly list the fourth cross-product state, collapsed out of the minimum because the original bodies are unchanged and true-capability head executes those same bodies. All seven changed tests, both existing symlink controls, and all 109 tests without symlink fixtures are covered by the minimum. The native Windows row remains an explicit limitation; it cannot be replaced by an assertion that Linux EPERM injection is a Windows run.

## Source anchors

- [Shared symlink probe](https://git.cafe/pingdotgg/t3code/blob/bfd52848f9c02add53ab87e4a7dff31aae12b745/packages/shared/src/testing/symlinks.ts)
- [Server settings tests](https://git.cafe/pingdotgg/t3code/blob/bfd52848f9c02add53ab87e4a7dff31aae12b745/apps/server/src/serverSettings.test.ts)
- [Scanner tests](https://git.cafe/pingdotgg/t3code/blob/bfd52848f9c02add53ab87e4a7dff31aae12b745/apps/server/src/project/AgentSessionScanner.test.ts)
- [OpenCode usage tests](https://git.cafe/pingdotgg/t3code/blob/bfd52848f9c02add53ab87e4a7dff31aae12b745/packages/provider-opencode/src/server/usage.test.ts)
- [ACP policy tests](https://git.cafe/pingdotgg/t3code/blob/bfd52848f9c02add53ab87e4a7dff31aae12b745/packages/provider-acp/src/server/clientPolicy.test.ts)
- [Root test config](https://git.cafe/pingdotgg/t3code/blob/bfd52848f9c02add53ab87e4a7dff31aae12b745/vite.config.ts), [server config](https://git.cafe/pingdotgg/t3code/blob/bfd52848f9c02add53ab87e4a7dff31aae12b745/apps/server/vite.config.ts)
- Local installed Vitest `dist/chunks/index.1TqnEahn.js`: default forks at line 8802; worker env spread at 6108-6111; fork invocation at 5479-5484. Effect NodeFileSystem captures `NFS.symlink` in `@effect/platform-node-shared/dist/NodeFileSystem.js:423`, which the preload patches before import.

FRICTION: infra | Native Windows unavailable, as stated in brief; target-platform row cannot run here. | A Windows runner without Developer Mode/elevation would verify that row.

VERDICT: INSUFFICIENT S-P-E, S-H-E, S-H-N, O-P-E, O-H-E, O-H-N, A-P-E, A-H-E, A-H-N need capture; cannot-verify windows
