Skip to content

Threads born committed: local drafts + startThread - #71

Merged
soorya-u merged 4 commits into
mainfrom
issue-67-threads-born-committed
Jul 17, 2026
Merged

Threads born committed: local drafts + startThread#71
soorya-u merged 4 commits into
mainfrom
issue-67-threads-born-committed

Conversation

@soorya-u

@soorya-u soorya-u commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • Controller-local draft route (/d/$draftId) opens without creating a worker thread row; first send runs compound startThread (row → git/worktree → session → prefs → binding → turn).
  • Mid-flight failure after row creation keeps the user message plus thread_error / turn_interrupted; the thread can be bound and prompted again in place.
  • Branch/worktree choices stay local until first send; leaving a draft clears controller-local draft state with no worker cleanup.
  • Draft preference application treats ACP Method not found (e.g. session/set_model) as best-effort so agents that advertise models but lack setters can still bind and prompt.

Closes #67.

Test plan

  • Open a new conversation — no new thread appears in the list on another controller until first send
  • Configure agent/model/branch on a draft, send — lands on a real thread and streams the turn
  • Force a session failure on first send — thread exists with message + error; sending again retries in place
  • Abandon a draft by navigating away — no worker thread/worktree left behind
  • bun test apps/cli/src/core/threads/coordinator.start-thread.test.ts
  • bun run check:types in apps/cli, apps/web, shared/hooks

Summary by CodeRabbit

  • New Features

    • Added local draft workspaces for composing conversations before creating a thread.
    • Start a thread with an initial message, selected agent preferences, branch, and worktree options.
    • Added project-level Git status and branch selection for drafts.
    • Drafts can be launched directly from the project thread explorer.
  • Bug Fixes

    • Improved thread-start recovery and error handling when session setup or Git operations fail.
    • Ensured conversations retain failed messages and display interruption status appropriately.
  • Refactor

    • Improved turn launching and event persistence for more consistent chat updates.

