---
name: ensemble-beads-build
description: Drive an existing bead hierarchy to completion through the full builder, code-review, and close pipeline (Codex skill for /ensemble:beads-build)
user-invocable: true
argument-hint: '[epic-id|slug-pattern] [--trd trd-path] [--strategy tdd|characterization|bug-fix|refactor|test-after|flexible] [max parallel N]'
model: medium
---

# Ensemble Command: /ensemble:beads-build

This Codex skill mirrors the Ensemble slash command `/ensemble:beads-build`.
Follow the workflow below, adapt to the current repository, and keep outputs structured.

<!-- DO NOT EDIT - Generated from beads-build.yaml -->
<!-- To modify this file, edit the YAML source and run: npm run generate -->


Drive an existing bead hierarchy (epic -> stories -> tasks) to completion through
the full builder -> code-review -> close pipeline. This is the canonical build
engine — works for raw beads with no TRD required. implement-trd-beads --execute
is effectively a TRD-augmented version of this command.

Uses bv --robot-next for graph-aware task selection (required) or br ready as
fallback. Records all state transitions in beads for cross-session resumability.
When --trd is provided, enables TRD augmentations: traceability tokens, TRD
checkbox sync, and requirement satisfaction report.

Key behaviors:
- bv --robot-next determines what to run next (fallback: br ready)
- Quality gates: phase completion triggers test delegation; results recorded as br comments
- Sync: br sync --flush-only before every bv call
- Wheel instructions: printed every run with NTM spawn commands for multi-agent flywheel
- Graceful degradation: bv features skipped if bv unavailable; br required
- TRD mode: optional --trd flag enables traceability tokens, checkbox sync, requirement report

## Workflow

### Phase 1: Preflight

**1. Argument Parsing**
   Parse epic-id or slug pattern, --trd path, --strategy, and max parallel N

   - Parse $ARGUMENTS: if first token matches pattern beads-NNN or a numeric ID, treat as direct epic bead ID (EPIC_ID_MODE=true); otherwise treat as slug pattern (EPIC_ID_MODE=false)
   - Parse --trd <path> from $ARGUMENTS (optional); if present set TRD_MODE=true and TRD_PATH=<path>; if absent set TRD_MODE=false
   - Parse --strategy <value> from $ARGUMENTS (optional); valid values: tdd, characterization, bug-fix, refactor, test-after, flexible
   - Parse "max parallel N" from $ARGUMENTS (e.g., "max parallel 3") — default MAX_PARALLEL=1 if not present

**2. Tool Availability Check**
   Verify br is installed and detect bv availability

   - "which br || { echo 'ERROR: br (beads_rust) not installed. Install from https://github.com/Dicklesworthstone/beads_rust'; exit 1; }"
   - "br list --status=open > /dev/null 2>&1 || { echo 'ERROR: br not functional'; exit 1; }"
   - "which bv && BV_AVAILABLE=true || { echo 'WARNING: bv (beads_viewer) not installed. Graph-aware triage will be unavailable. Install from https://github.com/Dicklesworthstone/beads_viewer'; BV_AVAILABLE=false; }"

**3. Git-Town and Working Directory Verification**
   Verify git-town is installed and the working directory is clean

   - Run: bash packages/git/skills/git-town/scripts/validate-git-town.sh — handle exit codes 0 (ok), 1 (not installed), 2 (not configured), 3 (version mismatch), 4 (not git repo)
   - Run: git status --porcelain — HALT if output non-empty (dirty working directory)

**4. Epic Discovery**
   Locate the root epic bead using the provided ID or slug pattern, detect cross-session resume

   - If EPIC_ID_MODE=true: run br show <RAW_INPUT> to confirm epic exists; if exit code != 0 print "ERROR: Bead <RAW_INPUT> not found." and HALT; store ROOT_EPIC_ID=RAW_INPUT; derive EPIC_SLUG from bead title
   - If EPIC_ID_MODE=false: run br list --status=open --json; parse JSON array; scan .title fields for entries containing RAW_INPUT as substring (case-insensitive); collect matches
   - If zero matches found: print "ERROR: No open epic found matching slug pattern '<RAW_INPUT>'." and HALT
   - If multiple matches found: print "ERROR: Multiple epics match '<RAW_INPUT>':" followed by each matching title; HALT
   - If exactly one match: store ROOT_EPIC_ID from .id field; derive EPIC_SLUG (lowercase, replace non-alphanumeric with hyphens, strip leading/trailing hyphens)
   - Check for existing in-progress tasks: run br list --status=in_progress --json; filter by EPIC_SLUG prefix; count IN_PROGRESS_COUNT
   - If IN_PROGRESS_COUNT > 0: print "Resume detected: <IN_PROGRESS_COUNT> tasks already in_progress. Resuming from current state." and print bead IDs with their titles

