Skip to content

feat(worktrees): server-managed worktree lifecycle on orchestrator v2 - #5589

Open
StiensWout wants to merge 244 commits into
pingdotgg:t3code/codex-turn-mappingfrom
StiensWout:t3code/worktree-management-v2
Open

feat(worktrees): server-managed worktree lifecycle on orchestrator v2#5589
StiensWout wants to merge 244 commits into
pingdotgg:t3code/codex-turn-mappingfrom
StiensWout:t3code/worktree-management-v2

Conversation

@StiensWout

@StiensWout StiensWout commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Important

Stacked pull request. This targets t3code/codex-turn-mapping from #2829 and lands after it. Once #2829 merges, rebase this branch and retarget the PR to main.

This supersedes #4742. The earlier PR was built on the legacy orchestration paths; this version ports the feature to V2 and incorporates its outstanding review feedback.

Problem

Thread worktrees pile up with no way to see or clean them. Web and remote users had nothing at all, and the only cleanup path was a desktop-native prompt on thread deletion.

Solution

The server now owns the worktree lifecycle: it derives an inventory from Git plus the V2 projections, protects anything with active threads, local changes, or unpushed commits, and cleans up the rest by retention policy (or immediately when a worktree loses its last thread, if enabled). Missing worktrees are revived before a provider turn starts. Every connected client gets the same management surface.

Settings → Source Control gains a Worktrees section: one ledger per connected environment that advertises the new worktreeManagement capability, with per-environment cleanup policy and safe manual removal — so remote environments' worktrees are manageable from any client. Older servers are excluded per the usual version-skew contract.

Light Dark
Worktree settings, light Worktree settings, dark

Safety notes

  • Pruning is non-forced and revalidates current state on the server; all worktree mutations are serialized.
  • Safety joins all projects that share one Git common directory, including nested project roots.
  • Paths are canonicalized, and revival rejects symlink-ancestor escapes outside the managed worktree root.
  • Local branches and checkpoint refs are retained for revival.

Verification

  • Server vcs suite (14 files / 113 tests), web settings + worktree suites (18 files / 117 tests), contracts (275 tests) pass; server, contracts, client-runtime, and web typechecks clean.
  • Integrated browser passes on the live dev environment: inventory streaming without reloads, prune with confirmation, revival, and the environment-scoped section after the multi-environment rework.

Initial V2 port implemented with GPT-5.6 Sol via Codex in T3 Code. Worktree settings redesign, review fixes, and multi-environment management by Claude Fable 5 via Claude Code in T3 Code.

Note

Add server-managed worktree lifecycle with listing, pruning, revival, and background cleanup on orchestrator v2

  • Introduces WorktreeLifecycle, WorktreeService, WorktreeReaper, WorktreeDeletionCleanup, and WorktreeRevivalService to manage the full lifecycle of Git worktrees on the server, including serialized mutations, inventory change streaming, scheduled pruning, and post-deletion cleanup.
  • Adds four new WebSocket RPCs (vcs.listWorktrees, subscribeWorktreeInventory, vcs.pruneWorktrees, vcs.reviveWorktree) with authorization scopes and corresponding client-runtime atoms for the web app.
  • ProviderTurnStartService now revives and validates the worktree for a thread before provider session operations, restarts the session when the worktree generation or path changes, and serializes startup per ProviderSessionId.
  • GitWorkflowService methods preparePullRequestThread, createWorktree, and removeWorktree now acquire a mutation permit and emit an inventory change notification after completion.
  • Adds a Worktree Management section to Source Control settings, with retention controls, rich per-worktree metadata, and an in-app confirmation dialog for project removal.
  • Removes the client-side prompt to delete orphaned worktrees when deleting a thread; orphan cleanup is now handled server-side via WorktreeDeletionCleanup.
  • Risk: Worktree creation and removal commands are now serialized per environment (not per environment+cwd), which changes concurrency behavior for clients issuing concurrent worktree commands.

Macroscope summarized 0eec832.


Note

High Risk
Changes provider turn startup, shared Git worktree state, and automated deletion/pruning paths where incorrect safety checks could remove data or strand sessions.

Overview
Introduces server-managed worktree lifecycle so clients can list, subscribe to, prune, and revive worktrees uniformly, gated by a new worktreeManagement environment capability.

Inventory and mutations: WorktreeService builds inventory from git worktree list plus V2 thread shells, applies prune blockers (active threads, dirty state, unpushed commits), and revalidates immediately before removal. WorktreeLifecycle serializes mutations and publishes inventory revision streams. WorktreeRevivalService recreates missing paths under the managed root (with symlink/path checks) and runs project setup scripts; WorktreeReaper and WorktreeDeletionCleanup handle retention sweeps and thread.deleted orphan cleanup per server settings.

Git layer: Adds listWorkspaces and shared porcelain parsing for newline git worktree list output (replacing -z-only parsing for older Git). GitWorkflowService acquires mutation permits and bumps inventory on PR worktree prep, create, and remove.