soorya-u and others added 3 commits July 17, 2026 23:22
Opening a conversation is now controller-local; the worker only creates a row, worktree, session, and turn when startThread runs, so abandoned drafts leave no debris (#67).

Co-authored-by: Cursor <cursoragent@cursor.com>
Skip listThreads for controller-local drafts, clear draft UI state on leave, and prove failed startThread threads can bind and prompt again.

Co-authored-by: Cursor <cursoragent@cursor.com>
DraftWorkspace uses Result.tryPromise for startThread; knip requires it as a direct dependency.

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel

vercel Bot commented Jul 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cyrus Ready Ready Preview, Comment Jul 17, 2026 6:57pm

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 06a60c12-2966-4380-b245-c81a641da74f

📥 Commits

Reviewing files that changed from the base of the PR and between 0cee0a7 and 34c1433.

📒 Files selected for processing (6)
  • apps/cli/src/core/threads/coordinator.start-thread.test.ts
  • apps/cli/src/core/threads/coordinator.ts
  • apps/cli/src/core/threads/start-thread.ts
  • apps/cli/src/handlers/controller/turn-emit.ts
  • apps/web/src/components/chat/composer/index.tsx
  • apps/web/src/components/chat/main/draft-workspace.tsx
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/cli/src/handlers/controller/turn-emit.ts
  • apps/web/src/components/chat/composer/index.tsx
  • apps/cli/src/core/threads/start-thread.ts
  • apps/web/src/components/chat/main/draft-workspace.tsx
  • apps/cli/src/core/threads/coordinator.start-thread.test.ts

📝 Walkthrough

Walkthrough

Adds controller-local draft conversations and a compound startThread operation. The flow defers thread creation until first send, supports Git setup and preferences, persists partial failures for retry, and routes turns through shared launch and persistence logic.

Changes

Thread startup and draft workflow

Layer / File(s) Summary
Start-thread contract and orchestration
shared/schemas/src/rtc/threads.ts, shared/connections/src/contracts/controller.ts, apps/cli/src/core/threads/..., shared/constants/src/operation-keys.ts
Adds start-thread schemas and RPC wiring, then creates threads with Git setup, runtime sessions, preferences, binding, locking, and persisted failure events under a project mutex.
Turn launching and event persistence
apps/cli/src/handlers/controller/chat.ts, apps/cli/src/handlers/controller/turn-emit.ts
Moves turn execution into launchTurn and shared emitters that persist, publish, title, lock, and recover turn events.
Start-thread coordinator tests
apps/cli/src/core/threads/coordinator.start-thread.test.ts
Covers startup ordering, worktrees, preferences, partial failures, unsupported model setters, and retry recovery.
Draft state and project Git queries
shared/hooks/src/stores/local-draft.ts, shared/hooks/src/queries/..., shared/hooks/src/agent-catalog/use-agent-catalog.ts
Adds draft-local Git choices, project-scoped Git queries, draft-aware agent selection, and the start-thread mutation hook.
Draft workspace and route flow
apps/web/src/components/chat/..., apps/web/src/components/sidebar/..., apps/web/src/routes/..., apps/web/src/routeTree.gen.ts
Adds the draft route and workspace, navigates new threads to local drafts, and wires draft-specific composer, branch, Git, and header behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

  • Issue 62 — Covers the controller-local draft and compound startThread objectives implemented here.

Possibly related PRs

  • soorya-u/cyrus#23 — Refactors the chat flow toward immediate turn responses and shared event-bus turn handling.
  • soorya-u/cyrus#51 — Modifies the thread-bound draft session lifecycle in the same coordinator area.
  • soorya-u/cyrus#52 — Changes coordinator thread/worktree bootstrapping used by the new startup flow.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly names the two main changes: local drafts and the new startThread flow.
Linked Issues check ✅ Passed The draft route, local state, startThread RPC, retry persistence, and discard flow all align with #67's requirements.
Out of Scope Changes check ✅ Passed The changes stay focused on draft-local chat flow, startThread plumbing, routing, hooks, and tests with no clear unrelated additions.
✨ 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 issue-67-threads-born-committed

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/cli/src/core/threads/coordinator.start-thread.test.ts`:
- Around line 195-228: Update the test setup and mocks used by createCoordinator
to record repository/runtime operation calls, then assert in the “births a
thread with a bound session ready to prompt” test that startup operations occur
in order: createThread, Git setup, createBoundSession, preferences,
bindThreadAgent, and setAgentLocked. Keep the existing final-state and prompt
assertions.

In `@apps/cli/src/core/threads/coordinator.ts`:
- Around line 210-214: Update Coordinator.startThread to serialize the entire
startThreadFn operation with a mutex keyed by projectId or the resolved project
directory. Acquire the project-scoped lock before invoking startThreadFn and
release it after completion, including failures, while preserving the existing
Result return behavior.

In `@apps/cli/src/core/threads/start-thread.ts`:
- Around line 52-84: Update persistFailure to commit the user message, thread
error, and turn_interrupted entries as one atomic operation when supported, and
propagate any persistence failure instead of silently returning after isErr().
Update the retryable-failure flow around the callers of persistFailure so it
does not return Result.ok(...) unless all required conversation entries were
successfully persisted.
- Around line 94-113: Update the worktree flow in the thread-start logic around
createGitWorktree and updateThreadWorktreePath to require a branch whenever
worktree or worktreePath is requested, and persist the path only after
successful creation. If updateThreadWorktreePath fails after creation, remove
the newly created worktree before returning the repository error, while
preserving the existing error mappings.

In `@apps/cli/src/handlers/controller/turn-emit.ts`:
- Around line 143-170: Update the runTurn promise handling in the turn emission
flow to track whether a terminal event has been published. In the rejection
catch, when no terminal event was emitted, call emitTerminal with a
turn_interrupted event before or alongside logging the error; preserve the
existing logging and avoid publishing duplicate interruptions after a terminal
event.

In `@apps/web/src/components/chat/composer/index.tsx`:
- Around line 565-567: Add key={thread.id} to the ComposerBranchToolbar rendered
in the isGitRepo branch so it remounts whenever the thread changes, preventing
workspaceMode state from leaking between threads. Leave the existing props and
conditional rendering unchanged.
🪄 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: 9af4f3c9-aa63-4f10-a9a9-8315d8b874c0

📥 Commits

Reviewing files that changed from the base of the PR and between db0c284 and 0cee0a7.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (21)
  • apps/cli/src/core/threads/coordinator.start-thread.test.ts
  • apps/cli/src/core/threads/coordinator.ts
  • apps/cli/src/core/threads/start-thread.ts
  • apps/cli/src/handlers/controller/chat.ts
  • apps/cli/src/handlers/controller/turn-emit.ts
  • apps/web/package.json
  • apps/web/src/components/chat/composer/composer-branch-toolbar.tsx
  • apps/web/src/components/chat/composer/index.tsx
  • apps/web/src/components/chat/main/draft-workspace.tsx
  • apps/web/src/components/chat/main/thread-header.tsx
  • apps/web/src/components/sidebar/projects/project-thread-explorer.tsx
  • apps/web/src/routeTree.gen.ts
  • apps/web/src/routes/_workspace/workers/$workerId/p/$projectId/d/$draftId/index.tsx
  • shared/connections/src/contracts/controller.ts
  • shared/constants/src/operation-keys.ts
  • shared/hooks/src/agent-catalog/use-agent-catalog.ts
  • shared/hooks/src/queries/use-git.ts
  • shared/hooks/src/queries/use-start-thread.ts
  • shared/hooks/src/stores/local-draft.ts
  • shared/schemas/src/rtc/threads.test.ts
  • shared/schemas/src/rtc/threads.ts

Comment thread apps/cli/src/core/threads/coordinator.start-thread.test.ts
Comment thread apps/cli/src/core/threads/coordinator.ts Outdated
Comment thread apps/cli/src/core/threads/start-thread.ts
Comment thread apps/cli/src/core/threads/start-thread.ts
Comment thread apps/cli/src/handlers/controller/turn-emit.ts
Comment thread apps/web/src/components/chat/composer/index.tsx
Serialize project checkouts, require committed failure entries, clean up orphan worktrees, and emit turn_interrupted on uncaught turn rejection so draft first-send stays retryable and agent-safe.

Co-authored-by: Cursor <cursoragent@cursor.com>
@soorya-u
soorya-u merged commit de31668 into main Jul 17, 2026
9 checks passed
@soorya-u
soorya-u deleted the issue-67-threads-born-committed branch July 17, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Threads born committed: local drafts + startThread

1 participant