**5. TRD Augmentation Setup**
   Validate TRD file and build traceability map when TRD_MODE is enabled

   - If TRD_MODE=false: set TASK_TRACEABILITY={} (empty); skip remaining steps in this phase step; print "TRD augmentations: disabled (no --trd flag)"
   - If TRD_MODE=true: verify TRD_PATH file exists on disk; if not found print "ERROR: TRD file not found at <TRD_PATH>" and HALT
   - Read TRD file; parse YAML frontmatter block (between --- delimiters) for design_readiness_score field
   - If score >= 4.0 (PASS): print "Design Readiness: PASS (<score>)" and continue
   - If score >= 3.0 AND < 4.0 (CONCERNS): print "WARNING: TRD has Design Readiness score of <score> (CONCERNS). Consider running /ensemble:refine-trd before implementation."
   - If score < 3.0 (FAIL): print "ERROR: TRD has Design Readiness score of <score> (FAIL). Run /ensemble:refine-trd to improve the TRD before implementation." and HALT
   - If no design_readiness_score found: print "NOTE: No Design Readiness score found (pre-v3.0.0 TRD). Consider running /ensemble:refine-trd." and continue
   - Build TASK_TRACEABILITY map: scan TRD for [satisfies REQ-NNN], [satisfies INFRA], [satisfies ARCH], [verifies TRD-NNN], "Validates PRD ACs:" fields, "Implementation AC:" blocks, "Proof of requirement:" fields per task; store in map keyed by task.id
   - Classify task type: if task.id ends in -TEST suffix, mark is_test_task=true; extract verifies_task_id and satisfies_req_id; store in TASK_TRACEABILITY[task.id]
   - Print "TRD augmentations: enabled (traceability, checkbox sync, requirement report)"

**6. Strategy Detection**
   Determine implementation strategy from arguments, TRD content, or auto-detection

   - Priority: --strategy arg -> TRD explicit (if TRD_MODE) -> auto-detect from bead titles/descriptions -> default (tdd)
   - Auto-detect: legacy/brownfield/untested -> characterization; bug fix/regression -> bug-fix; refactor/tech debt -> refactor; prototype/spike/POC -> test-after; default -> tdd
   - Store STRATEGY; print "Strategy: <STRATEGY>"

**7. Team Configuration Detection**
   Detect team configuration from --team-config argument or bead metadata, default to single-agent

   - If TRD_MODE=true: check TRD "## Team Configuration" section; if found parse YAML block; validate schema (roles array, lead and builder roles required); set TEAM_MODE=true, TEAM_ROLES; else fall through
   - If TRD_MODE=false: check $ARGUMENTS for --team-config <yaml-snippet>; if found parse snippet; else check bead metadata comments on ROOT_EPIC_ID for team config; if found parse and set TEAM_MODE=true
   - If no team config found: set TEAM_MODE=false (single-agent); print "TEAM MODE: disabled (single-agent execution)"
   - If TEAM_MODE=true: extract REVIEWER_ENABLED (true if reviewer role present), QA_ENABLED (true if qa role present); print team configuration summary

### Phase 2: Execute