Orchestration: ProviderTurnStartService calls reviveForThread before opening a provider session, closes/reopens the session when the worktree was revived or its generation changed, and serializes startup per ProviderSessionId. Projection rechecks for “still starting” no longer swallow read failures.

Wire-up: New WS methods with auth scopes, server layer composition, and startup hooks for deletion cleanup and the reaper after the effect worker starts.

Reviewed by Cursor Bugbot for commit 0eec832. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b1a1bf39-e72a-4ff4-bbab-b9ad5f9a2ea0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 7, 2026
Comment thread apps/server/src/vcs/WorktreeRevivalService.ts Outdated
Comment thread packages/contracts/src/worktrees.ts Outdated
Comment thread apps/server/src/vcs/GitVcsDriver.ts
Comment thread apps/server/src/vcs/WorktreeService.ts
Comment thread apps/server/src/vcs/WorktreeDeletionCleanup.ts Outdated
Comment thread apps/web/src/components/settings/SourceControlSettings.tsx
Comment thread apps/server/src/vcs/WorktreeRevivalService.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new worktree services against the Effect service conventions. Four convention issues found: two standalone *Shape service interfaces, a redundant singleton operation discriminator plus free-form message on the new worktree error classes, and a hidden optional service dependency in ProviderTurnStartService.

Posted via Macroscope — Effect Service Conventions

Comment thread packages/contracts/src/worktrees.ts Outdated
Comment thread apps/server/src/orchestration-v2/ProviderTurnStartService.ts Outdated
Comment thread apps/server/src/vcs/WorktreeRevivalService.ts Outdated
Comment thread apps/server/src/vcs/WorktreeLifecycle.ts Outdated
Comment thread apps/server/src/vcs/WorktreeService.ts
Comment thread apps/server/src/orchestration-v2/ProviderTurnStartService.ts Outdated
Comment thread apps/server/src/orchestration-v2/ProviderTurnStartService.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review of the worktree management services. Prior findings on WorktreeLifecycle/WorktreeRevivalService shape interfaces, the unstructured worktree error payloads, and the Effect.serviceOption acquisition of WorktreeRevivalService all look addressed. A few smaller convention issues remain.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/vcs/WorktreeReaper.ts Outdated
Comment thread apps/server/src/vcs/WorktreeDeletionCleanup.ts
Comment thread apps/server/src/vcs/WorktreeService.ts Outdated
Comment thread apps/server/src/vcs/GitVcsDriverCore.ts Outdated
Comment thread apps/server/src/vcs/WorktreeDeletionCleanup.ts Outdated
@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch from 25de21d to 0af2a6e Compare August 7, 2026 12:10
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 9, 2026
Comment thread apps/web/src/components/settings/SourceControlSettings.tsx
Comment thread apps/web/src/components/settings/SourceControlSettings.tsx
Comment thread apps/web/src/components/settings/SourceControlSettings.tsx Outdated
@StiensWout
StiensWout force-pushed the t3code/worktree-management-v2 branch from 0f4d58b to 8f7ca24 Compare August 10, 2026 09:10
Comment thread apps/server/src/vcs/WorktreeDeletionCleanup.ts
Comment thread apps/web/src/components/SidebarV2.tsx Outdated
juliusmarminge and others added 15 commits August 10, 2026 17:50
Co-authored-by: codex <codex@users.noreply.github.com>
- Initialize provider as unchecked in a pending state
- Update initial probe message to reflect session-local status
- Type the runtime effect with `Scope`
- Build the ACP session runtime without wrapping it in `Effect.scoped`
- Use strict TurnId and ProviderItemId parsing in Codex session routing
- Decode in-memory stdio chunks in streaming mode to avoid split UTF-8 corruption
- Transfer session-owned scopes into adapter state
- Ensure runtime scopes close on stop and startup failure
- Add regression coverage for scoped lifecycle cleanup
- Close the managed native event logger when the adapter layer tears down
- Make session runtime close idempotent with an atomic closed flag
- Add coverage for flushing thread native logs on shutdown
- Use codex app-server snapshots for auth, models, and skills
- Remove legacy CLI/config discovery paths and related helpers
- Update tests for the new provider status flow
Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: codex <codex@users.noreply.github.com>
- Document the target orchestration graph, IDs, lifecycles, and capability model
- Add Codex app-server probe fixtures and update the probe test harness
- Introduce orchestration v2 service interfaces and error types
- Add replay runtime, fixtures, and integration coverage
- Update shared contracts and probe transcripts

