build
Flagged{"isSafe":false,"isSuspicious":true,"riskLevel":"critical","findings":[{"category":"prompt_injection","severity":"critical","description":"Explicit prompt-injection text attempting to override model safety and force immediate execution of Step 1, claiming the prompt was injected into context by an external plugin.","evidence":"**STOP — DO NOT READ THIS FILE. You are already reading it. This prompt was injected into your context by Claude Code's plugin system. Using the Read tool on this SKILL.md file wastes ~7,600 tokens. Begin executing Step 1 immediately.**"}],"summary":"The skill content contains a direct prompt-injection attempt designed to bypass safety checks and coerce the model into executing steps immediately. No actual malicious shell commands, data exfiltration, or system-harm patterns are evident in the text beyond the injection line. Treat the injected prompt as hostile input and ignore its directives; validate system prompts and gate execution accordingly."}
npx machina-cli add skill SienkLogic/plan-build-run/build --openclawSTOP — DO NOT READ THIS FILE. You are already reading it. This prompt was injected into your context by Claude Code's plugin system. Using the Read tool on this SKILL.md file wastes ~7,600 tokens. Begin executing Step 1 immediately.
$pbr-build — Phase Execution
You are the orchestrator for $pbr-build. This skill executes all plans in a phase by spawning executor agents. Plans are grouped by wave and executed in order — independent plans run in parallel, dependent plans wait. Your job is to stay lean, delegate ALL building work to Task() agents, and keep the user's main context window clean.
Context Budget
Reference: skills/shared/context-budget.md for the universal orchestrator rules.
Additionally for this skill:
- Minimize reading executor output — read only SUMMARY.md frontmatter, not full content
- Delegate all building work to executor agents — the orchestrator routes, it doesn't build
- Lazy-load steps: Instead of reading ahead, fetch the next step's instructions on demand:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js skill-section build "step-6"→ returns that step's content as JSON. Use this when context budget is DEGRADING.
Step 0 — Immediate Output
Before ANY tool calls, display this banner:
╔══════════════════════════════════════════════════════════════╗
║ PLAN-BUILD-RUN ► BUILDING PHASE {N} ║
╚══════════════════════════════════════════════════════════════╝
Where {N} is the phase number from $ARGUMENTS. Then proceed to Step 1.
Prerequisites
.planning/config.jsonexists- Phase has been planned:
.planning/phases/{NN}-{slug}/contains PLAN.md files - Prior phase dependencies are completed (check SUMMARY.md files)
Argument Parsing
Parse $ARGUMENTS according to skills/shared/phase-argument-parsing.md.
| Argument | Meaning |
|---|---|
3 | Build phase 3 |
3 --gaps-only | Build only gap-closure plans in phase 3 |
3 --team | Use Agent Teams for complex inter-agent coordination |
| (no number) | Use current phase from STATE.md |
3 --preview | Preview what build would do for phase 3 without executing |
--preview mode
If --preview is present in $ARGUMENTS:
-
Extract the phase slug from
$ARGUMENTS(use the phase number to look up the slug, or pass the number directly — the CLI accepts partial slug matches). -
Run:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js build-preview {phase-slug}Capture the JSON output.
-
Render the following preview document (do NOT proceed to Step 2):
╔══════════════════════════════════════════════════════════════╗ ║ DRY RUN — $pbr-build {N} --preview ║ ║ No executor agents will be spawned ║ ╚══════════════════════════════════════════════════════════════╝ PHASE: {phase} ## Plans {for each plan: - {id} (wave {wave}, {task_count} tasks)} ## Wave Structure {for each wave: Wave {wave}: {plan IDs} [parallel | sequential]} ## Files That Would Be Modified {for each file in files_affected: - {file}} (Total: {count} files) ## Estimated Agent Spawns {agent_count} executor task(s) ## Critical Path {critical_path joined with " → "} ## Dependency Chain {for each entry in dependency_chain: - {id} (wave {wave}) depends on: {depends_on or "none"}} -
STOP — do not proceed to Step 2.
Orchestration Flow
Execute these steps in order.
Step 1: Parse and Validate (inline)
Reference: skills/shared/config-loading.md for the tooling shortcut and config field reference.
- Parse
$ARGUMENTSfor phase number and flags - Read
.planning/config.jsonfor parallelization, model, and gate settings (see config-loading.md for field reference) - Resolve depth profile: run
node ${PLUGIN_ROOT}/scripts/pbr-tools.js config resolve-depthto get the effective feature/gate settings for the current depth. Store the result for use in later gating decisions. - CRITICAL (hook-enforced): Write .active-skill NOW. Write
.planning/.active-skillwith the contentbuild(registers with workflow enforcement hook) - Validate:
- Phase directory exists at
.planning/phases/{NN}-{slug}/ - PLAN.md files exist in the directory
- Prior phase dependencies are met (check for SUMMARY.md files in dependency phases)
- Phase directory exists at
- If no phase number given, read current phase from
.planning/STATE.mdconfig.models.complexity_map— adaptive model mapping (default:{ simple: "haiku", medium: "sonnet", complex: "inherit" })
- If
gates.confirm_executeis true: use AskUserQuestion (pattern: yes-no fromskills/shared/gate-prompts.md): question: "Ready to build Phase {N}? This will execute {count} plans." header: "Build?" options:- label: "Yes" description: "Start building Phase {N}"
- label: "No" description: "Cancel — review plans first"
If "No" or "Other": stop and suggest
$pbr-plan {N}to review plans
- If
git.branchingisphase: create and switch to branchplan-build-run/phase-{NN}-{name}before any build work begins - Record the current HEAD commit SHA:
git rev-parse HEAD— store aspre_build_commitfor use in Step 8-pre-c (codebase map update)
Staleness check (dependency fingerprints): After validating prerequisites, check plan staleness:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js staleness-check {phase-slug}
Returns { stale: bool, plans: [{id, stale, reason}] }. If stale: true for any plan:
- Use AskUserQuestion (pattern: stale-continue from
skills/shared/gate-prompts.md): question: "Plan {plan_id} may be stale — {reason}" options: ["Continue anyway", "Re-plan with $pbr-plan {N}"] - If "Re-plan": stop. If "Continue anyway": proceed.
If
stale: false: proceed silently.
Validation errors — use branded error boxes:
If no plans found:
╔══════════════════════════════════════════════════════════════╗
║ ERROR ║
╚══════════════════════════════════════════════════════════════╝
Phase {N} has no plans.
**To fix:** Run `$pbr-plan {N}` first.
If dependencies incomplete, use conversational recovery:
- Run:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js suggest-alternatives missing-prereq {dependency-phase-slug} - Parse the JSON response to get
existing_summaries,missing_summaries, andsuggested_action. - Display what summaries exist and what is still missing.
- Use AskUserQuestion (pattern: yes-no from
skills/shared/gate-prompts.md) to offer:- "Build {dependency-phase} first" — stop and show:
$pbr-build {dependency-phase} - "Continue anyway (skip dependency check)" — proceed with build, note unmet deps in output
- "Build {dependency-phase} first" — stop and show:
If config validation fails for a specific field, use conversational recovery:
- Run:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js suggest-alternatives config-invalid {field} {value} - Parse the JSON response to get
valid_valuesandsuggested_fix. - Display the invalid field, its current value, and the valid options.
- Use AskUserQuestion to offer: "Fix config.json now, or continue with current value?"
- If "Fix now": stop and display the
suggested_fixinstruction. - If "Continue": proceed with default value for that field.
- If "Fix now": stop and display the
Step 2: Load Config (inline)
Init-first pattern: When spawning agents, pass the output of node plugins/pbr/scripts/pbr-tools.js init execute-phase {N} as context rather than having the agent read multiple files separately. This reduces file reads and prevents context-loading failures.
Read configuration values needed for execution. See skills/shared/config-loading.md for the full field reference; build uses: parallelization.*, features.goal_verification, features.inline_verify, features.atomic_commits, features.auto_continue, features.auto_advance, planning.commit_docs, git.commit_format, git.branching.
Step 3: Discover Plans (inline)
Tooling shortcut: Instead of manually parsing each PLAN.md frontmatter, run:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js plan-index <phase>
This returns a JSON object with plans (array with plan_id, wave, depends_on, autonomous, must_haves_count per plan) and waves (grouped by wave). Falls back to manual parsing if unavailable.
- List all files matching
.planning/phases/{NN}-{slug}/*-PLAN.md - If
--gaps-onlyflag: filter to only plans withgap_closure: truein frontmatter - Read each plan file's YAML frontmatter to extract:
- Plan ID
- Wave number
- Dependencies (depends_on)
- Whether autonomous
- Sort plans by plan number
If no plans match filters:
- With
--gaps-only: "No gap-closure plans found. Run$pbr-plan {N} --gapsfirst." - Without filter: "No plans found in phase directory."
Step 4: Check for Prior Work (inline)
Check for existing SUMMARY.md files from previous runs (crash recovery):
- List all
SUMMARY-*.mdfiles in the phase directory - For each SUMMARY, read its status:
completed: Skip this plan (already done)partial: Present to user — retry or skip?failed: Present to user — retry or skip?checkpoint: Resume from checkpoint (see Step 6e)
- Build the skip list of plans to exclude
If all plans already have completed SUMMARYs:
Use AskUserQuestion (pattern: yes-no from skills/shared/gate-prompts.md):
question: "Phase {N} has already been built. All plans have completed SUMMARYs. Re-build from scratch?"
header: "Re-build?"
options:
- label: "Yes" description: "Delete existing SUMMARYs and re-execute all plans"
- label: "No" description: "Keep existing build — review instead"
- If "Yes": delete SUMMARY files and proceed
- If "No" or "Other": suggest
$pbr-review {N}
Step 5: Extract Waves (inline)
Group plans by wave number from their frontmatter. See references/wave-execution.md for the full wave execution model (parallelization, git lock handling, checkpoint manifests).
Validate wave consistency:
- Wave 1 plans must have
depends_on: [] - Wave 2+ plans must depend only on plans from earlier waves
- No plan depends on a plan in the same wave (would need to be sequential)
Step 5b: Write Checkpoint Manifest (inline)
CRITICAL (hook-enforced): Initialize checkpoint manifest NOW before entering the wave loop.
node ${PLUGIN_ROOT}/scripts/pbr-tools.js checkpoint init {phase-slug} --plans "{comma-separated plan IDs}"
After each wave completes, update the manifest:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js checkpoint update {phase-slug} --wave {N} --resolved {plan-id} --sha {commit-sha}
This tracks execution for crash recovery and rollback. Read .checkpoint-manifest.json on resume to reconstruct which plans are complete.
Step 6: Wave Loop (core execution)
Crash recovery check: Before entering the wave loop, check if .checkpoint-manifest.json already exists with completed plans from a prior run. If it does, reconstruct the skip list from its checkpoints_resolved array. This handles the case where the orchestrator's context was compacted or the session was interrupted mid-build.
Orphaned progress file check: Also scan the phase directory for .PROGRESS-* files. These indicate an executor that crashed mid-task. For each orphaned progress file:
- Read it to find the
plan_id,last_completed_task, andtotal_tasks - If the plan is NOT in
checkpoints_resolved(not yet complete), inform the user:Detected interrupted execution for plan {plan_id}: {last_completed_task}/{total_tasks} tasks completed. - The executor will automatically resume from the progress file when spawned — no special action needed from the orchestrator.
- If the plan IS in
checkpoints_resolved, the progress file is stale — delete it.
For each wave, in order (Wave 1, then Wave 2, etc.):
6a. Spawn Executors
For each plan in the current wave (excluding skipped plans):
Local LLM plan quality check (optional, advisory):
Before spawning executors for this wave, if config.local_llm.enabled is true, run a quick classification on each plan to catch stubs before wasting an executor spawn:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js llm classify PLAN ".planning/phases/{NN}-{slug}/{plan_id}-PLAN.md"
- If classification is
"stub"or"partial"with confidence >= 0.7: warn the user before spawning:"⚠ Plan {plan_id} classified as {classification} (confidence {conf}) — consider refining before building." - If the command fails or returns null: skip silently (local LLM unavailable — not an error)
- This is advisory only — never block on the result
Present plan narrative before spawning:
Display to the user before spawning:
◐ Spawning {N} executor(s) for Wave {W}...
Then present a brief narrative for each plan to give the user context on what's about to happen:
Wave {W} — {N} plan(s):
Plan {id}: {plan name}
{2-3 sentence description: what this plan builds, the technical approach, and why it matters.
Derive this from the plan's must_haves and first task's <action> summary.}
Plan {id}: {plan name}
{2-3 sentence description}
This is a read-only presentation step — extract descriptions from plan frontmatter must_haves.truths and the plan's task names. Do not read full task bodies for this; keep it lightweight.
State fragment rule: Executors MUST NOT modify STATE.md directly. The build skill orchestrator is the sole STATE.md writer during execution. Executors report results via SUMMARY.md only; the orchestrator reads those summaries and updates STATE.md itself.
Model Selection (Adaptive): Before spawning the executor for each plan, determine the model:
- Read the plan's task elements for
complexityandmodelattributes - If ANY task has an explicit
modelattribute, use the most capable model among them (inherit > sonnet > haiku) - Otherwise, use the HIGHEST complexity among the plan's tasks to select the model:
- Look up
config.models.complexity_map.{complexity}(defaults: simple->haiku, medium->sonnet, complex->inherit)
- Look up
- If
config.models.executoris set (non-null), it overrides adaptive selection entirely — use that model for all executors - Pass the selected model to the Task() spawn
Reference: references/model-selection.md for full details.
- Extract the
## Summarysection from the PLAN.md (everything after the## Summaryheading to end of file). If no ## Summary section exists (legacy plans), fall back to reading the full PLAN.md content. Note: The orchestrator reads the full PLAN.md once for narrative extraction AND summary extraction; only the ## Summary portion is inlined into the executor prompt. The full PLAN.md stays on disk for the executor to Read. - Read
.planning/CONTEXT.md(if exists) - Read
.planning/STATE.md - Read prior SUMMARY.md files from the same phase (completed plans in earlier waves)
- Read
.planning/config.json
Construct the executor prompt by reading skills/build/templates/executor-prompt.md.tmpl and filling in all {placeholder} values:
{NN}-{slug}— phase directory (e.g.,02-authentication){plan_id}— plan being executed (e.g.,02-01){commit_format},{tdd_mode},{atomic_commits}— from loaded config- File paths: absolute paths to project root, config.json, STATE.md, CONTEXT.md
{prior_work table rows}— one row per completed plan in this phase
Use the filled template as the Task() prompt.
Spawn strategy based on config:
-
If
parallelization.enabled: trueAND multiple plans in this wave:- Spawn up to
max_concurrent_agentsTask() calls in parallel - Each Task() call is independent
- Use
run_in_background: truefor each executor - While waiting, display progress to the user:
- After spawning: "Wave {W}: launched {N} executors in parallel: {list of plan names}"
- Periodically (~30s): check
TaskOutputwithblock: falseand report status - When each completes: "Plan {id} complete ({duration})"
- When all complete: "Wave {W} finished. {passed}/{total} plans succeeded."
- Spawn up to
-
If
parallelization.enabled: falseOR single plan in wave:- Spawn Task() calls sequentially, one at a time
Task({
subagent_type: "pbr:executor",
prompt: <executor prompt constructed above>
})
NOTE: The pbr:executor subagent type auto-loads the agent definition.
After executor completes, check for completion markers: `## PLAN COMPLETE`, `## PLAN FAILED`, or `## CHECKPOINT: {TYPE}`. Route accordingly — PLAN COMPLETE proceeds to next plan, PLAN FAILED triggers failure handling, CHECKPOINT triggers checkpoint flow. Do NOT inline it.
Path resolution: Before constructing the agent prompt, resolve ${PLUGIN_ROOT} to its absolute path. Do not pass the variable literally in prompts — Task() contexts may not expand it. Use the resolved absolute path for any pbr-tools.js or template references included in the prompt.
6b. Wait for Wave Completion
Block until all executor Task() calls for this wave complete.
6c. Read Results
For each completed executor:
- Check if SUMMARY.md was written to the expected location
- Read the SUMMARY.md frontmatter (not the full body — keep context lean)
- Extract status:
completed|partial|checkpoint|failed - Display per-plan completion to the user:
Extract the brief summary from the SUMMARY.md frontmatter (use the✓ Plan {id} complete — {brief summary from SUMMARY.md frontmatter description or first key_file}descriptionfield if present, otherwise use the first entry fromkey_files). - Record commit hashes, files created, deviations
- Update checkpoint manifest
commit_log: For each completed plan, append{ plan: "{plan_id}", sha: "{commit_hash}", timestamp: "{ISO date}" }to thecommit_logarray. Updatelast_good_committo the last commit SHA from this wave.
Spot-check executor claims:
CRITICAL (no hook): Before reading results or advancing to the next wave, run the spot-check CLI for each completed plan.
For each completed plan in this wave:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js spot-check {phaseSlug} {planId}
Where {phaseSlug} is the phase directory name (e.g., 49-build-workflow-hardening) and {planId} is the plan identifier (e.g., 49-01).
The command returns JSON: { ok, summary_exists, key_files_checked, commits_present, detail }
If ok is false for ANY plan: STOP. Do NOT advance to the next wave. Present the user with:
Spot-check FAILED for plan {planId}: {detail}
Choose an action:
Retry — Re-spawn executor for this plan
Continue — Skip this plan and proceed to next wave (may leave phase incomplete)
Abort — Stop the build entirely
Use AskUserQuestion with the three options. Route:
- Retry: Re-spawn the executor for this plan (go back to Step 6a for this plan only)
- Continue: Log the failure, skip the plan, proceed
- Abort: Stop all build work, leave phase in partial state
If ok is true for all plans:
- Also check SUMMARY.md frontmatter for
self_check_failures: if present, warn the user: "Plan {id} reported self-check failures: {list}. Inspect before continuing?" - Also search SUMMARY.md for
## Self-Check: FAILEDmarker — if present, warn before next wave - Between waves: verify no file conflicts from parallel executors (
git statusfor uncommitted changes)
Read executor deviations: After all executors in the wave complete, read all SUMMARY frontmatter and:
- Collect
deferreditems into a running list (append to.checkpoint-manifest.jsondeferred array) - Flag any deviation-rule-4 (architectural) stops — these require user attention
- Present a brief wave summary to the user: "Wave {W} complete. {N} plans done. {D} deferred ideas logged. {A} architectural issues."
Build a wave results table:
Wave {W} Results:
| Plan | Status | Tasks | Commits | Deviations |
|------|--------|-------|---------|------------|
| {id} | complete | 3/3 | abc, def, ghi | 0 |
| {id} | complete | 2/2 | jkl, mno | 1 |
6c-ii. Inline Per-Task Verification (conditional)
Skip if the depth profile has features.inline_verify: false.
To check: use the resolved depth profile. Only comprehensive mode enables inline verification by default. When inline verification is enabled, each completed plan gets a targeted verification pass before the orchestrator proceeds to the next wave — catching issues early before dependent plans build on a broken foundation.
For each plan that completed successfully in this wave:
-
Read the plan's SUMMARY.md to get
key_files(the files this plan created/modified) -
Display to the user:
◐ Spawning inline verifier for plan {plan_id}...Spawn
Task({ subagent_type: "pbr:verifier", model: "haiku", prompt: ... }). Readskills/build/templates/inline-verifier-prompt.md.tmpland fill in{NN}-{slug},{plan_id}, and{comma-separated key_files list}(key_files from PLAN.md frontmatter). Use the filled template as thepromptvalue. -
If verifier reports FAIL for any file:
- Present the failure to the user: "Inline verify failed for plan {plan_id}: {details}"
- Re-spawn the executor for just the failed items: include only the failing file context in the prompt
- If the retry also fails: proceed but flag in the wave results table (don't block indefinitely)
-
If verifier reports all PASS: continue to next wave
Note: This adds latency (~10-20s per plan for the haiku verifier). It's opt-in via features.inline_verify: true for projects where early detection outweighs speed.
6d. Handle Failures
If any executor returned failed or partial:
Handoff bug check (false-failure detection):
Before presenting failure options, check whether the executor actually completed its work despite reporting failure (known Claude Code platform bug where handoff reports failure but work is done):
- Check if SUMMARY.md exists at the expected path for this plan
- If SUMMARY.md exists:
a. Read its frontmatter
statusfield b. Ifstatus: completeAND frontmatter hascommitsentries:- Run the same spot-checks from Step 6c (file existence, commit count)
- If spot-checks pass: treat this plan as success, not failure
- Tell user: "Plan {id} reported failure but SUMMARY.md shows completed work. Spot-checks passed — treating as success."
- Skip the failure flow for this plan
c. If
status: partialor spot-checks fail: proceed with normal failure handling below
Present failure details to the user:
Plan {id} {status}:
Task {N}: {name} - FAILED
Error: {verify output or error message}
Deviations attempted: {count}
Last verify output: {output}
Use AskUserQuestion (pattern: multi-option-failure from skills/shared/gate-prompts.md):
question: "Plan {id} failed at task {N} ({name}). How should we proceed?"
header: "Failed"
options:
- label: "Retry" description: "Re-spawn the executor for this plan"
- label: "Skip" description: "Mark as skipped, continue to next wave"
- label: "Rollback" description: "Undo commits from this plan, revert to last good state"
- label: "Abort" description: "Stop the entire build"
If user selects 'Retry':
- Re-spawn executor Task() with the same prompt
- If retry also fails: ask user again (max 2 retries total)
If user selects 'Skip':
- Note the skip in results
- Check if any plans in later waves depend on the skipped plan
- If yes: warn user that those plans will also need to be skipped or adjusted
If user selects 'Rollback': Run the rollback CLI:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js rollback .planning/phases/{NN}-{slug}/.checkpoint-manifest.json
Returns { ok, rolled_back_to, plans_invalidated, files_deleted, warnings }.
- If
okistrue: display "Rolled back to commit {rolled_back_to}. {plans_invalidated.length} downstream plans invalidated." Show any warnings. Continue to next wave or stop based on user preference. - If
okisfalse: display the error message. Suggest "Use abort instead."
If user selects 'Abort':
- Update STATE.md with current progress
- Present what was completed before the abort
- Suggest: "Fix the issue and run
$pbr-build {N}to resume (completed plans will be skipped)"
6e. Handle Checkpoints
If any executor returned checkpoint:
- Read the checkpoint details from the executor's response
- Present the checkpoint to the user:
Checkpoint in Plan {id}, Task {N}: {checkpoint type}
{checkpoint details — what was built, what is needed}
{For decision type: present options}
{For human-action type: present steps}
{For human-verify type: present what to verify}
- Wait for user response
- Spawn a FRESH continuation executor:
Reference: references/continuation-format.md for the continuation protocol.
Read skills/build/templates/continuation-prompt.md.tmpl and fill in:
{NN}-{slug},{plan_id}— current phase and plan{plan_summary}— the ## Summary section from PLAN.md{task table rows}— one row per task with completion status{user's response}— the checkpoint resolution from Step 3{project context key-values}— config values + file paths
Use the filled template as the Task() prompt.
6e-ii. CI Gate (after wave completion, conditional)
If config.ci.gate_enabled is true AND config.git.branching is not none:
- Push current commits:
git push - Wait 5 seconds for CI to trigger
- Get the current run ID:
gh run list --branch $(git branch --show-current) --limit 1 --json databaseId -q '.[0].databaseId' - Poll CI status using CLI:
Returnsnode ${PLUGIN_ROOT}/scripts/pbr-tools.js ci-poll <run-id> [--timeout <seconds>]{ status, conclusion, url, next_action, elapsed_seconds }. - If
next_actionis"continue": proceed to next wave - If
next_actionis"wait": re-run ci-poll after 15 seconds (repeat up toconfig.ci.wait_timeout_seconds) - If
next_actionis"abort"orstatusis"failed": Show warning box and use AskUserQuestion: Wait / Continue anyway / Abort - If "Continue anyway": log deviation —
DEVIATION: CI gate bypassed for wave {N} - If "Abort": stop build, update STATE.md
6f. Update STATE.md
After each wave completes (all plans in the wave are done, skipped, or aborted):
SUMMARY gate — verify before updating STATE.md: For every plan in the wave, run:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js summary-gate {phase-slug} {plan-id}
Returns { ok: bool, gate: string, detail: string }. Block STATE.md update until ALL plans return ok: true. If any fail, warn: "SUMMARY gate failed for plan {id}: {gate} — {detail}. Cannot update STATE.md."
Once gates pass, update .planning/STATE.md:
Tooling shortcut: Use the CLI for atomic STATE.md updates instead of manual read-modify-write:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js state update plans_complete {N}
node ${PLUGIN_ROOT}/scripts/pbr-tools.js state update status building
node ${PLUGIN_ROOT}/scripts/pbr-tools.js state update last_activity now
- Current plan progress: "{completed}/{total} in current phase"
- Last activity timestamp
- Progress bar percentage
- Any new decisions from executor deviations
STATE.md size limit: Follow the size limit enforcement rules in skills/shared/state-update.md (150 lines max — collapse completed phases, remove duplicated decisions, trim old sessions).
Completion check: Before proceeding to next wave, confirm ALL of:
- SUMMARY gate passed for every plan in this wave
- STATE.md frontmatter
plans_completeupdated - STATE.md body progress bar updated
-
last_activitytimestamp refreshed
To verify programmatically: node ${PLUGIN_ROOT}/scripts/pbr-tools.js step-verify build step-6f '["STATE.md updated","SUMMARY.md exists","commit made"]'
If any item fails, investigate before proceeding to Step 7.
Step 7: Phase Verification (delegated, conditional)
Event-driven auto-verify signal: Check if .planning/.auto-verify exists (written by event-handler.js SubagentStop hook). If the signal file exists, read it and delete it (one-shot). The signal confirms that auto-verification was triggered — proceed with verification even if the build just finished.
Skip if:
- Build was aborted
- Depth profile has
features.goal_verification: false - Depth is
quickAND the total task count across all plans in this phase is fewer than 3
To check: run node ${PLUGIN_ROOT}/scripts/pbr-tools.js config resolve-depth and read profile["features.goal_verification"]. For the task-count check in quick mode, sum the task counts from all PLAN.md frontmatter must_haves (already available from Step 3 plan discovery).
This implements budget mode's "skip verifier for < 3 tasks" rule: small phases in quick mode don't need a full verification pass.
If skipping because features.goal_verification is false:
Note for Step 8f completion summary: append "Note: Automatic verification was skipped (goal_verification: false). Run $pbr-review {N} to verify what was built."
If verification is enabled:
Display to the user: ◐ Spawning verifier...
Spawn a verifier Task():
Task({
subagent_type: "pbr:verifier",
prompt: <verifier prompt>
})
NOTE: The pbr:verifier subagent type auto-loads the agent definition. Do NOT inline it.
After verifier completes, check for completion marker: `## VERIFICATION COMPLETE`. Read VERIFICATION.md frontmatter for status.
Path resolution: Before constructing the agent prompt, resolve ${PLUGIN_ROOT} to its absolute path. Do not pass the variable literally in prompts — Task() contexts may not expand it. Use the resolved absolute path for any pbr-tools.js or template references included in the prompt.
Verifier Prompt Template
Use the same verifier prompt template as defined in $pbr-review: read skills/review/templates/verifier-prompt.md.tmpl and fill in its placeholders with the phase's PLAN.md must_haves and SUMMARY.md file paths. This avoids maintaining duplicate verifier prompts across skills.
Prepend this block to the verifier prompt before sending:
<files_to_read>
CRITICAL (no hook): Read these files BEFORE any other action:
1. .planning/phases/{NN}-{slug}/PLAN-*.md — must-haves to verify against
2. .planning/phases/{NN}-{slug}/SUMMARY-*.md — executor build summaries
3. .planning/phases/{NN}-{slug}/VERIFICATION.md — prior verification results (if exists)
</files_to_read>
After the verifier returns, read the VERIFICATION.md frontmatter and display the results:
- If status is
passed: display✓ Verifier: {X}/{Y} must-haves verified(where X =must_haves_passedand Y =must_haves_checked) - If status is
gaps_found: display⚠ Verifier found {N} gap(s) — see VERIFICATION.md(where N =must_haves_failed)
Step 8: Finalize (inline)
After all waves complete and optional verification runs:
8-pre. Re-verify after gap closure (conditional):
If --gaps-only flag was used AND features.goal_verification is true:
- Delete the existing
VERIFICATION.md(it reflects pre-gap-closure state) - Re-run the verifier using the same Step 7 process — this produces a fresh
VERIFICATION.mdthat accounts for the gap-closure work - Read the new verification status for use in determining
final_statusbelow
This ensures that $pbr-review after a --gaps-only build sees the updated verification state, not stale gaps from before the fix.
8-pre-b. Determine final status based on verification:
- If verification ran and status is
passed: final_status = "built" - If verification ran and status is
gaps_found: final_status = "built*" (built with unverified gaps) - If verification was skipped: final_status = "built (unverified)"
- If build was partial: final_status = "partial"
8-pre-c. Codebase map incremental update (conditional):
CRITICAL (no hook): Run codebase map update if conditions are met. Do NOT skip this step.
Only run if ALL of these are true:
.planning/codebase/directory exists (project was previously scanned with$pbr-scan)- Build was not aborted
git diff --name-only {pre_build_commit}..HEADshows >5 files changed ORpackage.json/requirements.txt/go.mod/Cargo.tomlwas modified
If triggered:
-
Record the pre-build commit SHA at the start of Step 1 (before any executors run) for comparison
-
Run
git diff --name-only {pre_build_commit}..HEADto get the list of changed files -
Display to the user:
◐ Spawning codebase mapper (incremental update)...Spawn a lightweight mapper Task():
Task({ subagent_type: "pbr:codebase-mapper", model: "haiku", prompt: "Incremental codebase map update. These files changed during the Phase {N} build:\n{diff file list}\n\nRead the existing .planning/codebase/ documents. Update ONLY the sections affected by these changes. Do NOT rewrite entire documents — make targeted updates. If a new dependency was added, update STACK.md. If new directories/modules were created, update STRUCTURE.md. If new patterns were introduced, update CONVENTIONS.md. Write updated files to .planning/codebase/." }) -
Do NOT block on this — use
run_in_background: trueand continue to Step 8a. Report completion in Step 8f if it finishes in time.
CRITICAL (no hook): Update ROADMAP.md progress table NOW. Do NOT skip this step. (roadmap-sync warns)
8a. Update ROADMAP.md Progress table (REQUIRED — do this BEFORE updating STATE.md):
Tooling shortcut: Use the CLI for atomic ROADMAP.md table updates instead of manual editing:
node ${PLUGIN_ROOT}/scripts/pbr-tools.js roadmap update-plans {phase} {completed} {total}
node ${PLUGIN_ROOT}/scripts/pbr-tools.js roadmap update-status {phase} {final_status}
These return { success, old_status, new_status } or { success, old_plans, new_plans }. Falls back to manual editing if unavailable.
- Open
.planning/ROADMAP.md - Find the
## Progresstable - Locate the row matching this phase number
- Update the
Plans Completecolumn to{completed}/{total}(e.g.,2/2if all plans built successfully) - Update the
Statuscolumn to the final_status determined in Step 8-pre - Save the file — do NOT skip this step
CRITICAL (no hook): Update STATE.md NOW with phase completion status. Do NOT skip this step. (state-sync warns)
8b. Update STATE.md (CRITICAL (no hook) — update BOTH frontmatter AND body):
- Frontmatter:
status,plans_complete,last_activity,progress_percent,last_command - Body
## Current Position:Phase:line,Plan:line,Status:line,Last activity:line,Progress:bar - These MUST stay in sync — the status line reads frontmatter, humans read the body
Completion check: Before proceeding to 8c, confirm ALL of:
- STATE.md frontmatter fields set: status, plans_complete, last_activity, progress_percent, last_command
- STATE.md body ## Current Position updated: Phase, Status, Last activity, Progress bar
- Frontmatter and body are consistent (same status value in both)
To verify programmatically: node ${PLUGIN_ROOT}/scripts/pbr-tools.js step-verify build step-8b '["STATE.md updated","ROADMAP.md updated","commit made"]'
If any item fails, investigate before marking phase complete.
8c. Commit planning docs (if configured):
Reference: skills/shared/commit-planning-docs.md for the standard commit pattern.
If planning.commit_docs is true:
- Stage SUMMARY.md files and VERIFICATION.md
- Commit:
docs({phase}): add build summaries and verification
8d. Handle git branching:
If git.branching is phase:
- All work was done on the phase branch (created in Step 1)
- Squash merge to main:
git checkout main && git merge --squash plan-build-run/phase-{NN}-{name} - Use AskUserQuestion (pattern: yes-no from
skills/shared/gate-prompts.md): question: "Phase {N} complete on branchplan-build-run/phase-{NN}-{name}. Squash merge to main?" header: "Merge?" options:- label: "Yes, merge" description: "Squash merge to main and delete the phase branch"
- label: "No, keep" description: "Leave the branch as-is for manual review"
- If "Yes, merge": complete the merge and delete the phase branch
- If "No, keep" or "Other": leave the branch as-is and inform the user
8d-ii. PR Creation (when branching enabled):
If config.git.branching is phase or milestone AND phase verification passed:
- Push the phase branch:
git push -u origin {branch-name} - If
config.git.auto_pristrue:- Run: `gh pr create --title "feat({phase-scope}): {phase-slug}" --body "$(cat <<'EOF'
Phase {N}: {phase name}
Goal: {phase goal from ROADMAP.md}
Key Files
{key_files from SUMMARY.md, bulleted}
Verification
{pass/fail status from VERIFICATION.md}
Generated by Plan-Build-Run
EOF
)"3. Ifconfig.git.auto_prisfalse`:
- Use AskUserQuestion to ask: "Phase branch pushed. Create a PR?"
- Options: Yes (create PR as above) / No / Later (skip)
8e. Auto-advance / auto-continue (conditional):
If features.auto_advance is true AND mode is autonomous:
Chain to the next skill directly within this session. This eliminates manual phase cycling.
| Build Result | Next Action | How |
|---|---|---|
| Verification passed, more phases | Plan next phase | Skill({ skill: "pbr:plan", args: "{N+1}" }) |
| Verification skipped | Run review | Skill({ skill: "pbr:review", args: "{N}" }) |
| Verification gaps found | HARD STOP — present gaps to user | If auto_continue also true: write .planning/.auto-next with $pbr-review {N} before stopping. Do NOT auto-advance past failures. |
| Last phase in current milestone | HARD STOP — milestone boundary | If auto_continue also true: write .planning/.auto-next with $pbr-milestone complete before stopping. Suggest $pbr-milestone audit. Explain: "auto_advance pauses at milestone boundaries — your sign-off is required." |
| Build errors occurred | HARD STOP — errors need human review | If auto_continue also true: write .planning/.auto-next with $pbr-build {N} before stopping. Do NOT auto-advance past errors. |
After invoking the chained skill, it runs within the same session. When it completes, the chained skill may itself chain further (review→plan, plan→build) if auto_advance remains true. This creates the full cycle: build→review→plan→build→...
Else if features.auto_continue is true:
Write .planning/.auto-next containing the next logical command (e.g., $pbr-plan {N+1} or $pbr-review {N})
- This file signals to the user or to wrapper scripts that the next step is ready
Completion check: Before proceeding to 8f, confirm ALL of:
- auto_advance OR auto_continue evaluated (one path taken)
- If auto_continue:
.auto-nextfile written with correct next command - Pending todos evaluated (Step 8e-ii)
- Clearly-satisfied todos auto-closed via
pbr-tools.js todo done
To verify programmatically: node ${PLUGIN_ROOT}/scripts/pbr-tools.js step-verify build step-8e '["STATE.md updated","commit made"]'
If any item fails, investigate before closing the session.
8e-ii. Check Pending Todos:
CRITICAL (no hook): Check pending todos after build. Do NOT skip this step.
After completing the build, check if any pending todos are now satisfied:
- Check if
.planning/todos/pending/exists and contains files - If no pending todos: skip to 8f
- If pending todos exist:
a. Read the title and description from each pending todo's YAML frontmatter
b. Compare each todo against the phase work (plans executed, files changed, features built)
c. If a todo is clearly satisfied: move it to
.planning/todos/done/, updatestatus: done, addcompleted: {YYYY-MM-DD}, delete frompending/via Bashrm. Display:✓ Auto-closed todo {NNN}: {title} (satisfied by Phase {N} build)d. If partially related: displayℹ Related pending todo {NNN}: {title} — may be partially addressede. If unrelated: skip silently
Only auto-close when the match is unambiguous. When in doubt, leave it open.
8f. Present completion summary:
Use the branded output templates from references/ui-formatting.md. Route based on status:
| Status | Template |
|---|---|
passed + more phases in current milestone | "Phase Complete" template |
passed + last phase in current milestone | "Milestone Complete" template |
Milestone boundary detection: To determine "last phase in current milestone", read ROADMAP.md and find the ## Milestone: section containing the current phase. Check its **Phases:** start - end range. If the current phase equals end, this is the last phase in the milestone. For projects with a single milestone or no explicit milestone sections, "last phase in ROADMAP" is equivalent.
| gaps_found | "Gaps Found" template |
Before the branded banner, include the results table:
Results:
| Plan | Status | Tasks | Commits |
|------|--------|-------|---------|
| {id} | complete | 3/3 | 3 |
| {id} | complete | 2/2 | 2 |
{If verification ran:}
Verification: {PASSED | GAPS_FOUND}
{count} must-haves checked, {count} passed, {count} gaps
Total commits: {count}
Total files created: {count}
Total files modified: {count}
Deviations: {count}
Then present the appropriate branded banner from Read references/ui-formatting.md § "Completion Summary Templates":
- If
passed+ more phases: Use the "Phase Complete" template. Fill in phase number, name, plan count, and next phase details. - If
passed+ last phase: Use the "Milestone Complete" template. Fill in phase count. - If
gaps_found: Use the "Gaps Found" template. Fill in phase number, name, score, and gap summaries from VERIFICATION.md.
Include <sub>/clear first → fresh context window</sub> inside the Next Up routing block of the completion template.
8g. Display USER-SETUP.md (conditional):
Check if .planning/phases/{NN}-{slug}/USER-SETUP.md exists. If it does:
Setup Required:
This phase introduced external setup requirements. See the details below
or read .planning/phases/{NN}-{slug}/USER-SETUP.md directly.
{Read and display the USER-SETUP.md content — it's typically short}
This ensures the user sees setup requirements prominently instead of buried in SUMMARY files.
Error Handling
Executor agent timeout
If a Task() doesn't return within a reasonable time, display:
╔══════════════════════════════════════════════════════════════╗
║ ERROR ║
╚══════════════════════════════════════════════════════════════╝
Executor agent timed out for Plan {id}.
**To fix:** Check `.planning/phases/{NN}-{slug}/` for partial SUMMARY.md, then retry or skip.
Treat as partial status. Present to user: retry or skip.
For commit conventions and git workflow details, see references/git-integration.md.
Git lock conflicts
If multiple parallel executors create git lock conflicts:
- The executor agent handles retries internally (see executor agent definition)
- If lock conflicts persist, display:
⚠ Git lock conflicts detected with parallel execution. Consider reducing max_concurrent_agents to 1.
Executor produces unexpected files
If SUMMARY.md shows files not listed in the plan's files_modified:
- Note the discrepancy in the wave results
- Do not fail — the executor's deviation rules may have required additional files
- Flag for review: "Plan {id} modified files not in the plan: {list}"
Build on wrong branch
If git.branching is phase but we're not on the phase branch:
- Create the phase branch:
git checkout -b plan-build-run/phase-{NN}-{name} - Proceed with build on the new branch
Files Created/Modified by $pbr-build
| File | Purpose | When |
|---|---|---|
.planning/phases/{NN}-{slug}/.checkpoint-manifest.json | Execution progress for crash recovery | Step 5b, updated each wave |
.planning/phases/{NN}-{slug}/SUMMARY-{plan_id}.md | Per-plan build summary | Step 6 (each executor) |
.planning/phases/{NN}-{slug}/USER-SETUP.md | External setup requirements | Step 6 (executor, if needed) |
.planning/phases/{NN}-{slug}/VERIFICATION.md | Phase verification report | Step 7 |
.planning/codebase/*.md | Incremental codebase map updates | Step 8-pre-c (if codebase/ exists) |
.planning/ROADMAP.md | Plans Complete + Status → built or partial | Step 8a |
.planning/STATE.md | Updated progress | Steps 6f, 8b |
.planning/.auto-next | Next command signal (if auto_continue enabled) | Step 8e |
| Project source files | Actual code | Step 6 (executors) |
Cleanup
Delete .planning/.active-skill if it exists. This must happen on all paths (success, partial, and failure) before reporting results.
Source
git clone https://github.com/SienkLogic/plan-build-run/blob/main/plugins/codex-pbr/skills/build/SKILL.mdView on GitHub Overview
The build skill acts as the phase orchestration layer for $pbr-build. It spawns executor Task() agents to run plans in parallel within waves, and commits changes atomically once the phase completes. This lean approach keeps the user context clean while maximizing throughput.
How This Skill Works
It reads the planning structure and delegates all building work to Task() agents, coordinating waves so independent plans run in parallel while dependent plans wait. It minimizes output by reading only SUMMARY.md frontmatter and uses lazy-loading to fetch the next steps on demand.
When to Use It
- Execute all plans in a phase with parallelizable tasks
- Handle waves where independent plans run in parallel and dependencies enforce order
- Keep the orchestration lean by delegating builds to Task() agents
- Require atomic commits after the entire phase succeeds
- Preview a phase to estimate spawns and output without executing
Quick Start
- Step 1: Ensure .planning/config.json exists and phase plan is ready
- Step 2: Run the build for the target phase using the CLI (e.g., build {phase-slug})
- Step 3: Review the atomic commit result and check for any failed tasks
Best Practices
- Structure plans into waves with clear dependencies before starting
- Leverage parallel execution within a wave to speed up builds
- Delegate all build work to Task() agents and monitor via summarized output
- Validate .planning/config.json and phase planning before Step 1
- Use the --preview option to sanity-check phase flow and spawns
Example Use Cases
- Two-wave build: Wave 1 builds libs in parallel; Wave 2 builds services once libs succeed, with an atomic commit at the end
- Ten microservices built in parallel within each wave, reducing total build time significantly
- Complex interdependencies coordinated with Agent Teams for cross-service coordination
- Preview mode to estimate agent spawns and file changes before committing to execution
- Minimal executor output by focusing on SUMMARY.md frontmatter to keep logs clean