**1. Execution Loop**
   Poll bv robot-next (or br ready) and execute tasks until epic is complete. NOTE: This Execute phase implements the same execution engine as /ensemble:implement-trd-beads. If you want to drive a TRD-generated hierarchy with full TRD augmentations use /ensemble:implement-trd-beads <trd-path>.

   - NOTE: This Execute phase implements the same execution engine as /ensemble:beads-build. If you have raw beads (not from a TRD), use /ensemble:beads-build <epic-id> instead. beads-build also accepts --trd <path> to enable TRD augmentations on any bead hierarchy.
   - TASK_TRACEABILITY rebuild guard: if TRD_MODE=true AND TASK_TRACEABILITY is empty (cross-session resume): re-parse TRD to rebuild TASK_TRACEABILITY (re-run Preflight step 5 passes for [satisfies], [verifies], validation ACs, and test task classification); print "NOTE: TASK_TRACEABILITY rebuilt from TRD (cross-session resume). Tasks: <N>"
   - If TRD_MODE=false: TASK_TRACEABILITY remains empty; print "NOTE: TRD augmentations disabled — traceability tokens will not be written."
   - Context Budget Monitoring (applies to both TEAM_MODE=true and TEAM_MODE=false):
   -   After every 5 task completions OR after any task that produces more than 500 lines of output:
   -     Print context budget warning: "Context checkpoint: <N> tasks completed this session. If quality is degrading, consider:"
   -     "  1. /compact to compress conversation context"
   -     "  2. Start a new session with /ensemble:beads-build <ROOT_EPIC_ID> (beads preserve all state)"
   -     "  3. Use max parallel N to delegate more work to fresh-context subagents"
   -   This is informational only — do not halt or pause execution
   - 
   - TEAM_MODE Gate (evaluated once at the start of the Execute phase):
   -   if TEAM_MODE == false:
   -     - Use the single-agent Execute loop (all steps 1-6 below)
   -     - Skip all team-specific steps (reviewer delegation, QA delegation, rejection loop, parallel builders)
   -     - Quality Gate phase: run full scope
   -     - Continue to LOOP below
   -   if TEAM_MODE == true:
   -     - Replace the standard execution loop with the Lead Orchestration Loop below
   -     - Reviewer delegation: enabled
   -     - QA delegation: enabled if QA_ENABLED=true
   -     - Parallel builder slots: active
   -     - Quality Gate phase: reduced scope if QA_ENABLED=true
   -     - Note: v2.1.0 beads without status: comments are treated as in_progress (builder stage) — safe default for backward compat
   -     - RETURN (team loop handles all remaining execution; skip LOOP below)
   - 
   -     LEAD ORCHESTRATION LOOP (TEAM_MODE=true):
   - 
   -     Variables: active_builders = {} (bead_id -> builder_agent)
   - 
   -     LOOP:
   -       1. br sync --flush-only (ensure JSONL current)
   - 
   -       2. Check in-flight tasks (tasks with br native status=in_progress that have sub-states in_review or in_qa):
   -          - Run: br list --status=in_progress --json, filter by EPIC_SLUG
   -          - For each in-progress bead: call get_sub_state(bead_id)
   -            - If sub_state == 'in_review': proceed to Reviewer Delegation step (step 3a)
   -            - If sub_state == 'in_qa': proceed to QA Delegation step (step 3b)
   -            - If sub_state == 'in_progress': task is with builder (normal)
   - 
   -       3. Count available slots: available_slots = MAX_PARALLEL - len(active_builders)
   - 
   -       4. If available_slots > 0:
   -          - Get next tasks: if BV_AVAILABLE, run bv --robot-next --format toon; else run br ready filtered by EPIC_SLUG prefix
   -          - For each task (up to available_slots):
   -            a. Architecture Review: check task description for keywords: 'architecture', 'design', 'system', 'cross-cutting', 'multi-component', 'orchestrat'
   -               If ANY keyword found: lead performs brief architectural review; generate guidance notes; record: br comment add <bead_id> 'architecture-review lead:<agent> guidance:<url_encoded_summary>'; include guidance in builder prompt
   -            b. Lead Skip Decision: evaluate task characteristics before delegating to builder
   -               If task is documentation-only: SKIP_REVIEW=true, SKIP_QA=true
   -               If REVIEWER_ENABLED=false: SKIP_REVIEW=true; If QA_ENABLED=false: SKIP_QA=true
   -               Record skip decisions via br comment add; transition directly based on skip flags
   -            c. Sibling Task Context: collect completed sibling tasks in same phase (up to 5 most recent closed)
   -               Add to builder prompt if siblings found
   -            d. Select builder from TEAM_ROLES.builder.agents using keyword matching
   -            e. validate_transition(bead_id, 'in_progress') — write status comment
   -            f. Delegate to builder via Task(subagent_type=<builder>, prompt=<builder_prompt>)
   -            g. active_builders[bead_id] = builder
   - 
   -       5. Check loop exit:
   -          - If no tasks returned by bv/br AND no active_builders AND no in-flight tasks: break to Completion
   -          - If no tasks returned but tasks exist in_review or in_qa: wait (check in-flight tasks next iteration)
   - 
   -       6. br sync --flush-only
   -       7. Continue LOOP
   - LOOP:
   - Run: br sync --flush-only (ensure JSONL current before bv call)
   - If BV_AVAILABLE: run bv --robot-next --format toon to get single top-priority task
   - If not BV_AVAILABLE: run br ready, filter by title prefix [<EPIC_SLUG>] or [trd:<EPIC_SLUG>:task:]
   - If no tasks returned: run br list --status=open --json filtered by EPIC_SLUG; if no open tasks remain break to Completion; else PAUSE (possible dependency cycle)
   - If MAX_PARALLEL==1 or single task ready: execute_single_task
   - Else if BV_AVAILABLE: use bv --robot-plan --format toon for parallel tracks; take up to MAX_PARALLEL candidates; run file conflict detection; execute conflict-free group in parallel
   - Else: run br ready filtered by EPIC_SLUG; take up to MAX_PARALLEL candidates; run file conflict detection; execute conflict-free group in parallel
   - After each task (or parallel group): br sync --flush-only, then if BV_AVAILABLE run bv --robot-triage --format toon for progress check else run br list --status=open filtered by EPIC_SLUG