Co-authored-by: codex <codex@users.noreply.github.com>
StiensWout and others added 12 commits August 11, 2026 13:39
Replace the worktree card grid with a divide-y ledger that follows the
settings design conventions: policy controls as standard settings rows,
semantic status badges with count-aware blocker labels, ahead/behind
counters, ticking relative activity times, and house-pattern loading,
error, empty, and removal-in-progress states.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Retry the deletion-cleanup stream's initial sequence lookup through the
existing stream retry instead of falling back to 0, which would replay
every historical thread.deleted event against the current cleanup
policy. Make the project removal dialog reflect the immediate orphan
cleanup policy instead of unconditionally promising worktrees survive.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reset the observed inventory revision and close the prune confirmation
when the primary environment changes, so a stale candidate can't prune
the same path against a different server and the first revision of the
next environment always refreshes the list. Also pluralize the closed
retention select for the 1-day option.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The base branch folded SidebarV2 into Sidebar and moved project removal
into ProjectSettingsPanel, which still used the blocking
api.dialogs.confirm flow. Restore the AlertDialog confirmation with the
mono path line and the cleanup-policy-aware worktree copy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add a worktreeManagement server capability and rework the Worktrees
settings section to render one ledger per connected environment that
advertises it: inventory, cleanup policy, and prune all target the
owning environment, so remote worktrees are manageable from any client.
Environments on older servers are excluded per the version-skew
contract, with a hint when none support it. Per-environment mounting
replaces the primary-switch reset effects.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@StiensWout
StiensWout force-pushed the t3code/worktree-management-v2 branch from 61184a3 to d56b638 Compare August 11, 2026 11:57
@StiensWout StiensWout changed the title [WIP] Manage worktree lifecycle on orchestrator V2 [WIP] feat(worktrees): server-managed worktree lifecycle on orchestrator v2 Aug 11, 2026
@StiensWout StiensWout changed the title [WIP] feat(worktrees): server-managed worktree lifecycle on orchestrator v2 feat(worktrees): server-managed worktree lifecycle on orchestrator v2 Aug 11, 2026
@StiensWout
StiensWout marked this pull request as ready for review August 11, 2026 12:03
Add the base branch's new isOnPullRequestHead field to the
GitWorkflowService test mock that broke the Check job, and shorten the
auto-remove policy description.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: raw git stderr is copied into a new error attribute. Everything flagged in earlier runs (service-shape interfaces, make/layer naming, the single-use mutationError helper, the parseWorktreeBranchPaths shim, structural stages on the new worktree errors, and the hidden WorktreeRevivalService requirement) is resolved in this revision.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/vcs/GitVcsDriver.ts Outdated
Report a constant detail plus stderrLength instead of copying raw git
stderr into the error attribute, matching the listWorkspaces convention
in GitVcsDriverCore.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread apps/server/src/vcs/GitVcsDriver.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the Effect service conventions in this update. Previously flagged items (inline service interfaces, plain make/layer names, structural error stages with derived messages, required WorktreeRevivalService acquisition in ProviderTurnStartService, shared worktree porcelain parser, bounded git worktree list error context) all look resolved. One remaining error-modeling nit below.

Posted via Macroscope — Effect Service Conventions

Comment thread packages/contracts/src/worktrees.ts Outdated
Comment thread apps/server/src/vcs/WorktreeService.ts
Comment thread apps/server/src/orchestration-v2/ProviderTurnStartService.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

Diff is too large for automated approval analysis. A human reviewer should evaluate this PR.

You can customize Macroscope's approvability policy. Learn more.

- Recheck thread linkage on a fresh shell snapshot immediately before
  removing a worktree; thread linking does not take the mutation permit,
  so the inventory snapshot alone could miss a just-linked thread.
- Keep the provider session restart atomic: once startup closes a shared
  session for a revival or generation change, always reopen it instead
  of bailing when the attempt left "starting".
- Drop `-z` from `git worktree list --porcelain` (needs Git 2.36; Ubuntu
  22.04 ships 2.34) and parse both porcelain formats.
- Make WorktreeInventoryError.cause required; every stage wraps a real
  failure, matching the sibling VCS boundary errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread apps/server/src/vcs/WorktreeService.ts

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on the new GitVcsDriver.listWorkspaces truncation error: its context fields are hardcoded/fabricated rather than derived from the actual command and output.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/vcs/GitVcsDriver.ts Outdated
StiensWout and others added 2 commits August 11, 2026 14:36
Report the real argument count and the observed truncated stdout length
instead of hardcoded values in the listWorkspaces output-limit error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0eec832. Configure here.

// After closing for restart, the reopen must happen even if this
// attempt just left "starting": the session can be shared, and
// bailing here would strand sibling threads without a runtime.
if (!closedForRestart && !(yield* isCurrentAttemptInStatus("starting"))) return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cancelled restart still loads thread

Medium Severity

After closedForRestart, open and the generation update correctly continue even when the attempt left "starting", but there is no matching gate before ensureThread / resumeThread / handoff writes. A superseded attempt can still mutate the shared provider session and emit handoff events before the later "starting" check returns.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0eec832. Configure here.

const listWorkspaces: GitVcsDriver.GitVcsDriver["Service"]["listWorkspaces"] = Effect.fn(
"GitVcsDriver.listWorkspaces",
)(function* (cwd) {
const args = ["worktree", "list", "--porcelain"] as const;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

listRefs still requests -z

Medium Severity

This change drops -z from listWorkspaces and documents that the codebase no longer requests it for Git 2.34 compatibility, but listRefs still runs git worktree list --porcelain -z. On Ubuntu 22.04 Git that call fails soft and clears worktree path associations on refs.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0eec832. Configure here.

@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch from 72e3863 to a186d64 Compare August 11, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants