You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Resolve folder case on write so notes don't split into case-only twin folders #1796
A project can end up with two folders that differ only by letter case, for example marketing/Teams and marketing/teams, or customers/CPC and customers/cpc. Both production cases behind #1787 look like this. The likely source is agents writing notes with inconsistent casing. In Cloud's storage (Tigris keys) and on Linux, the two spellings are separate folders, so nothing stops the split.
Sync: macOS and Windows file systems are case-insensitive by default, and macOS also normalizes Unicode. A workspace synced there through rclone or WebDAV merges the two folders on disk. Notes with the same filename in both folders overwrite each other.
Browsing: the user sees two folders for one topic, and notes are split between them.
#1789 handles the symptom. This issue is about preventing the split.
Proposed fix
When a write targets a folder path that matches an existing folder under the portable-path key (casefold plus Unicode NFC, the same _portable_path_key the wiki projector uses), write into the existing folder's spelling instead of creating a new one.
Apply this on every write path that creates folders: write_note, move_note, and API entity create and update. The rule should live in one place, not be copied per tool.
Resolve each path segment against the folders that already exist, so marketing/teams/q4 lands in marketing/Teams/q4.
When a path is rewritten, return the actual path in the tool response, so an agent learns the real spelling.
Leave existing duplicates alone. Merging folders that already exist is a separate decision, because it moves user files.
First step
Confirm where the production duplicates came from. Check the note history or write activity for the notes under marketing/teams and customers/cpc in the two affected workspaces (cloud Logfire issue #2636). If they came from local sync or import rather than MCP writes, the fix also needs to cover the sync path.
Acceptance
Writing marketing/teams/new-note when marketing/Teams/ exists creates marketing/Teams/new-note.md and reports that path.
A path differing only by Unicode normalization resolves the same way.
A folder that is genuinely new is created as written.
Tests cover write, move and API create, on both SQLite and Postgres.
Component: Cloud, because the production duplicates come from Cloud/Tigris storage. The change itself touches MCP tools (write_note, move_note), the API entity create and update paths, and services. I applied the cloud label.
Priority: Medium. Nothing is lost, but the wiki can't project the affected folders, and syncing to a case-insensitive file system can overwrite notes that share a filename.
Complexity: Medium. The rule should live in one shared resolver that uses _portable_path_key (casefold plus NFC) and resolves each path segment against existing folders. It then has to be wired into every write path that creates folders. Tests are needed for write, move and API create on both SQLite and Postgres.
Do the "First step" before implementing. If the duplicates came from local sync or import rather than MCP writes, the fix has to cover the sync path as well.
The resolver reads the existing folder set. Per the consistency model in CLAUDE.md, don't add SELECT ... FOR UPDATE or wider transactions for this. A concurrent write that creates a twin is derived-state drift, not a canonical-content problem.
Return the rewritten path in the tool response so agents learn the real spelling.
I haven't made any code changes. This pass was triage only.
Activity
claude commentedon Oct 20, 2026
Claude finished @phernandez's task in 20s —— View job
Triage
write_note,move_note), the API entity create and update paths, and services. I applied thecloudlabel._portable_path_key(casefold plus NFC) and resolves each path segment against existing folders. It then has to be wired into every write path that creates folders. Tests are needed for write, move and API create on both SQLite and Postgres.Notes for whoever picks this up
CLAUDE.md, don't addSELECT ... FOR UPDATEor wider transactions for this. A concurrent write that creates a twin is derived-state drift, not a canonical-content problem.I haven't made any code changes. This pass was triage only.