**2. Task Claim and Specialist Selection**
   Claim task in beads before delegating to specialist agent

   - Run: br update <BEAD_ID> --status=in_progress — skip task if exit code != 0 (already claimed)
   - Extract TASK_ID from task.title prefix (TRD-XXX pattern if TRD_MODE; otherwise use bead title text)
   - Select specialist by keyword matching: architecture/design/system/multi-component/cross-cutting/orchestrat -> @tech-lead-orchestrator; backend/api/endpoint/database/server/model/migration -> @backend-developer; frontend/ui/component/react/vue/angular/svelte/css -> @frontend-developer; test/spec/e2e/playwright/coverage -> @test-runner or @playwright-tester; docs/readme/documentation/changelog/api-docs -> @documentation-specialist; infra/deploy/docker/k8s/kubernetes/aws/cloud/terraform -> @infrastructure-developer; refactor/optimize/cleanup spanning multiple domains -> @tech-lead-orchestrator; default -> @backend-developer
   - Check .claude/router-rules.json first; project-specific agents take priority over keyword defaults

**3. Task Delegation**
   Build prompt and delegate to selected specialist, require closing summary comment

   - Build prompt with: Task ID + bead ID, TRD file path (if TRD_MODE), strategy, completed tasks this phase, acceptance criteria, inferred file paths, matched skills, strategy-specific instructions
   - Builder prompt construction MUST follow these context curation rules:
   -   - Include ONLY: task description from bead, TRD section for this task (if TRD_MODE), architecture guidance (if any), sibling context (if any)
   -   - Do NOT include: full TRD content, other phase tasks, conversation history, previous builder outputs
   -   - Include the file path(s) the task targets so the builder can Read them directly
   -   - Each builder subagent starts with clean context — this is intentional for quality
   - Include in prompt: "When done, provide a structured summary: files changed, what was implemented, any issues encountered, and recommendations for follow-up work."
   - Delegate: Task(agent_type=<specialist>, prompt=<prompt>)
   - On success: br comment add <BEAD_ID> "Implementation complete: <agent_summary_of_work_done — files changed, what was implemented, any issues or recommendations>"; proceed to Code Review step
   - On failure: br comment add <BEAD_ID> "Failed: <error_summary>. Files touched: <changed_files>. Agent: <specialist_type>."; br update <BEAD_ID> --status=open; br sync --flush-only; enter debug loop

**3a. Reviewer Delegation and Verdict Handling (TEAM_MODE=true only)**
   Delegate to reviewer after builder submits, parse verdict, route accordingly

   - TEAM_MODE=true only (after builder writes status:in_review comment):
   - 
   - 1. Build reviewer prompt: bead ID and task title; files changed; builder implementation_description; acceptance criteria from bead description; strategy and coverage targets; relevant test results
   -    Instruction: "Review the implementation. Return verdict: APPROVED or REJECTED. If REJECTED: provide specific feedback with file, line, issue, and suggestion."
   - 
   - 2. Delegate: Task(subagent_type=<TEAM_ROLES.reviewer.agents[0]>, prompt=<reviewer_prompt>)
   - 
   - 3. Parse reviewer response for APPROVED or REJECTED keyword; extract rejection reason if REJECTED
   - 
   - 4. On APPROVED: validate_transition(bead_id, 'in_qa') — writes status:in_qa comment; proceed to QA Delegation (step 3b)
   - 
   - 5. On REJECTED: validate_transition(bead_id, 'in_progress') — writes status:in_progress verdict:rejected comment; increment rejection count; re-delegate to builder with rejection context (rejection loop step 3c)

