Skip to content

feat(mcp): launch a top-level thread with an explicit workspace choice - #2276

Merged
chuks-qua merged 3 commits into
mainfrom
feat/issue-2214
Oct 21, 2026
Merged

chuks-qua merged 3 commits into
mainfrom
feat/issue-2214

Conversation

@chuks-qua

@chuks-qua chuks-qua commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

Before this change, an agent had no way to start an ordinary top-level thread for the user. It could only delegate child work with delegate_task, which makes a hidden Delegated thread in the caller's checkout or a new worktree at the caller's commit.

The Mcode MCP server now has a thread_launch tool. It starts a visible, user-owned thread in a workspace the agent names:

thread_launch({ title, prompt, workspace?, providerId?, modelId?, permissionMode?, interactionMode? })
  workspace omitted or {type:"root"}            -> project root on its current branch
  {type:"new_worktree", baseRef}                -> new worktree at the local branch's commit
  {type:"new_worktree", baseRef, startFromOrigin:true}
                                                -> fetch origin first, new worktree at origin's commit
  {type:"existing_worktree", worktreePath, baseBranch?}
                                                -> attach one of the project's worktrees
  -> { status:"launched", threadId } | { status:"rejected", error }
ThreadLaunchService.launch
  read source thread                       not_found if missing
  resolveModes                             forbidden if broader than the caller
  resolveTarget                            provider and model default to the caller's
  placement                                invalid_placement for a missing branch or bad worktree
  commands.createAndSend                   same first-turn path as the composer
    worktree creation, then the setup gate, then the first turn

Key choices:

  • The new thread goes through the existing createAndSend path with no delegation lineage and no setup skip. Project setup therefore finishes before the first message runs.
  • For startFromOrigin, the service fetches the origin branch itself and passes the resolved commit. The coordinator's own origin path would block the tool call on a human fetch decision when the fetch fails.
  • The coordinator stays the single owner of existing-worktree validation. Its placement errors are now a typed ExistingWorktreePlacementError with the same messages, so the service can report them as invalid_placement. The check runs before any thread row is written.
  • The permission ceiling is the caller's lease. The interaction ceiling is the source thread's mode, with null treated as Build. Omitted modes inherit the ceiling.
  • The tool description and the Mcode instruction block say to launch only when the user asks for a separate thread or conversation, and to use delegate_task when the result is needed back. An omitted workspace means the project root, not the caller's worktree.
  • The web timeline labels thread_launch rows in plain words, like fix(web): name Mcode thread tools and approvals in plain words #2274.

Closes #2214. Part of #2205.

Why

Users ask agents to "start this in its own conversation" or "spin up a thread on a new worktree from main". Until now the agent could only fake that with a hidden delegated task. thread_launch gives the user a real thread they own and can find in the sidebar, prepared before the agent starts. T3 Code's t3_thread_launch is the reference shape.

UI Changes

A thread_launch call in the chat timeline.

Before After
before after

Review Notes

Verification, run locally:

  • apps/server: thread-launch-service, thread-control-toolkit, mcode-mcp-server, thread-creation-startup and agent-service-existing-worktree tests. 5 files, 124 tests pass.
  • apps/web: tool-row-overflow and approval-receipts tests. 2 files, 116 tests pass.
  • packages/contracts and packages/thread-orchestration targeted tests pass.
  • tsc --noEmit is clean for server and web. bun run lint shows only two existing warnings, in scripts/doctor.mjs and runtime-lifecycle.test.mjs.

The launch tests use a real git fixture with a local branch and a differing origin branch. They cover these cases:

  • A new worktree starts at the local commit, and the first turn waits for setup.
  • startFromOrigin starts at origin's commit.
  • An unknown local branch and a branch missing on origin are rejected without inserting a thread.
  • A registered worktree is attached, and an arbitrary directory or the repository root is rejected.
  • Broader modes and a Supervised new-worktree launch are rejected, and Supervised plus Plan are inherited when omitted.
  • An omitted workspace uses the project root even when the caller runs in a worktree.
  • The thread is visible and has no delegation lineage.

Known gaps:

  • No idempotency key. Two identical calls create two threads. This matches T3 and the issue.
  • Supervised callers cannot launch into a new worktree. Delegation makes a Supervised Coordinator wait for the user's approval before it creates a worktree. thread_launch has no approval flow yet, so it rejects that placement with forbidden instead of bypassing the gate. The root and existing-worktree placements still work. Supporting it later needs a launch approval kind in contracts and approval copy in the web app.
  • Wording gate. The explicit-request wording gate recognizes thread_launch. Its wider scope is tracked in feat: offer Delegation without the wording gate, bounded by a runtime-mode ceiling #2218.

No migrations, config changes, or docs changes.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

Add the thread_launch tool. It starts an ordinary user-owned thread in
the project root, a new worktree from a local or fetched origin branch,
or an existing project worktree. Setup gates the first turn, and the
launched thread cannot run with broader permission or interaction
modes than its caller.

Refs #2214
Delegation makes a supervised Coordinator wait for the user's approval
before it creates a worktree. thread_launch has no approval flow yet, so
it rejects that placement instead of bypassing the gate.

Refs #2214
@chuks-qua
chuks-qua merged commit 46b5079 into main Oct 21, 2026
14 checks passed
@chuks-qua
chuks-qua deleted the feat/issue-2214 branch October 21, 2026 15:29
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.

feat: launch a top-level thread with an explicit workspace choice

1 participant