# Final-head proof audit — pass 1

Issue: [#24547](https://git.cafe/pingdotgg/t3code/issues/24547). Reviewed head [2c6b98457c](https://git.cafe/pingdotgg/t3code/commit/2c6b98457c776394c9628259c24b6d5801c5895c) against base [3afb9b366f](https://git.cafe/pingdotgg/t3code/commit/3afb9b366f). Supersedes the [previous matrix](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/7b4c9e3f6498ac84/matrix.md).

Read-only source audit; clean checkout at the requested head at inspection. No tests run, captures taken, servers started, fixture/state changes, browser use, comments, pushes, PR creation, or extra agents. Only this artifact outside the worktree was written/uploaded. Test names below identify available proof or required additional assertions, not passing execution evidence.

## Decision and scope

The minimum representative web visual set is **V1 and V3**, each in four width/theme variants, plus structured data proof. V2/V4/V5 do not each need independent captures to prove this server-only change. They consume newly eligible entries through unchanged renderers/helpers; their distinct input/filter semantics must still be tested. This is equivalence of the changed data boundary, not a claim that every UI branch was executed.

The only production changes are WorkspaceSearchIndex and the new bounded IgnorePatterns matcher. Components, layouts, contracts, and ordinary directory-scoped listing are unchanged. Scope is link entries in file search/@mentions and the flat index. Normal directory listing's exclusion of symlinks is a separate issue, not a failed acceptance criterion here. Do not claim directory links are recursively indexed or that symlink content search was added.

## Fixture and capture contract

Lead owns server 7886 and `/home/ubuntu/wt/issue-24547/.t3/symlink-project`. Do not restart, switch, or mutate the shared checkout. Lead must verify selected project and stopped thread have that effective cwd. Prior fixture description: `src/index.ts`, `src-link -> src`, `index-link.ts -> src/index.ts`, `pkg/a/deep.ts`, `pkg/nested-link.ts -> ../src/index.ts`. Existence/registration was not rechecked by this pass. Extra data fixtures belong to isolated service tests, not concurrent mutations of the lead fixture.

Every retained web visual row: **1440px and 390px, light and dark**, identical fixed height, zoom, DPR, fonts, fixture and settled state within each base/head pair. Interaction proof requires recordings. Clearly label BEFORE/base and AFTER/head. Use a separate isolated base instance, never switch/restart the lead checkout. Base/head cannot have identical alias results: that is the intended change.

Extract settled static frames from the recordings. For unchanged ordinary-file control states require **diff0** in deterministic matched crops. If rasterization prevents exact zero, predeclare **diffthreshold** (e.g. RGB channel delta >16 on at most 0.1% of crop pixels), report threshold, count, masks and actual result; inspect all residual changes. For changed alias-result states use annotated expected additions/kinds and compare unchanged chrome/control regions with diff0/diffthreshold. Never demand whole-frame diff0 across an intentional result change, mask away the result under review, or call an unmeasured comparison passed. Freeze/identify transient cursors and timestamps consistently. Static frames prove layout/readability, not interaction or watcher timing.

## Minimum matrix

| ID | Branch and action | Required proof / disposition | Status in this audit |
|---|---|---|---|
| V1 | Composer mixed search: type `@link`; show root file, root directory and nested file aliases; keyboard-select file then directory in separate undoable actions; query nested alias and ordinary `@index` control | Four before/after recording pairs. Correct icons/kinds, alias paths retained in composer, selection/dismissal works; nested discovery is visible. Extract settled result/control frames under capture contract. No provider turn. | Required captures; not run |
| V3 | Files panel mixed search `link`; select `index-link.ts`, inspect target contents; query nested alias; clear search | Four before/after recording pairs. Correct path/kind/hierarchy and readable preview. Clearing returns to unchanged directory listing; do not require aliases there. Directory-link expansion is optional boundary observation, not acceptance proof for flat index. Extract static frames. | Required captures; not run |
| V2 | Command/keybinding ProjectFilePicker: file-only query and empty query | Equivalent changed service boundary: D2 must prove file aliases included and directory aliases excluded, including watcher misclassification. Picker mapping, fuzzy highlighting, path description and open callback are unchanged. V1 covers selection/path rendering and V3 covers file preview, but neither proves this picker was operated. No independent capture required for scoped eligibility claim. If claiming command/keybinding selection/opening end-to-end, retain V2 recording in all four variants. | Service proof required; UI execution unverified |
| V4 | Markdown basename / web repeated-workspace-prefix fallback | D2 exact file-only query responses plus existing basename helper assertions prove eligibility and unchanged lookup semantics. Preserve exact filename/case/ambiguity controls; repeated-prefix fallback also needs literal-original-exists precedence, not just basename helper tests. No new Markdown markup or renderer. No independent capture for scoped eligibility claim. To claim fallback actually opens a symlink, retain seeded-message click recording in four variants; use missing root basename `nested-link.ts`, not directly openable root alias. | Logic proof required; end-to-end opening unverified |
| V5 | Project icon picker imageOnly/file branch | D2 must prove alias-extension eligibility, directory exclusion, ordinary/non-image exclusion and filter-before-limit. Thumbnail and persistence are distinct unchanged behaviors, not established by V1/V3 or service tests. No independent capture for result eligibility alone. If claiming thumbnail load, selection or persisted icon, retain V5 four-variant recording using valid linked PNG; restore prior icon. | Filter proof required; thumbnail/persistence unverified |
| D1 | Flat `WorkspaceEntries.list({cwd})`, directoryPath omitted | Root/nested aliases exactly once with resolved target kind, directory ancestors, lexical ordering and max-entry/truncated contract. Existing `indexes symlinked files and directories inside the workspace` proves positive root membership when run; `lists a symlink the watcher already indexed once, with the link's kind` covers duplicate/correct-kind behavior. Add/retain explicit nested/order/boundary assertions; UI search is not flat-list proof. | Tests present, not run; additional assertions needed |
| D2 | Search mixed/file/directory/imageOnly, empty and nonempty query | Assert alias paths and kinds; linked PNG vs linked TS and directory named `.png`; empty query, normalization, no-match, exact-vs-fuzzy ordering, ordinary+alias merge, limit 1/boundary and truncated (including incomplete index). Test duplicate paths with incorrect indexed kind and filtered removal. Named existing tests: `filters image searches before applying the result limit`; `lists a symlink the watcher already indexed once, with the link's kind`. These do not alone cover symlink-image filtering, all limits/rank cases or directory-only search. | Partial named coverage, not run; missing cases remain |
| D3 | Eligibility and final ignore precedence | Run `skips ignored symlinks and symlinks that leave the workspace`; `honors .ignore files, ignored tracked links, and submodule rules for symlinks`; `lets the nearest .ignore rule decide a symlink, ahead of .gitignore`. Required semantics: last matching pattern within a file, deepest matching .ignore wins (no-match falls through), .ignore include overrides git ignore, tracked aliases use --no-index, nested repository owns git rules, outside-git behavior and git failure policy. Assert alias-to-ignored-target remains eligible when alias name is allowed; no directory-link traversal; outside/sibling-prefix, broken, cycle, .git target and special targets excluded. Some of these are source branches only, not current test assertions. | Partial integration tests present, not run; eligibility/error gaps remain |
| D4 | New matcher boundedness and syntax | All four `IgnorePatterns.test.ts` tests: `lets the last matching pattern decide, including negations`; `anchors patterns that contain a slash and matches bare names at any depth`; `supports globstars, classes, escapes, and folder-only patterns`; `matches adversarial patterns in linear time`. Existing adversarial negative and positive paths are essential. Add/retain CRLF/trailing escaped spaces, malformed classes/literal escape controls if claiming full documented syntax. NFA avoids exponential backtracking; do not infer measured performance or a constant resource bound from the test title. POSIX class names explicitly unsupported. | Named tests present, not run |
| D5 | Watcher and explicit refresh | Run `reads symlinks again after the watcher reports a change` (shared concurrent scan, ordinary edit cache retained, replacement after event); `keeps symlinks once the watcher subscribes after starting late`. Extend proof to removed/renamed links, retarget kind, .ignore/.gitignore modification invalidation, scan-in-flight invalidation and incomplete initial scan; assert both search and flat list. Explicit refresh must invalidate cache too. Fake callback tests prove response to a batch, not real watcher delivery; obtain one real fff event-to-service-result proof using an awaited event/milestone, no sleeps/polling. | Partial fake-watcher tests present, not run; real delivery/refresh gaps remain |
| D6 | Directory discovery pagination | `finds symlinks in folders past the first page of the index`: offset sequence 0, 25,002, nested alias and ancestor; missing indexed directories tolerated. Preserve empty/short/exact-full page termination and no repeated/duplicate results at boundaries. Source now pages; previous single-page defect is superseded, not still asserted. | Named regression test present, not run |
| D7 | Unchanged boundaries / construction | Existing content-search test `continues whole-word searches after a filtered grep page` plus targeted WorkspaceEntries searchContents tests establish construction with added service dependencies when run. Ordinary directoryPath listing remains separate; a read-only response assertion may record its unchanged exclusion, no theme/video matrix required. | Unchanged paths, execution unverified |

Minimum: **8 after and 8 before recordings** (2 flows × 4 variants × 2 revisions = 16), or four before/four after videos with both labeled segments. Static frames extracted, no extra static sessions. Optional V2/V4/V5 recordings become required only for their explicit end-to-end claims above. Reducing captures never removes D-row proof obligations.

## Rationale and surface accounting

V2 is an unchanged command-palette action renderer over file-only results; V5 shares its file-query wrapper with an additional server image filter but uses a distinct thumbnail. V4 consumes file-only results through unchanged lookup and metadata precedence. These are affected consumers, deliberately retained in the table with their logic obligations and limits. The diff does not warrant three extra theme/viewport cross products merely to repeat response eligibility. V1/V3 exercise two real affected render paths, alias labels/kinds, insertion and preview. They cannot certify thumbnail fetching, icon persistence or Markdown fallback interactions.

Web and Electron share these web components; Electron shell/IPC has no changed path, but **Electron execution is unverified**. Native mobile has separate composer, file-tree and Markdown renderers; **iOS/Android execution is unverified**. **390px web is responsive web, never native proof**. If native behavior is claimed, run native V1/V3 and basename V4 on actual device dimensions in light/dark with recordings. No native 1440px phone requirement. Providers share filesystem services; no provider cross product or agent turn needed. Remote/relay/tunnel execution and destination routing are unverified; no transport changes require a full cross product. A remote smoke is needed only to claim that runtime was exercised.

## FRICTION

1. This is a proof plan/source audit, not successful test or visual evidence. No head-specific logs/captures were supplied or executed here. Lead must attach exact command, head, results and artifacts; test presence is insufficient.
2. Existing tests now address nearest .ignore precedence, adversarial matching, watcher retries, duplicate kind correction and paged discovery. They still leave the D-row cases listed above unproven. Do not mark whole rows green from one related test name.
3. Prior matrix over-scoped ordinary listing as a failure and retained a now-fixed paging finding. Both are corrected here. V3 clear-search is a boundary observation, not a demand to fix the separate listing issue.
4. V4 seeded-message and V5 valid linked-image fixtures are unnecessary for the minimum scoped visual set; needed if their end-to-end claims are retained. Never fake captures or mutate the lead fixture during this audit.
5. Large-workspace latency/memory, real watcher delivery, Electron, native mobile and connection modes remain unmeasured. Bounded matching avoids regex backtracking but does not establish overall scan performance.

Source anchors at reviewed head: [server index](https://git.cafe/pingdotgg/t3code/src/commit/2c6b98457c776394c9628259c24b6d5801c5895c/apps/server/src/workspace/WorkspaceSearchIndex.ts), [ignore matcher](https://git.cafe/pingdotgg/t3code/src/commit/2c6b98457c776394c9628259c24b6d5801c5895c/apps/server/src/workspace/IgnorePatterns.ts), [index tests](https://git.cafe/pingdotgg/t3code/src/commit/2c6b98457c776394c9628259c24b6d5801c5895c/apps/server/src/workspace/WorkspaceSearchIndex.test.ts), [integration tests](https://git.cafe/pingdotgg/t3code/src/commit/2c6b98457c776394c9628259c24b6d5801c5895c/apps/server/src/workspace/WorkspaceEntries.test.ts), [file query wrapper](https://git.cafe/pingdotgg/t3code/src/commit/2c6b98457c776394c9628259c24b6d5801c5895c/apps/web/src/components/files/projectFilesQueryState.ts), [Markdown lookup](https://git.cafe/pingdotgg/t3code/src/commit/2c6b98457c776394c9628259c24b6d5801c5895c/apps/web/src/components/ChatMarkdown.tsx), [icon picker](https://git.cafe/pingdotgg/t3code/src/commit/2c6b98457c776394c9628259c24b6d5801c5895c/apps/web/src/components/settings/ProjectFaviconPickerDialog.tsx).
