Repository navigation
Conversation
canonicalTree returned the spelled path whenever the leaf did not exist, so a workspace under a linked ancestor (macOS /tmp and /var, a linked home or project folder) changed spelling the moment it was created. Follow then recorded one tree and the next save rebound to the other, and ForeignFolder called a linked chat's own absent work/ foreign. Resolve the longest existing ancestor and keep the missing rest as written; other errors keep the absolute spelling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review fixes: only components that are truly absent (Lstat says so) are kept as written; a link whose target is missing keeps the absolute spelling, so a chat's dangling work/ link named through an alias stays foreign. The missing suffix is collected in one pass and the existing ancestor resolved once. The through-a-file test runs on Windows too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AbirAbbas
force-pushed
the
fix/cellstore-absent-tree-alias
branch
from
October 29, 2026 23:17
42e85ec to
ce1ad45
Compare
Collaborator
Author
|
Closing unmerged: the Mac push stopped early to save usage. What this fixes and what is left is tracked in #2053. The branch |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found while running the engine suite on macOS (Apple M4 Pro, macOS 15.6), where
/tmpand/varare links into/private.What was wrong
canonicalTree(internal/cellstore/engine.go) resolved a tree only when it already existed. For a folder that did not exist yet it returned the spelled path, so the same folder changed spelling the moment it was created whenever an ancestor was a link (macOS/tmpand/var, or a linked home or project folder):Engine.Follow(used bysyncsetuptake, the desktop's Continue here, and byhandoff) computes the target tree before the workspace exists and writes that spelling intoengine-tree. The next save'sbindTargetthen reads the resolved spelling, sees a different tree and runs a second rebind.work/folder foreign (ForeignFoldercompared the resolved chat root with the spelledwork/), so the chat's own folder would be sealed instead of its working folder.Mac evidence: two of the engine tests that fail on macOS at app/v3
12dadd64aare exactly these paths —TestFollowLongWorkspaceW4(Follow registers/var/…/work, the dirty plan then runs on/private/var/…/work) andTestAHomeChatNeverCapturesTheSendersHomeOnAnotherMachine("the chat's own work/ is called foreign"). Both pass with this change.What changes
Lstatsays so) are kept as written. A link whose target is missing is not a missing folder: a path through it keeps its absolute spelling, as before, so a danglingwork/link named through an alias stays foreign. Any other error (permission, a path through a file) also keeps the absolute spelling.Callers checked:
tree,ForeignFolder,holdsHome,policyDir,target,materialize,socketFor(Unix and Windows) and WindowscomposedPath. Existing folders resolve exactly as before; only absent ones under a link change spelling, andbindTarget's existing rebind keeps any older recorded spelling working.Tests
New, in
internal/cellstore/canonical_tree_test.go(each makes its own link, so they mean the same on Linux):TestCanonicalTreeResolvesAncestorOfMissingWorkspace— same spelling before and after creation.TestCanonicalTreeKeepsAPathThroughAFileTestForeignFolderKeepsMissingWorkUnderSymlinkedChat— own absentwork/is the chat's; an outside folder stays foreign.TestCanonicalTreeDoesNotResolvePastADanglingLinkThe first three fail on app/v3 and pass here.
Gates (on the Mac)
gofmt;go vet ./internal/cellstorefor darwin, linux and windows;CGO_ENABLED=0 go build ./cmd/codeaffor darwin/arm64, linux/amd64 and windows/amd64.TestFollowLongWorkspaceW4andTestAHomeChatNeverCapturesTheSendersHomeOnAnotherMachine: pass (both failed at12dadd64aon the Mac).internal/cellstoreon the Mac: 4 failures, all already failing at12dadd64aon the Mac (socket andTMPDIRfixtures); the 2 above now pass.go test -count=1 -p 6 ./...compared by test name with the12dadd64aMac baseline: running (results will be added here).12dadd64a: PR gate 40933976895 fails exactly the 5 tests app/v3's PR gate 40925411112 fails (commentlaw, guard, session ×2, taxonomy); Full check 40933980773 fails 27 tests, all among app/v3's 28 (40925415150). No new failures.12dadd64a;git merge-treeonto the new app/v3 (1c4ec8a25, pair: merge a computer's own chats when it joins, instead of replacing them #2031) is clean and pair: merge a computer's own chats when it joins, instead of replacing them #2031 touches none of these files.Codex review (adversarial, read-only)
pr: 0in the change entry → kept, see below.pr: 0.The change entry follows app/v3's convention (
docs/changes/unreleased/0-app-<slug>.md,pr: 0, as in #2014–#2016).codeaf-changes checkreports "pr is missing" for every such entry on app/v3 (249 at the base); the number can be filled when app/v3's entries are rolled up.Manual verification
Not reachable live here: the take path needs two paired computers (no second machine; the production relay is not used for tests). Covered instead by
TestFollowLongWorkspaceW4, which drivesEngine.Follow→Dirtyexactly as a take does, and theForeignFoldertests.🤖 Generated with Claude Code