# Issue 22402 runtime evidence

Issue: [#22402](https://git.cafe/pingdotgg/t3code/issues/22402). Captured 2026-10-22 UTC. Visual matrix: **EMPTY (0 rows)**; server error wording only.

Actual isolated development servers compared [8acbefefc5](https://git.cafe/pingdotgg/t3code/commit/8acbefefc51b4d281dcd04108c82baa1ab902b0e) before with [0a98dfd95c](https://git.cafe/pingdotgg/t3code/commit/0a98dfd95c2de4513392da972c63ecd1b083e210) after. No error-class-only simulation, no live userdata, no repository edits, no push, PR, comments, or other forge writes.

## Environments and transport

Both ran on machine `freestyle`, Linux 6.1.102 x86_64, Node v24.21.0, actual server-browser runtime. Both used their own worktree's `node_modules/.bin/vp run dev --no-seed`; separate fresh `.t3/userdata` databases were migrated normally. No production database was copied or opened. Head: `/home/ubuntu/wt/issue-22402`, backend `http://127.0.0.1:14964`, Vite port 6924. Before: detached `/home/ubuntu/wt/issue-22402-baseline-evidence`, backend `http://127.0.0.1:16100`, Vite port 8060. Exact SHA, timestamps, disposable project/thread IDs, tab IDs, requests and full responses are in the JSON transcripts.

Authentication used each dev server's own pairing credential and supported token exchange, then its authenticated app WebSocket RPC. A disposable thread was launched through `orchestration.launchThread`. A temporary external wrapper around the real Codex binary captured only that dev thread's injected MCP configuration to a private file. To keep the live caller guard satisfied without assigning model work, the wrapper held `turn/start` before forwarding it. Browser operations then used actual HTTP JSON-RPC `tools/call` requests to that server's `/mcp`, authenticated by its issued registry credential. Every preview call traversed the real toolkit, caller guard, broker and server browser. No handler, manager, broker, or error was instantiated by the harness. No delegated task/subagent was created.

The RPC capture uses the shipped `WsRpcGroup` client and records actual received WebSocket error frames plus the decoded error's message getter. This distinguishes `PreviewInvalidUrlError` from the MCP execution error carrying shared URL-normalization wording. The top-level RPC message getter is not a serialized wire field; its decoded message is explicitly recorded separately.

## Coverage

| Row | Outcome |
| --- | --- |
| U1 | PASS, exact-base old message and head guidance, `preview_open {url:"about:blank",open:false}` |
| U2 | PASS both revisions, omitted URL with `reuseExistingTab:false` opens owned blank tab; `available:true`, `url:null`, explicit tabId used thereafter |
| U3 | PASS both revisions, authenticated app `preview.open` RPC with actual disposable threadId, `url:"about:blank"`, `runtime:"server"`; wire tag `PreviewInvalidUrlError` plus decoded message |
| L1 | PASS both revisions, `preview_click` with `locator:"["`, 1000ms; head includes latest-snapshot aria-ref, role/text and CSS guidance |
| S1 | PASS both revisions, same with `selector:"["`; head explains CSS and locator alternatives |
| P1 | PASS for returned public payloads, both revisions: malformed URL with synthetic username/password/query/fragment markers, malformed locator and selector with marker comment; markers absent from full returned MCP envelopes. Additional RPC synthetic-URL response and complete error wire frame also omit markers |
| Navigate | PASS both revisions, `preview_navigate` with bad `about:blank`; new head explicitly qualifies blank-tab omission advice as `With preview_open` |
| Original CSS / D1 | Exact issue expression times out on Linux server browser on both revisions. macOS desktop rejection remains UNVERIFIED, nonblocking as instructed |

MCP failures return `isError:true` and text, with no structured error object or tag. The full envelopes are retained; an internal invalid-selector tag is not claimed as an observed wire field. The RPC error does expose its tag and structured fields.

## Exact observed errors, before and after

### baseline

Request: `preview_open {"url":"about:blank","open":false}`

```text
Preview automation open failed: Invalid preview URL (parse: https:; input length 11).
```

Request: `preview_click {"tabId":"tab_2_ac126dec-08f5-41d5-a00d-f016a57d37fb","locator":"[","timeoutMs":1000}`

```text
Preview automation click received an invalid locator (1 characters).
```

Request: `preview_click {"tabId":"tab_2_ac126dec-08f5-41d5-a00d-f016a57d37fb","selector":"[","timeoutMs":1000}`

```text
Preview automation click received an invalid selector (1 characters).
```

Request: `preview_navigate {"tabId":"tab_2_ac126dec-08f5-41d5-a00d-f016a57d37fb","url":"about:blank","timeoutMs":1000}`

```text
Preview automation navigate failed: Invalid preview URL (parse: https:; input length 11).
```

Request: `preview_open {"url":"https://AUDIT_SENTINEL_22402:SECRET22402@[invalid/?query=AUDIT_SENTINEL_22402#AUDIT_SENTINEL_22402","open":false}`

```text
Preview automation open failed: Invalid preview URL (parse: https:; input length 98).
```

Request: `preview_click {"tabId":"tab_2_ac126dec-08f5-41d5-a00d-f016a57d37fb","locator":"/*AUDIT_SENTINEL_22402*/[","timeoutMs":1000}`

```text
Preview automation click received an invalid locator (25 characters).
```

Request: `preview_click {"tabId":"tab_2_ac126dec-08f5-41d5-a00d-f016a57d37fb","selector":"/*AUDIT_SENTINEL_22402*/[","timeoutMs":1000}`

```text
Preview automation click received an invalid selector (25 characters).
```

Request: `preview_click {"tabId":"tab_2_ac126dec-08f5-41d5-a00d-f016a57d37fb","locator":"button[type=\"submit\"]","timeoutMs":1000}`

```text
Preview automation click timed out after 1000ms.
```

App RPC decoded `PreviewInvalidUrlError.message`:

```text
Invalid preview URL (parse: https:; input length 11).
```

Exact issue CSS request: `{"name":"preview_click","arguments":{"tabId":"tab_2_ac126dec-08f5-41d5-a00d-f016a57d37fb","locator":"div:has(> div > p:text-is(\"Hello\")) > button","timeoutMs":1000}}`

```text
Preview automation click timed out after 1000ms.
```

### head

Request: `preview_open {"url":"about:blank","open":false}`

```text
Preview automation open failed: Invalid preview URL (parse: https:; input length 11). Use an http(s) URL or a schemeless host such as localhost:5173. With preview_open, omit url to open a blank tab.
```

Request: `preview_click {"tabId":"tab_4_12d2001f-e35e-4392-90d3-7746a635466b","locator":"[","timeoutMs":1000}`

```text
Preview automation click received an invalid locator (1 characters). Use aria-ref=<ref> from the latest snapshot or a Playwright role/text selector; put CSS in selector.
```

Request: `preview_click {"tabId":"tab_4_12d2001f-e35e-4392-90d3-7746a635466b","selector":"[","timeoutMs":1000}`

```text
Preview automation click received an invalid selector (1 characters). selector takes CSS; use locator for aria-ref=<ref>, role, or text targets.
```

Request: `preview_navigate {"tabId":"tab_4_12d2001f-e35e-4392-90d3-7746a635466b","url":"about:blank","timeoutMs":1000}`

```text
Preview automation navigate failed: Invalid preview URL (parse: https:; input length 11). Use an http(s) URL or a schemeless host such as localhost:5173. With preview_open, omit url to open a blank tab.
```

Request: `preview_open {"url":"https://AUDIT_SENTINEL_22402:SECRET22402@[invalid/?query=AUDIT_SENTINEL_22402#AUDIT_SENTINEL_22402","open":false}`

```text
Preview automation open failed: Invalid preview URL (parse: https:; input length 98). Use an http(s) URL or a schemeless host such as localhost:5173. With preview_open, omit url to open a blank tab.
```

Request: `preview_click {"tabId":"tab_4_12d2001f-e35e-4392-90d3-7746a635466b","locator":"/*AUDIT_SENTINEL_22402*/[","timeoutMs":1000}`

```text
Preview automation click received an invalid locator (25 characters). Use aria-ref=<ref> from the latest snapshot or a Playwright role/text selector; put CSS in selector.
```

Request: `preview_click {"tabId":"tab_4_12d2001f-e35e-4392-90d3-7746a635466b","selector":"/*AUDIT_SENTINEL_22402*/[","timeoutMs":1000}`

```text
Preview automation click received an invalid selector (25 characters). selector takes CSS; use locator for aria-ref=<ref>, role, or text targets.
```

Request: `preview_click {"tabId":"tab_4_12d2001f-e35e-4392-90d3-7746a635466b","locator":"button[type=\"submit\"]","timeoutMs":1000}`

```text
Preview automation click timed out after 1000ms.
```

App RPC decoded `PreviewInvalidUrlError.message`:

```text
Invalid preview URL (parse: https:; input length 11). Use an http(s) URL or a schemeless host such as localhost:5173. With preview_open, omit url to open a blank tab.
```

Exact issue CSS request: `{"name":"preview_click","arguments":{"tabId":"tab_4_12d2001f-e35e-4392-90d3-7746a635466b","locator":"div:has(> div > p:text-is(\"Hello\")) > button","timeoutMs":1000}}`

```text
Preview automation click timed out after 1000ms.
```

## Limits and FRICTION

- macOS desktop was unavailable on this Linux host. The exact issue selector `div:has(> div > p:text-is("Hello")) > button` timed out on both server revisions. That is not evidence of desktop validation behavior.
- The first disposable turn ended before MCP writes, correctly returning `The calling provider no longer owns an active thread run.` Setup then used a separate provider instance with the transport wrapper holding `turn/start`. Successful evidence contains only the final authenticated active-run captures.
- One startup pairing credential was already consumed when reused; a new credential was minted against the isolated dev home's normal `pair` command. A second project-create attempt hit the duplicate-workspace guard; subsequent setup reused the disposable project. No auth/lifecycle guard was bypassed.
- Marker absence is demonstrated only for the returned public error payloads captured here, including RPC nested causes. It does not establish zero internal retention, logs, heap, or tool-request history. Synthetic inputs intentionally appear in recorded requests.
- Supplied prior test evidence: test-only revision [f33cc8a2e8](https://git.cafe/pingdotgg/t3code/commit/f33cc8a2e8360762ba283ce594f0486ec0f6871b) demonstrated 3 assertion failures; green focused tests 29 and broker tests 24 passed. These counts were provided by the lead and were not rerun in this runtime-only step.
- The temporary baseline worktree and both servers were cleaned up. Dev-runner PIDs 1696864 (head) and 1712092 (baseline) were verified from the owned listening sockets and their `/proc` cwd/ancestry, recorded, and sent SIGINT. Both originating command sessions exited 130, and all four dev listening ports were absent afterward. The requested branch still has its original clean HEAD.
- Raw startup/pairing logs, credentials, settings, and captured provider config remain private outside the repository and are excluded from uploads. Public files were scanned against the actual credentials held in those private files.
