Skip to content

Merge upstream: Move worktree bootstrap to server and persist terminal launch context (#1518)#45

Merged
aaditagrawal merged 2 commits intomainfrom
merge/upstream-1518-worktree-bootstrap
Apr 5, 2026
Merged

Merge upstream: Move worktree bootstrap to server and persist terminal launch context (#1518)#45
aaditagrawal merged 2 commits intomainfrom
merge/upstream-1518-worktree-bootstrap

Conversation

@aaditagrawal
Copy link
Copy Markdown
Owner

@aaditagrawal aaditagrawal commented Apr 4, 2026

What

Cherry-picks upstream commit 8515f027 (PR #1518) onto the fork.

Upstream changes

  1. Worktree bootstrap moved server-side — Thread creation, worktree preparation, and setup script execution now happen atomically on the server via a bootstrap payload in thread.turn.start, eliminating client-side race conditions.

  2. New ProjectSetupScriptRunner service — Effect service that runs project setup scripts (e.g. bun install) in a terminal for a given thread/worktree.

  3. Terminal launch context persistenceterminalStateStore now tracks terminalLaunchContextByThreadId for correct working directory even before server thread metadata settles. projectScriptCwd and projectScriptRuntimeEnv moved to packages/shared.

Conflict resolution

  • CheckpointStore.test.ts — Both sides reduced lineCount; took upstream value (5,000).
  • packages/contracts/src/git.ts — Kept both: upstream's ThreadId import + fork's ProviderKind import.
  • ChatView.tsx — Merged upstream's bootstrap/launchContext changes with fork's multi-provider model options, split-limit guard, and per-thread terminal visibility.

Verification

  • bun typecheck passes (all 7 packages)
  • bun fmt clean
  • bun lint clean (0 errors, 20 pre-existing warnings)
  • All cherry-pick-affected tests pass (server.test.ts, ProjectSetupScriptRunner, Manager, CheckpointStore, web tests)
  • Pre-existing flaky test (MessagesTimeline timeout under full suite load) unrelated to this change

Summary by CodeRabbit

  • New Features

    • Optional project setup scripts can run automatically when preparing PR worktrees (starts terminals to run init commands).
    • Terminal sessions now preserve and surface worktree context so terminals open with correct cwd/worktree.
    • Thread bootstrap payloads support structured prepare/create instructions for safer, resumable initialization.
  • Bug Fixes / Reliability

    • Improved bootstrap error handling and cleanup to avoid orphaned threads and record setup lifecycle events.

…text (pingdotgg#1518)

Co-authored-by: codex <codex@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 88340d99-09cf-445e-bc9a-99ed89112b2e

📥 Commits

Reviewing files that changed from the base of the PR and between c9f2584 and b329139.

📒 Files selected for processing (4)
  • apps/server/src/project/Layers/ProjectSetupScriptRunner.ts
  • apps/server/src/terminal/Layers/Manager.ts
  • apps/web/src/components/ChatView.tsx
  • apps/web/src/components/ThreadTerminalDrawer.tsx
✅ Files skipped from review due to trivial changes (1)
  • apps/server/src/terminal/Layers/Manager.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/src/components/ThreadTerminalDrawer.tsx

📝 Walkthrough

Walkthrough

Adds a ProjectSetupScriptRunner service and bootstrapped worktree flow: web client sends bootstrap payload, server prepares worktrees, invokes setup scripts via a terminal manager, records setup activity, and updates contracts/state to track per-worktree paths. Tests and schemas updated accordingly.

Changes

Cohort / File(s) Summary
Project setup runner (types, impl, tests)
apps/server/src/project/Services/ProjectSetupScriptRunner.ts, apps/server/src/project/Layers/ProjectSetupScriptRunner.ts, apps/server/src/project/Layers/ProjectSetupScriptRunner.test.ts, packages/shared/src/projectScripts.ts, packages/shared/package.json
Added ProjectSetupScriptRunner interface, live Layer implementation, and tests; moved project script helpers to shared package.
Git manager integration & tests
apps/server/src/git/Layers/GitManager.ts, apps/server/src/git/Layers/GitManager.test.ts
Wired ProjectSetupScriptRunner into preparePullRequestThread; runs setup script on PR worktree creation, logs/suppresses failures; updated tests to cover runner invocation and failure cases.
WebSocket bootstrap & orchestration
apps/server/src/ws.ts, packages/contracts/src/orchestration.ts, packages/contracts/src/orchestration.test.ts
Added bootstrap payload for thread.turn.start, dispatch path for bootstrap, setup-script activity recording, error normalization, and cleanup on bootstrap failure; schema extended for bootstrap.
Terminal contract + manager changes
packages/contracts/src/terminal.ts, packages/contracts/src/terminal.test.ts, apps/server/src/terminal/Services/Manager.ts, apps/server/src/terminal/Layers/Manager.ts, apps/server/src/terminal/Layers/Manager.test.ts
Added optional worktreePath to TerminalOpen/Restart inputs and snapshot; terminal manager/state carry worktreePath through lifecycle and tests updated to assert preservation.
Web client: bootstrap, launch context, state
apps/web/src/components/ChatView.tsx, apps/web/src/components/ChatView.browser.tsx, apps/web/src/components/ThreadTerminalDrawer.tsx, apps/web/src/components/PullRequestThreadDialog.tsx, apps/web/src/lib/gitReactQuery.ts, apps/web/src/terminalStateStore.ts, apps/web/src/terminalStateStore.test.ts, apps/web/src/routes/__root.tsx
Introduced TerminalLaunchContext and terminalLaunchContext store slice; changed message-send to include bootstrap payload and removed local setup scheduling; threaded worktreePath through terminal open calls; updated PR dialog to accept threadId.
Server runtime composition & tests
apps/server/src/server.ts, apps/server/src/server.test.ts
Added ProjectSetupScriptRunnerLive into runtime chain and refactored runtime layer composition; extended server tests with mocked setup-runner and multiple bootstrap integration tests.
Prepare PR input & small fixes
packages/contracts/src/git.ts, apps/server/src/checkpointing/Layers/CheckpointStore.test.ts, apps/web/src/projectScripts.ts, apps/web/src/projectScripts.test.ts, apps/web/src/terminalActivity.test.ts
Added optional threadId to prepare PR input schema; adjusted large-diff test lineCount expectation; moved project script helpers to shared; updated terminal snapshot test fixtures to include worktreePath: null.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Web Client
    participant WS as WebSocket Server
    participant Git as GitManager
    participant Setup as ProjectSetupScriptRunner
    participant Term as TerminalManager
    participant Orch as Orchestration Engine

    Client->>WS: dispatchCommand(thread.turn.start { bootstrap })
    WS->>Git: preparePullRequestThread(..., threadId?)
    Git->>Git: create worktree (if needed)
    Git->>Setup: runForThread(threadId, worktreePath)
    Setup->>Orch: load project/read-model to resolve script
    Setup->>Term: open(threadId, terminalId, cwd, env)
    Term-->>Setup: started
    Setup-->>Git: result { status: "started" | "no-script" }
    WS->>Orch: thread.activity.append("setup-script.*")
    WS->>Orch: thread.turn.start (bootstrap cleared)
    Orch-->>WS: processed
    WS-->>Client: RPC response + events
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I hopped through branches, spun a thread,
Opened a terminal where setup led,
Bun install tapped its little key—
Worktree ready, scripts run free,
A tiny rabbit claps with joy and spread!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main changes: moving worktree bootstrap to the server and persisting terminal launch context, with a reference to the upstream PR.
Description check ✅ Passed The description follows the template structure with 'What' and 'Why' sections. It explains the upstream changes, conflict resolution, and verification steps performed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch merge/upstream-1518-worktree-bootstrap

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 and usage tips.

@github-actions github-actions bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ effective changed lines (test files excluded in mixed PRs). labels Apr 4, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
apps/server/src/terminal/Layers/Manager.ts (2)

1648-1702: ⚠️ Potential issue | 🟠 Major

Worktree metadata is not updated for already-running sessions when only context changes.

If cwd and env are unchanged, open() returns without applying a newly provided worktreePath, so session snapshots/events can keep stale context.

💡 Proposed fix
           const liveSession = existing.value;
           const nextRuntimeEnv = normalizedRuntimeEnv(input.env);
           const currentRuntimeEnv = liveSession.runtimeEnv;
+          const nextWorktreePath =
+            input.worktreePath === undefined ? liveSession.worktreePath : input.worktreePath ?? null;
           const targetCols = input.cols ?? liveSession.cols;
           const targetRows = input.rows ?? liveSession.rows;
           const runtimeEnvChanged = !Equal.equals(currentRuntimeEnv, nextRuntimeEnv);
+          const worktreePathChanged = liveSession.worktreePath !== nextWorktreePath;

           if (liveSession.cwd !== input.cwd || runtimeEnvChanged) {
             yield* stopProcess(liveSession);
             liveSession.cwd = input.cwd;
-            liveSession.worktreePath = input.worktreePath ?? null;
+            liveSession.worktreePath = nextWorktreePath;
             liveSession.runtimeEnv = nextRuntimeEnv;
             liveSession.history = "";
             ...
           } else if (liveSession.status === "exited" || liveSession.status === "error") {
             liveSession.runtimeEnv = nextRuntimeEnv;
-            liveSession.worktreePath = input.worktreePath ?? null;
+            liveSession.worktreePath = nextWorktreePath;
             liveSession.history = "";
             ...
+          } else if (worktreePathChanged) {
+            liveSession.worktreePath = nextWorktreePath;
+            liveSession.updatedAt = new Date().toISOString();
           }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/server/src/terminal/Layers/Manager.ts` around lines 1648 - 1702, The
code currently returns a snapshot without updating worktree metadata when cwd
and runtime env are unchanged, so ensure the session's worktreePath is updated
from input.worktreePath even for already-running sessions: update
liveSession.worktreePath = input.worktreePath ?? null (and set updatedAt if you
track it) before the early return that calls snapshot(liveSession), and call
persistHistory if your state-change invariants require it; refer to
liveSession.worktreePath, input.worktreePath, snapshot(liveSession),
startSession, and persistHistory to locate where to apply the change.

1808-1830: ⚠️ Potential issue | 🟠 Major

restart() drops existing worktree context when worktreePath is omitted.

Current logic coerces omitted worktreePath to null, so restart calls that don’t pass this field clear previously persisted metadata.

💡 Proposed fix
         } else {
           session = existingSession.value;
           yield* stopProcess(session);
           session.cwd = input.cwd;
-          session.worktreePath = input.worktreePath ?? null;
+          session.worktreePath =
+            input.worktreePath === undefined ? session.worktreePath : input.worktreePath ?? null;
           session.runtimeEnv = normalizedRuntimeEnv(input.env);
         }

         ...
         yield* startSession(
           session,
           {
             threadId: input.threadId,
             terminalId,
             cwd: input.cwd,
-            ...(input.worktreePath !== undefined ? { worktreePath: input.worktreePath } : {}),
+            worktreePath: session.worktreePath,
             cols,
             rows,
             ...(input.env ? { env: input.env } : {}),
           },
           "restarted",
         );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/server/src/terminal/Layers/Manager.ts` around lines 1808 - 1830, The
restart logic unconditionally sets session.worktreePath to null when
input.worktreePath is omitted; change the assignment so session.worktreePath is
only updated when input.worktreePath is provided. Replace the line using the
nullish-coalescing (session.worktreePath = input.worktreePath ?? null) with a
conditional update (e.g. if (input.worktreePath !== undefined)
session.worktreePath = input.worktreePath) so existing worktree context is
preserved; adjust within the same restart flow where session.runtimeEnv is set
if needed.
apps/web/src/components/ThreadTerminalDrawer.tsx (1)

629-640: ⚠️ Potential issue | 🟠 Major

worktreePath is not included in the effect dependency list, preventing session reinitialization when the path changes.

The openTerminal() function passes worktreePath to api.terminal.open(), but the enclosing effect dependency list at line 723 is [cwd, runtimeEnv, terminalId, threadId]worktreePath is absent. ChatView can supply a new worktreePath through launchContext after mount, and the TerminalManager.open method explicitly reuses the existing session for the same threadId/terminalId. When worktreePath changes, the effect doesn't re-run, so the updated path never reaches the live terminal.

Add worktreePath to the dependency list, or implement an explicit close/reopen mechanism when the path changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/ThreadTerminalDrawer.tsx` around lines 629 - 640, The
effect that calls openTerminal (which invokes api.terminal.open with
worktreePath) omits worktreePath from its dependency list causing the terminal
session not to reinitialize when worktreePath changes; update the effect
dependencies to include worktreePath so the effect reruns and passes the new
value to api.terminal.open, or alternatively detect worktreePath changes (using
props/launchContext) and call the TerminalManager.close/open sequence for the
current threadId/terminalId to force a reopen with the new worktreePath
(referencing openTerminal, api.terminal.open, and TerminalManager.open/close).
🧹 Nitpick comments (2)
apps/server/src/checkpointing/Layers/CheckpointStore.test.ts (1)

118-118: Avoid hardcoded last-line marker in assertion.

Line 118 is correct now, but this literal is brittle if lineCount changes again. Consider deriving it from the same source of truth.

♻️ Proposed tweak
+        const lineCount = 5_000;
-        yield* writeTextFile(path.join(tmp, "README.md"), buildLargeText());
+        yield* writeTextFile(path.join(tmp, "README.md"), buildLargeText(lineCount));
         yield* checkpointStore.captureCheckpoint({
           cwd: tmp,
           checkpointRef: toCheckpointRef,
         });
@@
-        expect(diff).toContain("+line 04999");
+        expect(diff).toContain(`+line ${String(lineCount - 1).padStart(5, "0")}`);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/server/src/checkpointing/Layers/CheckpointStore.test.ts` at line 118,
Replace the brittle hardcoded assertion expect(diff).toContain("+line 04999")
with a value computed from the same source of truth (the lineCount used to
generate the diff). In the CheckpointStore.test.ts test, compute the expected
last-line marker from lineCount (e.g., use lineCount - 1 and apply the same
zero-padding/formatting used when building the diff) and assert
expect(diff).toContain(expectedLastLine) so the test stays correct when
lineCount changes; locate the assertion that references diff and lineCount and
replace the literal with the derived expectedLastLine.
apps/web/src/terminalStateStore.ts (1)

604-624: Logic is correct but could be clearer.

The interplay between lines 610-616 and 617-619 is correct but subtle. The normalizeThreadTerminalState call at line 623 will fix any inconsistencies if the restored activeTerminalGroupId becomes invalid after newThreadTerminal modifies the groups.

Consider simplifying to make intent explicit:

♻️ Optional: Clearer active handling
 ensureTerminal: (threadId, terminalId, options) =>
   updateTerminal(threadId, (state) => {
     let nextState = state;
     if (!state.terminalIds.includes(terminalId)) {
       nextState = newThreadTerminal(nextState, terminalId);
     }
-    if (options?.active === false) {
-      nextState = {
-        ...nextState,
-        activeTerminalId: state.activeTerminalId,
-        activeTerminalGroupId: state.activeTerminalGroupId,
-      };
-    }
-    if (options?.active ?? true) {
+    const shouldActivate = options?.active ?? true;
+    if (shouldActivate) {
       nextState = setThreadActiveTerminal(nextState, terminalId);
+    } else {
+      // Preserve original active terminal when active: false
+      nextState = {
+        ...nextState,
+        activeTerminalId: state.activeTerminalId,
+        activeTerminalGroupId: state.activeTerminalGroupId,
+      };
     }
     if (options?.open) {
       nextState = setThreadTerminalOpen(nextState, true);
     }
     return normalizeThreadTerminalState(nextState);
   }),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/terminalStateStore.ts` around lines 604 - 624, The
ensureTerminal update is subtle: newThreadTerminal may change group structure
then later code tries to preserve or set active IDs; make this explicit by
capturing the original activeTerminalId and activeTerminalGroupId from the
incoming state before any mutations, then apply newThreadTerminal, then if
options?.active === false restore those captured IDs onto nextState, else if
options?.active ?? true call setThreadActiveTerminal(nextState, terminalId);
finally apply setThreadTerminalOpen if needed and call
normalizeThreadTerminalState; reference ensureTerminal, updateTerminal,
newThreadTerminal, setThreadActiveTerminal, setThreadTerminalOpen, and
normalizeThreadTerminalState to locate where to implement the fix.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/server/src/project/Layers/ProjectSetupScriptRunner.ts`:
- Around line 18-25: The current project resolution assigns to the variable
project by preferring input.projectId over input.projectCwd, which silently
permits mismatched selectors; modify the resolution in
ProjectSetupScriptRunner.ts so that if both input.projectId and input.projectCwd
are provided you resolve each against readModel.projects (using the same find
logic) and compare their ids/workspaceRoot — if they refer to different projects
throw a clear error (or reject) indicating conflicting selectors; allow the flow
to continue only if a single selector is provided or both resolve to the same
project.

In `@apps/web/src/components/ChatView.tsx`:
- Around line 2535-2546: The effect currently clears persisted launch context
whenever activeThreadId is falsy, which wipes
terminalLaunchContextByThreadId[threadId] during hydration; change the logic in
the useEffect that updates setTerminalLaunchContext so it does not call
storeClearTerminalLaunchContext(threadId) when activeThreadId is null/undefined
during hydration—only clear the persisted context when there is an actual thread
switch (i.e., when the current terminal launch context exists, current.threadId
!== activeThreadId, and activeThreadId is non-null/truthy). Keep references to
useEffect, setTerminalLaunchContext, storeClearTerminalLaunchContext,
activeThreadId, threadId, and the terminal launch context "current" to locate
and implement this conditional.

---

Outside diff comments:
In `@apps/server/src/terminal/Layers/Manager.ts`:
- Around line 1648-1702: The code currently returns a snapshot without updating
worktree metadata when cwd and runtime env are unchanged, so ensure the
session's worktreePath is updated from input.worktreePath even for
already-running sessions: update liveSession.worktreePath = input.worktreePath
?? null (and set updatedAt if you track it) before the early return that calls
snapshot(liveSession), and call persistHistory if your state-change invariants
require it; refer to liveSession.worktreePath, input.worktreePath,
snapshot(liveSession), startSession, and persistHistory to locate where to apply
the change.
- Around line 1808-1830: The restart logic unconditionally sets
session.worktreePath to null when input.worktreePath is omitted; change the
assignment so session.worktreePath is only updated when input.worktreePath is
provided. Replace the line using the nullish-coalescing (session.worktreePath =
input.worktreePath ?? null) with a conditional update (e.g. if
(input.worktreePath !== undefined) session.worktreePath = input.worktreePath) so
existing worktree context is preserved; adjust within the same restart flow
where session.runtimeEnv is set if needed.

In `@apps/web/src/components/ThreadTerminalDrawer.tsx`:
- Around line 629-640: The effect that calls openTerminal (which invokes
api.terminal.open with worktreePath) omits worktreePath from its dependency list
causing the terminal session not to reinitialize when worktreePath changes;
update the effect dependencies to include worktreePath so the effect reruns and
passes the new value to api.terminal.open, or alternatively detect worktreePath
changes (using props/launchContext) and call the TerminalManager.close/open
sequence for the current threadId/terminalId to force a reopen with the new
worktreePath (referencing openTerminal, api.terminal.open, and
TerminalManager.open/close).

---

Nitpick comments:
In `@apps/server/src/checkpointing/Layers/CheckpointStore.test.ts`:
- Line 118: Replace the brittle hardcoded assertion
expect(diff).toContain("+line 04999") with a value computed from the same source
of truth (the lineCount used to generate the diff). In the
CheckpointStore.test.ts test, compute the expected last-line marker from
lineCount (e.g., use lineCount - 1 and apply the same zero-padding/formatting
used when building the diff) and assert expect(diff).toContain(expectedLastLine)
so the test stays correct when lineCount changes; locate the assertion that
references diff and lineCount and replace the literal with the derived
expectedLastLine.

In `@apps/web/src/terminalStateStore.ts`:
- Around line 604-624: The ensureTerminal update is subtle: newThreadTerminal
may change group structure then later code tries to preserve or set active IDs;
make this explicit by capturing the original activeTerminalId and
activeTerminalGroupId from the incoming state before any mutations, then apply
newThreadTerminal, then if options?.active === false restore those captured IDs
onto nextState, else if options?.active ?? true call
setThreadActiveTerminal(nextState, terminalId); finally apply
setThreadTerminalOpen if needed and call normalizeThreadTerminalState; reference
ensureTerminal, updateTerminal, newThreadTerminal, setThreadActiveTerminal,
setThreadTerminalOpen, and normalizeThreadTerminalState to locate where to
implement the fix.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 662d575c-7c2d-4bd3-a512-c609c941c490

📥 Commits

Reviewing files that changed from the base of the PR and between 24b27a0 and c9f2584.

📒 Files selected for processing (30)
  • apps/server/src/checkpointing/Layers/CheckpointStore.test.ts
  • apps/server/src/git/Layers/GitManager.test.ts
  • apps/server/src/git/Layers/GitManager.ts
  • apps/server/src/project/Layers/ProjectSetupScriptRunner.test.ts
  • apps/server/src/project/Layers/ProjectSetupScriptRunner.ts
  • apps/server/src/project/Services/ProjectSetupScriptRunner.ts
  • apps/server/src/server.test.ts
  • apps/server/src/server.ts
  • apps/server/src/terminal/Layers/Manager.test.ts
  • apps/server/src/terminal/Layers/Manager.ts
  • apps/server/src/terminal/Services/Manager.ts
  • apps/server/src/ws.ts
  • apps/web/src/components/ChatView.browser.tsx
  • apps/web/src/components/ChatView.tsx
  • apps/web/src/components/PullRequestThreadDialog.tsx
  • apps/web/src/components/ThreadTerminalDrawer.tsx
  • apps/web/src/lib/gitReactQuery.ts
  • apps/web/src/projectScripts.test.ts
  • apps/web/src/projectScripts.ts
  • apps/web/src/routes/__root.tsx
  • apps/web/src/terminalActivity.test.ts
  • apps/web/src/terminalStateStore.test.ts
  • apps/web/src/terminalStateStore.ts
  • packages/contracts/src/git.ts
  • packages/contracts/src/orchestration.test.ts
  • packages/contracts/src/orchestration.ts
  • packages/contracts/src/terminal.test.ts
  • packages/contracts/src/terminal.ts
  • packages/shared/package.json
  • packages/shared/src/projectScripts.ts
💤 Files with no reviewable changes (1)
  • apps/web/src/projectScripts.ts

…guard, conflicting selectors, and dependency fix

- ProjectSetupScriptRunner: validate that projectId and projectCwd resolve to
  the same project when both are provided
- ChatView: only clear terminal launch context on actual thread switch, not
  during hydration when activeThreadId is falsy
- Terminal Manager open(): update worktreePath for already-running sessions
  even when cwd/env are unchanged
- Terminal Manager restart(): preserve existing worktreePath when input omits it
- ThreadTerminalDrawer: add worktreePath to effect dependency list so terminal
  reinitializes when the path changes
@aaditagrawal aaditagrawal merged commit 54fdcd2 into main Apr 5, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ effective changed lines (test files excluded in mixed PRs). 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.

2 participants