Skip to content
This repository was archived by the owner on Jul 13, 2026. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ Story Automator automates the BMAD implementation loop for one or more stories:
5. commit verified work
6. trigger retrospective when an epic is fully complete

Experimental quick-dev support is available as an alternate child step for environments that provide a `bmad-quick-dev` skill. In that mode the child workflow combines planning, coding, test generation, and review, while Automator still verifies story/sprint-status completion before commit.

The core runtime model is:

- one orchestrator session
Expand Down
2 changes: 2 additions & 0 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ Critical rule:

These commands are the orchestration control plane.

`tmux-wrapper build-cmd quick-dev <story-id>` is available as an experimental combined execution step when a `bmad-quick-dev` skill is installed. Monitor it with `monitor-session --workflow quick-dev --story-key <story-id>` so completion is verified against story/sprint-status artifacts.

## Agent Config Commands

- `agent-config list`
Expand Down
10 changes: 9 additions & 1 deletion scripts/smoke-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ make_required_skills() {
printf '# checklist\n' >"$root/$skills_root/bmad-dev-story/checklist.md"

make_skill "$root" bmad-retrospective "$skills_root"
make_skill "$root" bmad-quick-dev "$skills_root"
}

make_required_workflow_only_skills() {
Expand Down Expand Up @@ -266,6 +267,9 @@ verify_common_install() {
assert_contains 'build-cmd create {story_id} --agent "$current_agent" --model "$primary_model" --state-file "$state_file"' "$story_dir/steps-c/step-03-execute.md"
assert_contains 'build-cmd dev {story_id} --agent "$current_agent" --state-file "$state_file"' "$story_dir/steps-c/step-03-execute.md"
assert_contains 'build-cmd dev {story_id} --agent "$current_agent" --model "$primary_model" --state-file "$state_file"' "$story_dir/steps-c/step-03-execute.md"
assert_contains 'build-cmd quick-dev {story_id} --agent "$current_agent" --state-file "$state_file"' "$story_dir/steps-c/step-03-execute.md"
assert_contains 'build-cmd quick-dev {story_id} --agent "$current_agent" --model "$primary_model" --state-file "$state_file"' "$story_dir/steps-c/step-03-execute.md"
assert_contains 'workflow quick-dev --story-key {story_id} --state-file "$state_file"' "$story_dir/steps-c/step-03-execute.md"
assert_contains 'build-cmd auto {story_id} --agent "$current_agent" --state-file "$state_file"' "$story_dir/steps-c/step-03a-execute-review.md"
assert_contains 'build-cmd auto {story_id} --agent "$current_agent" --model "$primary_model" --state-file "$state_file"' "$story_dir/steps-c/step-03a-execute-review.md"
assert_contains 'should_apply_primary_model' "$story_dir/data/retry-fallback-strategy.md"
Expand All @@ -283,10 +287,11 @@ verify_qa_prompts() {
local root="$1"
local skills_root="${2:-.claude/skills}"
local story_dir="$root/$skills_root/bmad-story-automator"
local auto_claude auto_codex review_claude retro_claude
local auto_claude auto_codex quick_dev_codex review_claude retro_claude

auto_claude="$(cd "$root" && "$story_dir/scripts/story-automator" tmux-wrapper build-cmd auto 5.3 --agent claude)"
auto_codex="$(cd "$root" && "$story_dir/scripts/story-automator" tmux-wrapper build-cmd auto 5.3 --agent codex)"
quick_dev_codex="$(cd "$root" && "$story_dir/scripts/story-automator" tmux-wrapper build-cmd quick-dev 5.3 --agent codex)"
review_claude="$(cd "$root" && "$story_dir/scripts/story-automator" tmux-wrapper build-cmd review 5.3 --agent claude)"
retro_claude="$(cd "$root" && "$story_dir/scripts/story-automator" tmux-wrapper build-cmd retro 5 --agent claude)"
# Per-task model injection on both providers, including the bracketed `[1m]`
Expand All @@ -303,6 +308,9 @@ verify_qa_prompts() {
assert_string_contains "approval_policy=\"never\"" "$auto_codex"
assert_string_contains "--disable plugins --disable sqlite --disable shell_snapshot" "$auto_codex"
assert_string_contains "READ this skill first: $skills_root/bmad-qa-generate-e2e-tests/SKILL.md" "$auto_codex"
assert_string_contains "READ this skill first: $skills_root/bmad-quick-dev/SKILL.md" "$quick_dev_codex"
assert_string_contains "Quick Dev owns planning, coding, test generation, and review" "$quick_dev_codex"
assert_string_contains "use subagents for planning, implementation, test generation, and review where useful" "$quick_dev_codex"
assert_string_contains "READ this skill first: $skills_root/bmad-story-automator-review/SKILL.md" "$review_claude"
assert_string_contains "auto-fix all issues without prompting" "$review_claude"
assert_string_contains "READ this skill first: $skills_root/bmad-retrospective/SKILL.md" "$retro_claude"
Expand Down
23 changes: 23 additions & 0 deletions skills/bmad-story-automator/data/orchestration-policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,29 @@
"contractFile": "<skills-root>/bmad-story-automator-review/contract.json"
}
},
"quick-dev": {
"label": "quick-dev",
"assets": {
"skillName": "bmad-quick-dev",
"workflowCandidates": ["workflow.md", "workflow.yaml"],
"instructionsCandidates": [],
"checklistCandidates": ["checklist.md"],
"templateCandidates": [],
"required": []
},
"prompt": {
"templateFile": "data/prompts/quick-dev.md",
"interactionMode": "autonomous",
"defaultExtraInstruction": "use subagents for planning, implementation, test generation, and review where useful; complete the story without prompting"
},
"parse": {
"schemaFile": "data/parse/quick-dev.json"
},
"success": {
"verifier": "review_completion",
"contractFile": "<skills-root>/bmad-story-automator-review/contract.json"
}
},
"retro": {
"label": "retrospective",
"assets": {
Expand Down
11 changes: 11 additions & 0 deletions skills/bmad-story-automator/data/parse/quick-dev.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"requiredKeys": ["status", "story_done", "tests_passed", "critical_issues_remaining", "summary", "next_action"],
"schema": {
"status": "SUCCESS|FAILURE|AMBIGUOUS",
"story_done": "true|false",
"tests_passed": "true|false",
"critical_issues_remaining": "integer",
"summary": "brief description",
"next_action": "proceed|retry|escalate"
}
}
17 changes: 17 additions & 0 deletions skills/bmad-story-automator/data/prompts/quick-dev.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Execute the Quick Dev workflow for story {{story_id}}.

{{skill_line}}{{workflow_line}}{{instructions_line}}{{checklist_line}}{{template_line}}Story file: _bmad-output/implementation-artifacts/{{story_prefix}}-*.md
Story ID: {{story_id}}

Quick Dev owns planning, coding, test generation, and review for this story.

Requirements:
- Use the existing BMAD story tracking artifacts: task checkboxes, Dev Agent Record, File List, story Status, and sprint-status.yaml.
- Use subagents for planning, implementation, test generation, and review when they materially improve throughput or quality.
- Keep subagent write scopes disjoint when running them in parallel.
- Run the relevant tests or verification commands.
- Update the story file and sprint-status.yaml through the normal story workflow contract.
- Mark the story done only when no critical issues remain.
- Do not wait for user input.

{{extra_instruction}}
1 change: 1 addition & 0 deletions skills/bmad-story-automator/data/scripts-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ model=$(echo "$selection" | jq -r '.model // ""')
| `dev` | Implement story tasks | Claude, Codex |
| `auto` | Test automation | Claude, Codex |
| `review` | Code review with auto-fix | Claude, Codex |
| `quick-dev` | Combined planning, coding, tests, and review | Codex, Claude |
| `retro` | Retrospective (YOLO mode) | Claude, Codex |

## Retrospective Commands (v1.5.0)
Expand Down
17 changes: 17 additions & 0 deletions skills/bmad-story-automator/data/workflow-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@ Implement all tasks marked [ ]. Run tests. Update checkboxes."' Enter

---

## quick-dev

```bash
tmux send-keys -t "SESSION" 'codex exec "Execute the Quick Dev workflow for story STORY_ID.

READ this skill first: <installed-skill-root>/bmad-quick-dev/SKILL.md
READ this workflow file next: <installed-skill-root>/bmad-quick-dev/workflow.md
Story file: _bmad-output/implementation-artifacts/STORY_PREFIX-*.md
Use subagents for planning, implementation, test generation, and review where useful.
Complete the story without prompting.
Mark the story done only when no critical issues remain."' Enter
```

`quick-dev` is an experimental combined execution step. The monitor still verifies completion through the story/sprint-status done gate before Automator can commit.

---

## code-review

**MUST use the dedicated `bmad-story-automator-review` skill. Do NOT use a generic Task agent for reviews.**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def _usage(code: int) -> int:
print(" get-epic-stories <epic> [--state-file path]", file=target)
print(" check-blocking <story_id>", file=target)
print(" agents-build --state-file path --complexity-file path --output path --config-json '{}'", file=target)
print(" agents-resolve (--state-file path | --agents-file path) --story ID --task create|dev|auto|review", file=target)
print(" agents-resolve (--state-file path | --agents-file path) --story ID --task create|dev|auto|review|quick-dev", file=target)
print(" retro-agent --state-file path", file=target)
return code

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def agents_build_action(args: list[str]) -> int:
for story in complexity.get("stories", []):
level = str(story.get("complexity", {}).get("level", "medium")).lower() or "medium"
tasks = {}
for task in ("create", "dev", "auto", "review"):
for task in ("create", "dev", "auto", "review", "quick-dev"):
primary, fallback, model = resolve_agent(config, level, task)
entry = {
"primary": primary,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def cmd_build_state_doc(args: list[str]) -> int:
text = re.sub(
r"(?m)^overrides:\n(?:(?:\s{2}.*\n)*)",
"overrides:\n"
f" executionMode: {json.dumps(str(overrides.get('executionMode') or 'split'))}\n"
f" skipAutomate: {str(bool(overrides.get('skipAutomate', False))).lower()}\n"
f" maxParallel: {int(overrides.get('maxParallel', 1) or 1)}\n",
text,
Expand Down Expand Up @@ -153,12 +154,13 @@ def cmd_build_state_doc(args: list[str]) -> int:
for key, value in replacements.items():
text = re.sub(rf"(?m)^{re.escape(key)}:.*$", lambda m, k=key, v=value: f"{k}: {json.dumps(v)}", text)
story_range = [item for item in config.get("storyRange", []) if isinstance(item, str)]
progress_rows = "\n".join(f"| {story_id} | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ | pending |" for story_id in story_range)
progress_rows = "\n".join(f"| {story_id} | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ | pending |" for story_id in story_range)
body = {
"{{epicName}}": str(config.get("epicName", "")),
"{{epic}}": str(config.get("epic", "")),
"{{storyRange}}": ", ".join(story_range),
"{{createdAt}}": now,
"{{overrides.executionMode}}": str(overrides.get("executionMode") or "split"),
"{{overrides.skipAutomate}}": str(bool(overrides.get("skipAutomate", False))).lower(),
"{{overrides.maxParallel}}": str(int(overrides.get("maxParallel", 1) or 1)),
"{{customInstructions}}": str(config.get("customInstructions", "")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ def build_agents_file(state_file: str | Path, complexity_file: str | Path, outpu
for story in complexity_payload.get("stories", []):
level = str(((story.get("complexity") or {}).get("level")) or "medium").strip().lower() or "medium"
tasks = {}
for task in ("create", "dev", "auto", "review"):
for task in ("create", "dev", "auto", "review", "quick-dev"):
primary, fallback, model = resolve_agent_for_task(config, level, task)
entry: dict[str, Any] = {
"primary": primary,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .utils import ensure_dir, get_project_root, iso_now, md5_hex8, read_text, write_atomic

VALID_TOP_LEVEL_KEYS = {"version", "snapshot", "runtime", "workflow", "steps"}
VALID_STEP_NAMES = {"create", "dev", "auto", "review", "retro"}
VALID_STEP_NAMES = {"create", "dev", "auto", "review", "quick-dev", "retro"}
VALID_VERIFIERS = {"create_story_artifact", "session_exit", "review_completion", "epic_complete"}
VALID_ASSET_NAMES = {"skill", "workflow", "instructions", "checklist", "template"}
VALID_PARSER_PROVIDERS = {"claude"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ config_json=$(jq -n \
--arg currentStep "preflight" \
--arg aiCommand "$agent_cmd" \
--arg customInstructions "$custom_instructions" \
--argjson overrides "{\"skipAutomate\":$skip_automate,\"maxParallel\":$max_parallel}" \
--argjson overrides "{\"executionMode\":\"split\",\"skipAutomate\":$skip_automate,\"maxParallel\":$max_parallel}" \
--argjson agentConfig "$agent_config_json" \
'{epic:$epic,epicName:$epicName,storyRange:$storyRange,status:$status,currentStory:null,currentStep:$currentStep,aiCommand:$aiCommand,customInstructions:$customInstructions,overrides:$overrides,agentConfig:$agentConfig}'
)
Expand Down
43 changes: 39 additions & 4 deletions skills/bmad-story-automator/steps-c/step-03-execute.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ state_file="{outputFile}"
- REQUIRED patterns (verify state after each step)
- Monitoring failure fallback sequence

**Key rule:** Each step (create/dev/auto/review) MUST be executed and monitored separately. NEVER chain steps in loops.
**Key rule:** Each step in the selected execution mode MUST be executed and monitored separately. NEVER chain steps in loops.

**Execution modes:**
- `split` (default): run create-story, dev-story, automate, and code-review as separate child sessions.
- `quick-dev` (experimental): run one Quick Dev child session per story, then verify the same story/sprint-status completion gate before finalization.

## Story Loop

Expand All @@ -94,7 +98,7 @@ echo "- **[$(date -u +%Y-%m-%dT%H:%M:%SZ)]** Starting story {story_id}" >> "$sta

# Initialize Story Progress row
tmp_state=$(mktemp)
awk -v row="| {story_id} | - | - | - | - | - | in-progress |" '
awk -v row="| {story_id} | - | - | - | - | - | - | in-progress |" '
/^<!-- Progress rows -->$/ { print row }
{ print }
' "$state_file" > "$tmp_state" && mv "$tmp_state" "$state_file"
Expand All @@ -121,6 +125,35 @@ If multiple logs exist, run one grep/regex pass across all log files and forward
- Return only: `next_action`, `confidence`, `error_class`, `retryable`, `reasons`, `session_id`
- Do not pass full raw logs to parent flow unless escalation explicitly requires evidence payload

### Quick Dev Mode

If `overrides.executionMode == "quick-dev"`, skip sections A and B and run this section instead.

```bash
resolve_agent_for_task "quick-dev" "$state_file" "{story_id}"
if should_apply_primary_model "$current_agent"; then
built_cmd=$("$scripts" tmux-wrapper build-cmd quick-dev {story_id} --agent "$current_agent" --model "$primary_model" --state-file "$state_file")
else
built_cmd=$("$scripts" tmux-wrapper build-cmd quick-dev {story_id} --agent "$current_agent" --state-file "$state_file")
fi
session=$("$scripts" tmux-wrapper spawn quick-dev {epic} {story_id} \
--agent "$current_agent" \
--command "$built_cmd")
result=$("$scripts" monitor-session "$session" --json --agent "$current_agent" --workflow quick-dev --story-key {story_id} --state-file "$state_file")
"$scripts" tmux-wrapper kill "$session"
validation=$("$scripts" orchestrator-helper verify-step quick-dev {story_id} --state-file "$state_file")
parsed=$("$scripts" orchestrator-helper parse-output "$(printf '%s' "$result" | jq -r '.output_file')" quick-dev --state-file "$state_file")
```

- If `validation.verified == true`:
```bash
tmp_state=$(mktemp)
sed "s/^| ${story_id} |.*$/| ${story_id} | - | - | done | - | done | - | in-progress |/" "$state_file" > "$tmp_state" && mv "$tmp_state" "$state_file"
```
→ skip `{nextStep}` and proceed directly to `step-03b-execute-finish.md`
- If `validation.verified == false` AND attempts < 5 → retry with next agent (see `{retryStrategy}`)
- If `validation.verified == false` AND attempts == 5 → escalate (all retries exhausted)

### A. Create Story
*Skip if story file exists*

Expand Down Expand Up @@ -149,7 +182,7 @@ validation=$("$scripts" orchestrator-helper verify-step create {story_id} --stat
```bash
# Update Story Progress: mark create-story done
tmp_state=$(mktemp)
sed "s/^| ${story_id} |.*$/| ${story_id} | done | - | - | - | - | in-progress |/" "$state_file" > "$tmp_state" && mv "$tmp_state" "$state_file"
sed "s/^| ${story_id} |.*$/| ${story_id} | done | - | - | - | - | - | in-progress |/" "$state_file" > "$tmp_state" && mv "$tmp_state" "$state_file"
```
→ proceed to B
- If `validation.verified == false` AND attempts < 5 → retry with next agent (see `{retryStrategy}`)
Expand Down Expand Up @@ -191,7 +224,7 @@ reasons=$(echo "$parsed" | jq -c '.reasons // []')
```bash
# Update Story Progress: mark dev-story done
tmp_state=$(mktemp)
sed "s/^| ${story_id} |.*$/| ${story_id} | done | done | - | - | - | in-progress |/" "$state_file" > "$tmp_state" && mv "$tmp_state" "$state_file"
sed "s/^| ${story_id} |.*$/| ${story_id} | done | done | - | - | - | - | in-progress |/" "$state_file" > "$tmp_state" && mv "$tmp_state" "$state_file"
```
→ proceed to C (next step)
- If `next_action == "retry"` OR `result.final_state == "crashed"`:
Expand All @@ -201,6 +234,8 @@ reasons=$(echo "$parsed" | jq -c '.reasons // []')

## Auto-Proceed to Review Phase

If `overrides.executionMode == "quick-dev"` and Quick Dev verification passed, skip this section and load `step-03b-execute-finish.md`.

Display: "**Dev story complete. Proceeding to automate and code review...**"

```bash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ result=$("$scripts" monitor-session "$session" --json --agent "$current_agent")
```bash
# Update Story Progress: mark automate done
tmp_state=$(mktemp)
sed "s/^| ${story_id} |.*$/| ${story_id} | done | done | done | - | - | in-progress |/" "{outputFile}" > "$tmp_state" && mv "$tmp_state" "{outputFile}"
sed "s/^| ${story_id} |.*$/| ${story_id} | done | done | - | done | - | - | in-progress |/" "{outputFile}" > "$tmp_state" && mv "$tmp_state" "{outputFile}"
```
Display: `[story {N}/{total}] automate -> done`
→ proceed to D
- FAILURE → retry up to 3 attempts (non-blocking, so fewer retries), then log warning:
```bash
# Update Story Progress: mark automate skipped
tmp_state=$(mktemp)
sed "s/^| ${story_id} |.*$/| ${story_id} | done | done | skip | - | - | in-progress |/" "{outputFile}" > "$tmp_state" && mv "$tmp_state" "{outputFile}"
sed "s/^| ${story_id} |.*$/| ${story_id} | done | done | - | skip | - | - | in-progress |/" "{outputFile}" > "$tmp_state" && mv "$tmp_state" "{outputFile}"
```
Display: `[story {N}/{total}] automate -> skip (non-blocking)`
→ proceed to D
Expand Down Expand Up @@ -99,7 +99,7 @@ Key points:
```bash
# Update Story Progress: mark code-review done
tmp_state=$(mktemp)
sed "s/^| ${story_id} |.*$/| ${story_id} | done | done | done | done | - | in-progress |/" "{outputFile}" > "$tmp_state" && mv "$tmp_state" "{outputFile}"
sed "s/^| ${story_id} |.*$/| ${story_id} | done | done | - | done | done | - | in-progress |/" "{outputFile}" > "$tmp_state" && mv "$tmp_state" "{outputFile}"
```
Display: `[story {N}/{total}] review -> done`
→ E | `incomplete` → count as failed attempt, retry until maxCycles, then CRITICAL escalate (Trigger #8)
Expand Down
Loading