with one click
do-build
// Use when executing a plan document to ship a feature. Triggered by 'build this', 'execute the plan', 'implement the plan', or any request to run/ship a plan.
// Use when executing a plan document to ship a feature. Triggered by 'build this', 'execute the plan', 'implement the plan', or any request to run/ship a plan.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | do-build |
| description | Use when executing a plan document to ship a feature. Triggered by 'build this', 'execute the plan', 'implement the plan', or any request to run/ship a plan. |
| argument-hint | <plan-path-or-issue-number> |
| context | fork |
You are the team lead executing a plan document. You orchestrate work using Task tools - you NEVER build directly.
| Sub-file | Load when... |
|---|---|
WORKFLOW.md | Starting execution (Steps 1-5: task creation, agent deployment, monitoring) |
PR_AND_CLEANUP.md | All build tasks complete and validated (Steps 6-9: docs gate, PR, cleanup, migration) |
/do-build docs/plans/my-feature.md/do-build #17 or /do-build 17PLAN_ARG: $ARGUMENTS
If PLAN_ARG is empty or literally $ARGUMENTS: The skill argument substitution did not run. Resolve PLAN_ARG using this priority order:
/do-build <something>, extract <something> as PLAN_ARG.docs/plans/foo.md) or issue number (e.g., #564, issue 564). Use the most recently referenced one.docs/plans/foo.md) or issue number (e.g., #564)." Do NOT guess or pick a plan at random.Step 1: Detect argument type
PLAN_ARG starts with # or is a pure number, treat as issue numberStep 2A: If issue number
# if present)docs/plans/*.mdtracking: field/issues/{NUMBER} where NUMBER equals the argumentStep 2B: If file path
PLAN_ARG directly as PLAN_PATHStep 3: Set PLAN_PATH
PLAN_PATH now contains the resolved absolute path to the plan documentAfter resolving PLAN_PATH, determine which git repository the plan belongs to. This is critical for cross-repo builds where the plan lives in a different repo than the orchestrator.
# Resolve the target repo root from the plan file's location
TARGET_REPO=$(git -C "$(dirname "$PLAN_PATH")" rev-parse --show-toplevel)
ORCHESTRATOR_REPO=$(git rev-parse --show-toplevel)
# Check if this is a cross-repo build
if [ "$TARGET_REPO" != "$ORCHESTRATOR_REPO" ]; then
echo "CROSS-REPO BUILD: Plan is in $TARGET_REPO (orchestrator is $ORCHESTRATOR_REPO)"
# Resolve the target repo's GitHub identity for PR creation
TARGET_GH_REPO=$(git -C "$TARGET_REPO" remote get-url origin | sed 's/.*github.com[:/]//' | sed 's/\.git$//')
fi
Or using Python:
python -c "from agent.worktree_manager import resolve_repo_root; print(resolve_repo_root('$PLAN_PATH'))"
All subsequent git, worktree, and PR operations must use TARGET_REPO as the repo root, not the orchestrator repo. Specifically:
create_worktree(Path(TARGET_REPO), slug) instead of create_worktree(Path('.'), slug)git -C $TARGET_REPO/.worktrees/{slug} for all git commands in the worktreegh pr create --repo $TARGET_GH_REPO when creating the PRtarget_repo in the state dictIf TARGET_REPO == ORCHESTRATOR_REPO, this is a same-repo build and no special handling is needed (all existing behavior works as-is).
Resolve the plan path using the Plan Resolution logic above
Read the plan at PLAN_PATH
Check pipeline state - After resolving the plan path, derive {slug} from the plan filename and check for existing state:
python -c "from agent.build_pipeline import load; import json; s = load('{slug}'); print(json.dumps(s) if s else 'null')"
stage != "plan": resume from that stage, skip already-completed stages listed in completed_stagesnull): proceed normally — initialize state after worktree creationCheck issue comment freshness - Verify the plan has incorporated the latest issue comments before building. This check is delegated to a helper script so the orchestrator only runs a single allowlisted command. If the script exits non-zero, the plan is stale and /do-plan must run before the build:
python scripts/check_plan_freshness.py {PLAN_PATH}
/do-plan firsttracking:, last_comment_id:) and calls gh issue view {number} --json comments to fetch the latest comment id. It does NOT use gh api -- gh api is excluded from PM session Bash by agent/hooks/pre_tool_use.py::PM_BASH_ALLOWED_PREFIXES as a silent mutation vector.Run prerequisite validation - python scripts/check_prerequisites.py {PLAN_PATH}. If any check fails, report the failures and stop. Do not proceed to task execution. If no Prerequisites section exists, this passes automatically.
Resolve target repo - Determine which repo the plan belongs to (see "Target Repo Resolution" above):
TARGET_REPO=$(git -C "$(dirname "$PLAN_PATH")" rev-parse --show-toplevel)
Ensure clean git state - Before creating a worktree, verify the main working tree has no in-progress merge, rebase, or cherry-pick operations that would block git operations:
python -c "from agent.worktree_manager import ensure_clean_git_state; from pathlib import Path; print(ensure_clean_git_state(Path('$TARGET_REPO')))"
This aborts any in-progress merge/rebase/cherry-pick and stashes uncommitted changes. See docs/features/git-state-guard.md for details.
Get or create an isolated worktree - Get the existing worktree or create .worktrees/{slug}/ with branch session/{slug} in the target repo using the worktree manager (handles stale worktrees and session resumption automatically):
python -c "from agent.worktree_manager import get_or_create_worktree; from pathlib import Path; print(get_or_create_worktree(Path('$TARGET_REPO'), '{slug}'))"
This is idempotent: if the worktree already exists (e.g., from an interrupted session), it returns the existing path. If not, it creates a fresh one. It also handles stale worktrees from crashed sessions, missing directories with lingering git references, and branch-already-in-use errors. Settings files are copied automatically.
All subsequent agent work happens inside $TARGET_REPO/.worktrees/{slug}/, NOT the orchestrator repo directory.
Record the plan hash at build start (defense-in-depth against mid-build plan revisions — see guard G7):
# PLAN_REPO may differ from TARGET_REPO for cross-repo builds (e.g. cuttlefish).
# Always resolve the plan's owning repo separately.
PLAN_REPO=$(git -C "$(dirname "$PLAN_PATH")" rev-parse --show-toplevel)
git -C "$PLAN_REPO" fetch origin main 2>/dev/null || true
PLAN_REL=$(python -c "import os; print(os.path.relpath('$PLAN_PATH', '$PLAN_REPO'))")
PLAN_HASH=$(git -C "$PLAN_REPO" log -1 --format=%H origin/main -- "$PLAN_REL")
sdlc-tool meta-set --key plan_hash_at_build_start --value "$PLAN_HASH" \
--issue-number {issue_number} 2>/dev/null || true
If PLAN_HASH is empty (e.g. the plan file is not tracked by git), the meta-set call writes an empty string, and the Step 21 check becomes a no-op (guarded by STORED_HASH non-empty check).
Initialize pipeline state - For fresh builds (no prior state), initialize now:
python -c "from agent.build_pipeline import initialize; initialize('{slug}', 'session/{slug}', '$TARGET_REPO/.worktrees/{slug}', target_repo='$TARGET_REPO')"
Skip this step if state already existed from step 3.
Advance to branch stage after worktree is ready:
python -c "from agent.build_pipeline import advance_stage; advance_stage('{slug}', 'branch')"
Parse the Team Members and Step by Step Tasks sections
Create all tasks using TaskCreate before starting execution
Deploy agents in order, respecting dependencies and parallel flags (agents follow SDLC: Build → Test loop with up to 5 iterations)
Advance to implement stage before deploying builder agents:
python -c "from agent.build_pipeline import advance_stage; advance_stage('{slug}', 'implement')"
Monitor progress and handle any issues
Advance to test stage after implementation tasks complete:
python -c "from agent.build_pipeline import advance_stage; advance_stage('{slug}', 'test')"
Verify Definition of Done - Ensure all tasks completed with: code working, tests passing, quality checks pass 16b. Run build validation against plan - After verifying definition of done, run the deterministic plan validator:
(cd $TARGET_REPO/.worktrees/{slug} && python scripts/validate_build.py $PLAN_PATH)
/do-patch for fixes, then re-run validation (up to 3 iterations)(cd $TARGET_REPO/.worktrees/{slug} && python scripts/evaluate_build.py $PLAN_PATH)
/do-patch call (not one call per FAIL); log [AI Evaluator] FAIL on N criteria — routing to patch cycle (attempt X/2) before each invocation; max 2 iterations; if FAIL persists after 2 iterations, log "AI evaluator: 2 iterations reached, proceeding to review" and proceed to step 17## Acceptance Criteria section — log "AI evaluator: no Acceptance Criteria section, skipping" and proceed to step 17Advance to review stage after tests pass:
python -c "from agent.build_pipeline import advance_stage; advance_stage('{slug}', 'review')"
Advance to document stage after review passes:
python -c "from agent.build_pipeline import advance_stage; advance_stage('{slug}', 'document')"
Run documentation gate - Validate docs changed, scan related docs, create review issues
Advance to pr stage after documentation gate passes:
python -c "from agent.build_pipeline import advance_stage; advance_stage('{slug}', 'pr')"
Verify commits exist before PR - Run git -C $TARGET_REPO/.worktrees/{slug} log --oneline main..HEAD and count the output lines. If zero commits exist on the session branch, ABORT with error: "BUILD FAILED: No commits on session/{slug}. Builder agents produced no code changes." Do NOT proceed to push or PR creation.
Defense-in-depth: verify plan hash has not changed mid-build (G7 second layer — catches revisions that committed during build execution):
git -C "$PLAN_REPO" fetch origin main 2>/dev/null || true
CURRENT_HASH=$(git -C "$PLAN_REPO" log -1 --format=%H origin/main -- "$PLAN_REL")
STORED_HASH=$(sdlc-tool stage-query --issue-number {issue_number} \
| python -c "import sys,json; print(json.load(sys.stdin).get('_meta',{}).get('plan_hash_at_build_start') or '')")
if [ -n "$STORED_HASH" ] && [ "$CURRENT_HASH" != "$STORED_HASH" ]; then
echo "BUILD ABORT: plan revised mid-build (was=$STORED_HASH, now=$CURRENT_HASH, path=$PLAN_PATH)"
sdlc-tool stage-marker --stage BUILD --status failed --issue-number {issue_number} 2>/dev/null || true
exit 1
fi
This check is a no-op when STORED_HASH is empty (sessions that pre-date this feature, or when the plan is not git-tracked). A non-empty mismatch means the plan was revised by a concurrent critique/plan cycle — abort so the router can re-route via G7 to a fresh revision round.
22. Push and open a PR - git -C $TARGET_REPO/.worktrees/{slug} push -u origin session/{slug} then gh pr create --repo $TARGET_GH_REPO (use --repo only for cross-repo builds)
23. Run documentation cascade - Invoke /do-docs {PR-number} to surgically update affected docs
24. Plan stays until merge - Do NOT delete the plan here; do-merge deletes it after the PR merges (issue closes automatically via Closes #N)
25. Report completion with PR URL when all tasks are done
Lint and formatting are handled automatically -- agents should never waste iterations on lint fixes.
--no-verify to skip the pre-commit hook during WIP commits mid-task. This avoids unnecessary lint interruptions while the agent is still working.--no-verify). The hook auto-fixes all fixable lint/format issues via ruff format + ruff check --fix and re-stages the changes. Only genuinely unfixable issues block the commit.ruff check . or ruff format --check . as a separate step. The pre-commit hook handles this automatically on final commits.format_file.py hook runs ruff check --fix + ruff format on individual files after every Write/Edit, so files stay clean as agents work.Depends On tasks are completeParallel: true and no blocking dependencies can run simultaneouslyvalidate-* task always waits for its corresponding build-* taskgit -C $TARGET_REPO/.worktrees/{slug} for git commands, subshells (cd $TARGET_REPO/.worktrees/{slug} && ...) when Python scripts need worktree CWD, and --head session/{slug} for gh pr create. For cross-repo builds, use --repo $TARGET_GH_REPO with gh pr create. Only subagents (Task tool) should have bare cd into worktrees — their shell sessions are independent and disposable. If the orchestrator's CWD ends up inside a worktree and that worktree is deleted, the shell breaks permanently and cannot recover.Read the plan and create tasks:
// For each task in "Step by Step Tasks":
TaskCreate({
subject: "[Task Name]",
description: "[Full task details from plan]",
activeForm: "[Description in progress form]"
})
// Note the returned taskId for dependency tracking
After creating all tasks, set up the dependency chain:
TaskUpdate({
taskId: "[task-id]",
addBlockedBy: ["dependency-task-id-1", "dependency-task-id-2"]
})
For each task, deploy the assigned agent:
Task({
description: "[Task subject]",
prompt: `Execute task: [Task Name]
IMPORTANT: You MUST work in the worktree directory: {absolute_path_to}/.worktrees/{slug}/
Run \`cd {absolute_path_to}/.worktrees/{slug}/\` before doing any work.
All file reads, writes, and commands should use this worktree path, not the main repo.
NEVER use \`git checkout\` or \`git checkout -b\` on session/ branches. The worktree IS the checkout — just \`cd\` into it. Running \`git checkout session/{slug}\` will fail with a fatal error because the branch is locked by the worktree.
Plan context: [relevant plan sections]
Your assignment:
- [specific actions from task]
Commit at logical checkpoints as you work — not as one batch at the end. The commit message hook enforces hygiene at each commit.
SELF-CHECK (mandatory before marking task complete):
1. Run \`git status\` in the worktree and include the output in your response
2. Run \`git log --oneline main..HEAD\` and include the output
3. If you made zero file changes, explicitly state "NO CHANGES MADE" and explain why
When complete, update your task status.`,
subagent_type: "[agent type from task]",
run_in_background: [true if Parallel: true]
})
TaskList({}) to see overall progressTaskOutput({task_id, block: false}) to check on background agentsHealth Monitoring for Background Agents:
After deploying background agents, actively monitor their health:
TaskOutput({task_id, block: false, timeout: 30000}) for each background agent when checking progressTaskList to see if tasks have moved to completed statusin_progress, use TaskUpdate to mark itgit -C .worktrees/{slug} add -A && git -C .worktrees/{slug} commit -m "[WIP] partial work before agent failure" || true
When the final validate-all task completes, verify Definition of Done criteria:
Pipeline stage at this point: test → advance to review before proceeding.
python -c "from agent.build_pipeline import advance_stage; advance_stage('{slug}', 'review')"
Definition of Done Checklist (pre-documentation):
If any criterion is not met, report the issue and do NOT proceed to the Document stage.
Note: Documentation validation happens AFTER review passes — see Step 6. The canonical pipeline order is: Plan → Branch → Implement → Test → Review → Document → PR. Fix-and-retry loops re-enter at Test (for test failures) or Review (for review failures).
If the plan has a ## Verification section with a machine-readable table, extract and run each check automatically. This replaces manual validation judgment with deterministic pass/fail:
(cd .worktrees/{slug} && python -c "
from agent.verification_parser import parse_verification_table, run_checks, format_results
from pathlib import Path
plan = Path('{PLAN_PATH}').read_text()
checks = parse_verification_table(plan)
if checks:
results = run_checks(checks)
print(format_results(results))
if not all(r.passed for r in results):
raise SystemExit(1)
else:
print('No verification table found in plan -- skipping automated checks.')
")
## Verification section, this step is a no-opBefore running any orchestrator bash commands, verify the shell CWD is the main repo root (not inside a worktree). Run this as a sanity check:
cd $(git rev-parse --show-toplevel) && pwd
The output should be the main repo path, NOT a .worktrees/ path. If the CWD is somehow inside the worktree, this resets it. All subsequent orchestrator commands depend on CWD being the repo root.
After validating Definition of Done, run a soft check for the working-state scratchpad. Missing PROGRESS.md is a warning, not a blocker — PR creation is not gated on this:
[ -f $TARGET_REPO/.worktrees/{slug}/PROGRESS.md ] || echo "[warn] No PROGRESS.md at worktree root — not blocking, but recovery from compaction may be degraded next run."
After review passes, advance to the document stage and run documentation lifecycle checks:
python -c "from agent.build_pipeline import advance_stage; advance_stage('{slug}', 'document')"
This is the Document phase of the pipeline: Plan → Branch → Implement → Test → Review → **Document** → PR. Documentation is written and validated here, after implementation is reviewed — not interleaved with implementation.
6.1 Validate Documentation Changes
Run the doc validation script to verify documentation was created/updated. This script runs git diff internally and needs the worktree as CWD to see the session branch changes.
Execute each command below exactly as written, including the parentheses. The (...) subshell syntax ensures the cd happens in a child process — the orchestrator's CWD stays in the main repo.
(cd .worktrees/{slug} && python scripts/validate_docs_changed.py {PLAN_PATH})
docs/features/ or docs/6.2 Scan for Related Documentation
Collect all changed files from git and scan for related docs:
(cd .worktrees/{slug} && CHANGED_FILES=$(git diff --name-only main...HEAD | tr '\n' ' ') && python scripts/scan_related_docs.py --json $CHANGED_FILES > /tmp/related_docs.json)
This identifies existing documentation that may need updates based on code changes.
6.3 Create Review Issues for Discrepancies
Pipe the scan results to create GitHub issues for HIGH/MED-HIGH confidence matches:
cat /tmp/related_docs.json | python scripts/create_doc_review_issue.py
This creates tracking issues for documentation that should be reviewed for updates.
After documentation gate passes, advance to the pr stage and push:
python -c "from agent.build_pipeline import advance_stage; advance_stage('{slug}', 'pr')"
Then push and create the PR. For cross-repo builds, use $TARGET_REPO and --repo $TARGET_GH_REPO:
git -C $TARGET_REPO/.worktrees/{slug} push -u origin session/{slug}
# For cross-repo builds, add: --repo $TARGET_GH_REPO
gh pr create --head session/{slug} --title "[plan title]" --body "$(cat <<'EOF'
## Summary
[Brief description of what was built]
## Changes
- [List key changes made]
## Testing
- [x] Unit tests passing
- [x] Integration tests passing
- [x] Linting (ruff, black) passing
## Documentation
- [x] Docs created per plan requirements
- [x] Related docs scanned for updates
## Definition of Done
- [x] Built: Code implemented and working
- [x] Tested: All tests passing
- [x] Documented: Docs created/updated
- [x] Quality: Lint and format checks pass
Closes #[issue-number]
EOF
)"
Important: The PR creation step is handled by the BUILD ORCHESTRATOR (this skill), NOT by individual builder agents. Builder agents focus on their assigned tasks, while the orchestrator creates the final PR after all tasks complete and gates pass.
After pushing and creating the PR, return to the repo root and clean up the worktree. The cd prevents CWD death if the shell is inside the worktree (issue #301):
# Return to repo root BEFORE cleanup (prevents CWD death)
cd ~/src/ai
python -c "
from pathlib import Path
from agent.worktree_manager import remove_worktree, prune_worktrees
# Use TARGET_REPO for cross-repo builds, orchestrator repo for same-repo builds
repo = Path('$TARGET_REPO')
remove_worktree(repo, '{slug}', delete_branch=False)
prune_worktrees(repo)
"
Note: delete_branch=False because the PR still references session/{slug}. The branch is cleaned up when the PR is merged.
After the PR is created, run the /do-docs cascade to find and surgically update any existing documentation affected by the code changes in this build. Pass the PR number AND plan context so the cascade understands the feature intent:
/do-docs {PR-number}
Plan: {PLAN_PATH}
Goal: [1-2 sentence summary from plan]
Issue: #{issue-number}
This invokes the cascade skill defined in .claude/skills-global/do-docs/SKILL.md, which:
Note: The cascade is best-effort. If it finds nothing to update, that's fine — proceed to reporting. If it makes edits, those are committed directly to the PR branch.
After PR is created and documentation cascade completes, the plan document is not deleted here. It remains at {PLAN_PATH} so that:
do-merge can read it to verify all checklist items are donedo-docs can use it as context during the DOCS stageThe plan will be deleted by do-merge after the PR is successfully merged.
After plan migration completes, include the PR URL prominently in your final response. When running via Telegram bridge, the agent's response (containing the PR link) will be automatically sent back to the chat where the build was initiated. No special action required - just ensure the PR URL is visible in your completion report.
As the very last line of your final response, emit an OUTCOME contract so the pipeline can classify the build result programmatically:
<!-- OUTCOME {"status":"success","stage":"BUILD","artifacts":{"pr_url":"<URL>"}} --><!-- OUTCOME {"status":"fail","stage":"BUILD","artifacts":{}} -->This structured output is parsed by classify_outcome() in agent/pipeline_state.py (Tier 0) before any text pattern matching.
When deploying an agent, include:
By file path:
/do-build docs/plans/implement-auth.md
By issue number:
/do-build #42
/do-build 42
Both methods will execute the same plan if the plan file has:
tracking: https://github.com/valor-labs/ai/issues/42
Given a plan with tasks:
1. build-api (Parallel: true)
2. build-frontend (Parallel: true)
3. validate-api (Depends On: build-api)
4. validate-frontend (Depends On: build-frontend)
5. integration-test (Depends On: validate-api, validate-frontend)
Execution order:
After all tasks complete:
## Plan Execution Complete
**Plan**: [plan name]
**Pull Request**: [PR URL]
**Total Tasks**: [count]
### Definition of Done
- [x] Built: All code implemented and working
- [x] Tested: Unit tests passing, integration tests passing
- [x] Reviewed: Review passed (no blocking issues)
- [x] Documented: Docs created after review (validated by docs gate)
- [x] Quality: Ruff and Black checks pass
- [x] Plans migrated: Plan moved from docs/plans/ to completed state
### Task Summary
| Task | Agent | Status | Test Iterations | Notes |
|------|-------|--------|----------------|-------|
| [name] | [agent] | Done | [N] | [brief note] |
### Validation Results
- [x] All build tasks completed
- [x] All validators passed
- [x] Documentation gate passed
- [x] Documentation cascade completed (`/do-docs`)
- [x] Success criteria met
### Artifacts Created
- [list of files created/modified]
### Next Steps
- Review and merge PR: [PR URL]
- PR link has been sent to Telegram chat
- [Any follow-up items or manual steps needed]
If a task fails:
TaskStop only if you need to abort a runaway agent