**3b. QA Delegation and Verdict Handling (TEAM_MODE=true only)**
   Delegate to QA agent after reviewer approves, parse verdict, route accordingly

   - TEAM_MODE=true only (invoked when task sub-state == 'in_qa'):
   - 
   - 1. Build QA prompt: bead ID and task title; files changed; builder implementation_description; reviewer verdict and notes; acceptance criteria; strategy and coverage targets; test results
   - 
   - 2. Delegate to @test-runner first for fresh test execution: Task(subagent_type='test-runner', prompt='Run tests for changed files: <files_changed>. Report pass/fail and coverage.') Capture test_results.
   - 
   - 3. Apply TASK_TRACEABILITY absent-key guard: if TASK_ID not present in TASK_TRACEABILITY map (TRD_MODE=false or map rebuild failed), treat as impl task and skip audit token writing.
   -    Check TASK_TRACEABILITY[TASK_ID].is_test_task if TRD_MODE=true: if true append to QA prompt "IMPORTANT: For each PRD AC listed in Validates PRD ACs:, provide explicit verdict (PROVEN/NOT_PROVEN) with evidence."
   -    Delegate: Task(subagent_type=<TEAM_ROLES.qa.agents[0]>, prompt=<qa_prompt_with_test_results>)
   - 
   - 4. Parse QA response for PASSED/REJECTED keyword
   - 
   - 5. On PASSED:
   -    a. If TRD_MODE=true AND is_test_task: parse QA response for per-AC verdicts; build PROVEN_ACS list
   -       Extract REQ_ID from TASK_TRACEABILITY[TASK_ID].satisfies_req_id
   -    b. validate_transition(bead_id, 'closed') — for test tasks writes status:closed with req-satisfied and ac-proven tokens; for impl tasks writes status:closed qa:passed
   -    c. If TRD_MODE=true AND test task AND PASSED: br comment add <ROOT_EPIC_ID> 'req-verified:<REQ_ID> by:<TASK_ID> qa:<QA_AGENT> ac-proven:<PROVEN_ACS comma-joined>'
   -    d. br sync --flush-only
   -    e. If TRD_MODE=true: update TRD checkbox: replace "- [ ] **<TASK_ID>**" with "- [x] **<TASK_ID>**" in TRD file
   -    f. git commit -m "feat(<EPIC_SLUG>): complete <TASK_ID> - <task_title_short>"
   - 
   - 6. On REJECTED: validate_transition(bead_id, 'in_progress') — writes status:in_progress verdict:rejected comment; br update <bead_id> --status=open; increment rejection count; return to builder via rejection loop (step 3c)

**3c. Rejection Loop with Builder Re-Delegation (TEAM_MODE=true only)**
   Triggered by reviewer REJECTED or QA REJECTED. Collects full rejection context, enforces MAX_REJECTIONS cap, re-delegates to builder or escalates to lead.

   - TEAM_MODE=true, triggered by reviewer OR QA REJECTED verdict:
   - 
   - 1. Collect full rejection context: run br comment list <bead_id>; extract ALL verdict:rejected comments; build rejection_context with rejection_count, latest_reason, previous_attempts, reviewer_feedback, qa_feedback
   - 
   - 2. Check rejection_count against MAX_REJECTIONS (default 2):
   -    a. If rejection_count < MAX_REJECTIONS: identify original builder from first status:in_progress assigned: comment; re-delegate to same builder with augmented prompt including rejection reason, reviewer feedback, QA feedback, and previous attempt summary; continue through full pipeline (reviewer -> QA)
   -    b. If rejection_count >= MAX_REJECTIONS: lead architectural review (review task description, all rejection reasons, builder attempts, acceptance criteria); lead chooses action (restructure task, adjust acceptance criteria, reassign, architectural fix); record: br comment add <bead_id> 'lead-escalation:max-rejections lead:tech-lead-orchestrator action:<decision>'; reset rejection baseline; allow one more full cycle; if still failing: PAUSE for user decision

**3d. Team Metrics Collection (TEAM_MODE=true only)**
   In-memory metrics accumulator invoked after each task closure. Tracks per-builder stats and rejection cycles.

   - TEAM_MODE=true, invoked after each task closure in step 3b PASSED path:
   - 
   - Initialization (once at Execute phase start): TEAM_METRICS = { phase: <current_phase_number>, tasks_completed: 0, builders: {}, task_details: [] }
   - 
   - After each task closure:
   - 1. Identify builder agent: run br comment list <bead_id>; scan forward for first (or most recent post-lead-reset) status:in_progress assigned:<agent> comment; extract builder_agent
   - 2. Count rejection cycles: count lines containing exact token verdict:rejected in post-baseline comment slice
   - 3. Extract timestamps from br comments: compute time_in_progress, time_in_review, time_in_qa; record null if unavailable
   - 4. Determine first_pass_approval: true if rejection_cycles == 0
   - 5. Update TEAM_METRICS: increment tasks_completed; update per-builder stats; append task_details entry
   - 
   - At Quality Gate phase completion: include TEAM_METRICS summary in gate result comment if TEAM_MODE=true

