# Full running app RPC runtime evidence

Evidence for [#23537](https://git.cafe/pingdotgg/t3code/pulls/23537) ([GitHub mirror](https://github.com/pingdotgg/t3code/pull/23537)), exact head [3926acc0d4](https://git.cafe/pingdotgg/t3code/commit/3926acc0d4d70d95a5e8747bfacec032a0253ebd), branch `fix/issue-23513`, exclusively `/home/ubuntu/wt/pr-23537`. Clean before and after. Successful run: 2026-10-22 10:37:30–10:38:00 UTC. Node v26.12.1, Linux x64, real installed Chrome Headless Shell 154.0.8037.92. No code-review or merge verdict.

## App versus harness

**This capture runs the full production app**, with `node apps/server/src/bin.ts serve`: HTTP listener, authentication, WebSocket RPC router, production preview event consumers, manager, browser services and real Chromium. Fresh isolated state at `/tmp/pr23537-evidence/fullapp/state`; no live database or credentials copied. CLI-issued ten-minute bearer credential authenticates the real HTTP ticket endpoint; its single-use ticket authenticates `/ws?orchestrationProtocol=2&wsTicket=…`. Credential values are kept in memory and withheld from logs. Server pairing token/QR lines are omitted before logging.

All tested tab opens and closes go through real authenticated `preview.open` and `preview.close` WebSocket requests; exact request/response envelopes and timings are in `transcript.jsonl`. The thread identifier `fullapp-evidence-23537` is an ephemeral preview namespace, not a launched provider/agent session. No client UI or agent subprocess is launched. This is app RPC coverage, not coverage of UI interactions or a provider's MCP tool invocation.

An executable wrapper, installed only in this fresh T3 home's tools directory, forwards every launch argument unchanged to the installed pinned Chromium executable, adding `--remote-debugging-port=0 --remote-debugging-address=127.0.0.1`. It captures its own PID before `exec`. External CDP connections discover the actual app-owned pages from Chromium's `DevToolsActivePort` files. They install fixture handlers, observe dialogs/console/target events and evaluate sibling responsiveness. They never issue a close, dialog answer or context-disposal command. Production Playwright protocol diagnostics (`DEBUG=pw:protocol`) show the actual app's close and context-disposal commands. No injected server services, prototype wrappers, mocked close behavior, source edits or production lifecycle hooks.

The previous `runtime-report.md` / `runtime-capture.mts` remain **service-harness evidence**. Sufficient ancestor listener/guard/frozen-isolated evidence is reused without repetition. This run adds full-app pending-dialog/shared-frozen coverage and a real app incognito isolated delayed-ordering observation.

## Timed observations

Times below are monotonic milliseconds from `transcript.jsonl`; its line numbers are given for easy lookup.

- **Pending confirm, shared context:** real CDP pending dialog at 12512.820 (line 371), never answered. Authenticated close RPC returns in 6.076ms at 12519.173 (line 380). Production sends `Target.closeTarget` at 12517.511 (line 375), rather than a graceful `Page.close` on the blocked dialog. Target disappearance follows; sibling evaluation succeeds at 12523.655. Sibling and pending target have the identical CDP `browserContextId`.
- **Shared frozen target/fallback:** real `freeze-start` console marker precedes close. Production sends graceful `Page.close` at 12745.072 (line 497); close RPC returns in 7.556ms. Sibling responds while target remains frozen at 12747.994. Production fallback sends `Target.closeTarget` at 17741.673 (line 506), about 4996.6ms after the diagnostic `Page.close` send. Target destruction is observed 5008.037ms after RPC request; sibling responds again at 17748.874. The target and sibling share the same real CDP context. Five seconds is grace before a force-close attempt, not a guaranteed completion bound; observer scheduling/pipe buffering affects these timings.
- **Finite delayed isolated ordering:** the explicit `incognito` profile selects a separate per-tab context through real app RPC. Its context differs from the shared sibling. Production sends `Page.close` at 17968.029 (line 634); finite handler start at 17969.491 (line 638). CDP `Target.getBrowserContexts` still includes that context during the handler at 17971.836. The synchronous 1800ms handler finishes at 19771.694 (line 643). Production receives target detach at 19774.079 (line 647), then sends `Target.disposeBrowserContext` at 19777.911 (line 650). External CDP also observes target destruction before disposal, and confirms the isolated context is gone at 19781.446. No fallback `Target.closeTarget` is issued for this isolated page. This establishes observed page shutdown before context disposal in the full-app path, for a finite synchronous handler; it makes no promise about arbitrary async unload work.
- **Cleanup:** sibling closes through RPC; row completion at 19794.801. SIGTERM is sent only to captured server PID 2254690. It exits at 30065.848 (code 130 from its interruption handler). Captured Chromium PIDs 2255346 and 2255660 are absent. `cleanup-check.json` independently confirms server/fixture/both CDP ports refuse connections, all captured PIDs are absent, and state was removed. Git remains at the exact requested head with empty `git status --short`.

## Exact reproduction and environment

`capture.mjs` is the complete executed final script, including server spawn, executable wrapper, authentication, wire protocol, fixtures, assertions, diagnostics and cleanup. It uses Node built-ins only; no package install or module-resolution symlink is needed. The first transcript row records the exact absolute Node command, environment allowlist and wrapper bytes; all subprocesses use that explicit allowlist (PATH, HOME, USER, LANG, sandbox opt-out, NO_COLOR, DEBUG). No ambient API-key, proxy-token, dev-auth-token or `.env` variables are inherited by subprocesses. HOME points to the existing user's home, and no authentication files there are copied into state.

```sh
cd /home/ubuntu/wt/pr-23537
mkdir -p /tmp/pr23537-evidence/fullapp
# Place the delivered capture.mjs in that scratch directory.
node /tmp/pr23537-evidence/fullapp/capture.mjs > /tmp/pr23537-evidence/fullapp/transcript.jsonl 2>&1
```

The server invocation inside the script is:

```sh
node apps/server/src/bin.ts serve --base-dir /tmp/pr23537-evidence/fullapp/state --host 127.0.0.1 --port 43873 --no-browser
```

This exact revision calls the isolated-home flag `--base-dir`; `serve --help` confirms that it means the T3 data directory with runtime under userdata. There is no `--home-dir` flag. The script creates fresh state and the external observation wrapper before spawning. It stops its server by captured PID and removes state on both success and failure. Reproduction should use an unused port and a fresh scratch directory.

## Preserved capture friction and limits

`attempt-1.jsonl`: 10:36:29–10:36:41. Server and bearer auth succeeded; script incorrectly used `ticket` rather than `wsTicket`, so WS opening failed. Fixed only that external script parameter.

`attempt-2.jsonl`: 10:36:48–10:37:07. Full-app pending-dialog and shared-frozen rows passed. The external script incorrectly assumed that omitting a profile on client `preview.open` selects an isolated context; the CDP assertion correctly rejected that assumption. This is capture setup friction, not a product failure. Final script uses `profileId:'incognito'` for the delayed isolated row, as production selection requires. Both attempts stopped their captured servers and removed isolated state; their sanitized raw transcripts are included. Final script otherwise uses the same commands. Preparation used `mkdir -p` and a temporary node_modules symlink (unused by the final built-in-only script); that symlink is removed before packaging.

No initial-close rejection/fault injection, crash, desktop/mobile UI path, arbitrary async unload guarantee, universal five-second completion guarantee, or explicit timer-cancellation instrumentation is claimed. No independent review verdict. No implementation edits, commits, PR comments/body edits, pushes, merges, watches or PR polling. App-owned PR registration/listing was performed as required by the harness; watching remains false.
