Skip to content

Run draft-thread project scripts from resolved project/worktree cwd#1178

Merged
juliusmarminge merged 6 commits intomainfrom
t3code/fix-draft-thread-script-cwd
Mar 24, 2026
Merged

Run draft-thread project scripts from resolved project/worktree cwd#1178
juliusmarminge merged 6 commits intomainfrom
t3code/fix-draft-thread-script-cwd

Conversation

@juliusmarminge
Copy link
Member

@juliusmarminge juliusmarminge commented Mar 17, 2026

Summary

  • Fix project script execution in draft threads by resolving cwd through a shared projectScriptCwd helper.
  • Allow script runs from local draft threads without requiring a server-thread-only guard.
  • Use the resolved cwd consistently for terminal/script actions and the “Open in…” cwd value in ChatView.
  • Add coverage for cwd resolution helper behavior and browser-level ChatView flows for both local and worktree draft threads.
  • Regenerate mockServiceWorker.js (MSW package version bump) and include updated Vitest attachment artifact.

Testing

  • apps/web/src/projectScripts.test.ts: verifies projectScriptCwd prefers worktreePath and falls back to project cwd.
  • apps/web/src/components/ChatView.browser.tsx: verifies terminalOpen for local draft thread uses cwd: /repo/project and env includes T3CODE_PROJECT_ROOT.
  • apps/web/src/components/ChatView.browser.tsx: verifies worktree draft thread uses cwd: /repo/worktrees/feature-draft and env includes both T3CODE_PROJECT_ROOT and T3CODE_WORKTREE_PATH.
  • apps/web/src/components/ChatView.browser.tsx: verifies script command dispatch (terminalWrite) sends the expected command (bun run lint\r).
  • Not run: bun fmt, bun lint, bun typecheck.

Note

Medium Risk
Changes how project scripts and “Open in…” resolve cwd and removes a guard that blocked script runs on local draft threads, which could affect terminal execution behavior across thread types. Also consolidates draft-clearing to delete composer drafts and revoke image preview URLs, so regressions could impact draft persistence and attachments.

Overview
Project scripts and related actions now resolve their execution directory via a new projectScriptCwd helper, preferring worktreePath when present and falling back to the project cwd; ChatView uses this consistently (including the header “Open in…” cwd).

The script runner no longer blocks execution on non-server (local draft) threads, and new browser tests assert terminalOpen/terminalWrite behavior for both local-draft and worktree-draft threads.

Draft cleanup is consolidated into clearDraftThread (replacing clearThreadDraft), which now also clears composer drafts and revokes image preview URLs; isTerminalFocused is updated to ignore detached xterm helper elements with new unit tests, and .gitignore adds .tanstack.

Written by Cursor Bugbot for commit d7dea68. This will update automatically on new commits. Configure here.

Note

Run project scripts from draft threads using resolved project/worktree cwd

  • Adds projectScriptCwd in projectScripts.ts to resolve the execution cwd for project scripts, preferring worktreePath when set, otherwise using the project's cwd.
  • Removes the guard in ChatView.runProjectScript that blocked script execution on non-server (local draft) threads, allowing scripts to run from both local and worktree-backed draft threads.
  • Consolidates draft-clearing logic into clearDraftThread in composerDraftStore.ts, which now also clears the composer draft and revokes image preview URLs.
  • Fixes isTerminalFocused to return false for detached xterm helper textareas.
  • Behavioral Change: project scripts on draft threads now execute with T3CODE_PROJECT_ROOT (and T3CODE_WORKTREE_PATH for worktrees) set in the terminal environment.

Macroscope summarized d7dea68.

@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

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

Run ID: bce76415-9b85-4eff-bfcf-66d2395d92f3

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/fix-draft-thread-script-cwd

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

@github-actions github-actions bot added size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Mar 17, 2026
@juliusmarminge juliusmarminge force-pushed the t3code/fix-draft-thread-script-cwd branch from b06a638 to 1caf2db Compare March 17, 2026 23:41
- use shared `projectScriptCwd` to choose worktree path or project root
- allow script execution from local draft threads with correct terminal env/cwd
- add ChatView and helper tests covering local and worktree draft cases
- Treat detached `xterm-helper-textarea` nodes as unfocused in `isTerminalFocused`
- Add unit tests for connected vs detached terminal focus behavior
- Harden ChatView shortcut test flow by waiting for keybindings/config and retrying route transition
@juliusmarminge juliusmarminge force-pushed the t3code/fix-draft-thread-script-cwd branch from 1caf2db to 6fe2331 Compare March 24, 2026 07:47
@github-actions github-actions bot added size:S 10-29 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Mar 24, 2026
- Remove draft prompt state alongside draft thread cleanup
- Update tests for terminal context removal and new-thread shortcut
@github-actions github-actions bot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Mar 24, 2026
- Clean up existing draft image object URLs when a thread is removed
- Prevent stale preview URLs from leaking after draft-thread resets
Copy link
Contributor

