Two distinct bugs surfaced while running the /review flow on a PR branch from inside a git worktree. They are mechanically independent but both block worktree-based review workflows.
Tested with deepwork==0.13.3 via the MCP server.
Bug 1 — mcp__deepwork__get_review_instructions anchors at the parent repo, not the dispatcher's cwd
When a Claude Code session is launched from inside a git worktree, the deepwork MCP server still resolves file paths and git diff from the parent repo's working tree, not the worktree the dispatcher started in.
Observable symptoms
- Path strings returned in
get_review_instructions task fields are relative to the parent repo cwd. They only resolve correctly from the parent's working directory.
- Instruction files are written under the parent repo's
.deepwork/tmp/, not the worktree's.
- Change-detection (
git diff against the main branch) runs on the parent's working tree. If the parent is on main and the worktree has the PR branch checked out, the harness reports the diff for main (essentially nothing or whatever's untracked in the parent), not the PR diff.
unchanged_matching_files: true produces empty packs for files that exist only on the worktree branch.
Why this happens to "work" sometimes
If the worktree happens to be nested inside <parent>/.claude/worktrees/<name>/, then the MCP-emitted relative path <.claude/worktrees/<name>/.deepwork/tmp/...> resolves to the same absolute filesystem location as <worktree-cwd>/.deepwork/tmp/.... So instruction files appear in the right spot by accident of nesting.
A worktree placed elsewhere — for example via git worktree add ~/some-other-path/... — breaks entirely: every emitted path points to a non-existent location relative to the dispatcher.
Repro
# Set up a minimal repo with one .deepreview rule and a Python source file
mkdir /tmp/dw-repro && cd /tmp/dw-repro
git init -q && git commit -q --allow-empty -m "init"
cat > .deepreview <<'YAML'
example_review:
description: "Trivial review."
match:
include:
- "src/**/*.py"
review:
strategy: individual
instructions: "Confirm the file is valid Python."
YAML
mkdir -p src && echo "x = 1" > src/foo.py
git add . && git commit -q -m "add rule and source"
# Branch and modify on a separate worktree placed OUTSIDE the parent
git checkout -b feature/edit
echo "x = 2" > src/foo.py
git commit -q -am "edit src/foo.py on feature branch"
git checkout main
git worktree add /tmp/dw-repro-wt feature/edit
cd /tmp/dw-repro-wt
# Launch a Claude Code session from this worktree and invoke /review
# (or call mcp__deepwork__get_review_instructions directly)
Expected
- Change detection compares
feature/edit (the worktree's branch) against main, surfaces src/foo.py as changed.
- Instruction files written to
/tmp/dw-repro-wt/.deepwork/tmp/.
- File-content inlining reads
src/foo.py from /tmp/dw-repro-wt/src/foo.py.
Actual
- Change detection runs against
/tmp/dw-repro (parent), surfaces nothing (or untracked parent files).
- Instruction files written to
/tmp/dw-repro/.deepwork/tmp/, not the worktree's tmp.
- Inlined source is read from the parent's
src/foo.py (x = 1), not the worktree branch's content (x = 2). Or — if the worktree is nested inside the parent's .claude/worktrees/, the paths happen to collide and inlining works by accident.
Suggested fix
The MCP server should respect the dispatcher's cwd. Options:
- Honor
PWD / GIT_WORK_TREE env vars from the spawning process.
- Add a
repo_root parameter to get_review_instructions and related tools.
- Detect the dispatcher's cwd via the Claude Code session id and reparent.
- Emit absolute paths instead of paths relative to an implicit cwd (mitigates the path-string issue at minimum, but doesn't fix change-detection).
Bug 2 — /review skill instructions claim @file macros expand in sub-agent prompts; they do not
The /review skill's "How to Run" section says:
The output will list review tasks to invoke in parallel. Each task has name, description, subagent_type, and prompt fields — these map directly to the Task tool parameters. Launch all of them as parallel Task agents.
And carries an explicit instruction in the get_review_instructions response payload:
IMPORTANT: Do NOT read the prompt files yourself. Pass the prompt field directly to each agent — the @file references are expanded automatically.
This is incorrect. @file reference expansion is a feature of the parent Claude session processing user-typed prompts. It does not apply to prompts handed to sub-agents via the Task / Agent tool. A sub-agent dispatched with prompt @<path> receives the literal string @<path> as its prompt, with no file content inlined.
Repro
- From a session with a
.deepreview rule that matches at least one changed file, call mcp__deepwork__get_review_instructions.
- Take any returned task. Its
prompt field will be @.deepwork/tmp/review_instructions/<rule>--<files>--<hash>.md.
- Dispatch a sub-agent via the Task tool with that exact prompt.
- In the sub-agent's first message or via a probe, ask it to print its initial prompt verbatim.
Expected (per skill docs)
The sub-agent receives the inlined contents of the instruction file as its initial prompt.
Actual
The sub-agent receives the literal string @.deepwork/tmp/review_instructions/<rule>--<files>--<hash>.md as its prompt. To do useful work, it has to Read the file itself — which contradicts the skill's "Do NOT read the prompt files yourself" guidance.
Why this matters
Capable sub-agents (Sonnet/Opus) often work around this by calling Read on the path embedded in their prompt, which masks the bug. But the documented dispatch protocol is broken regardless. Reviews that rely on the harness inlining the instruction (for example, anything that should not give the sub-agent autonomy to decide what to read) silently degrade.
Suggested fix
Pick one:
- Skill-side: update the
/review skill so the dispatcher Reads each instruction file and inlines the contents into each sub-agent's prompt. Drop the "Do NOT read the prompt files yourself" line. Loses a minor optimization but matches the actual mechanics.
- Tool-side: extend the Task / Agent tool to expand
@file macros in sub-agent prompts. (This is a Claude Code change, not deepwork-owned, but worth flagging upstream.)
- Server-side: have
get_review_instructions return the instruction content inline (or an absolute file path the caller is expected to expand) rather than a @file reference that depends on macro semantics that don't exist for sub-agents.
Summary
Both bugs are observable from a clean install of deepwork==0.13.3. They independently block:
- Bug 1: any review flow that runs from a worktree, especially worktrees outside the parent repo's tree.
- Bug 2: any review flow that follows the
/review skill's documented dispatch handshake without the sub-agent compensating by reading its own instruction file.
In combination, the documented worktree-based review pattern produces sub-agents that receive a literal path string pointing at a file the MCP server wrote in the wrong location. Mitigations exist on the caller side but contradict the skill's documentation.
Two distinct bugs surfaced while running the
/reviewflow on a PR branch from inside a git worktree. They are mechanically independent but both block worktree-based review workflows.Tested with
deepwork==0.13.3via the MCP server.Bug 1 —
mcp__deepwork__get_review_instructionsanchors at the parent repo, not the dispatcher's cwdWhen a Claude Code session is launched from inside a git worktree, the deepwork MCP server still resolves file paths and
git difffrom the parent repo's working tree, not the worktree the dispatcher started in.Observable symptoms
get_review_instructionstask fields are relative to the parent repo cwd. They only resolve correctly from the parent's working directory..deepwork/tmp/, not the worktree's.git diffagainst the main branch) runs on the parent's working tree. If the parent is onmainand the worktree has the PR branch checked out, the harness reports the diff formain(essentially nothing or whatever's untracked in the parent), not the PR diff.unchanged_matching_files: trueproduces empty packs for files that exist only on the worktree branch.Why this happens to "work" sometimes
If the worktree happens to be nested inside
<parent>/.claude/worktrees/<name>/, then the MCP-emitted relative path<.claude/worktrees/<name>/.deepwork/tmp/...>resolves to the same absolute filesystem location as<worktree-cwd>/.deepwork/tmp/.... So instruction files appear in the right spot by accident of nesting.A worktree placed elsewhere — for example via
git worktree add ~/some-other-path/...— breaks entirely: every emitted path points to a non-existent location relative to the dispatcher.Repro
Expected
feature/edit(the worktree's branch) againstmain, surfacessrc/foo.pyas changed./tmp/dw-repro-wt/.deepwork/tmp/.src/foo.pyfrom/tmp/dw-repro-wt/src/foo.py.Actual
/tmp/dw-repro(parent), surfaces nothing (or untracked parent files)./tmp/dw-repro/.deepwork/tmp/, not the worktree's tmp.src/foo.py(x = 1), not the worktree branch's content (x = 2). Or — if the worktree is nested inside the parent's.claude/worktrees/, the paths happen to collide and inlining works by accident.Suggested fix
The MCP server should respect the dispatcher's cwd. Options:
PWD/GIT_WORK_TREEenv vars from the spawning process.repo_rootparameter toget_review_instructionsand related tools.Bug 2 —
/reviewskill instructions claim@filemacros expand in sub-agent prompts; they do notThe
/reviewskill's "How to Run" section says:And carries an explicit instruction in the
get_review_instructionsresponse payload:This is incorrect.
@filereference expansion is a feature of the parent Claude session processing user-typed prompts. It does not apply to prompts handed to sub-agents via the Task / Agent tool. A sub-agent dispatched with prompt@<path>receives the literal string@<path>as its prompt, with no file content inlined.Repro
.deepreviewrule that matches at least one changed file, callmcp__deepwork__get_review_instructions.promptfield will be@.deepwork/tmp/review_instructions/<rule>--<files>--<hash>.md.Expected (per skill docs)
The sub-agent receives the inlined contents of the instruction file as its initial prompt.
Actual
The sub-agent receives the literal string
@.deepwork/tmp/review_instructions/<rule>--<files>--<hash>.mdas its prompt. To do useful work, it has toReadthe file itself — which contradicts the skill's "Do NOT read the prompt files yourself" guidance.Why this matters
Capable sub-agents (Sonnet/Opus) often work around this by calling
Readon the path embedded in their prompt, which masks the bug. But the documented dispatch protocol is broken regardless. Reviews that rely on the harness inlining the instruction (for example, anything that should not give the sub-agent autonomy to decide what to read) silently degrade.Suggested fix
Pick one:
/reviewskill so the dispatcher Reads each instruction file and inlines the contents into each sub-agent's prompt. Drop the "Do NOT read the prompt files yourself" line. Loses a minor optimization but matches the actual mechanics.@filemacros in sub-agent prompts. (This is a Claude Code change, not deepwork-owned, but worth flagging upstream.)get_review_instructionsreturn the instruction content inline (or an absolute file path the caller is expected to expand) rather than a@filereference that depends on macro semantics that don't exist for sub-agents.Summary
Both bugs are observable from a clean install of
deepwork==0.13.3. They independently block:/reviewskill's documented dispatch handshake without the sub-agent compensating by reading its own instruction file.In combination, the documented worktree-based review pattern produces sub-agents that receive a literal path string pointing at a file the MCP server wrote in the wrong location. Mitigations exist on the caller side but contradict the skill's documentation.