# Proof audit PASS1 — issue 24423

Read-only audit of /home/ubuntu/wt/issue-24423, branch fix/issue-24423.
Base a46f80ee28; head 3e0865515fccd5dfa1356977f1ab482620432f8b.
Complete diff: ProjectSetupScriptRunner.ts (shell selection and completion wrapper), plus new ProjectSetupScriptRunner.test.ts (two real-Nushell subprocess cases with a mocked TerminalManager). No client, contract, render, style, navigation, or interaction-handler changes.

## Render fixture matrix

EMPTY. The server-only/no changed render surface exemption applies. Existing setup cards and terminal views consume changed server outcomes, but their rendering paths and interactions are unchanged. No screenshot, recording, viewport/theme sweep, or actual-app browser route is required by this matrix. This does not exempt real-server runtime evidence or make output compatibility proven.

## Complete changed-path inventory and runtime coverage

| Path/conditional/caller | Required evidence / audit disposition |
| --- | --- |
| Non-Windows SHELL basename exactly nu | Real server launched with SHELL pointing to the installed Nu executable; record server revision and Nu version. A spawnSync nu -c test alone does not prove the actual interactive terminal path. |
| win32 wins before shell detection; fish/pwsh/powershell/default POSIX unchanged | Outside changed behavior. Source confirms dispatch unchanged. No new surface fixture. |
| observeCompletion present + completion token | New Nu wrapper applies. Exercise actual TerminalManager/PTY and sentinel parsing; prove completion is numeric, not null, and does not hang. |
| Successful internal command; LAST_EXIT_CODE reset to 0 | Existing test report says echo setup-ok -> 0. Real-server after transcript still missing. Final internal value is suppressed by this wrapper: do not require setup-ok to appear for this exact command or claim its appearance was preserved. Record actual terminal output. |
| Failed external inside try/catch; e.exit_code present | Existing test report says bash -c 'exit 3' -> 3. Real-server after transcript still missing: rendered diagnostic, numeric completion 3, no literal $? marker, no indefinitely running setup. |
| Internal Nu error; e.exit_code absent -> default 1 | Not covered by the two tests. Runtime transcript should include a deterministic internal error (for example error make {msg: "setup-internal-fail"}) and numeric completion 1. |
| External output streaming, explicit print, multiline body | Not established by exit-code-only assertions. Include a setup fixture with explicit print and an external stdout/stderr command; record output ordering/visibility and sentinel completion. Do not infer streaming from one aggregated subprocess output event. |
| ThreadLaunchService tracked new/reused worktree, synchronous setup | Actual-app seed: isolated project importing Setup from t3.json, async:false, runOnWorktreeCreate:true, SHELL=nu; launch a new worktree thread. Success must mark setup done/exited with 0, release the prepared run, finish preparation, and close successful idle setup terminal. Failure 3 must mark setup/launch failed and withhold run release, retaining the failed terminal for inspection. This is the principal issue reproduction route; no browser launch requested from this reviewer. |
| ThreadLaunchService tracked new/reused worktree, async setup | Same seed with async:true (or default). Prove launch can release while setup runs, then numeric success/failure updates setup status and preparation finishes without hanging. Async failure must not be presented as synchronous launch blocking. |
| ThreadSettlementService cleanUpSettledThread, trigger:settle, observeCompletion:{} | Same wrapper is used by settle scripts. Seed a settle script on a thread with an existing worktree; trigger genuine settlement. Prove success completion closes the idle terminal and failure retains it, without an unresolved completion. No setup-card assertion is applicable to this caller. |
| ThreadLaunchService untracked; GitManager.preparePullRequestThread; WorktreeMcpService handoff | These omit observeCompletion: raw script path remains unchanged. No new runtime/visual requirement for these callers. |
| No script / no worktree; non-Nu shells | No changed wrapper execution. No new fixture requirement. |
| Added tests' success and failure cases | Lead reports actual Nu 0.116.1; red null/null at base, green 0/3 at head. Attach exact commands, revisions, version, and unskipped output if not already retained. These tests mock terminal open/write/events and do not prove a real server/PTY. |

## Existing evidence versus missing proof

Lead-provided evidence (not independently executed by this audit): Nu 0.116.1 tests ran rather than skipped; base returned null/null and head passed success 0/external failure 3. Before app reproduction: synchronous imported Setup `echo setup-ok`, SHELL=nu, new worktree; literal $? marker and hung setup.

Missing blocking proof: matching real-server AFTER transcript for that synchronous seed at the audited head, including server shell/version, terminal input/output, persisted setup stage/status and numeric exit code, prepared-run release/finished preparation, and successful terminal cleanup. Also collect the real-server external failure 3 counterpart, with failed status and no release/hang. Red/green tests must be attached as evidence, not only summarized, unless their transcripts are already available to the lead.

Coverage gaps to close before claiming every changed path is proven: async observed setup, observed settle caller, internal-error fallback 1, and output visibility/streaming (including the intentionally suppressed final internal echo value). These can share a compact runtime transcript; a new visual matrix is unnecessary. If the lead procedure narrows mandatory runtime proof to the issue's synchronous route, explicitly disclose these as unverified rather than claiming full caller/conditional coverage.

## FRICTION

- No permission blocker. Reviewer was explicitly prohibited from editing, capturing, starting servers/browsers, pushing, commenting, or merging, so none was attempted.
- Exact lead proof procedure was not supplied beyond the server-only exemption; this artifact separates the principal reproduction proof from exhaustive changed-path gaps rather than inventing a screenshot requirement.
- Tests use mocked TerminalManager and a fresh noninteractive nu -c subprocess. They emit an exited event after the combined output, unlike a persistent interactive shell; green tests cannot substitute for PTY/runtime proof.
- echo setup-ok is a poor visible-output assertion for the new wrapper: the source explicitly suppresses final internal values. Use explicit print/external output for streaming assertions and record whether this output change is accepted; do not silently describe it as preserved.
- No repo files modified; artifact created outside worktree. No PR exists and none was created or linked.