**4. Code Review**
   Mandatory code review before task closure — delegate to code-reviewer for quality validation

   - Delegate to @code-reviewer: "Review the changes for task <TASK_ID> (bead: <BEAD_ID>). Files changed: <changed_files>. Strategy: <strategy>. Check for: correctness, adherence to project conventions, security issues, test coverage, and code quality. Provide: approval/rejection with specific feedback."
   - If approved:
   -   br comment add <BEAD_ID> "Code review PASSED by @code-reviewer: <review_summary>"
   -   Apply TASK_TRACEABILITY absent-key guard: if TRD_MODE=false or TASK_ID not in map, treat as impl task.
   -   If TRD_MODE=true AND is_test_task == true:
   -     Extract REQ_ID from TASK_TRACEABILITY[TASK_ID].satisfies_req_id
   -     Extract PROVEN_ACS from TASK_TRACEABILITY[TASK_ID].validates_acs
   -     Run br close <BEAD_ID>; write: br comment add <BEAD_ID> 'status:closed reviewer:code-reviewer verdict:approved req-satisfied:<REQ_ID> ac-proven:<PROVEN_ACS comma-joined>'
   -     Write root epic comment: br comment add <ROOT_EPIC_ID> 'req-verified:<REQ_ID> by:<TASK_ID> reviewer:code-reviewer ac-proven:<PROVEN_ACS comma-joined>'
   -     br sync --flush-only; update TRD checkbox - [ ] -> - [x]; git commit
   -   If is_test_task == false (or TRD_MODE=false):
   -     br close <BEAD_ID> --reason='Completed — code review passed'; br sync --flush-only
   -     If TRD_MODE=true: update TRD checkbox - [ ] -> - [x]; git commit
   -     If TRD_MODE=false: git commit -m "feat(<EPIC_SLUG>): complete <bead_title_short>"
   - If rejected with fixable issues: br comment add <BEAD_ID> "Code review REJECTED: <issues_found>"; delegate back to original specialist with review feedback; re-submit to code review after fixes (max 2 review rounds)
   - If rejected after 2 rounds: br comment add <BEAD_ID> "Code review failed after 2 rounds. Issues: <remaining_issues>."; PAUSE for user decision (force-close, fix manually, abort)
   - Skip code review only if strategy == 'flexible' or task type is docs/documentation-only

**5. Debug Loop**
   Attempt automated fix on task failure via deep-debugger (max 2 retries)

   - Delegate to @deep-debugger with error details, changed files, strategy, bead ID
   - If fix applied: re-run tests; if pass -> proceed to Code Review step (order 4); if fail -> retry
   - After 2 retries: br comment add <BEAD_ID> "Debug loop exhausted after 2 retries. Root cause: <error_analysis>. Attempted fixes: <fix_attempts>. Manual intervention required."; br sync --flush-only; PAUSE for user decision
   - When TEAM_MODE=true and builder fails with actual error (crash/exception): record debug attempt: br comment add <bead_id> "debug-attempt:<N> debugger:deep-debugger error:<summary>"; if fix applied re-run through builder then continue through handoff pipeline (reviewer -> QA); after 2 debug retries: PAUSE for user decision

**6. Error Handling**
   Handle br command failures during execution

   - After any br command: if exit code != 0 AND prior br commands in session succeeded -> possible br failure
   - Print error message with br command that failed and its exit code
   - Print: check br status and .beads/ directory integrity
   - PAUSE for user decision (resume with /ensemble:beads-build <ROOT_EPIC_ID> after issue resolved)

**7. Utility: Sub-State Query Function (get_sub_state)**
   Inline utility to read the most recent status comment for a bead. References br comment history in reverse.

   - Function signature: get_sub_state(bead_id) -> (state, metadata_dict)
   - Step 1: Run: br comment list <bead_id> — capture full output as COMMENT_LIST
   - Step 2: Split COMMENT_LIST into individual lines
   - Step 3: Scan lines in REVERSE ORDER (last line first; last comment is most recent)
   - Step 4: For each line, check if the line STARTS WITH the exact prefix "status:" (not merely contains it)
   - Step 5 — If a matching line is found: extract state (first whitespace-delimited token after "status:"); extract metadata (remaining key:value tokens); URL-decode any reason: values; return (state, {key: value, ...})
   - Step 6 — Edge cases: malformed comment with status: but no state token -> skip and continue; empty comment list -> fall through to Step 7
   - Step 7 — If NO status: comment found: run br list --json; filter for .id == bead_id; read .status field; map open -> ('open', {}), in_progress -> ('in_progress', {}), closed -> ('closed', {})

**8. Utility: Rejection Cycle Tracking and Cap**
   Inline utility invoked after any verdict:rejected comment to enforce MAX_REJECTIONS cap and escalate to lead.

   - Step 1: Count rejection cycles for this bead (respecting lead-reset baseline): run br comment list <bead_id>; scan for most recent line containing lead-reset:true to set BASELINE_LINE_INDEX (-1 if none); count lines containing exact token verdict:rejected in post-baseline slice; REJECTION_COUNT = count
   - Step 2: Determine cap: MAX_REJECTIONS = 2 (default); override if team config contains max_rejections: field
   - Step 3: If REJECTION_COUNT < MAX_REJECTIONS: return task to builder with full rejection context (reason, reviewer/QA feedback, previous attempt summaries); continue normal rejection loop
   - Step 4: If REJECTION_COUNT >= MAX_REJECTIONS: lead architectural review; lead may restructure task, adjust acceptance criteria, reassign, or identify architectural root cause; record: br comment add <bead_id> 'lead-escalation:max-rejections-reached lead:tech-lead-orchestrator action:<lead_decision>'; reset tracking baseline; allow one additional review cycle
   - Step 5: If still failing after lead escalation: PAUSE for user decision

