# Independent evidence audit pass 1

PR [#23396](https://git.cafe/pingdotgg/t3code/pulls/23396), branch `fix/issue-22402`, audited head [f6e8762257](https://git.cafe/pingdotgg/t3code/commit/f6e8762257a73c882f405c0067de17b8bbca5c1e). Evidence-only; no source edits, tests, servers, browsers, committed fixtures, PR comments, merges, watches, or check polling in this pass. Worktree clean before and after.

Conclusion: existing evidence sufficiently covers every changed diagnostic-message branch through the real server. The missing runtime proof is successful recovery on a populated fixture and preservation of an existing nonblank tab when URL is omitted. These are evidence gaps, not demonstrated code defects or grounds to claim a capability change. Do not redo the sufficient captures below.

## Diff and evidence provenance

Read the entire six-file PR diff, all five existing comments and three reviews through cafe, the original supplied JSON/report, and downloaded both linked runtime transcripts/reports and red/green logs. Actual PR base is [3b95e7831b](https://git.cafe/pingdotgg/t3code/commit/3b95e7831b11b17627dff16843bc087bfca397ec); `git diff 3b95e7831b11b17627dff16843bc087bfca397ec...HEAD` is 120 lines. Local `main` is much newer and produces an unrelated enormous comparison; it is not the correct historical PR base.

Baseline transcript identifies [8acbefefc5](https://git.cafe/pingdotgg/t3code/commit/8acbefefc51b4d281dcd04108c82baa1ab902b0e). It is an older main revision, not the exact PR base. Verified zero diff between that baseline and the recorded PR base in the relevant shared URL code, preview contracts, server preview directory, broker, and preview toolkit. Thus its old-message evidence remains usable for these paths. Final transcript explicitly identifies the exact audited head. The earlier runtime report's after revision and unqualified wording are superseded by the final transcript, not counted as final-head evidence.

Changes: message getters in shared URL normalization, the public PreviewInvalidUrlError, and the locator/selector branches of PreviewAutomationInvalidSelectorError; three added regression tests. No accepted-input, normalization, routing, caller-guard, tool schema, default, error-tag, or wire-field changes. Observable semantics change only in diagnostic content: accepted URL forms, new-tab-only blank-tab recovery, latest-snapshot ref/role/text advice, CSS field advice. MCP error text and RPC decoded getters/nested diagnostic cause messages change. This is not an MCP capability change.

Sources: [baseline transcript](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d6a43fe87bc0bf53/issue-22402-baseline-runtime.json), [final transcript](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/35f48f8f70e30fd8/issue-22402-final-runtime.json), [baseline report](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/8d189a6737dcd882/issue-22402-runtime-report.md), [final report](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d88a78d04f28f7b3/issue-22402-final-report.md).

## Server runtime fixture matrix

All rows concern Linux server-browser protocol behavior. A populated local HTML fixture is needed only for M1–M6. No viewport variants, screenshots, image attachments, mobile navigation, or Electron-shell matrix applies to protocol text changes. Desktop reproduction remains an explicitly unverified original-issue variant, nonblocking for this pass.

| Row | Fixture / request | Existing baseline vs final-head proof | Decision |
| --- | --- | --- | --- |
| U1 | MCP preview_open `{url:"about:blank",open:false}` | mcp id 3 in both: HTTP 200, isError true, old terse parse/length vs complete qualified guidance | Sufficient |
| U2 | MCP preview_open `{open:false,reuseExistingTab:false}` | mcp id 4 in both: available true, owned tab, url null | Sufficient new-tab blank recovery |
| U3 | authenticated app RPC preview.open `{threadId,url:"about:blank",runtime:"server",reveal:false}` | baseline appRpc / final rpc: same tag, reason, length, protocol; final decoded message and nested wire cause contain qualification | Sufficient public error path |
| L1 | MCP preview_click `{tabId,locator:"[",timeoutMs:1000}` | mcp id 5 in both: final latest-snapshot aria-ref, role/text, CSS guidance | Sufficient locator rejection |
| S1 | MCP preview_click `{tabId,selector:"[",timeoutMs:1000}` | mcp id 6 in both: final CSS/locator alternative guidance | Sufficient CSS rejection |
| N1 | MCP preview_navigate `{tabId,url:"about:blank",timeoutMs:1000}` | mcp id 7 in both: qualified preview_open-only advice | Sufficient navigate error propagation |
| P1 | synthetic malformed URL/locator/selector | mcp ids 8–10; baseline appRpcSyntheticMarker / final rpcSyntheticMarker: markers absent from full returned error envelopes, RPC result/message/wire | Sufficient returned-payload privacy; no claim about logs/history/heap |
| T1 | valid-looking CSS in locator on empty blank page | mcp id 11 in both times out at 1000ms | Sufficient unchanged timeout path; NOT successful selector recovery |
| M1 | populated fixture opened via explicit HTTP URL | Not present in either transcript | Missing successful advertised URL recovery |
| M2 | same fixture via schemeless loopback host:port | Not present | Missing successful advertised schemeless recovery |
| M3 | omit URL while reusing existing nonblank tab | U2 creates a new blank tab; it cannot prove reuse preservation | Missing proof directly motivating final-head qualification |
| M4 | valid CSS in selector matching a real target | No populated fixture, only malformed CSS and timeout | Missing successful CSS recovery |
| M5 | fresh snapshot ref followed by aria-ref click | No snapshot/ref action captured | Missing successful latest-snapshot recovery |
| M6 | Playwright role and text selectors matching unique controls | Not present | Missing successful advertised role/text recovery; capture two calls in one row |
| D1 | original issue CSS expression on macOS desktop | Baseline Linux originalIssueCss times out; earlier report says both earlier revisions time out; final transcript does not repeat originalIssueCss | Desktop unverified, explicitly nonblocking; do not recapture Linux timeout |

No mandatory changed rejection branch remains uncaptured. M1–M6 close recovery-evidence gaps; unchanged branches such as stale refs and selector errors without metadata do not need a new full regression matrix for this text-only diff. Empty input is schema-rejected by MCP before normalization; do not mistake its generic decode error for the changed normalization message. Optional unsupported-protocol expansion is not needed to cover another changed message branch.

## Exact minimal capture plan for the next agent

Run only M1–M6 on the exact final head. Reuse the existing baseline and all U/L/S/N/P/T evidence. No source changes or committed fixtures. Keep scripts, fixture HTML and sanitized results in an authorized /tmp evidence directory. The capture agent must arrange isolated runtime state as authorized by the lead; never use live ~/.t3/userdata. This pass starts nothing.

1. Verify `git rev-parse HEAD` equals `f6e8762257a73c882f405c0067de17b8bbca5c1e` and clean status. Start the normal isolated dev server with `node_modules/.bin/vp run dev --no-seed`, capture its own PID, and read actual dev ports/readiness. Use the supported pairing exchange, authenticated app RPC and an active disposable thread. Reuse the prior external wrapper/live-issued MCP credential technique if needed; preserve caller guards. Do not substitute direct class construction or in-process broker calls.
2. Write a temporary fixture containing exactly four visible unique buttons: IDs `css-target`, `ref-target`, `role-target`, `text-target`, labelled `CSS target`, `Ref target`, `Role target`, `Text target`. Each inline click handler increments `document.body.dataset[this.id]` as a numeric string; initialize all four counters to `"0"`. Give the page title `Preview recovery fixture`.
3. Serve that directory using `python3 -m http.server 0 --bind 127.0.0.1 --directory <fixture-directory>` with unbuffered output. Capture the spawned PID and allocated port P. This avoids public network/TLS dependencies; fixture URL is `http://127.0.0.1:P/fixture.html`.
4. Use actual HTTP JSON-RPC tools/call with the live-issued MCP authorization. Record complete requests, HTTP statuses, JSON envelopes, context SHA/platform/runtime and timestamps. Never publish authorization headers or pairing tokens. M1: `preview_open {url:"http://127.0.0.1:P/fixture.html",open:false,reuseExistingTab:false}`. Assert no error, owned tab A and normalized URL. Read title and counters with `preview_evaluate` on A to prove a loaded page rather than URL assignment alone.
5. M2: `preview_navigate {tabId:A,url:"127.0.0.1:P/fixture.html",timeoutMs:5000}`. Assert no error, resulting `http://127.0.0.1:P/fixture.html` and title. One existing tab is sufficient; no multiple-tab ambiguity.
6. M3: `preview_open {tabId:A,open:false}` (omit URL and reuseExistingTab). Assert same tab ID and same nonblank URL/title. With only A open, optionally also `{open:false}` to demonstrate the default current-tab path. Do not count a blank-to-blank comparison as proof.
7. M4: `preview_click {tabId:A,selector:"#css-target",timeoutMs:1000}`; `preview_evaluate` counter must become `"1"`. M5: `preview_snapshot {tabId:A,includeImage:false}`; extract the newly issued ref for `Ref target` from accessibilityTree; immediately `preview_click {tabId:A,locator:"aria-ref=<actual fresh ref>",timeoutMs:1000}` and verify ref-target counter `"1"`. Do not hardcode refs or take another snapshot between obtaining and using the ref.
8. M6: `preview_click {tabId:A,locator:'internal:role=button[name="Role target"i]',timeoutMs:1000}`, then `preview_click {tabId:A,locator:'text="Text target"',timeoutMs:1000}`. Verify role-target and text-target counters each `"1"`. Preserve actual syntax/results. If a suggested syntax is unsupported, record the error and correct it through the existing runtime; do not claim successful guidance recovery on a timeout.
9. Finish with `preview_evaluate {tabId:A,expression:"({url:location.href,title:document.title,counts:{...document.body.dataset}})"}`. Expected four counts all `"1"`. Close A with preview_close, stop only recorded owned PIDs, and verify worktree clean. Sanitize and upload the supplemental JSON/report. Link it alongside prior evidence; do not replace sufficient captures. No screenshot required.

Code basis: [shared normalization](https://git.cafe/pingdotgg/t3code/blob/f6e8762257a73c882f405c0067de17b8bbca5c1e/packages/shared/src/preview.ts), [URL error](https://git.cafe/pingdotgg/t3code/blob/f6e8762257a73c882f405c0067de17b8bbca5c1e/packages/contracts/src/preview.ts), [selector error](https://git.cafe/pingdotgg/t3code/blob/f6e8762257a73c882f405c0067de17b8bbca5c1e/packages/contracts/src/previewAutomation.ts), [server open/reuse](https://git.cafe/pingdotgg/t3code/blob/f6e8762257a73c882f405c0067de17b8bbca5c1e/apps/server/src/preview/ServerBrowser.ts), [runtime targeting](https://git.cafe/pingdotgg/t3code/blob/f6e8762257a73c882f405c0067de17b8bbca5c1e/apps/server/src/preview/ServerBrowserPage.ts).

## Snapshot checks and limitations

Supplied original.json records the exact requested head and open PR but contains no check/status collection. Therefore pending check names/count cannot be determined from that snapshot; no current or pending-green claim is made. Existing PR comment snapshot reports successful thread-transfer source CI at the final SHA; Macroscope approvability at that SHA and CodeRabbit's no-actionable-comments report are existing evidence, not fresh CI verification. No status/ready/ci polling performed.

Downloaded green execution log reports 53 tests, lint and contracts/shared typechecks passing on the earlier f2a644 revision. Final-head 29-test/lint pass is asserted in the PR description/reply, not independently demonstrated by a final-head execution log here. This is a provenance limitation, not missing runtime proof; this pass did not rerun tests. Red log includes initial setup failure followed by the three intended package-local assertion failures.

FRICTION: local main drift made the first comparison huge; corrected to recorded PR base before scope assessment. Relevant baseline-path drift was independently checked and is zero.
FRICTION: Python urllib download received HTTP 403; curl successfully downloaded all six linked evidence files.
FRICTION: existing snapshots contain no pending-check inventory; no polling was used to fill it.
FRICTION: broad temporary-file discovery encountered protected system temp directories; no files there were read or modified. All audit writes are confined to /tmp/pr-23396-evidence/audit1.
