Repository navigation
Add a .worktreeinclude reader for seeding new worktrees - #15413
Conversation
A new agent worktree arrives without the files git does not track. Today AgentMoveScripts carries the working tree with `git add -A`, which respects .gitignore, so `.env`, local config and installed dependency directories are exactly what a fresh worktree lacks and exactly what the session then cannot run without. This adds the portable half: a `.worktreeinclude` at the repository root naming what to carry, a planner that expands it against the tree, and an applier that copies or symlinks the result. The CLI surface comes separately, since the file format is a product decision and is going to cmux#13742 first. Two departures from .gitignore syntax, both deliberate and documented in the sources. Every pattern is a path from the repository root, because gitignore's basename-anywhere matching would force a walk through the very directories (node_modules) that make a walk expensive; `**` is how a pattern opts into one. And a matched directory is taken whole, because a copy could filter its contents but a symlink cannot, so one rule serves both actions. The second departure silently disarms a `!` aimed inside such a directory, so the planner reports those as ineffectiveNegations rather than dropping them on the floor. A symlink is a leaf even when it points at a directory, the way git reads one, so the walk cannot loop through a link to its own ancestor. A pattern whose target resolves outside the repository is refused rather than followed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 18 seconds. View limit detailsLimit details: You’ve used all 10 included reviews currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository: manaflow-ai/cmux/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (10)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
All contributors have signed the CLA ✍️ ✅ |
CI failure attributionCI passes on Written by |
|
Repaired the worktree seeding edge cases before merge: destination symlink ancestors cannot redirect delivery, source dangling symlinks use no-follow existence checks, repeated Validation after merging current main: focused WorktreeSeed coverage reached 76/76; full CMUXAgentLaunch passed 659/659; diff checks clean. Independent final review was clean. — Mochi |
|
Merge receipt for |
4e0f7d2 fix(bash): keep $? for PROMPT_COMMAND hooks after cmux's (manaflow-ai#15255) ae49bf5 fix(examples): show custom description in Project Worktrees sidebar (manaflow-ai#15256) a9a229d Add cross-provider token usage accounting for agent transcripts (manaflow-ai#15332) 860619f Add a .worktreeinclude reader for seeding new worktrees (manaflow-ai#15413) 3edbd83 Clear the stale Needs input badge when Claude's permission is decided in the terminal (manaflow-ai#15170) 9ed9294 CodeRouter: hold capacity errors on the same model instead of failing fast (manaflow-ai#15310) 56d4547 docs: add a front door for outside contributors (manaflow-ai#15263) 799f906 fix(ci): recognize GUI token acquisition failures (manaflow-ai#15449) f118d43 ci: age parked builds by measured reuse distance (manaflow-ai#15616) 1f6744d ci: harden overflow switch recovery (manaflow-ai#15617) 9987778 Predicted echo: remote terminals only, withdraw on pasted and sent input (manaflow-ai#15211) d9e199b Subtle selection follow-ups: group header hairline, no focus re-render for legacy rows, cmux.json test (manaflow-ai#15195) c13afe1 test: cover UTF-8 workspace create commands (manaflow-ai#15622) e76a660 fix: preserve Claude remote-control names on restore (manaflow-ai#15619) 900f248 feat: expose cmux-owned scratch metadata in session listing (manaflow-ai#15615) b5604fa ci: say why compiled-product reuse refused an artifact (manaflow-ai#15553) # Conflicts: # .github/workflows/ci-cloud-overflow-probe.yml
|
These app-host tests newly fail in main's full suite at
Commits in the range: 3edbd83...5850596 Pull requests run only the suites their diff reaches, so main's full suite is where this shows first. If this pull request is the cause, please fix forward or revert; if it is not, say so here. This is an automated attribution and can be wrong, most often for a flaky test. |
Summary
A new agent worktree arrives without the files git does not track.
AgentMoveScriptscarries the working tree withgit add -A, which respects.gitignore, so.env, local config and installed dependency directories are exactly what a fresh worktree lacks and exactly what the session then cannot run without. Right now the answer is hand-runcpafter every worktree creation.This is the portable half of the fix: a
.worktreeincludeat the repository root naming what to carry, a planner that expands it against the tree, and an applier that copies or symlinks the result. Six types, all Foundation only, all injectable (the planner takes a directory listing closure, so plans are testable without a filesystem):WorktreeSeedPattern/WorktreeSeedFileparse the file. A bad line becomes a reported problem, not a parse failure, so one typo does not discard the rest of the file.WorktreeSeedPlannerexpands patterns into a plan, and reports what it decided against:excluded,refused,shadowed,alreadyPresent,unmatched,ineffectiveNegations.WorktreeSeedRepositoryreads a real tree.WorktreeSeedApplierperforms the plan and reports per path; one failure never stops the rest.Two departures from
.gitignoresyntax, both deliberate and documented at their definitions. Every pattern is a path from the repository root, because gitignore's basename-anywhere matching would force a walk through the very directories (node_modules) that make a walk expensive;**is how a pattern opts into a walk. And a matched directory is taken whole, because a copy could filter its contents but a symlink cannot, so one rule serves both actions. The second departure silently disarms a!aimed inside such a directory, which is why the planner detects that case and reports it asineffectiveNegationsinstead of no-oping.Two safety properties worth a reviewer's attention. A symlink is a leaf even when it points at a directory, the way git reads one, so the walk cannot loop through a link to its own ancestor and a
build/pattern does not match a symlink namedbuild. And a path whose target resolves outside the repository isrefusedrather than followed, with the inside test comparing resolved paths plus a separator so/repo-backupdoes not read as inside/repo. The walk is also budgeted (maximumVisitedDirectories, default 20000) and says so in the plan (reachedWalkLimit) rather than silently truncating.No CLI surface here, and nothing calls this yet. The file format is a product decision, so it goes to #13742 with a recommendation before a
cmux worktreeverb reads it.Testing
70 swift-testing tests added in
CMUXAgentLaunchTests: 17 on line parsing, 8 on file parsing, 25 on planning against an injected listing (including root anchoring, last-match-wins negation, the walk budget, and a pathological glob that must not hang), and 20 on a real filesystem in temp directories (escaping symlink refused, symlink loop not hanging the walk, dangling destination symlink counting as occupied, alinkentry landing as an absolute symlink, one failure not stopping the rest).Executed: every one of those 70, by
swift testin a scratch SwiftPM package on Linux (Swift 6.1.3), sinceCMUXAgentLaunchas a whole needs Darwin and cannot build there. The eight files are byte-identical to what ran, apart from the test module import. Result:Test run with 70 tests passed.Not executed by me: the same tests inside
CMUXAgentLaunchon macOS. That is what CI's package lane establishes on this SHA, and it is the thing to check before merge. No app build, no tagged build, no dogfood: nothing in this PR is reachable from the UI yet.New files land in an existing SwiftPM target with no explicit
sources, so there are noproject.pbxprojedits andscripts/sync-test-wiringdoes not apply (it coverscmuxTests/).Changelog
none
Demo Video
Not applicable: no user-reachable surface in this PR.
Checklist
WorktreeSeedProblemadvice strings are developer-facing today; the PR that surfaces them through the CLI owns their audit.cmux ssh: none.🤖 Generated with Claude Code
Summary by cubic
Adds a
.worktreeincludereader so new agent worktrees carry the files git doesn't track. Today a worktree arrives without.env, local config, and installed dependency directories, so the first command a session runs fails on missing configuration; the workaround is a hand-runcpafter every creation.The feature parses the file, expands its patterns into a plan against the repository tree, and copies or symlinks the result into the new worktree. Everything is Foundation-only and injectable, so the planner is testable without a filesystem. Patterns are paths from the repository root —
**is how a pattern opts into a walk, so a root pattern never descends intonode_modules— and a matched directory is taken whole. A!aimed inside a selected directory is reported asineffectiveNegationsnaming the covering ancestor. A symlink is a leaf even when it points at a directory, so the walk cannot loop, and paths resolving outside the repository are refused.Delivery never overwrites what git checked out: occupied destinations (including dangling symlinks) are skipped, a destination symlink ancestor that could redirect a write is refused, a dangling source symlink is delivered as a link node, and one failure never stops the rest.
Testing
CMUXAgentLaunchon macOS is what CI establishes.No surface yet
cmux worktreeverb reads it.Written for commit c783cce. Summary will update on new commits.