**9. Utility: State Machine Transition Validator**
   Inline utility called before any status transition to verify it is legal and execute it atomically.

   - Valid transitions table (current_state -> allowed target_states):
   -   open        -> in_progress   (actor: lead)
   -   in_progress -> in_review     (actor: builder)
   -   in_progress -> in_qa         (actor: lead, when REVIEWER_ENABLED=false)
   -   in_progress -> closed        (actor: lead, when REVIEWER_ENABLED=false AND QA_ENABLED=false)
   -   in_review   -> in_qa         (actor: reviewer, verdict: approved)
   -   in_review   -> in_progress   (actor: reviewer, verdict: rejected)
   -   in_qa       -> closed        (actor: qa, verdict: passed)
   -   in_qa       -> in_progress   (actor: qa, verdict: rejected)
   - Validation and transition algorithm:
   - Step 1: call get_sub_state(bead_id) — capture (current_state, metadata)
   - Step 2: look up VALID_TRANSITIONS[current_state] to get allowed target states
   - Step 3: if target_state NOT in allowed set: print "ERROR: Invalid transition from {current_state} to {target_state} for bead {bead_id}" and HALT
   - Step 4: if valid, execute transition: build comment_string (status:{target_state} {key}:{value} ...); run br comment add <bead_id> <comment_string>; run br sync --flush-only; if target_state == 'closed': run br close <bead_id>; if target_state == 'in_progress' from in_review or in_qa: run br update <bead_id> --status=open

### Phase 3: Quality Gate

**1. Phase Completion Detection**
   Detect when all tasks in a phase are closed

   - After each task completion: run br list --status=open --json filtered by EPIC_SLUG and current phase prefix to find remaining open tasks
   - If no open tasks remain for this phase: trigger quality gate for this story/phase

**2. Test Execution**
   Delegate test suite execution to test-runner, with scope adjusted for team mode

   - When TEAM_MODE=true AND QA_ENABLED=true (per-task QA already ran via step 3b):
   -   Phase gate focuses on INTEGRATION-ONLY scope: delegate to @test-runner with integration tests only for files modified in this phase
   -   Cross-file consistency checks: verify API contracts, shared types, and module import/export contracts
   -   Aggregate coverage report: collect per-task coverage data from QA verdict comments; confirm aggregate coverage meets strategy target
   -   gate_passed = integration_tests_pass AND aggregate_coverage >= target
   -   Exception: strategy=characterization or flexible -> gate_passed = true (informational only)
   - 
   - When TEAM_MODE=false OR (TEAM_MODE=true AND QA_ENABLED=false) (no per-task QA ran, full gate required):
   -   Delegate to @test-runner: run full test suite (unit + integration) for files modified in this phase; report pass/fail, unit coverage %, integration coverage %, failures with file:line
   -   gate_passed = tests_pass AND unit_cov >= target AND int_cov >= target
   -   Exception: strategy=characterization or flexible -> gate_passed = true (informational only)

**3. Gate Result Recording**
   Record quality gate outcome as br comment and close story on pass

   - When TEAM_MODE=true AND QA_ENABLED=true: run br comment add <STORY_BEAD_ID> "Quality gate result: <PASS|FAIL> | integration: <X tests> | aggregate-coverage: <Y%> | scope: integration-only (team-QA)"
   -   If TEAM_METRICS populated: append team metrics summary: br comment add <STORY_BEAD_ID> "team-metrics phase:<N> tasks:<tasks_completed> first-pass-rate:<X%> total-rejections:<Y>"
   - When TEAM_MODE=false or QA_ENABLED=false: run br comment add <STORY_BEAD_ID> "Quality gate result: <PASS|FAIL> | unit: <X%> | integration: <Y%> | strategy: <strategy>"
   - Run: br sync --flush-only
   - If gate_passed: br close <STORY_BEAD_ID> --reason='Phase complete - quality gate passed'; br sync --flush-only; git commit -m "chore(phase <N>): checkpoint (tests pass; unit <X%>, int <Y%>)"
   - If gate_passed AND more phases remain AND TEAM_MODE=true: reset TEAM_METRICS for next phase: TEAM_METRICS = { phase: <N+1>, tasks_completed: 0, builders: {}, task_details: [] }
   - If NOT gate_passed AND blocking strategy (tdd/refactor/bug-fix): print gate failure details; PAUSE for user: fix/skip/abort

