Repository navigation
Conversation
…macOS Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — The folder picker now recognizes canonically equivalent Unicode names while preserving actual filesystem paths. Literal matches take priority, and ambiguous normalized names are not automatically selected, keeping the change narrowly scoped. You can add or adjust custom eligibility rules. Learn more. |
Findings
|
| Layer / File(s) | Summary |
|---|---|
Filesystem browse matching packages/client-runtime/src/state/filesystem.ts, packages/client-runtime/src/state/filesystem.test.ts |
Prefix matching checks raw and NFC-normalized names. Exact matching prefers a raw name, then selects a normalized match only when it is unique. Tests cover composed and decomposed names, exact-spelling preference, and ambiguous matches. |
Pinned-entry exact matching apps/web/src/components/CommandPalette.logic.ts, apps/web/src/components/CommandPalette.logic.test.ts |
Pinned-entry lookup falls back to NFC-normalized matching when literal matching finds no entry. The fallback selects an entry only when its normalized name is unique. Tests cover a composed query matching a decomposed name and ambiguous normalized names. |
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix
Suggested reviewers: maria-rcks
Merge Risk: 
Low · up to 40c7a
-
A narrow clone flow can select an invisible hidden folder instead of a visible browse choice; restrict the normalized fallback before merging.
Pre-merge checks: 
4
-
Full details: Title check
-
Explanation
The title names the main change: the folder picker now finds folders with accented names on macOS. It matches the NFC/NFD normalization fix in filterFilesystemBrowseEntries and filterPinnedBrowseEntries. It follows the conventional commit format from the template.
Full details: Description check
-
Explanation
The description follows the template. It has Problem, Change, Scope and approval, and Verification sections. The Problem and Change sections clearly explain the NFD/NFC mismatch, the affected functions, and the NFC-only fallback for ambiguous matches. The Scope section justifies the small fix without a prior issue, and it cites a search for overlapping work. The Verification section lists specific tests, observed before/after results, and what was not checked. The description does not link a triaged issue or maintainer approval, but it gives the required exemption reasoning for a small, focused bug fix. The template's comment says a UI change needs screenshots. This PR changes no UI, so the omission is acceptable.
-
Finishing Touches
-
Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
CodeRabbit Verify
- Run CodeRabbit Verify to test the changes in this pull request.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dismissing prior approval to re-evaluate 1c700c2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dismissing prior approval to re-evaluate d7c3a57
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dismissing prior approval to re-evaluate 40c7a29
Problem
On macOS, Finder and other Cocoa apps save new folder names in decomposed Unicode (NFD), so
éis stored ase+ U+0301. Korean names and Japanese kana with dakuten are stored the same way. Text typed into T3 Code is composed (NFC). The folder browser used by Add project and clone (command palette on web/desktop, Add Project screen on mobile) compares names byte for byte, which causes two problems:~/Dév, hidesDéveloppement, even though it is right there under~/.Change
filterFilesystemBrowseEntriesinpackages/client-runtimeis shared by web and mobile. It now compares the NFC forms of the query and each folder name, for both the prefix filter and the exact-match lookup. An exact literal match still wins first, so on Linux, where NFC and NFD spellings can be two different folders, the folder you typed is the one picked. Entry names and paths are not changed, so navigation and Tab completion keep the on-disk spelling. The command palette already normalizes its own search to NFC (packages/shared/src/paletteSearch.ts).While choosing a clone destination, the palette uses
filterPinnedBrowseEntries(apps/web). That function reuses the shared filter for the visible list but has its own exact-match lookup. That lookup now follows the same rule, a literal match first and then the NFC form, so Create & Clone picks the existing decomposed folder instead of the typed path.In both places the NFC fallback is used only when exactly one folder normalizes to the typed name. If several spellings normalize to it and none matches literally, there is no exact match, so a typed submit never picks one sibling folder over another at random.
Scope and approval
Very small, focused fix for an obvious bug, so no prior issue: existing folders vanish from the folder browser, and it offers to create a folder that already exists. The fix is in one shared client function and the web clone-destination lookup that sits beside it, with one test assertion each. It changes no contract, server, or UI.
Overlap search: the local PR index and GitHub searches (NFD, normalize/browse, Korean folder,
filterFilesystemBrowseEntries) found no fix for this. Open #26376 rewrites this function for fuzzy matching (a feature) and does not normalize names. Merged #28243 (Tab completion) and the symlink picker PRs (#28725, #26168) cover different problems.Verification
NSFileManagerasDéveloppementcomes back fromreaddirin NFD (14 UTF-16 units), andname.toLowerCase().startsWith("dév")isfalse.filesystem.test.ts›filesystem browse model. On main it fails withvisibleEntries: []where the folder was expected. It also checks the NFC/NFD collision case.vp test run src/state/filesystem.test.ts(client-runtime): 10/10 pass.CommandPalette.logic.test.ts›filterPinnedBrowseEntries. Before the fix it fails withexpected null to be { name: 'Développement', …(1) }.vp test run src/components/CommandPalette.logic.test.ts(web): 36/36 pass.\u212BandA\u030A) that both normalize to the typed\u00C5. Before the fix both fail withexpected { name: 'Å', … } to be null; after it, 10/10 and 36/36 pass.vp run check:changed: format, lint, knip, typecheck (7 packages), and tests all pass.filesystem.browseprefix filter has the same comparison, but current clients always browse with a trailing separator, so it filters with an empty prefix. It is left unchanged.Reviewed with sol-loop: 4 rounds with GPT-6.1 Sol on high. Sol verdict: approved (round 1 found the NFC/NFD collision case, fixed above; round 3 approved the clone-destination follow-up; round 4 approved the ambiguous-match fix, all with no open findings).
Created with Claude Opus 5.5 in Claude Code (T3 Code).
🤖 Generated with Claude Code