Summary
Replace the fragile stash/reset/branch/pop sequence in create_merge_request.sh with git worktrees. Each workflow run gets an isolated checkout on its own branch, eliminating working tree pollution and enabling parallel ticket support.
Problem
The docs-orchestrator pipeline currently modifies the user's working tree directly during the writing (update-in-place mode) and create-merge-request steps. This causes three problems:
- Fragile branch creation:
create_merge_request.sh (lines 120-151) performs a git stash push / git reset --hard / git checkout -b / git stash pop sequence. If the user has uncommitted work or stash conflicts, this breaks.
- Working tree pollution: Update-in-place mode writes directly to the user's current checkout, intermingling pipeline output with any in-progress work.
- No parallel ticket support: Two concurrent workflow runs would collide in the same working tree.
Proposal
Scope
Worktrees apply only to the docs repo (where documentation gets written). Analysis steps (requirements, planning, scope-req-audit, code-evidence) are read-only and continue writing metadata to .claude/docs/<ticket>/. Source code repos continue using shallow clones. Draft mode is unaffected.
Key changes
-
New script: manage_worktree.sh — Creates/removes worktrees at <base-path>/worktree/ on a docs/<ticket> branch. Called by the orchestrator before the writing step.
-
Orchestrator gains a "Prepare worktree" phase — Runs between planning and writing (non-draft mode only). Creates the worktree, records the path in the progress file, and passes it as --repo-path to writing and create-merge-request steps.
-
Simplified create_merge_request.sh — With a --worktree flag, skips the stash/reset/branch/pop dance entirely. The worktree is already on a feature branch. Old logic preserved as fallback for standalone use.
-
Progress file schema extended — New worktree field tracks path, branch, and repo root for resume across sessions.
Files to modify
| File |
Change |
plugins/docs-tools/skills/docs-orchestrator/scripts/manage_worktree.sh |
NEW — worktree lifecycle script |
plugins/docs-tools/skills/docs-orchestrator/SKILL.md |
Add "Prepare worktree" section, update arg wiring, add cleanup |
plugins/docs-tools/skills/docs-orchestrator/schema/step-result-schema.md |
Add worktree to progress schema |
plugins/docs-tools/skills/docs-workflow-create-merge-request/scripts/create_merge_request.sh |
Add --worktree flag |
plugins/docs-tools/skills/docs-workflow-create-merge-request/SKILL.md |
Document --worktree flag |
Files NOT modified
build_writing_args.sh — already handles --repo-path
docs-workflow-writing/SKILL.md — orchestrator passes worktree path as --repo-path
- Style-review, tech-review — read from
<base-path>/writing/, not the repo
resolve_source.py — handles source code repos, not docs repos
Edge cases
- Resume: Worktree persists at
<base-path>/worktree/. Progress file records the path. On resume, orchestrator reuses it.
- Draft mode: No worktree.
worktree field is null.
- User on feature branch: Worktree created from current branch, not
origin/main.
- User declines MR: Worktree kept for manual inspection.
- Backward compatibility:
create_merge_request.sh without --worktree flag retains old stash/branch logic.
Detailed plan
See attached plan file below.
Full implementation plan
1. New script: manage_worktree.sh
Path: plugins/docs-tools/skills/docs-orchestrator/scripts/manage_worktree.sh
Usage:
manage_worktree.sh create <ticket> --base-path <path> [--repo-path <path>]
manage_worktree.sh remove <ticket> --base-path <path>
manage_worktree.sh status <ticket> --base-path <path>
create behavior:
- Determine docs repo root:
--repo-path or git rev-parse --show-toplevel
- Determine base remote/default branch (check
upstream first, fall back to origin)
- Fetch latest:
git fetch <remote> <default-branch>
- Worktree path:
<base-path>/worktree/
- Branch name:
docs/<ticket-lowercase>
- Resume: if worktree exists, validate and emit
action: "exists"
- New:
git worktree add -b <branch> <path> <remote>/<default-branch>
- Emit JSON:
{ status, worktree_path, branch, base_ref, repo_root, action }
remove behavior:
git worktree remove <path> (fails on uncommitted changes)
git branch -d <branch> (only if merged)
status behavior:
- Check existence, emit JSON with state
Why <base-path>/worktree/ not .claude/worktrees/: Lifecycle tied to ticket workspace. Avoids conflicting with Claude Code's own .claude/worktrees/.
2. Orchestrator updates
New "Prepare worktree" phase (orchestrator-internal, not a YAML step):
- Skip if
options.draft is true
- Check progress file
worktree field for resume
- Run
manage_worktree.sh create
- Record in progress file
- Use
worktree.path as --repo-path for writing step
Updated arg wiring:
- Writing:
--repo-path <worktree.path> instead of --docs-repo-path
- Create-merge-request:
--repo-path <worktree.path> --worktree
Cleanup on completion:
- MR created successfully →
manage_worktree.sh remove
- MR not created → keep worktree, log path
3. Simplified create_merge_request.sh
- Add
--worktree flag
- When set: skip stash/reset/branch/pop block (lines 113-151)
- Without flag: old logic preserved for standalone use
4. Progress file schema
New top-level field:
{
"worktree": {
"path": "/absolute/path",
"branch": "docs/<ticket>",
"repo_root": "/absolute/path/to/docs-repo"
}
}
Verification
- Unit test
manage_worktree.sh against a test repo
- Draft mode: no worktree created
- Update-in-place: worktree created, writing goes there, MR created from worktree branch, user's tree clean
- Resume: worktree reused across sessions
- Parallel tickets: each gets own worktree
- Standalone create-merge-request: backward-compatible without
--worktree
Summary
Replace the fragile stash/reset/branch/pop sequence in
create_merge_request.shwith git worktrees. Each workflow run gets an isolated checkout on its own branch, eliminating working tree pollution and enabling parallel ticket support.Problem
The docs-orchestrator pipeline currently modifies the user's working tree directly during the writing (update-in-place mode) and create-merge-request steps. This causes three problems:
create_merge_request.sh(lines 120-151) performs agit stash push/git reset --hard/git checkout -b/git stash popsequence. If the user has uncommitted work or stash conflicts, this breaks.Proposal
Scope
Worktrees apply only to the docs repo (where documentation gets written). Analysis steps (requirements, planning, scope-req-audit, code-evidence) are read-only and continue writing metadata to
.claude/docs/<ticket>/. Source code repos continue using shallow clones. Draft mode is unaffected.Key changes
New script:
manage_worktree.sh— Creates/removes worktrees at<base-path>/worktree/on adocs/<ticket>branch. Called by the orchestrator before the writing step.Orchestrator gains a "Prepare worktree" phase — Runs between planning and writing (non-draft mode only). Creates the worktree, records the path in the progress file, and passes it as
--repo-pathto writing and create-merge-request steps.Simplified
create_merge_request.sh— With a--worktreeflag, skips the stash/reset/branch/pop dance entirely. The worktree is already on a feature branch. Old logic preserved as fallback for standalone use.Progress file schema extended — New
worktreefield tracks path, branch, and repo root for resume across sessions.Files to modify
plugins/docs-tools/skills/docs-orchestrator/scripts/manage_worktree.shplugins/docs-tools/skills/docs-orchestrator/SKILL.mdplugins/docs-tools/skills/docs-orchestrator/schema/step-result-schema.mdworktreeto progress schemaplugins/docs-tools/skills/docs-workflow-create-merge-request/scripts/create_merge_request.sh--worktreeflagplugins/docs-tools/skills/docs-workflow-create-merge-request/SKILL.md--worktreeflagFiles NOT modified
build_writing_args.sh— already handles--repo-pathdocs-workflow-writing/SKILL.md— orchestrator passes worktree path as--repo-path<base-path>/writing/, not the reporesolve_source.py— handles source code repos, not docs reposEdge cases
<base-path>/worktree/. Progress file records the path. On resume, orchestrator reuses it.worktreefield isnull.origin/main.create_merge_request.shwithout--worktreeflag retains old stash/branch logic.Detailed plan
See attached plan file below.
Full implementation plan
1. New script:
manage_worktree.shPath:
plugins/docs-tools/skills/docs-orchestrator/scripts/manage_worktree.shcreatebehavior:--repo-pathorgit rev-parse --show-toplevelupstreamfirst, fall back toorigin)git fetch <remote> <default-branch><base-path>/worktree/docs/<ticket-lowercase>action: "exists"git worktree add -b <branch> <path> <remote>/<default-branch>{ status, worktree_path, branch, base_ref, repo_root, action }removebehavior:git worktree remove <path>(fails on uncommitted changes)git branch -d <branch>(only if merged)statusbehavior:Why
<base-path>/worktree/not.claude/worktrees/: Lifecycle tied to ticket workspace. Avoids conflicting with Claude Code's own.claude/worktrees/.2. Orchestrator updates
New "Prepare worktree" phase (orchestrator-internal, not a YAML step):
options.draftis trueworktreefield for resumemanage_worktree.sh createworktree.pathas--repo-pathfor writing stepUpdated arg wiring:
--repo-path <worktree.path>instead of--docs-repo-path--repo-path <worktree.path> --worktreeCleanup on completion:
manage_worktree.sh remove3. Simplified
create_merge_request.sh--worktreeflag4. Progress file schema
New top-level field:
{ "worktree": { "path": "/absolute/path", "branch": "docs/<ticket>", "repo_root": "/absolute/path/to/docs-repo" } }Verification
manage_worktree.shagainst a test repo--worktree