**4. Team Performance Summary (TEAM_MODE=true only)**
   Print and persist team performance metrics after Quality Gate step 3 when TEAM_MODE=true and TEAM_METRICS is populated

   - Condition: execute only when TEAM_MODE=true AND TEAM_METRICS.tasks_completed > 0
   - 
   - 1. Compute derived metrics: total_rejections (sum of rejection_cycles); first_pass_rate = (first_pass_approvals_count / tasks_completed) * 100; per-builder breakdown
   - 
   - 2. Print team performance summary block:
   -    === TEAM PERFORMANCE SUMMARY — Phase <TEAM_METRICS.phase> ===
   -    Tasks completed: <tasks_completed>
   -    First-pass approval rate: <first_pass_rate>%
   -    Total rejection cycles: <total_rejections>
   -    Per-builder breakdown: <builder_agent>: tasks=<N> first-pass=<N> rejections=<N>
   -    === END TEAM SUMMARY ===
   - 
   - 3. Persist metrics as br comment on ROOT_EPIC_ID: run br comment add <ROOT_EPIC_ID> "team-metrics:phase-<N> tasks:<tasks_completed> first-pass-rate:<first_pass_rate>% total-rejections:<total_rejections> builders:<BUILDERS_JSON>"
   - 
   - 4. Run: br sync --flush-only

### Phase 4: Completion

**1. Epic Closure**
   Close the root epic when all children are done

   - Verify: br list --status=open --json filtered by EPIC_SLUG returns no open tasks
   - Run: br close <ROOT_EPIC_ID> --reason='Epic implementation complete'
   - Run: br sync --flush-only

**2. TRD Checkbox Sync**
   Update TRD file checkboxes to reflect bead closure state (TRD_MODE only)

   - If TRD_MODE=false: skip this step
   - If TRD_MODE=true: for each task in TRD Master Task List: if bead status == 'closed' -> replace "- [ ] **<task.id>**" with "- [x] **<task.id>**"
   - git commit -m "docs(TRD): sync checkboxes to bead closure state"

**3. Completion Report**
   Print final summary, requirement satisfaction table (if TRD_MODE), and PR reminder

   - Print completion report: EPIC_SLUG, branch, strategy, ROOT_EPIC_ID, task counts, coverage summary
   - If TRD_MODE=true: print Requirement Satisfaction Table:
   -   Scan ROOT_EPIC_ID comments for req-verified: tokens: run br comment list <ROOT_EPIC_ID>
   -   If br comment list fails: print "WARNING: Could not read root epic comments — req-verified data unavailable." Continue with empty VERIFIED_REQS.
   -   Parse each comment for tokens: req-verified:REQ-NNN, by:TRD-NNN-TEST, qa:<agent>, reviewer:<agent>, ac-proven:AC-NNN-M,...
   -   Build VERIFIED_REQS map; for each token check verification_mode (code-review vs qa-verified)
   -   Print table:
   -     === REQUIREMENT SATISFACTION REPORT ===
   -     REQ-001: SATISFIED(qa-verified) (TRD-001-TEST) — ACs: AC-001-1, AC-001-2
   -     REQ-002: NOT VERIFIED (TRD-002-TEST still open)
   -     TOTAL: <N> satisfied / <M> total requirements
   -     ========================================
   - If TRD_MODE=false: print "Requirement Satisfaction: N/A (no TRD — run with --trd <path> to enable traceability tracking)"
   - Run: br sync --flush-only
   - If BV_AVAILABLE: run bv --robot-triage --format toon for final progress summary
   - Remind user: git diff main...<branch>; gh pr create; after merge: move any TRD file to docs/TRD/completed/
   - Remind user: br sync --flush-only && git add .beads/ && git commit -m "chore: final beads sync"
   - TIP: The execution engine used here is also available via /ensemble:implement-trd-beads <trd-path> for TRD-driven workflows with full scaffold, traceability validation, and Design Readiness gate.
   - Do NOT auto-create PR — user must run gh pr create manually

## Expected Output

**Format:** Implemented features with quality gates and beads tracking

**Structure:**
- **Closed Beads**: All task and story beads closed with quality gate comments recorded via br comment add
- **Feature Branch**: Git feature branch with implementation commits and phase checkpoint commits
- **TRD Checkboxes**: TRD Master Task List updated with completed checkboxes synced to bead closure state (TRD_MODE only)
- **Completion Report**: Summary with epic ID, coverage metrics, PR creation reminder, and optional Requirement Satisfaction Table
- **Requirement Satisfaction Report**: Table of PRD REQ-NNN requirements with SATISFIED/NOT VERIFIED status, test task references, and proven AC sub-IDs (TRD_MODE only)

## Usage

```
/ensemble:beads-build [epic-id|slug-pattern] [--trd trd-path] [--strategy tdd|characterization|bug-fix|refactor|test-after|flexible] [max parallel N]
```
