feat: automatic managed git worktrees for agent tasks (create, snapshot, restore, GC)#100535
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d841132008
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| export function sidebarMoreRoutes(pinned: readonly SidebarNavRoute[]): SidebarNavRoute[] { | ||
| return SIDEBAR_NAV_ROUTES.filter((routeId) => !pinned.includes(routeId)); | ||
| } | ||
| export const SIDEBAR_SECTIONS = [ |
There was a problem hiding this comment.
Keep sidebar exports until callers migrate
This replaces the old sidebar export surface with SIDEBAR_SECTIONS, but ui/src/components/app-sidebar.ts and ui/src/app/settings.ts still import DEFAULT_SIDEBAR_PINNED_ROUTES, SIDEBAR_NAV_ROUTES, SidebarNavRoute, sidebarMoreRoutes, and normalizeSidebarPinnedRoutes; at this commit those symbols no longer exist, so the Control UI build/tests fail before the Worktrees page can load. Either migrate those callers to the new section model or keep the compatibility exports.
Useful? React with 👍 / 👎.
|
Codex review: found issues before merge. Reviewed July 5, 2026, 9:59 PM ET / 01:59 UTC. Summary Reproducibility: yes. for the PR blockers: source inspection shows removed sidebar exports still have callers, node_modules symlinks are tracked in the diff, and setup hook execution inherits process.env through runCommandWithTimeout. I did not run the PR branch. Review metrics: 3 noteworthy metrics.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review findings
Review detailsBest possible solution: Keep this PR as the implementation candidate, but merge only after removing install artifacts, preserving or migrating sidebar API callers, sanitizing setup-hook execution, and getting maintainer approval for the core/API/security boundary. Do we have a high-confidence way to reproduce the issue? Yes for the PR blockers: source inspection shows removed sidebar exports still have callers, node_modules symlinks are tracked in the diff, and setup hook execution inherits process.env through runCommandWithTimeout. I did not run the PR branch. Is this the best way to solve the issue? No, not as-is. The managed-worktree direction is plausible, but the branch needs blocker fixes and maintainer approval for the new core, protocol, plugin SDK, state, and security surfaces. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 4a5bdc6ae3a9. Label changesLabel changes:
Label justifications:
Evidence reviewedSecurity concerns:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
…apshot/restore/GC) Centralized managed worktrees under <state-dir>/worktrees/<repo-fingerprint>/<name> with branch-per-task (openclaw/<name>), .worktreeinclude provisioning, an optional .openclaw/worktree-setup.sh repo hook, and a SQLite registry in the shared state DB. Removal always snapshots the tree (untracked included, gitignored excluded) to refs/openclaw/snapshots/<id>; restore rebuilds the branch at the original commit with the snapshot content as uncommitted state. Lossless run-end cleanup, 7-day idle GC for run-owned worktrees (manual exempt), orphan reconciliation, 30-day snapshot retention. Surfaces: worktrees.* gateway RPC (operator.admin mutations), openclaw worktrees CLI, Control UI page, plugin-SDK facade + Workboard kind:"worktree" materialization. E2E-verified on Testbox: full create->work->remove->restore->gc lifecycle.
d841132 to
4150d98
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4150d98e2f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @@ -0,0 +1 @@ | |||
| ../../../normalization-core No newline at end of file | |||
There was a problem hiding this comment.
Remove committed node_modules symlinks
This commit starts tracking pnpm-generated node_modules symlinks here and in the other added packages/*/node_modules / ui/node_modules paths. In a clean checkout these local install artifacts will be materialized by Git and then package-manager installs can rewrite or remove them, leaving dirty worktrees and making the dependency layout depend on tracked node_modules entries instead of the lockfile; please drop these generated links from the commit.
Useful? React with 👍 / 👎.
…apshot/restore/GC) (openclaw#100535) Centralized managed worktrees under <state-dir>/worktrees/<repo-fingerprint>/<name> with branch-per-task (openclaw/<name>), .worktreeinclude provisioning, an optional .openclaw/worktree-setup.sh repo hook, and a SQLite registry in the shared state DB. Removal always snapshots the tree (untracked included, gitignored excluded) to refs/openclaw/snapshots/<id>; restore rebuilds the branch at the original commit with the snapshot content as uncommitted state. Lossless run-end cleanup, 7-day idle GC for run-owned worktrees (manual exempt), orphan reconciliation, 30-day snapshot retention. Surfaces: worktrees.* gateway RPC (operator.admin mutations), openclaw worktrees CLI, Control UI page, plugin-SDK facade + Workboard kind:"worktree" materialization. E2E-verified on Testbox: full create->work->remove->restore->gc lifecycle.
Adds an additive worktree flag to sessions.create so any new chat can run in an isolated managed worktree of the agent's git workspace, with the branch checked out and .worktreeinclude provisioning applied. The session's spawnedCwd points at the matching subdirectory inside the worktree so chat runs, CLI, and the file browser execute there. agents.list gains workspaceGit (workspace or an ancestor is a git checkout) to gate the affordance; web sidebar, iOS, and Android expose a New-Chat-in-worktree action. Uses the method's operator.write scope, but the .openclaw/worktree-setup.sh step runs only for operator.admin callers since it executes repo code. Deleting the session, or leaving via a plain New Chat, clears the cwd and lossless-removes the worktree; idle GC treats recent session activity as worktree activity so an active session's checkout is never swept. Live-verified end-to-end on a real gateway; follow-up to #100535 (issue #100534).
…aw#100788) Adds an additive worktree flag to sessions.create so any new chat can run in an isolated managed worktree of the agent's git workspace, with the branch checked out and .worktreeinclude provisioning applied. The session's spawnedCwd points at the matching subdirectory inside the worktree so chat runs, CLI, and the file browser execute there. agents.list gains workspaceGit (workspace or an ancestor is a git checkout) to gate the affordance; web sidebar, iOS, and Android expose a New-Chat-in-worktree action. Uses the method's operator.write scope, but the .openclaw/worktree-setup.sh step runs only for operator.admin callers since it executes repo code. Deleting the session, or leaving via a plain New Chat, clears the cwd and lossless-removes the worktree; idle GC treats recent session activity as worktree activity so an active session's checkout is never swept. Live-verified end-to-end on a real gateway; follow-up to openclaw#100535 (issue openclaw#100534).
…apshot/restore/GC) (openclaw#100535) Centralized managed worktrees under <state-dir>/worktrees/<repo-fingerprint>/<name> with branch-per-task (openclaw/<name>), .worktreeinclude provisioning, an optional .openclaw/worktree-setup.sh repo hook, and a SQLite registry in the shared state DB. Removal always snapshots the tree (untracked included, gitignored excluded) to refs/openclaw/snapshots/<id>; restore rebuilds the branch at the original commit with the snapshot content as uncommitted state. Lossless run-end cleanup, 7-day idle GC for run-owned worktrees (manual exempt), orphan reconciliation, 30-day snapshot retention. Surfaces: worktrees.* gateway RPC (operator.admin mutations), openclaw worktrees CLI, Control UI page, plugin-SDK facade + Workboard kind:"worktree" materialization. E2E-verified on Testbox: full create->work->remove->restore->gc lifecycle.
…aw#100788) Adds an additive worktree flag to sessions.create so any new chat can run in an isolated managed worktree of the agent's git workspace, with the branch checked out and .worktreeinclude provisioning applied. The session's spawnedCwd points at the matching subdirectory inside the worktree so chat runs, CLI, and the file browser execute there. agents.list gains workspaceGit (workspace or an ancestor is a git checkout) to gate the affordance; web sidebar, iOS, and Android expose a New-Chat-in-worktree action. Uses the method's operator.write scope, but the .openclaw/worktree-setup.sh step runs only for operator.admin callers since it executes repo code. Deleting the session, or leaving via a plain New Chat, clears the cwd and lossless-removes the worktree; idle GC treats recent session activity as worktree activity so an active session's checkout is never swept. Live-verified end-to-end on a real gateway; follow-up to openclaw#100535 (issue openclaw#100534).
Closes #100534
What Problem This Solves
Agent tasks and operators have no isolated, managed place to work on a git repo. Parallel tasks collide in the user's checkout, hand-made temporary checkouts leak forever, and Workboard cards that declare
workspace.kind: "worktree"silently do nothing because nothing materializes them. Automatic worktree management is the industry-standard answer (Claude Code, Codex, Cursor, Copilot, Hermes all ship it).Why This Change Was Made
Adds a core managed-worktree service with the convergent industry lifecycle — create → provision → work → snapshot → cleanup/restore — built on OpenClaw's canonical seams: SQLite registry in the shared state DB, additive
worktrees.*gateway methods (mutations requireoperator.admin), a narrow plugin-SDK facade, and hourly GC owned by gateway maintenance. Worktrees live centrally under<state-dir>/worktrees/<repo-fingerprint>/<name>on branchopenclaw/<name>. Removal always snapshots the tree (untracked files included, gitignored files excluded) torefs/openclaw/snapshots/<id>in the source repo, so even automatic cleanup is restorable; restore rebuilds the branch at the original commit and returns the snapshot content as uncommitted working state, so snapshot commits can never leak into pushed history. Provisioning follows the cross-vendor.worktreeincludeconvention plus an optional.openclaw/worktree-setup.shrepo hook (no new config keys). Manual worktrees are never auto-swept; workboard/session-owned ones GC after 7 idle days; snapshots are retained 30 days.Non-goals: foreign worktree management (
~/.codex/worktrees,.claude/worktrees), apply-to-main merge-back, port/env isolation, session-spawn trigger (follow-up).User Impact
workspace.kind: "worktree"now get a real isolated checkout per card, reused across retries, cleaned up losslessly when the run ends.openclaw worktrees list|create|remove|restore|gcmanages worktrees from the CLI; a new Control UI "Worktrees" page lists, deletes, and restores them..worktreeincludebrings.env-style gitignored files into fresh worktrees;.openclaw/worktree-setup.shruns repo-specific setup (fail-closed).Evidence
End-to-end lifecycle proof on Blacksmith Testbox (Linux, Node 24) via the real CLI against a real repo with a bare origin:
openclaw/e2e-demochecked out,.envprovisioned via.worktreeinclude, setup script ran,node_modulesnot copiedOpenClaw worktree snapshot: manual-deleteatrefs/openclaw/snapshots/<id>; untracked file captured;.envandnode_modulesexcluded; snapshot parent == worktree HEAD; dir and branch gone.envre-provisionedGates on Testbox (post-rebase on latest main):
tsgo:prod+tsgo:testgreen, oxlint 0 warnings/0 errors on all touched paths, focused suites green (worktrees service 44 tests, gateway methods, gateway maintenance, protocol schema, workboard incl. dispatcher materialization, UI navigation),pnpm buildclean,db:kysely:checkclean,ui:i18n:checkclean. Codex autoreview (gpt-5.5): no actionable findings.