@cursor cursor bot left a comment

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 and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: clearDraftThread is now identical to clearThreadDraft
    • Removed the duplicate clearThreadDraft method and its type declaration, and updated the single production caller in Sidebar.tsx to use clearDraftThread instead.

Create PR

Or push these changes by commenting:

@cursor push e0d6b2ab71
Preview (e0d6b2ab71)
diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx
--- a/apps/web/src/components/Sidebar.tsx
+++ b/apps/web/src/components/Sidebar.tsx
@@ -258,7 +258,7 @@
   const markThreadUnread = useStore((store) => store.markThreadUnread);
   const toggleProject = useStore((store) => store.toggleProject);
   const reorderProjects = useStore((store) => store.reorderProjects);
-  const clearComposerDraftForThread = useComposerDraftStore((store) => store.clearThreadDraft);
+  const clearComposerDraftForThread = useComposerDraftStore((store) => store.clearDraftThread);
   const getDraftThreadByProjectId = useComposerDraftStore(
     (store) => store.getDraftThreadByProjectId,
   );

diff --git a/apps/web/src/composerDraftStore.ts b/apps/web/src/composerDraftStore.ts
--- a/apps/web/src/composerDraftStore.ts
+++ b/apps/web/src/composerDraftStore.ts
@@ -219,7 +219,6 @@
     attachments: PersistedComposerImageAttachment[],
   ) => void;
   clearComposerContent: (threadId: ThreadId) => void;
-  clearThreadDraft: (threadId: ThreadId) => void;
 }
 
 const EMPTY_PROVIDER_MODEL_OPTIONS = Object.freeze<ProviderModelOptions>({});
@@ -1748,41 +1747,6 @@
           return { draftsByThreadId: nextDraftsByThreadId };
         });
       },
-      clearThreadDraft: (threadId) => {
-        if (threadId.length === 0) {
-          return;
-        }
-        const existing = get().draftsByThreadId[threadId];
-        if (existing) {
-          for (const image of existing.images) {
-            revokeObjectPreviewUrl(image.previewUrl);
-          }
-        }
-        set((state) => {
-          const hasComposerDraft = state.draftsByThreadId[threadId] !== undefined;
-          const hasDraftThread = state.draftThreadsByThreadId[threadId] !== undefined;
-          const hasProjectMapping = Object.values(state.projectDraftThreadIdByProjectId).includes(
-            threadId,
-          );
-          if (!hasComposerDraft && !hasDraftThread && !hasProjectMapping) {
-            return state;
-          }
-          const { [threadId]: _removedComposerDraft, ...restComposerDraftsByThreadId } =
-            state.draftsByThreadId;
-          const { [threadId]: _removedDraftThread, ...restDraftThreadsByThreadId } =
-            state.draftThreadsByThreadId;
-          const nextProjectDraftThreadIdByProjectId = Object.fromEntries(
-            Object.entries(state.projectDraftThreadIdByProjectId).filter(
-              ([, draftThreadId]) => draftThreadId !== threadId,
-            ),
-          ) as Record<ProjectId, ThreadId>;
-          return {
-            draftsByThreadId: restComposerDraftsByThreadId,
-            draftThreadsByThreadId: restDraftThreadsByThreadId,
-            projectDraftThreadIdByProjectId: nextProjectDraftThreadIdByProjectId,
-          };
-        });
-      },
     }),
     {
       name: COMPOSER_DRAFT_STORAGE_KEY,

@juliusmarminge
Copy link
Member Author

@cursor push e0d6b2a

clearThreadDraft was functionally identical to clearDraftThread after recent
changes. Remove the duplicate and update the single production caller in
Sidebar.tsx to use clearDraftThread instead.

Applied via @cursor push command
@juliusmarminge juliusmarminge merged commit 1371ce2 into main Mar 24, 2026
9 of 10 checks passed
@juliusmarminge juliusmarminge deleted the t3code/fix-draft-thread-script-cwd branch March 24, 2026 08:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 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.

2 participants