Skip to content

fix(runtime): use main project root for MCP preflight on task retry (#515) - #527

Merged
carlospedreira merged 2 commits into
andresharpe:mainfrom
kabaogluemre:fix/515-mcp-preflight-project-root
Jun 25, 2026
Merged

fix(runtime): use main project root for MCP preflight on task retry (#515)#527
carlospedreira merged 2 commits into
andresharpe:mainfrom
kabaogluemre:fix/515-mcp-preflight-project-root

Conversation

@kabaogluemre

Copy link
Copy Markdown
Contributor

Summary

Fixes #515Test-DotbotMcpReadiness crashing with "MCP server exited or returned an empty response" when a task is retried after a failed squash-merge.

Root cause

The standalone preflight MCP process had DOTBOT_PROJECT_ROOT set to the worktree path. On task retry the worktree's .control junction can be stale — teardown/re-creation is not atomic — so the MCP server cannot resolve runtime.json (via <worktree>/.bot/.control/) and exits before the handshake even begins.

Two existing fixes don't cover this case:

Fix

Add an optional -ProjectRoot parameter to Test-DotbotMcpReadiness. When supplied, it is used for DOTBOT_PROJECT_ROOT instead of the worktree path:

$psi.Environment['DOTBOT_PROJECT_ROOT'] = if ($ProjectRoot) { $ProjectRoot } else { $WorktreePath }

The call site now passes the main project root, which always has a stable .control/ directory:

$mcpReady = Test-DotbotMcpReadiness -WorktreePath $worktreePath -ProjectRoot $projectRoot

WorkingDirectory stays the worktree (work happens there); only task-state resolution is redirected to the main root — consistent with #356's intent. Backward compatible: callers that omit -ProjectRoot fall back to the previous worktree behaviour.

Closes #515

Test-DotbotMcpReadiness set DOTBOT_PROJECT_ROOT to the worktree path when
spawning the standalone preflight MCP process. On task retry the worktree's
.control junction can be stale (teardown/re-create is not atomic), so the MCP
server fails to resolve runtime.json and exits before the handshake begins —
the 2-attempt retry loop from andresharpe#479 cannot help because the process dies
pre-handshake.

This also bypassed andresharpe#356: Resolve-ProjectRoot returns DOTBOT_PROJECT_ROOT
verbatim when set, skipping git-common-dir detection entirely.

Add an optional -ProjectRoot parameter to Test-DotbotMcpReadiness and pass the
main project root at the call site. The main root always has a stable
.control/ directory, so runtime.json resolution keeps working on retry.
Backward compatible: callers that omit -ProjectRoot fall back to the worktree
path.

Closes andresharpe#515

Copy link
Copy Markdown
Collaborator

@kabaogluemre this highlights a bigger concern with the root model around MCP. Right now, DOTBOT_PROJECT_ROOT seems to carry two meanings: the worktree where the agent should operate, and the stable project root where dotbot runtime/task state lives. This PR fixes the preflight path by pointing it at the stable root, but the actual provider MCP config and launch paths still point the MCP server at the worktree, so preflight and the real session can diverge.

I think we should make that split explicit instead of patching one caller. The agent cwd should stay as the worktree, but MCP state/runtime resolution should use a dedicated DOTBOT_STATE_ROOT. That would avoid relying on worktree .control links being valid during retry/teardown windows, and it would give us tests that cover the actual failure mode rather than only checking the preflight assignment.

@kabaogluemre

Copy link
Copy Markdown
Contributor Author

@kabaogluemre this highlights a bigger concern with the root model around MCP. Right now, DOTBOT_PROJECT_ROOT seems to carry two meanings: the worktree where the agent should operate, and the stable project root where dotbot runtime/task state lives. This PR fixes the preflight path by pointing it at the stable root, but the actual provider MCP config and launch paths still point the MCP server at the worktree, so preflight and the real session can diverge.

I think we should make that split explicit instead of patching one caller. The agent cwd should stay as the worktree, but MCP state/runtime resolution should use a dedicated DOTBOT_STATE_ROOT. That would avoid relying on worktree .control links being valid during retry/teardown windows, and it would give us tests that cover the actual failure mode rather than only checking the preflight assignment.

@carlospedreira , thanks for your review, a dedicated DOTBOT_STATE_ROOT is the cleaner approach. Applied it across the resolver, all provider adapters, and the generated MCP configs, so preflight and the real session now share the same model. Also added tests for the actual resolver failure mode.

@carlospedreira carlospedreira added type:bug Something is broken bug Something isn't working labels Jun 25, 2026 — with ChatGPT Codex Connector
@carlospedreira carlospedreira removed the type:bug Something is broken label Jun 25, 2026
@carlospedreira
carlospedreira merged commit 9f4f705 into andresharpe:main Jun 25, 2026
6 checks passed
@github-project-automation github-project-automation Bot moved this from Inbox to Done in Dotbot Product Backlog Jun 25, 2026
mirzazekicapi pushed a commit to mirzazekicapi/dotbot that referenced this pull request Jun 25, 2026
PR andresharpe#527 (fix andresharpe#515) landed the Issue A fix upstream using DOTBOT_STATE_ROOT
rather than overwriting DOTBOT_PROJECT_ROOT. Resolved conflict in
Invoke-WorkflowProcess.ps1 by taking upstream s approach: DOTBOT_PROJECT_ROOT
stays the worktree, DOTBOT_STATE_ROOT carries the stable main root.
Issue A is now fully covered by upstream -- our v4-runtime unique changes
remaining are B (interview-answers.json), D (output delta), E (Products page).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Test-DotbotMcpReadiness crashes on task retry due to stale worktree junction

2 participants