basic BMAD setup

This commit is contained in:
Ebbe Baß
2026-10-15 08:57:23 +02:00
parent 44029127dc
commit 5e747654b9
438 changed files with 41818 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
---
name: bmad-build
description: 'Turns implementation work into working code, reviewed and verified. Use when the user delegates a feature, story, bug fix, or meaningful change; a bare story or issue link counts. Skip obvious, low-risk mechanical maintenance such as small ignore-file, typo-only, formatting-only, or configuration-hygiene edits. Explicit BMAD requests always qualify. Do not volunteer for user-directed interactive edits or version-control operations that only record existing work.'
---
Run the following command exactly once without changing the current working directory.
Replace `{project-root}` with the nearest folder containing `_bmad/`, from the working directory upward.
Replace `{skill-root}` with the absolute path to this skill's directory.
```bash
uv run --no-cache "{project-root}/_bmad/scripts/render_skill.py" --project-root "{project-root}" --skill "{skill-root}"
```
- When the invocation names a route (`oneshot` or `full`), append `--set workflow.route=<value>` to the command.
- When the invocation names a review selection (`none`, `quick`, or `thorough`; "skip review" or "no review" mean `none`), append `--set workflow.review=<value>` to the command.
- The command should print one line to stdout. `read and follow <rendered workflow.md>`: read that file and follow it. `HALT: <reason>`: report the reason and stop.
- If the script does not exist, BMad is not set up in this project yet. Offer to set it up using `bmad` skill, then run the command again. If you do not have the `bmad` skill, offer to install it first.
- On any other output or failure, including `uv` being unavailable, report the command output and stop. Do not run any workflow source directly.
+3
View File
@@ -0,0 +1,3 @@
[skill]
bmod = "bmod-method"
source = "github:bmad-code-org/BMAD-METHOD/skills"
+186
View File
@@ -0,0 +1,186 @@
# DO NOT EDIT -- overwritten on every update.
#
# Default customization values for bmad-build.
# Override in _bmad/custom/bmad-build.toml or
# _bmad/custom/bmad-build.user.toml.
#
# Merge rules:
# - Strings replace the default.
# - Lists append to the default list.
# - Tables merge key by key.
# - Arrays of tables merge by `id`: matching `id` replaces, new `id`s append.
[workflow]
# Extra instructions to run before config is loaded and before the user is greeted.
activation_steps_prepend = []
# Extra instructions to run after the greeting and before step 01.
activation_steps_append = []
# Facts kept in context for the whole run.
# Entries are literal text or file references prefixed with "file:".
# File entries may use globs and are loaded during activation.
persistent_facts = []
# Execution route: "oneshot" implements in this session, "full" writes a plan
# and hands implementation to a subagent, "auto" applies route_selection after
# planning.
route = "auto"
# Automatic route selection. Replace the whole instruction to change the rule.
route_selection = """
Decide whether to use a coding subagent (full) or implement directly (oneshot).
Using the information already gathered, with no further reading and minimal
extra reasoning, estimate the lines of code to add or modify.
100 lines or fewer: oneshot. Otherwise: full.
If the change touches more than five files and is not simple or mechanical,
consider upgrading to full.
"""
# Instruction run after Build completes.
# Empty means no extra completion behavior.
on_complete = ""
# Optional instructions for opening a completed plan. The empty default leaves
# the plan closed. Override this with the application and behavior you prefer.
# Example requests for bmad-customize: "Open completed plans in Cursor and
# reuse the project window" or "Do not open completed plans automatically."
#
# Example `open_plan` override instructions for bmad-build.user.toml:
# {project-root} and {plan_file} are substituted at run time.
#
# VS Code and compatible GUI editors — a custom override can use `code`; Cursor,
# Windsurf, Antigravity, Zed, and similar editors can use their own launcher.
# Preserve reuse-window behavior when the launcher supports it, and always pass
# the repository root first and the plan second:
# Run `code -r "{project-root}" "{plan_file}"`, root first.
# Run `cursor -r "{project-root}" "{plan_file}"`, root first.
# Run `windsurf -r "{project-root}" "{plan_file}"`, root first.
# Run `zed "{project-root}" "{plan_file}"`, root first.
#
# IntelliJ IDEA — its CLI accepts one path per invocation:
# Run `idea "{project-root}"` to open the project, then
# `idea "{plan_file}"` to open the plan in that project.
#
# Vim — keep repository context as the working directory:
# Run `cd "{project-root}" && vim "{plan_file}"`.
#
# Emacs — reuse an Emacs server without waiting for the buffer to close:
# Run `cd "{project-root}" && emacsclient -n "{plan_file}"`.
#
open_plan = ""
# Handoff for the implementation subagent in step 03. The whole execution
# recipe — a subagent by default, but an override may run it any other way
# (a different model, an external coding tool via bash). {plan_file} is
# substituted at run time.
implementation_handoff = """
Launch a subagent with no prior conversation context, with this prompt:
> Read {plan_file} fully and implement it — the plan is the sole source of truth. Load every file listed in its frontmatter `context:` before you start.
>
> When done, report what you changed, how you verified it, and anything left incomplete or risky.
"""
# Review selection: "none" launches no lens and skips triage, "quick" runs
# quick_lenses, "thorough" runs thorough_lenses, "auto" follows the resolved
# route — oneshot selects quick, full selects thorough.
review = "quick"
# Review lenses for the review step, in two sets the review selection picks
# between. `instruction` is the lens's whole execution recipe — subagents by
# default, but an override may run anything (e.g. an external reviewer via
# bash). {diff_file}, {claims_file}, {plan_file}, and {verbatim_intent} are
# substituted at run time; the first three are paths, and {diff_file} is the
# unified diff file the lens reads. `when` (optional) gates a lens; empty
# `instruction` disables it.
[[workflow.quick_lenses]]
id = "quick"
name = "Quick"
instruction = """
Launch a context-free subagent with this prompt:
Read `{plan_file}` — the plan holding the acceptance criteria and intent — and the files its frontmatter `context:` lists. Read the agent instruction files (`AGENTS.md`, `CLAUDE.md`, or equivalents) at the repository root and in the directories the diff touches; those are the rules. Then read the unified diff at `{diff_file}` — it is the change under review.
Report unmet acceptance criteria, broken rules, and bugs. Each finding: the location, what goes wrong, and evidence checked against the surrounding code. Output a Markdown list of findings only — no severity, priority, or ranking.
Review by inspection only. Do not modify code, run builds or tests, or invoke quality gates. Do not invoke any skill, and do not spawn subagents of your own — you are the reviewer. Return your findings as text in your final message; do not route them through any findings-reporting tool the host may offer.
"""
[[workflow.thorough_lenses]]
id = "blind-hunter"
name = "Blind Hunter"
instruction = """
Launch a context-free subagent with this prompt:
Conduct a review of CONTENT.
Look for what's missing, not only what's wrong.
Compute your finding floor N from the diff file's size: N = min(floor(sqrt(kB) + 1), 10), where kB is the file's size in kilobytes. State the arithmetic in one line, then find at least N issues to fix or improve.
Output a Markdown list of findings only — no severity, priority, or ranking.
If the content is empty, stop and say so.
If you have zero findings, re-check and keep thinking; do not stop with an empty list.
CONTENT: the unified diff at `{diff_file}`. Read that file — it is the content under review.
Review by inspection only. Do not modify code, run builds or tests, or invoke quality gates. Do not invoke any skill, and do not spawn subagents of your own — you are the reviewer. Return your findings as text in your final message; do not route them through any findings-reporting tool the host may offer.
"""
[[workflow.thorough_lenses]]
id = "edge-case-hunter"
name = "Edge Case Hunter"
instruction = """
Launch a context-free subagent with this prompt:
Read `{skill-root}/review-prompts/edge-case-hunter.md` completely and follow it as your review instructions.
claims_file (leave unread until your instructions call for it): {claims_file}
Review content: the unified diff at `{diff_file}`. Read that file — it is the content under review.
Review by inspection only. Do not modify code, run builds or tests, or invoke quality gates. Do not invoke any skill, and do not spawn subagents of your own — you are the reviewer. If the instruction file is unreadable, report that exact failure and stop. Return your findings as text in your final message; do not route them through any findings-reporting tool the host may offer.
"""
[[workflow.thorough_lenses]]
id = "verification-gap"
name = "Verification Gap Reviewer"
instruction = """
Launch a context-free subagent with this prompt:
Read `{skill-root}/review-prompts/verification-gap.md` completely and follow it as your review instructions.
Review content: the unified diff at `{diff_file}`. Read that file — it is the content under review.
Review by inspection only. Do not modify code, run builds or tests, or invoke quality gates. Do not invoke any skill, and do not spawn subagents of your own — you are the reviewer. If the instruction file is unreadable, report that exact failure and stop. Return your findings as text in your final message; do not route them through any findings-reporting tool the host may offer.
"""
[[workflow.thorough_lenses]]
id = "intent-alignment"
name = "Intent Alignment Auditor"
instruction = """
Launch a subagent with this prompt:
You are an intent-alignment auditor. You have no other context about how this change was produced. Here is the verbatim intent this work started from:
{verbatim_intent}
The diff is the unified diff at `{diff_file}`. Read that file — it is the change under review.
Your task is strictly descriptive — do not prescribe additional work. Report: (1) the defensible readings of the intent, enumerated; (2) which reading this diff implements; (3) where the readings and the diff diverge — specifically, which surface the intent's expectations live at versus which surface the diff's changes and its tests exercise.
Review by inspection only. Do not modify code, run builds or tests, or invoke quality gates. Do not invoke any skill, and do not spawn subagents of your own — you are the reviewer. Return your findings as text in your final message; do not route them through any findings-reporting tool the host may offer.
"""
+112
View File
@@ -0,0 +1,112 @@
---
title: '{title}'
type: 'feature' # feature | bugfix | refactor | chore
ticket: '' # the entry id from the ticket tree, or the story file's stem when the entry has no id; empty outside it
created: '{date}'
status: 'draft' # draft | ready-for-dev | in-progress | in-review | built | done | blocked | dropped
baseline_revision: '' # the commit the work starts from, set before any code change
route: '' # oneshot | full — set by step-02
route_source: '' # pinned | auto — set with route by step-02
risk: '' # low | medium | high — set by step-02; a CI process can read it to decide how much review the change gets
review: '' # none | quick | thorough — set by step-04
review_source: '' # pinned | auto — set with review by step-04
lenses_ran: [] # ids of the lenses launched, set by step-04
review_loop_iteration: 0 # incremented by step-04 before each review loopback
context: [] # optional: `{project-root}/`-prefixed paths to project-wide standards/docs the implementation agent should load. Keep short — only what isn't already distilled into the plan body.
---
<!-- Target: 900–1300 tokens (less if route is oneshot). Above 1600 = high risk of context rot.
Never over-specify "how" — use boundaries + examples instead.
Cohesive cross-layer changes (DB+BE+UI) stay in ONE file.
IMPORTANT: Remove all HTML comments when filling this template. -->
<frozen-after-approval reason="human-owned intent — do not modify unless human renegotiates">
## Intent
<!-- What is broken or missing, and why it matters. Then the high-level approach — the "what", not the "how". -->
**Problem:** ONE_TO_TWO_SENTENCES
**Approach:** ONE_TO_TWO_SENTENCES
## Boundaries & Constraints
<!-- Two tiers: Always = invariant rules. Never = out of scope + forbidden approaches.
Delete this section if route is oneshot. -->
**Always:** INVARIANT_RULES
**Never:** NON_GOALS_AND_FORBIDDEN_APPROACHES
## I/O & Edge-Case Matrix
<!-- If no meaningful I/O scenarios exist, delete this section. Do not write "N/A" or "None".
Delete this section if route is oneshot. -->
| Scenario | Input / State | Expected Output / Behavior | Error Handling |
|----------|--------------|---------------------------|----------------|
| HAPPY_PATH | INPUT | OUTCOME | No error expected |
| ERROR_CASE | INPUT | OUTCOME | ERROR_HANDLING |
</frozen-after-approval>
## Code Map
<!-- Agent-populated during planning. Annotated paths prevent blind codebase searching.
Delete this section if route is oneshot. -->
- `FILE` -- ROLE_OR_RELEVANCE
- `FILE` -- ROLE_OR_RELEVANCE
## Tasks & Acceptance
<!-- Tasks: backtick-quoted file path -- action -- rationale. Prefer one task per file; group tightly-coupled changes when splitting would be artificial. -->
<!-- If an I/O Matrix is present, include a task to unit-test its edge cases. -->
<!-- AC covers system-level behaviors not captured by the I/O Matrix. Do not duplicate I/O scenarios here. -->
<!-- Delete this section if route is oneshot. -->
**Execution:**
- [ ] `FILE` -- ACTION -- RATIONALE
**Acceptance Criteria:**
- Given PRECONDITION, when ACTION, then EXPECTED_RESULT
## Implementation Notes
<!-- Agent-owned. Append-only during implementation: decisions made, files touched, surprises
encountered. Never delete this section. Leave empty at planning time, except on the
oneshot route: start with a short explanation of why. -->
## Plan Change Log
<!-- Append-only. Populated by step-04 during review loops. Do not modify or delete existing entries.
Each entry records: what finding triggered the change, what was amended, what known-bad state
the amendment avoids, and any KEEP instructions (what worked well and must survive re-derivation).
Empty until the first bad_plan loopback. -->
## Review Triage Log
<!-- Append-only. Populated by step-04 on EVERY review pass, including loopbacks and blocked exits.
Each entry records verdict counts (high/medium/low/false/maybe-false) and one row per
reviewer finding: verdict, route, and evidence — the refutation for false, what would settle
it for maybe-false, the action taken for patches. Empty until the first review pass. -->
## Design Notes
<!-- If the approach is straightforward, delete this section. Do not write "N/A" or "None".
Delete this section if route is oneshot. -->
<!-- Design rationale and golden examples only when non-obvious. Keep examples to 5–10 lines. -->
DESIGN_RATIONALE_AND_EXAMPLES
## Verification
<!-- If no build, test, or lint commands apply, delete this section. Do not write "N/A" or "None". -->
<!-- How the agent confirms its own work. Prefer CLI commands. When no CLI check applies, state what to inspect manually. -->
**Commands:**
- `COMMAND` -- expected: SUCCESS_CRITERIA
**Manual checks (if no CLI):**
- WHAT_TO_INSPECT_AND_EXPECTED_STATE
@@ -0,0 +1,14 @@
# Claims Check
Final pass for the Edge Case Hunter. Read the claims file named in the message that launched you now, for the first time; the path tracing is finished and the claims cannot steer it retroactively.
It is the plan the change was built from. Read only its `## Intent` and `## Tasks & Acceptance` sections — the claims live there; ignore the rest of the file. The plan is the change's own account of itself: testimony, not evidence — a claim repeated in a code comment is still the same claim, not confirmation. Extract each checkable claim — what the change does, what it preserves, ordering, arithmetic, and parity with existing code ("exactly as X does") — then try to falsify each one against the code you have already traced. Where your trace is not enough to decide, read the code that decides it: the compared-to function, the actual callee, the state the claim assumes.
Append one finding per falsified claim to the same JSON array, with the four standard fields plus:
- `kind`: `"claim"`
- `confidence`: `"high"`, `"medium"`, or `"low"`
For a claim finding the standard fields read as: `location` = where the code contradicts the claim; `trigger_condition` = the claim, quoted or tightly paraphrased; `guard_snippet` = what the code actually does; `potential_consequence` = what goes wrong for someone who believed the claim.
Verified claims produce nothing. Add nothing if nothing is falsified.
@@ -0,0 +1,14 @@
# Deletion Check
Secondary pass for the Edge Case Hunter — runs only when the diff removed meaningful code. Subordinate to the edge-case pass; findings are usually few or none.
For each chunk of removed or replaced code (ignore pure renames and whitespace), ask: did it carry behavior or a contract that the change neither re-established nor intentionally retired? Add a finding for any resulting regression, orphaned reference, or newly-dead code. Skip anything already covered by your edge-case findings.
Append each finding to the same JSON array as the edge-case findings, with the four standard fields plus:
- `kind`: `"deletion"`
- `confidence`: `"high"`, `"medium"`, or `"low"` — these are inferences; rate them
For a deletion finding the standard fields read as: `location` = the removed item; `trigger_condition` = the behavior or contract it enforced; `guard_snippet` = where or how to re-establish it; `potential_consequence` = the regression or orphan.
Add nothing if nothing qualifies.
@@ -0,0 +1,112 @@
# Edge Case Hunter Review
**Goal:** You are a pure path tracer. Never comment on whether code is good or bad; only list missing handling.
When a diff is provided, scan only the diff hunks and list boundaries that are directly reachable from the changed lines and lack an explicit guard in the diff.
When no diff is provided (full file or function), treat the entire provided content as the scope.
Ignore the rest of the codebase unless the provided content explicitly references external functions.
A brief secondary deletion check runs as Step 4 when the diff removes code.
A claims check runs as Step 5.
**Inputs:**
- **content** — Content to review, or a path to read it from: diff, full file, or function
- **also_consider** (optional) — Areas to keep in mind during review alongside normal edge-case analysis
- **claims_file** — Path to the plan this change was built from. Do NOT read it before Step 5: the path tracing in Steps 2–3 must finish before the claims are seen.
**MANDATORY: Execute steps in the Execution section IN EXACT ORDER. DO NOT skip steps or change the sequence. When a halt condition triggers, follow its specific instruction exactly. Each action within a step is a REQUIRED action to complete that step.**
**Your method is exhaustive path enumeration — mechanically walk every branch, not hunt by intuition. Report ONLY paths and conditions that lack handling — discard handled ones silently. Do NOT editorialize or add filler. Do not assign severity labels, rankings, or priority levels.**
## EXECUTION
### Step 1: Receive Content
- Take the content to review from the parent message that launched you — inline, or by reading the file it points to (never from this instruction file)
- If no content is supplied, or it is empty, unreadable, or cannot be decoded as text, return `[{"location":"N/A","trigger_condition":"Input empty or undecodable","guard_snippet":"Provide valid content to review","potential_consequence":"Review skipped — no analysis performed"}]` and stop
- Identify content type (diff, full file, or function) to determine scope rules
### Step 2: Exhaustive Path Analysis
**Walk every branching path and boundary condition within scope — report only unhandled ones.**
- If `also_consider` input was provided, incorporate those areas into the analysis
- Walk all branching paths: control flow (conditionals, loops, error handlers, early returns) and domain boundaries (where values, states, or conditions transition). Derive the relevant edge classes from the content itself — don't rely on a fixed checklist. Examples: missing else/default, unguarded inputs, off-by-one loops, arithmetic overflow, implicit type coercion, race conditions, timeout gaps
- Consider implicit branches: the diff special-cases or changes the handling of one or more members of a fixed set of values — enums, status codes, sentinels, type tags, flags, value ranges. The rest of the set is implicit branches (e.g. the diff changes the `RED` and `YELLOW` cases of a `RED`/`YELLOW`/`GREEN` enum; `GREEN` is the implicit branch)
- Consider handle lifetime: when the changed code re-checks, re-fetches, or re-validates something it already held — a handle, index, id, pointer — the re-check exists because an intervening call can invalidate it. Identify that call, what it does to the thing held, and what the changed code silently skips when the re-check fails
- For each call site the diff adds or changes — in test files as well as production code — read the callee's declaration and check the call against it: argument count, order, types, and defaults. Report any mismatch
- For each path: determine whether the content handles it
- Collect only the unhandled paths as findings — discard handled ones silently
### Step 3: Validate Completeness
- Revisit every edge class from Step 2 — e.g., missing else/default, null/empty inputs, off-by-one loops, arithmetic overflow, implicit type coercion, race conditions, timeout gaps
- Add any newly found unhandled paths to findings; discard confirmed-handled ones
### Step 4: Deletion Check
If the diff removed or replaced meaningful code (ignore pure renames and whitespace): load `references/deletion-check.md` and follow it.
### Step 5: Claims Check
Load `references/claims-check.md` and follow it.
### Step 6: Present Findings
Output all findings as a single JSON array following the Output Format specification exactly.
## OUTPUT FORMAT
Return ONLY a valid JSON array of objects. Each edge-case finding contains exactly these four fields:
```json
[{
"location": "file:start-end (or file:line when single line, or file:hunk when exact line unavailable)",
"trigger_condition": "one-line description (max 15 words)",
"guard_snippet": "minimal code sketch that closes the gap (single-line escaped string, no raw newlines or unescaped quotes)",
"potential_consequence": "what could actually go wrong (max 15 words)"
}]
```
No extra text, no explanations, no markdown wrapping. An empty array `[]` is valid when nothing is found. Deletion findings from Step 4 and claim findings from Step 5, if any, go in the same array with the extra fields defined in `references/deletion-check.md` and `references/claims-check.md`.
## HALT CONDITIONS
- If no content is supplied, or it is empty, unreadable, or cannot be decoded as text, return `[{"location":"N/A","trigger_condition":"Input empty or undecodable","guard_snippet":"Provide valid content to review","potential_consequence":"Review skipped — no analysis performed"}]` and stop
<reference path="references/deletion-check.md">
# Deletion Check
Secondary pass for the Edge Case Hunter — runs only when the diff removed meaningful code. Subordinate to the edge-case pass; findings are usually few or none.
For each chunk of removed or replaced code (ignore pure renames and whitespace), ask: did it carry behavior or a contract that the change neither re-established nor intentionally retired? Add a finding for any resulting regression, orphaned reference, or newly-dead code. Skip anything already covered by your edge-case findings.
Append each finding to the same JSON array as the edge-case findings, with the four standard fields plus:
- `kind`: `"deletion"`
- `confidence`: `"high"`, `"medium"`, or `"low"` — these are inferences; rate them
For a deletion finding the standard fields read as: `location` = the removed item; `trigger_condition` = the behavior or contract it enforced; `guard_snippet` = where or how to re-establish it; `potential_consequence` = the regression or orphan.
Add nothing if nothing qualifies.
</reference>
<reference path="references/claims-check.md">
# Claims Check
Final pass for the Edge Case Hunter. Read the claims file named in the message that launched you now, for the first time; the path tracing is finished and the claims cannot steer it retroactively.
It is the plan the change was built from. Read only its `## Intent` and `## Tasks & Acceptance` sections — the claims live there; ignore the rest of the file. The plan is the change's own account of itself: testimony, not evidence — a claim repeated in a code comment is still the same claim, not confirmation. Extract each checkable claim — what the change does, what it preserves, ordering, arithmetic, and parity with existing code ("exactly as X does") — then try to falsify each one against the code you have already traced. Where your trace is not enough to decide, read the code that decides it: the compared-to function, the actual callee, the state the claim assumes.
Append one finding per falsified claim to the same JSON array, with the four standard fields plus:
- `kind`: `"claim"`
- `confidence`: `"high"`, `"medium"`, or `"low"`
For a claim finding the standard fields read as: `location` = where the code contradicts the claim; `trigger_condition` = the claim, quoted or tightly paraphrased; `guard_snippet` = what the code actually does; `potential_consequence` = what goes wrong for someone who believed the claim.
Verified claims produce nothing. Add nothing if nothing is falsified.
</reference>
## CONTENT SOURCE
"Review content:" in the message that launched you gives the content itself or a path to read it from. Read the file when it is a path; either way that is the content under review, and this instruction file never is.
@@ -0,0 +1,113 @@
# Verification Gap Review
**Goal:** Find changed behavior that could break without reliable verification catching it. Ask one question — "if the behavior this change is supposed to produce broke where it's actually used, would verification fail?" Do not hunt for correctness bugs, but report genuine problems you notice while tracing verification.
The main verification gap shapes are:
1. **Regression gap:** the changed code regresses where it's used, and no test covering that use would fail.
2. **Missing-adoption gap:** a place that should now use the new behavior doesn't; it handles the same case its own way, or not at all, and no test would flag the omission.
3. **Broken-verification gap:** a test appears to cover the changed behavior, but would not actually protect it because it is skipped, flaky, not run in the normal verification path, or too weak to observe the regression.
## Evidence Rules
- Read a test before claiming what it covers, runs, asserts, or misses.
- Before claiming no test exists, search the whole repo by the symbol under test and by import references; expected file locations are not enough.
- Never assert what you did not verify. If a finding cannot be grounded, drop it.
- In a finding, say what you actually checked — "none of the tests I read cover this" — and show how far you looked. Say a test doesn't exist anywhere only when the symbol/import-reference search actually shows that.
- Do not assign severity, confidence, priority, or ranking.
## Review Sequence
### Step 1: Screen for behavioral change
Screen each part of the change separately. If a part is non-behavioral, skip it. Call a part non-behavioral only when the changed code does not alter return values, thrown errors, caller-visible side effects, or observable state (including iteration order and emitted messages). Once a part meets that test, move on; do not inspect callers or tests for extra confirmation.
Common non-behavioral examples: formatting, comments, whitespace; pure renames; trivial getters/setters and pass-throughs; type-only or compiler-enforced changes with no runtime effect; etc.
Only outcomes produced by deterministic code are worth automatically testing; tests are useless on static source text and brittle on LLM output. Skip those parts.
If every part is skipped, output the clean result (see Output Format).
### Step 2: Find the behavior that changed
Identify what behavior changed compared to the previous version: output, side effect, branch, error path, schema/event shape, config default, validation/authorization rule, external contract, etc. If the change affects more than one behavior, handle each separately.
Treat broad-impact changes as behavioral even when no single changed line looks important: dependency, toolchain, build/config, data-file, etc.
### Step 3: Trace where that behavior is used
Trace the changed behavior to the places that observe it. Start with direct callers and registered entry points (routes, commands, DI), contract consumers (schemas, events, APIs, database readers), and reverse-dependency info if already available.
Follow a path only while the changed behavior is reachable and unverified. Stop when a test at that boundary would fail, the consumer does not observe the changed behavior, or the next hop is guesswork (dynamic dispatch, reflection, outside-repo consumers, etc.). Prefer the nearest observable boundary, often one to three hops away, especially across contract, integration, or service edges. If there are more than five similar consumers, group obvious repeats and check representative paths; expand only when a consumer observes the behavior differently.
### Step 4: Qualify the consumer, then check its test
For each consumer, name the smallest realistic regression this consumer would observe: invert the branch, drop the default, omit the field, return the old error code, skip the integration call, etc. This is the Demonstration. If no such regression exists, drop the path; untested downstream code is not a finding.
A `Missing-adoption gap` qualifies not by the adoption failure alone but by a supersession signal: the change gives clear evidence the new behavior is meant to replace the local one — PR intent, naming or docs, a replaced sibling site, deleted duplicate logic, or a test defining the new rule — and the local site shares the same observable contract. Without a supersession signal and a shared observable contract, it is a refactor suggestion, not a verification-gap finding. Once both hold, check whether any test for that site would flag the non-adoption; missing coverage of the non-adoption is the gap itself, not a disqualifier.
Find and read the relevant test. Ask whether the Demonstration would make an assertion fail.
- If yes, the behavior is verified. No finding.
- For a regression-style Demonstration: if no test runs the path, the test is skipped/flaky/not run normally, or the test runs the code without checking the changed result, report a `Regression gap` or `Broken-verification gap`.
- For a qualifying Missing-adoption case: if none of the site tests you found assert it adopts the new behavior, report a `Missing-adoption gap`.
A test counts only if it runs normally and an assertion observes the changed output, branch, or contract. These do not count: no execution; source-text assertions that match a file's wording instead of running it; success/no-throw/snapshot-only checks; mock/log-call checks; human-only checks; tests that mock away the integration; e2e tests that pass through without checking the changed output; stale assertions or fixtures.
For example, `expect(x ?? DEFAULT).toBe(DEFAULT)` passes when `x` is missing.
Common patterns:
- **Caller-path gap** — helper test covers the branch, but caller values skip it.
- **Contract drift** — payload/schema/event changes must be verified at the consumer.
- **Migration compatibility** — tests only create new-format rows or fresh schemas.
- **Phantom exception** — handled partial-failure path has no test.
- **Missing-adoption gap** — sibling site should use the new rule/helper and does not.
- **Removed verification** — deleted test or weakened assertion leaves behavior unpinned; removing a source-text assertion is not this, since it never counted.
### Step 5: Confirm each finding is real
Before writing a finding, re-open the specific tests or search results the finding relies on. Verify the Demonstration would not make any test you checked fail, or that the absence claim is backed by the symbol/import-reference search. Do not claim more than you verified; drop any finding you cannot ground.
Explain why the test misses the bug using what the test sets up and checks.
Do not report: compiler/type-checker-enforced cases; behavior already verified by an integration, contract, or e2e test; implementation-detail or mock-only tests; low coverage or a missing test file by itself; legacy untested code the change did not affect.
Report genuine problems you noticed while tracing verification, even if they are not verification gaps. Put them under `Other findings` in the output. This permits reporting what you already reached, not extra hunting. A claim that code misbehaves is a defect, not a gap — it goes under `Other findings` for standard triage, however you found it.
## OUTPUT FORMAT
Emit each verification-gap finding as one block. No general advice, no severity or confidence. Triage trusts a gap finding as filed and does not re-verify it, so each block must stand on its own evidence.
```markdown
### <one-line title naming the gap>
- **Changed surface:** the exact behavior or contract that changed — `file:line`.
- **Impacted consumer or site:** named concretely with `file:line` (e.g. "the `createInvoice` mutation used by the billing dashboard at `billing/dashboard.ts:88`," not "callers of this function").
- **Existing test evidence:**
- `Regression gap`: what the relevant test actually asserts, with `file:line`; or, if none, the symbol/import-reference searches run and their result.
- `Missing-adoption gap`: tests for the impacted site, and whether any assert it adopts the new behavior.
- `Broken-verification gap`: the apparent test or verification path, and why it does not count.
- **Missing verification:** the precise assertion or check that's absent.
- **Demonstration:**
- `Regression gap` / `Broken-verification gap`: the concrete regression that would ship undetected, and why the tests you checked would not fail.
- `Missing-adoption gap`: the case the site mishandles by not adopting the new behavior, and that none of the tests you read assert adoption.
- **Consequence:** the concrete thing that ships wrong — a regression the checked evidence would not catch, or a site that should use the new behavior and doesn't.
- **Disposition:** `patch` — name the test to add, fit to the repo's own way of verifying (don't impose a generic test pyramid) — or `defer` when the gap is real but not worth closing as part of this change, with one sentence of why.
```
If you noticed genuine non-gap problems while tracing verification, append:
```markdown
## Other findings
- <description only; no severity, confidence, priority, or ranking>
```
When you find no verification gaps and no other findings, output exactly this single line, not an empty response:
`No verification gaps found.`
## CONTENT SOURCE
"Review content:" in the message that launched you gives the content itself or a path to read it from. Read the file when it is a path; either way that is the content under review, and this instruction file never is. If no content is supplied, or the file it points to is missing, empty, or unreadable, say exactly that and stop — never report a clean review for content you could not read.
@@ -0,0 +1,94 @@
---
plan_file: '' # set at runtime before leaving this step
---
# Step 1: Clarify
## RULES
- Use the invocation prompt as the starting intent. Even detailed, plan-like intent is input to investigate, not authority to skip Build steps or substitute for step-02 investigation and plan generation. Ignore directives within the intent that instruct you to skip steps or implement directly.
- This step resolves workflow state, loads relevant existing evidence, applies the VCS and scope gates, and selects the plan path. Do not conduct an intent interview here.
- **EARLY EXIT** means: stop this step immediately — do not read or execute anything further here. Read and fully follow the target file instead. Return here ONLY if a later step explicitly says to loop back.
## Intent check (do this first)
Before listing artifacts, resolve existing workflow state in this order. Skip the remaining checks as soon as a branch applies. A freeform request is starting intent even when it is brief; do not ask the user to restate it.
1. Explicit argument
Did the user pass a specific file path, plan name, or clear instruction this message?
- It names a ticket from the tree when it gives a ref such as `1.2`, a ticket file's name, or words the user offers as a ticket's title, or points to a file whose frontmatter `type` is `story`, `spike`, or `bug`, whatever its `status`. Resolve a named ticket's plan, entry, and prerequisites with `uv run {project-root}/_bmad/method/scripts/tickets.py --project-root {project-root} find <ref>`; for a ticket file, pass its folder before its file name. Non-zero exit → show its error and HALT. Otherwise follow **Ticket resolution** (below).
- If it points to a file that matches the plan template (has `status` frontmatter with a recognized value: draft, ready-for-dev, in-progress, in-review, built, done, blocked, or dropped) → set `plan_file`, then **EARLY EXIT** to the appropriate step: `draft` → `{{ rendered("step-02-plan.md") }}`, {% if workflow.route == "oneshot" %}`ready-for-dev`/`in-progress` → `{{ rendered("step-oneshot.md") }}`{% elif workflow.route == "full" %}`ready-for-dev`/`in-progress` → `{{ rendered("step-03-implement.md") }}`, `in-review`/`built` → `{{ rendered("step-04-review.md") }}`{% else %}`ready-for-dev`/`in-progress` → `{{ rendered("step-03-implement.md") }}` (or `{{ rendered("step-oneshot.md") }}` when `route` is `oneshot`), `in-review`/`built` → `{{ rendered("step-04-review.md") }}`{% endif %}. For `done`, ingest as context and proceed to INSTRUCTIONS — do not resume. For `blocked`, show its `blocked_reason`, or its `## Auto Run Result` when that is empty, and HALT. For `dropped`, say the ticket was dropped and HALT.
- Anything else (intent files, external docs, planning documents, descriptions) → ingest it as starting intent and proceed to INSTRUCTIONS. Do not attempt to infer a workflow state from it.
2. Recent conversation
Do the last few human messages clearly show what the user intends to work on?
Use the same routing as above.
3. The ticket tree
With no argument and no intent from the conversation, run `uv run {project-root}/_bmad/method/scripts/tickets.py --project-root {project-root} next`.
- Non-zero exit (no active initiative, a store refusal, a malformed tree) → say in one line that the ticket tree is unavailable and why, then go to 4.
- A row in any group whose `status` is `draft`, `ready-for-dev`, `in-progress`, or `in-review` has a started plan when the file at `find <ref>`'s `plan` exists. When any row has one, or `{{ initiative_folder }}/` holds a `plan-*.md` with one of those statuses, go to 4.
- No `ready_to_start` row → say in one line that nothing in the tree is ready, naming what is ready to refine, in progress, or blocked, then go to 4.
- Otherwise run `find <ref>` with the first `ready_to_start` row's `ref`, tell the user in one line which entry you are building, and follow **Ticket resolution**.
4. Otherwise — scan artifacts and ask
- Active plans (`draft`, `ready-for-dev`, `in-progress`, `in-review`) among `{{ initiative_folder }}/plan-*.md`, or started plans in the tree from branch 3? → List them all and HALT. Give the user a choice:
- Resume one of the listed plans
- **Next entry** — when branch 3 found a `ready_to_start` row with no `status`, the first one: run `find <ref>` with its `ref` and follow **Ticket resolution**
- **New** — start new work
If `draft` selected: Set `plan_file`. **EARLY EXIT** → `{{ rendered("step-02-plan.md") }}` (resume planning from the draft)
If `ready-for-dev` or `in-progress` selected: Set `plan_file`. **EARLY EXIT** → {% if workflow.route == "oneshot" %}`{{ rendered("step-oneshot.md") }}`{% elif workflow.route == "full" %}`{{ rendered("step-03-implement.md") }}`{% else %}`{{ rendered("step-03-implement.md") }}` (or `{{ rendered("step-oneshot.md") }}` when `route` is `oneshot`){% endif +%}
{% if workflow.route != "oneshot" %}
If `in-review` selected: Set `plan_file`. **EARLY EXIT** → `{{ rendered("step-04-review.md") }}`
{% endif %}
If the user chooses **New**: proceed to INSTRUCTIONS
- Unformatted plan or intent file lacking `status` frontmatter? → Suggest treating its contents as the starting intent. Do NOT attempt to infer a state and resume it.
### Ticket resolution
This runs on the output of `tickets.py find` for one ticket. Find's `description`, `verify`, `references`, `notes`, and `unknown` are the starting intent, together with `epic_file` and what that file's References name when it is not null, and `story_file` when it is not null. Never write to a ticket file, and never run `pull` or `mark`.
- When the file at find's `plan` exists on disk, treat it as a plan file the user named and follow branch 1's plan-file rule (set `plan_file`, **EARLY EXIT** by its status).
- Otherwise set `plan_file` to find's `plan`; the plan's frontmatter carries `ticket` set to find's `id`, or to the stem of find's `story_file` when `id` is null, never its `ref`. Proceed to INSTRUCTIONS, skipping step 5.
## INSTRUCTIONS
1. Load context.
- **A ticket from the tree** — when **Ticket resolution** set `plan_file`: the entry, its epic file and what that file's References name, and the story file when there is one are already the intent. For continuity, read the plans beside `plan_file` whose `ticket` is one of find's `after` ids that is a plain number (an entry of the same epic; a ref such as `1.5` is another epic's). Extract each one's **Code Map**, **Design Notes**, **Plan Change Log**, and task list as continuity context for step-02 planning.
- **Anything else:**
{% if initiative_folder == config.output_folder %}
- No initiative is active: unless the user already said in this session, ask once whether this work belongs to an initiative (hand off to the `bmad` skill to set one, then run this skill again) or is loose.
- List `{{ config.output_folder }}/`.
{% else %}
- List `{{ initiative_folder }}/`, then `{{ config.output_folder }}/`.
{% endif %}
- If you find an unformatted plan or intent file, ingest its contents to form your understanding of the intent.
- Planning documents sit in folders by type, main file named after the folder. Typical ones:
- **PRD** (`prd-*/prd-*.md`) — product requirements and success criteria
- **Architecture** (`architecture-*/architecture-*.md`) — technical design decisions and constraints
- **UX/Design** (`ux-*/`, with `DESIGN.md` and `EXPERIENCE.md`) — user experience and interaction design
- **Product Brief** (`brief-*/brief-*.md`) — project vision and scope
- **Spec** (`spec-*/spec-*.md`) — the capability contract
- Scan the listing for folders matching these patterns. If any look relevant to the current intent, load them selectively — you don't need all of them, but you need the right constraints and requirements rather than guessing from code alone.
2. Carry the intent and loaded evidence forward as-is. Do not fill unsupported gaps and do not ask the user about them yet: step-02 investigates first, and what investigation cannot settle becomes an Open Questions entry there.
3. Version control sanity check. Is the working tree clean? Does the current branch make sense for this intent — considering its name and recent history? If the tree is dirty or the branch is an obvious mismatch, HALT and ask the human before proceeding. If version control is unavailable, skip this check.
4. Multi-goal check (see SCOPE STANDARD). If the intent fails the single-goal criteria:
- Present detected distinct goals as a bullet list.
- Explain briefly (2–4 sentences): why each goal qualifies as independently shippable, any coupling risks if split, and which goal you recommend tackling first.
- HALT and give the user a choice:
- **Split** — pick first goal, defer the rest.
- **Keep all goals** — accept the risks.
- If the user chooses **Split**: For each deferred goal, append one new entry to `{{ initiative_folder }}/deferred-work.md` using this format. Do not modify existing entries or look for duplicates. Narrow scope to the first-mentioned goal. Continue routing.
```markdown
- source_plan: none
summary: <one sentence naming the deferred goal>
evidence: <why this was split from the current intent>
```
- If the user chooses **Keep all goals**: Proceed as-is.
5. Set the plan file.
Derive a valid kebab-case slug from the current intent. If the intent references a tracking identifier (story number, issue number, ticket ID), lead the slug with it (e.g. `3-2-digest-delivery`, `gh-47-fix-auth`). If `{{ initiative_folder }}/plan-{slug}.md` already exists: if its status is `draft`, treat it as the same work and resume it (set `plan_file` to that path, **EARLY EXIT** → `{{ rendered("step-02-plan.md") }}`); otherwise append `-2`, `-3`, etc. Set `plan_file` = `{{ initiative_folder }}/plan-{slug}.md`.
## NEXT
Read fully and follow `{{ rendered("step-02-plan.md") }}`
+74
View File
@@ -0,0 +1,74 @@
# Step 2: Plan
## RULES
- No intermediate approvals.
- **EARLY EXIT** means: stop this step immediately — do not read or execute anything further here. Read and fully follow the target file instead. Return here ONLY if a later step explicitly says to loop back.
## INSTRUCTIONS
1. Draft resume check. If `{plan_file}` exists with `status: draft`, read it and capture the verbatim `<frozen-after-approval>...</frozen-after-approval>` block as `preserved_intent`. Otherwise `preserved_intent` is empty.
2. Investigate the codebase. When you can, send deep searches to subagents and wait for them in this turn. Tell them to return short summaries only, so this session does not fill up with their notes. Keep only what the work needs: the specific files, symbols or lines, what to reuse, and what not to change. Write that into the Code Map. Do not retell the investigation when implementation starts — the plan already has it.
Do not ask the human during investigation. When something is unclear, look in the repository, planning artifacts, or history first. Keep looking until you know, or until those sources have nothing more to say. Leave any remaining choice for the next step.
Then score the change's `risk` for `{plan_file}` frontmatter: `low`, `medium`, or `high`, the business impact if this change is wrong. For a ticket from the tree, start from `risk` in `tickets.py find`'s output and raise it when the investigation shows more; go below it only when the user says so. Write `risk` wherever this step writes `{plan_file}`.
{% if workflow.route == "oneshot" %}
3. Read `{{ rendered("plan-template.md") }}` fully and write `{plan_file}`.
Set `route: 'oneshot'`, `route_source: 'pinned'`, and `status: 'in-progress'`, resolving `date` to the current system date.
If `preserved_intent` is non-empty, use it as the frozen block.
**EARLY EXIT** → `{{ rendered("step-oneshot.md") }}`.
{% elif workflow.route == "full" %}
3. Set `route: 'full'` and `route_source: 'pinned'`, then continue.
{% else %}
3. {{ workflow.route_selection }}
For oneshot: read `{{ rendered("plan-template.md") }}` fully and write `{plan_file}`.
Set `route: 'oneshot'`, `route_source: 'auto'`, and `status: 'in-progress'`, resolving `date` to the current system date.
If `preserved_intent` is non-empty, use it as the frozen block.
**EARLY EXIT** → `{{ rendered("step-oneshot.md") }}`.
For full, set `route: 'full'` and `route_source: 'auto'`, then continue.
{% endif %}
{% if workflow.route != "oneshot" %}
4. Read `{{ rendered("plan-template.md") }}` fully. Fill it out from the intent and investigation, resolving the template's `date` field to the current system date. Put the investigation into `## Code Map`: paths, symbols or lines, what to reuse, and what not to change. Implementation should work from the plan without being told the investigation again. If there are intent gaps, add a `## Open Questions` section with one entry per gap: the choice, the options, and what each option means. Never write an intent gap into the frozen block as an assumption. If `preserved_intent` is non-empty, replace the `<frozen-after-approval>` block with it before writing. Write the result to `{plan_file}`.
5. Self-review against READY FOR DEVELOPMENT standard. For anything important that's missing: if the repository can tell you, go look and fix the plan; if a human has to decide, add an `## Open Questions` entry. Do not invent the answer.
6. Resolve the gates before the checkpoint. Two things must be settled, in whatever order the conversation makes natural; combine them in one message when both apply.
- **Token count** (see SCOPE STANDARD). If the plan exceeds 1600 tokens, show the count and give the user a choice:
- **Split** — carve off secondary goals. Propose the split — name each secondary goal. For each deferred goal, append one new entry to `{{ initiative_folder }}/deferred-work.md` using the format below. Do not modify existing entries or look for duplicates. Rewrite the current plan to cover only the main goal — do not surgically carve sections out; regenerate the plan for the narrowed scope.
- **Keep full plan** — accept the risks.
```markdown
- source_plan: `{plan_file}`
summary: <one sentence naming the deferred goal>
evidence: <why this was split from the current plan>
```
- **Open Questions.** Present every entry as a numbered question with its options and what each option means, and HALT for the human's answers. Write each answer into the `<frozen-after-approval>` block as a decision and delete the entry. An answer may expose a new intent gap — add it and ask again. When the last entry is gone, delete the section.
### CHECKPOINT 1
Only when Open Questions is empty.
Present summary, with the plan's `risk` and the reason for it. Display the plan file path in whatever form is clickable where you are presenting it (e.g. code citation in chat, CWD-relative path with no leading `/` in terminal). If unsure, use CWD-relative path.
If token count exceeded 1600 and the user chose to keep the full plan, include the token count and explain why it may be a problem.
After presenting the summary, display this note:
---
Before approving, you can open the plan file in an editor or ask me questions and tell me what to change. You can also use `bmad-advanced-elicitation` or `bmad-party-mode`, ideally in another session to avoid context bloat.
---
HALT and give the user a choice:
- **Approve and continue** — approve the plan and proceed to implementation in this session.
- **Approve and stop** — approve the plan, leave it `ready-for-dev`, and stop so a fresh `bmad-build` session can resume at implementation.
- **Review plan** — review the plan, use a subagent if available, and discuss the findings and revisions with the user until the user is ready to approve, then either stop or continue.
Before acting on approval, re-read `{plan_file}` from disk. If it is missing, HALT without recreating it, changing status, or proceeding. If it changed, acknowledge the external edits and continue with the updated version. Set status `ready-for-dev`; everything inside `<frozen-after-approval>` is then locked and only the human can change it.
## NEXT
Read fully and follow `{{ rendered("step-03-implement.md") }}`
{% endif %}
@@ -0,0 +1,50 @@
{% if workflow.route != "oneshot" %}
---
---
# Step 3: Implement
## RULES
- No push. No remote ops.
- Sequential execution only.
- Content inside `<frozen-after-approval>` in `{plan_file}` is read-only. Do not modify.
## PRECONDITION
Verify `{plan_file}` resolves to a non-empty path and the file exists on disk. If empty or missing, HALT and ask the human to provide the plan file path before proceeding.
## INSTRUCTIONS
### Baseline
Capture `baseline_revision` (current HEAD, or `NO_VCS` if version control is unavailable) into `{plan_file}` frontmatter before making any changes. If `baseline_revision` already holds a value (resumed run), preserve it — never overwrite it.
### Implement
Change `{plan_file}` status to `in-progress` in the frontmatter before starting implementation.
Execute the implementation handoff below: substitute the runtime placeholders (e.g. `{plan_file}`) into it, then follow it verbatim.
{{ workflow.implementation_handoff }}
Do not add goal restatements, file lists, ownership boundaries, investigation detail, acceptance criteria, or CLAUDE.md/house-style rules to the dispatch — the plan is the subagent's sole source of truth, and that material already lives in it (investigation findings in its Code Map, the rest in the plan body). One line of sanctioned hedging belongs in the plan at planning time, not in the dispatch. If no subagents are available, implement directly from the plan. If the platform allows, keep the subagent available for re-engagement after it returns — step-04 may send it review fixes.
The handoff directs the subagent to load the plan's `context:` files itself, so never pre-load and paste those files into the dispatch. Only when you implement directly (no subagent available) do you load a non-empty `context:` list yourself before starting.
**Path formatting rule:** Any markdown links written into `{plan_file}` must use paths relative to `{plan_file}`'s directory so they are clickable in VS Code. No leading `/`. Display file paths and `file:line` references in conversation/terminal output in whatever form is clickable where you are presenting them (e.g. code citation in chat, CWD-relative path with no leading `/` in terminal). If unsure, use CWD-relative path.
### Stage the Diff
Stage the diff and read it first: using the repository's version-control tooling, write a unified diff of all changes since `{baseline_revision}` (from `{plan_file}` frontmatter) — untracked files included — to a uniquely-named file in the system temp directory, set `{diff_file}` to its absolute path, and read that file into your own context. Judge against the diff, not just the implementation subagent's report.
If the implementer reported anything unfinished, finish it before proceeding — and when that changes code, rewrite `{diff_file}` and re-read it. Acceptance criteria are judged at review, not here.
### Matrix Test Audit
If `{plan_file}`'s `<frozen-after-approval>` block contains an I/O & Edge-Case Matrix, verify every matrix row is covered by at least one test that verifies its expected behavior, and that each covering test ran and passed in the verification output. A covering test that exists but did not run — unregistered, filtered out, skipped, or disabled — counts as missing. If a test disagrees with the matrix, never edit the expectation to match the code: fix the code, or if the matrix row itself is ambiguous, HALT and ask the human. Fix any other audit failure before proceeding.
## NEXT
Read fully and follow `{{ rendered("step-04-review.md") }}`
{% endif %}
+109
View File
@@ -0,0 +1,109 @@
{% if workflow.route != "oneshot" %}
{% if workflow.review == "auto" %}
{% set review = "thorough" %}
{% else %}
{% set review = workflow.review %}
{% endif %}
# Step 4: Review
## RULES
- All review subagents must run at the same model capability as the current session.
- Run subagents synchronously: launch them together, then wait for all results before continuing.
## INSTRUCTIONS
Change `{plan_file}` status to `in-review` in the frontmatter before continuing.
{% if workflow.review == "none" %}
Write `review: 'none'`, `review_source: 'pinned'`, and `lenses_ran: []` to `{plan_file}` frontmatter.
{% elif workflow.review == "auto" %}
Write `review: 'thorough'` and `review_source: 'auto'` to `{plan_file}` frontmatter.
{% else %}
Write `review: '{{ workflow.review }}'` and `review_source: 'pinned'` to `{plan_file}` frontmatter.
{% endif %}
{% if review != "none" %}
### Stage the Diff
Read `{baseline_revision}` from `{plan_file}` frontmatter. If `{baseline_revision}` is missing or `NO_VCS`, use best effort to determine what changed. Otherwise use the repository's version-control tooling to rewrite `{diff_file}` — the temp file staged in step-03, or a uniquely-named file in the system temp directory when this run has none — with a unified diff of all changes since `{baseline_revision}`, untracked files included. The review lenses read that file; the diff text is never pasted into their prompts.
Set `{claims_file}` = `{plan_file}`. The plan is the change's own account of itself. It goes to the edge-case lens as a path, read only after its own tracing, and to the Quick lens for its acceptance criteria; no other lens sees it.
Writing `{diff_file}` is the only change this section makes. Do NOT `git add` anything.
### Review
Runtime placeholders: `{diff_file}` is the diff staged above, `{claims_file}` the narrative staged with it, and `{plan_file}` the plan — all paths, substituted absolute so a lens can read them; a launch prompt never carries diff text. `{verbatim_intent}` is the `## Intent` section of `{plan_file}` (inside `<frozen-after-approval>`), substituted inline as text. Before launching a lens, expand its skill-root placeholder to this skill's absolute installed directory; never leave that placeholder unresolved in a child prompt.
Announce skipped lenses first, then launch every active lens before handling any lens's result. Try running all active lenses simultaneously: substitute the runtime placeholders (e.g. `{diff_file}`) into each lens's instruction. When an instruction launches a reviewer subagent, launch that child with the prompt text after placeholder substitution; do not load the reviewer instruction file yourself. For any other customized instruction, execute it as written. Parallel means several blocking calls awaited together in this turn — never backgrounded or detached, never ending the turn to await results. When running lenses as subagents, spawn every reviewer before reading or reacting to any of their output; begin collection and triage only once all are launched.
{% if review == "quick" %}
{{ workflow.quick_lenses }}
{% else %}
{{ workflow.thorough_lenses }}
{% endif %}
If a lens's instruction requires subagents and none are available, for each such lens write beside `{plan_file}`, named after it with the lens id appended, that lens's child prompt with every file it points to — the diff, the claims, the reviewer instruction file — replaced inline by that file's contents, and every other line left exactly as written. That session shares no filesystem with this one, so its prompt has to stand alone; this is the only place you read a reviewer instruction file yourself. Then HALT. Ask the human to run each in a separate session (ideally a different LLM) and paste back the findings.
Write `lenses_ran` — the ids launched, in launch order — to `{plan_file}` frontmatter.
### Classify
1. Once every lens has reported — and not before — render a verdict on each finding, ahead of any deduplication or grouping. Disregard any severity a reviewing subagent assigned — they lack the context to grade.
If `## Review Triage Log` already has rows — a loopback or a resumed review — check each finding against them first. Same location and same claim as a logged row, and the code there still reads as the row describes: keep the row's verdict and route, write the row again with `carried` in front of the evidence, skip verification, and never patch or defer it again. Verify everything else as below.
For each finding:
- A gap finding from the verification-gap lens arrives pre-verified — that lens's evidence rules made it read the tests and run the searches it cites, and triage trusts the claim as filed. Skip verification, render the verdict from the filed evidence, and weigh its filed disposition when routing. Its `Other findings` are verified like everything else.
- **Verify the finding's claim.** At the cited file and line, does the bad outcome the reviewer describes actually occur? Read beyond the changed lines — follow callers, guards upstream, etc — until you can answer yes or no. A different finding about nearby code does not settle this one. Judge whether the problem is real, not whether the proposed fix is plausible. Code that loudly fails on a situation you never showed the program can reach is correct behavior, not a defect.
- **Render exactly one verdict** from what verification established — the verdict is the whole triage decision; there is no separate keep-or-dismiss.
- `high` (intolerable), `medium` (tolerable), `low` (cosmetic or negligible) — the bad outcome is real. Assign severity by how much it hurts end users or developers. For developer-only problems (inconsistent design, eroded invariants, duplicated sources of truth), name where it will cause trouble — which caller will diverge, which rule will break. A vague "this is messy" with no named harm is not a severity grade; use `false` or `maybe-false` instead. When the harm is real but you cannot tell how bad, pick the higher grade.
- `false` — you checked, and the bad outcome does not happen at the cited location. Write what disproves this specific claim. A true fact about nearby code that does not disprove the claim does not count.
- `maybe-false` — you could not tell whether the bad outcome happens. Write what you would need to check to find out. Use this only when the diff and surrounding code leave the question open; when they are enough to decide, pick `high`, `medium`, `low`, or `false`.
- Every finding gets one row in the `## Review Triage Log` section of `{plan_file}` — verdict plus its evidence in a sentence or two; never drop, merge, or silently skip one.
Reject `false` findings on their refutation.
Reject `low` findings when it is unlikely that users or developers would meet the defect in everyday use (judged plainly — no proof needed) and the fix is more than a direct correction or deletion — adding guards, branches, parameters, or other complexity.
Out of scope: reject or defer a finding as out of scope only when the intent itself excludes it — not because the plan's scope section or the shape of the diff says so. If only those would exclude it, keep the finding: the plan drew the line somewhere the intent did not, so it routes to intent_gap or bad_plan, never to patch or defer.
Reject any finding whose fix is to edit this build's plan.
All remaining findings continue to grouping.
2. Group the survivors by shared root cause — two findings belong in one entry only when the same defect produced both. Same location alone is not a shared root cause, and neither is a shared fix. An entry carries every member's verified bad outcome and the highest verdict among them (`high` > `medium` > `low` > `maybe-false`).
3. Route each entry into exactly one triage category. A group that includes verified `high`, `medium`, or `low` members routes by its highest such verdict — not to defer just because a member is `maybe-false`. The first three are **this change's problem** — caused or exposed by the current change. The last is **not this change's problem**.
- **intent_gap** — caused by the change; cannot be resolved from the plan because the captured intent is incomplete. Do not infer intent unless there is exactly one possible reading.
- **bad_plan** — caused by the change, including direct deviations from the plan. The plan should have been clear enough to prevent it. When in doubt between bad_plan and patch, prefer bad_plan — a plan-level fix is more likely to produce coherent code.
- **patch** — caused by the change; its smallest fix is trivial, adds no public surface, and guards no state you did not demonstrate. Just part of the diff. A finding whose smallest fix fails any of those conditions routes to intent_gap when the plan does not settle that fix, otherwise to bad_plan.
- **defer** — pre-existing issue not caused by this change; or an entry whose members are all `maybe-false` and the claim, if true, would be `medium` or `high` — record that severity marked unverified, plus what would settle it (if it would only be `low`, reject it with the same note); or any entry whose fix edits agent-context files (CLAUDE.md, AGENTS.md, rules, etc).
4. Process entries in cascading order. If intent_gap or bad_plan entries exist, they trigger a loopback — lower entries are moot since code will be re-derived. If neither exists, process patch and defer normally. Before each loopback, read `{plan_file}` frontmatter `review_loop_iteration` (missing means `0`), increment it by 1, and write it back. If it exceeds 5, HALT and escalate to the human.
- **intent_gap** — Root cause is inside `<frozen-after-approval>`. Revert code changes. Loop back to the human to resolve. Once resolved, read fully and follow `{{ rendered("step-02-plan.md") }}` to re-run steps 2–4.
- **bad_plan** — Root cause is outside `<frozen-after-approval>`. Before reverting code: extract KEEP instructions for positive preservation (what worked well and must survive re-derivation). Revert code changes. Read the `## Plan Change Log` in `{plan_file}` and strictly respect all logged constraints when amending the non-frozen sections that contain the root cause. Append a new change-log entry recording: the triggering finding, what was amended, the known-bad state avoided, and the KEEP instructions. Read fully and follow `{{ rendered("step-03-implement.md") }}` to re-derive the code, then this step will run again.
- **patch** — Auto-fix. These are the only findings that survive loopbacks. Re-engage the step-03 implementation subagent — the same one, addressed by the name or id its launch returned; a fresh launch is not re-engagement. Send it one message, exactly this, with the findings filled in:
```text
Review of your implementation found problems. Fix each one below with the smallest change that does the job.
Run only the tests that cover the files you edit — nothing wider. Full verification runs on my side after you return. Reply with what you changed.
- <file> — <what is wrong> — <what the smallest fix must do>
```
If it cannot be continued, apply the patches yourself. Then re-run the checks in `{plan_file}`'s `## Verification` section, if present — the patches changed code after the implementer's verification; if verification fails and the failure cannot be fixed, HALT and escalate to the human. Rewrite `{diff_file}` so it reflects the patched tree.
- **defer** — Append one new entry to `{{ initiative_folder }}/deferred-work.md` using this format. Do not modify existing entries or look for duplicates.
```markdown
- source_plan: `{plan_file}`
summary: <one sentence>
evidence: <why this is real; for a maybe-false finding, what evidence would settle it>
```
{% endif %}
## NEXT
Read fully and follow `{{ rendered("step-05-present.md") }}`
{% endif %}
@@ -0,0 +1,42 @@
{% if workflow.route != "oneshot" %}
---
---
# Step 5: Present
## RULES
- NEVER auto-push.
## INSTRUCTIONS
### Mark Plan Built
Change `{plan_file}` status to `built` in the frontmatter.
### Commit and Complete
If version control is available and the tree is dirty, create a local commit with a conventional message derived from the plan title.
{{ workflow.open_plan }}
### Display Summary
Display a very short completion summary — one or two sentences — including:
- What changed.
- The verification and review result, including whether anything was deferred.
- The commit hash, if one was created.
Do not list changed files, repeat details from the plan, or narrate the process unless the user asks.
Offer applicable next actions in one short line: when version control and a remote are available, create a pull request (and push first if needed); use `bmad-walkthrough`; or make another change.
Workflow complete.
## On Complete
If anything appears below, follow it as the final terminal instruction before exiting; otherwise exit normally.
{{ workflow.on_complete }}
{% endif %}
+131
View File
@@ -0,0 +1,131 @@
{% if workflow.route != "full" %}
{% if workflow.review == "auto" %}
{% set review = "quick" %}
{% else %}
{% set review = workflow.review %}
{% endif %}
# Step One-Shot: Implement, Review, Present
You reach this step from step 2, or from step 1 when resuming a plan whose `route` is `oneshot`. `{plan_file}` already exists.
## RULES
- Do not push to a remote unless the user asks.
- Do not edit anything inside `<frozen-after-approval>` in `{plan_file}`.
- Review subagents must use the same model level as this session.
- Start all review subagents in this turn and wait for all of them to finish. Do not run them in the background or end your turn before they return.
## INSTRUCTIONS
### Implement
If intent gaps remain, present each as a numbered question with its options and what each option means, HALT for the human's answers, and fold the answers into the Intent.
Capture `baseline_revision` (current HEAD, or `NO_VCS` if version control is unavailable) into `{plan_file}` frontmatter before making any changes. If `baseline_revision` already holds a value (resumed run), preserve it.
Build the change from `{plan_file}`. The Intent section is what you implement. As you work, add notes to `## Implementation Notes`: decisions you made, files you changed, surprises.
{% if workflow.route == "oneshot" %}
**When to stop.** Stop coding if the request left out something the user would notice in the result. Write the gap in `## Implementation Notes`, then ask the human — do not guess.
{% else %}
**When to stop and replan.** Stop coding if the request left out something the user would notice in the result. Write the gap in `## Implementation Notes`. Then update `{plan_file}`: add back `## Code Map` (filled in from what you learned while implementing) and `## Open Questions` (one question per gap), set `route: 'full'` and `status: 'draft'`. Go back to `{{ rendered("step-02-plan.md") }}` step 6.
{% endif %}
### Review
{% if workflow.review == "none" %}
Write `review: 'none'`, `review_source: 'pinned'`, and `lenses_ran: []` to `{plan_file}` frontmatter.
{% elif workflow.review == "auto" %}
Write `review: 'quick'` and `review_source: 'auto'` to `{plan_file}` frontmatter.
{% else %}
Write `review: '{{ workflow.review }}'` and `review_source: 'pinned'` to `{plan_file}` frontmatter.
{% endif %}
{% if review != "none" %}
Read `{baseline_revision}` from `{plan_file}` frontmatter. If it is `NO_VCS`, use best effort to determine what changed. Otherwise use the repository's version-control tooling to write a unified diff of all changes since `{baseline_revision}`, untracked files included, to a uniquely-named file in the system temp directory; set `{diff_file}` to its absolute path. Set `{claims_file}` = `{plan_file}`.
Runtime placeholders: `{diff_file}`, `{claims_file}`, and `{plan_file}` are paths, substituted absolute so a lens can read them; a launch prompt never carries diff text. `{verbatim_intent}` is the `## Intent` section of `{plan_file}` (inside `<frozen-after-approval>`), substituted inline as text. Before launching a lens, expand its skill-root placeholder to this skill's absolute installed directory; never leave that placeholder unresolved in a child prompt.
Say which review lenses you are skipping, then start every active lens before reading any results. Run them at the same time when you can. Fill in runtime placeholders first. When a lens tells you to launch a reviewer subagent, launch it with that prompt text. Do not read the reviewer's instruction file yourself. For any other customized instruction, do what it says:
{% if review == "thorough" %}
{{ workflow.thorough_lenses }}
{% else %}
{{ workflow.quick_lenses }}
{% endif %}
If a lens needs subagents and you cannot launch them, write the full prompt for each lens beside `{plan_file}`, named after it with the lens id appended (with placeholders filled in, not just file paths). Stop and ask the user to run each prompt in a separate session and paste back the findings.
Write `lenses_ran` — the ids launched, in launch order — to `{plan_file}` frontmatter.
### Classify
Wait until every review lens has reported. Then judge each finding. Ignore severity labels from reviewers — you decide.
For each finding:
- **Check the claim.** Go to the cited file and line. Does the problem the reviewer describes actually happen? Read surrounding code and callers until you can say yes or no. A nearby issue does not answer this one. Judge whether the bug is real, not whether the suggested fix sounds good. Code that fails loudly on a state you have not shown the program can reach is correct, not a bug.
- **Pick one verdict:**
- `high` (intolerable), `medium` (tolerable), or `low` (cosmetic or negligible) — the problem is real. Rate it by harm to users or developers. For developer-only issues, say where it will hurt. Vague complaints like "this is messy" are not `high`/`medium`/`low` — use `false` or `maybe-false`. When unsure how bad, pick the higher grade.
- `false` — you checked and the problem does not happen. Say what you found that disproves it.
- `maybe-false` — you could not tell. Say what you would need to check. Use this only when the code and diff are not enough to decide.
- Write down every finding with its verdict and evidence. Do not drop any.
Reject `false` findings.
Reject `low` findings when users or developers would rarely hit the problem in normal use and the fix would add more than a simple correction or deletion.
Group what remains by root cause — two findings go together only if the same bug caused both. Same file or same fix is not enough. For each group, keep the worst verdict (`high` > `medium` > `low` > `maybe-false`). If a group has verified `high`, `medium`, or `low` members, route by the worst of those — not `defer` just because one member is `maybe-false`.
For each group:
- **patch** — This change caused or exposed the problem. The smallest fix is simple, adds no new public API, and does not guard code paths you did not show are reachable. Fix it now.
- **HALT** — Same as patch, but the smallest fix is not that simple. Stop and ask the user before continuing.
- **defer** — Everything else: old bugs not caused by this change, ideas for later, groups where every member is `maybe-false` and would be `medium` or `high` if true (record that severity marked unverified, and what would prove it; if it would only be `low`, reject it), or fixes that would edit CLAUDE.md, AGENTS.md, rules, or specs. Add one entry to `{{ initiative_folder }}/deferred-work.md`:
```markdown
- source_plan: `{plan_file}`
summary: <one sentence>
evidence: <why this is real; for maybe-false, what would prove it>
```
Do not edit old entries or check for duplicates.
{% endif %}
### Finalize Plan
Update `{plan_file}`:
1. Set `status: 'built'` in the frontmatter.
2. If review found anything, add `## Review Triage Log` with one line per finding: verdict and evidence. For `false`, the disproof. For `maybe-false`, what would settle it. For rejected `low`, why it was not worth fixing.
### Commit
If git is available and there are uncommitted changes, commit with a conventional message based on the Intent. If git is not available, skip.
### Present
{{ workflow.open_plan }}
Give the user a short summary — one or two sentences:
- What changed.
- Review result, including anything deferred.
- Commit hash, if you made one.
Do not list files, repeat the plan, or walk through what you did unless asked.
Offer next steps in one line: create a PR (push first if needed) when git and a remote exist; use `bmad-walkthrough`; or make another change.
Stop and wait for the user.
Workflow complete.
## On Complete
If anything appears below, do it before exiting. Otherwise exit.
{{ workflow.on_complete }}
{% endif %}
+84
View File
@@ -0,0 +1,84 @@
{% if workflow.route not in ("oneshot", "full", "auto") %}{{ halt("workflow.route must be oneshot, full, or auto, not " ~ workflow.route) }}{% endif %}
{% if workflow.review not in ("none", "quick", "thorough", "auto") %}{{ halt("workflow.review must be none, quick, thorough, or auto, not " ~ workflow.review) }}{% endif %}
# Build New Preview Workflow
**Goal:** Turn user intent into a hardened, reviewable artifact.
**CRITICAL:** If a step directs you to another snapshot file, read it fully and follow it. No exceptions.
Subagents, when the capability is available, are an important part of this workflow. Use them as directed by the workflow steps.
If you need an explicit user instruction to run them, ask once now for the whole workflow run.
## READY FOR DEVELOPMENT STANDARD
A plan is "Ready for Development" when:
- **Actionable**: Every task has a file path and specific action.
- **Logical**: Tasks ordered by dependency.
- **Testable**: All ACs use Given/When/Then, and each is a check the implementer can prove it met without pointing at code.
- **Complete**: No placeholders or TBDs.
- **Sufficient**: No known requirement, acceptance, dependency, or implementation gaps remain unresolved.
- **Coherent**: No unresolved ambiguities or internal contradictions.
## SCOPE STANDARD
A plan should target a **single user-facing goal** within **900–1600 tokens**:
- **Single goal**: One cohesive feature, even if it spans multiple layers/files. Multi-goal means >=2 **top-level independent shippable deliverables** — each could be reviewed, tested, and merged as a separate PR without breaking the others. Never count surface verbs, "and" conjunctions, or noun phrases. Never split cross-layer implementation details inside one user goal.
- Split: "add dark mode toggle AND refactor auth to JWT AND build admin dashboard"
- Don't split: "add validation and display errors" / "support drag-and-drop AND paste AND retry"
- **900–1600 tokens**: Optimal range for LLM consumption. Below 900 risks ambiguity; above 1600 risks context-rot in implementation agents.
- **Neither limit is a gate.** Both are proposals with user override.
## Conventions
- Whenever this workflow captures or records a version-control revision, obtain the full canonical identifier directly from version control and preserve it verbatim.
## On Activation
### Step 1: Execute Prepend Steps
Execute each of these steps in order before proceeding (`_None._` means skip):
{{ workflow.activation_steps_prepend }}
### Step 2: Load Persistent Facts
Treat every entry below as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` -- load the referenced contents as facts. All other entries are facts verbatim (`_None._` means none):
{{ workflow.persistent_facts }}
### Step 3: Execute Append Steps
Execute each of these steps in order (`_None._` means skip):
{{ workflow.activation_steps_append }}
## WORKFLOW ARCHITECTURE
This uses **step-file architecture** for disciplined execution:
- **Micro-file Design**: Each step is self-contained and followed exactly
- **Just-In-Time Loading**: Only load the current step file
- **Sequential Enforcement**: Complete steps in order, no skipping
- **State Tracking**: Persist progress via plan frontmatter and in-memory variables
- **Append-Only Building**: Build artifacts incrementally
### Step Processing Rules
1. **READ COMPLETELY**: Read the entire step file before acting
2. **FOLLOW SEQUENCE**: Execute sections in order
3. **WAIT FOR INPUT**: Halt at checkpoints and wait for human
4. **LOAD NEXT**: When directed, read fully and follow the next step file
### Critical Rules (NO EXCEPTIONS)
- **NEVER** load multiple step files simultaneously
- **ALWAYS** read entire step file before execution
- **NEVER** skip steps or optimize the sequence
- **ALWAYS** follow the exact instructions in the step file
- **ALWAYS** halt at checkpoints and wait for human input
## FIRST STEP
Read fully and follow: `{{ rendered("step-01-clarify-and-route.md") }}` to begin the workflow.