ワンクリックで
flywheel
Start or resume the full agentic coding flywheel. Drives the complete workflow: scan → discover → plan → implement → review.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Start or resume the full agentic coding flywheel. Drives the complete workflow: scan → discover → plan → implement → review.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Check if the codebase has drifted from the implementation plan.
Full health check of the codebase and flywheel dependencies.
Deep research on an external GitHub repository to extract implementation insights.
Set up flywheel prerequisites for this project.
Stop the current flywheel session and reset state.
Launch a parallel swarm of agents to implement multiple beads simultaneously.
| name | flywheel |
| description | Start or resume the full agentic coding flywheel. Drives the complete workflow: scan → discover → plan → implement → review. |
Run the agent-flywheel for this project. $ARGUMENTS (optional: initial goal or --mode single-branch)
⚠️ UNIVERSAL RULE 1 —
AskUserQuestionis the only way to ask the user anythingEvery user decision in this skill — phase routing, plan refinement, bead approval, launch confirmation, wrap-up choices, recovery branches — MUST be presented via the
AskUserQuestiontool with concrete labeled options (2–4 per question). Free-text "ask the user…" prompts, "wait for confirmation", "wait for the user's next message", or implicit decision points are bugs. The "Other" field absorbs custom answers when none of the prepared options fit.If you find yourself about to write text like "surface this to the user", "propose this to the user", "check with the user", or "only do X if the user confirms" — STOP and write an
AskUserQuestioncall instead. No exceptions.⚠️ UNIVERSAL RULE 2 — invoke specialist skills by name when they apply
This SKILL references many specialist skills by slash-name (
/idea-wizard,/ubs-workflow,/caam,/ui-polish,/docs-de-slopify, testing-*, stack-specific skills, etc.). When a step names one, invoke it via theSkilltool rather than re-implementing its logic inline. Specialist skills carry project-tested prompts and conventions you don't have time to recreate.Equally important: if a step does NOT name a skill but you notice one applies to the situation (e.g. a React component bead and
/react-component-generatorexists), invoke it anyway. Skills are hints-with-authority — use them by default, skip only when they clearly don't fit.
If the user's prompt contains anything beyond /flywheel <args> — a goal sentence, a pasted plan, a path to a plan file, a directive like "fix X then Y" — capture it as USER_INPUT and treat it as a candidate goal or plan. Do NOT act on it yet. Do NOT skip the welcome banner or Step 0b detection. Run the full Step 0a–0d flow silently so the user sees current state (existing session, open beads, AM status) before deciding.
Then route in Step 0e instead of showing the default main menu:
Classification heuristics:
##/### headers, mentions specific files, OR is an existing path matching docs/plans/*.md → treat as plan./brainstorming to refine first.Routing override for Step 0e (only when USER_INPUT is non-empty):
Plan-shaped:
AskUserQuestion(questions: [{
question: "I see a plan in your message ('<first 60 chars>…'). What should I do with it?",
header: "Plan input",
options: [
{ label: "Use as plan", description: "Register via flywheel_plan and jump to bead creation (Recommended)" },
{ label: "Treat as goal", description: "Use the plan content as the goal description and run the full flywheel from Step 4" },
{ label: "Discard", description: "Ignore the input and show the regular start menu" }
],
multiSelect: false
}])
flywheel_plan with planFile. If it was inline, write it to docs/plans/<date>-<goal-slug>.md first, then call flywheel_plan with planFile. Then jump to Step 5.5.flywheel_select with the input as goal, jump to Step 5.Goal-shaped:
AskUserQuestion(questions: [{
question: "I see a goal in your message: '<USER_INPUT>'. Run the flywheel on this?",
header: "Goal input",
options: [
{ label: "Yes, full flywheel", description: "Skip discovery, plan and implement this goal (Recommended)" },
{ label: "Refine first", description: "Run /brainstorming to clarify scope before planning" },
{ label: "Plan only", description: "Generate a plan, stop before implementation" },
{ label: "Discard", description: "Ignore the input and show the regular start menu" }
],
multiSelect: false
}])
flywheel_select with USER_INPUT as goal, proceed to Step 5./brainstorming with the input, then return to Step 4 with the refined goal.flywheel_select, proceed through Step 5, stop after bead creation.Ambiguous → always run /brainstorming first, then route as goal-shaped after refinement.
Hard rule: never act on USER_INPUT directly without first showing the banner and getting an explicit menu choice. The flywheel's gates exist for a reason — pre-prompt content does NOT bypass them.
Attempt to find mcp-server/package.json by searching the Claude plugins directory:
find ~/.claude/plugins -path "*/agent-flywheel/mcp-server/package.json" 2>/dev/null | head -1
Read it and extract the version. Also read the project name from package.json in cwd (or use the directory name).
Gather context silently (do NOT display raw output yet). Run checks 1-5 in parallel where possible:
flywheel_profile directly with cwd — if the call succeeds, MCP is available (cache the result to avoid a redundant call in Step 1). If the tool is not found or errors, set MCP_DEGRADED = true. Do NOT use ToolSearch — MCP tools may be deferred and unavailable to ToolSearch at startup..pi-flywheel/checkpoint.json if it exists. Note phase and goal.br list --json 2>/dev/null and count open/in-progress/closed beads.git log --oneline -1 to get latest commit.flywheel_memory with operation: "search" and query: "session learnings flywheel" to load prior session context. If CASS is unavailable, skip silently.curl -s --max-time 2 http://127.0.0.1:8765/health/liveness via Bash. If unreachable, set AGENT_MAIL_DOWN = true — display Agent Mail: offline in the banner and warn before any step that spawns parallel agents. Do NOT block the session or require /flywheel-setup — single-agent workflows work fine without it.Display a single cohesive welcome message. Example:
╔══════════════════════════════════════════════════╗
║ ║
║ agent-flywheel v3.0.0 ║
║ The Agentic Coding Flywheel ║
║ ║
║ Project: <project-name> ║
║ Branch: <current-branch> @ <short-sha> ║
║ Beads: <N open> | <M in-progress> | <K done> ║
║ ║
╚══════════════════════════════════════════════════╝
If beads is zero, show Beads: none yet. If MCP tools are unavailable, show MCP: not configured in the banner.
If CASS returned learnings from prior sessions, display them below the banner:
From prior sessions:
- <top 3-5 most relevant learnings, anti-patterns, or gotchas>
This gives the user (and the agent-flywheel) context from past runs before making any decisions.
Build the menu options dynamically based on detected state:
If a previous session exists (checkpoint found with non-idle phase):
AskUserQuestion(questions: [{
question: "What would you like to do?",
header: "Start",
options: [
{ label: "Resume session", description: "Continue '<goal>' from <phase> phase" },
{ label: "Work on beads", description: "<N> open beads exist — refine, implement, or inspect" },
{ label: "New goal", description: "Start fresh with a new goal (discards previous session)" },
{ label: "Research repo", description: "Paste a GitHub URL to study an external repo for insights" }
],
multiSelect: false
}])
If open/in-progress beads exist but no active session:
AskUserQuestion(questions: [{
question: "What would you like to do?",
header: "Start",
options: [
{ label: "Work on beads", description: "<N> open beads exist — refine, implement, or inspect" },
{ label: "New goal", description: "Scan the repo and discover improvement ideas" },
{ label: "Research repo", description: "Paste a GitHub URL to study an external repo for insights" },
{ label: "Quick fix", description: "Apply a targeted fix without the full flywheel" }
],
multiSelect: false
}])
If no beads and no session (fresh start):
AskUserQuestion(questions: [{
question: "What would you like to do?",
header: "Start",
options: [
{ label: "Scan & discover", description: "Profile the repo and find improvement opportunities" },
{ label: "Set a goal", description: "I already know what I want to build" },
{ label: "Research repo", description: "Paste a GitHub URL to study an external repo for insights" },
{ label: "Setup", description: "Run /flywheel-setup to configure prerequisites" }
],
multiSelect: false
}])
If
USER_INPUTwas captured in step 0.preflight, use the routing override there instead of this menu. The default menu below applies only when the user invoked/flywheelwith no extra prompt content.
| Choice | Action |
|---|---|
| Resume session | Run the drift check below before jumping to the saved phase |
| Work on beads | Run the Work-on-beads sub-menu + bootstrap below — do NOT call flywheel_approve_beads directly |
| New goal | Delete checkpoint if exists, proceed to Step 2 |
| Scan & discover | Proceed to Step 2 |
| Set a goal | Run /brainstorming to refine the goal, then proceed to Step 4 |
| Research repo | Prompt for GitHub URL via the menu below, then invoke /flywheel-research |
| Quick fix | Invoke /flywheel-fix |
| Audit | Invoke /flywheel-audit |
| Setup | Invoke /flywheel-setup |
flywheel_approve_beads requires state.selectedGoal. On a fresh session with leftover beads, the goal is empty and the tool errors with missing_prerequisite. Bootstrap it before any approve call:
br list --json and build a default like Continue: <title-1>; <title-2>; <title-3> (truncate at 200 chars).AskUserQuestion(questions: [{
question: "These beads need a goal label so the agent-flywheel can resume. Use the synthesized default?",
header: "Goal",
options: [
{ label: "Use default", description: "'<synthesized goal>' (Recommended)" },
{ label: "Custom goal", description: "Provide a one-line goal in the Other field" }
],
multiSelect: false
}])
flywheel_select with the chosen goal. This populates state.selectedGoal and unblocks every downstream tool.AskUserQuestion(questions: [{
question: "<N> open beads. What do you want to do with them?",
header: "Beads",
options: [
{ label: "Implement", description: "Jump to Step 6 with launch as the default action (Recommended)" },
{ label: "Refine", description: "Jump to Step 6 with polish as the default action — restructure beads/deps before implementing" },
{ label: "Inspect", description: "Show br list + bv dependency graph, then re-show this menu" }
],
multiSelect: false
}])
flywheel_approve_beads(action: "polish") first to enter refining_beads phase, then show Step 6's menu so the user can iterate (Polish further / Start / Reject) until satisfied.br list + bv --robot-triage (or bv alone if --robot-triage not supported), display, then re-show the action sub-menu.Before jumping to the saved phase, compare the checkpoint to reality:
git rev-parse HEAD → compare to checkpoint.gitHead. If they differ, HEAD has moved.br list --json → compare bead IDs/statuses to checkpoint.activeBeadIds and checkpoint.beadResults. If beads listed in checkpoint don't exist (or are all closed when checkpoint says phase: implementing), state is stale.If either check shows drift, present:
AskUserQuestion(questions: [{
question: "Checkpoint drift detected: <summary, e.g. 'HEAD moved 5 commits ahead; 0/8 active beads still open'>. How should I proceed?",
header: "Drift",
options: [
{ label: "Start fresh", description: "Discard the stale checkpoint and run the start menu (Recommended)" },
{ label: "Inspect first", description: "Show the diff between checkpoint and reality, then re-prompt" },
{ label: "Force resume", description: "Resume anyway — useful only if you know the checkpoint is still relevant" }
],
multiSelect: false
}])
.pi-flywheel/checkpoint.json, route as if user picked "New goal".git log <checkpoint.gitHead>..HEAD --oneline + bead status table), then re-show this menu.If both checks pass (no drift), resume directly without showing the menu.
Use AskUserQuestion to collect the URL and mode:
AskUserQuestion(questions: [{
question: "Paste the GitHub URL you want to research:",
header: "Research",
options: [
{ label: "Research only", description: "Extract insights and patterns — no code changes" },
{ label: "Research + integrate", description: "Study the repo, then create an integration plan with beads" }
],
multiSelect: false
}])
The user pastes the URL in the "Other" field, or picks a mode first and provides the URL when prompted. Then:
/flywheel-research <url>./flywheel-research <url> --mode integrate (the slash command's research skill reads --mode integrate to run Phases 8–12 / Major Feature Integration). If the slash command rejects the flag, fall back to invoking /flywheel-research <url> and prepend the prompt context "After research, generate an integration plan and create implementation beads."MCP tools missing (flywheel_profile call failed or tool not found in step 0b):
MCP: not configured — run /flywheel-setupMCP_DEGRADED = true and apply these overrides for all subsequent steps:
flywheel_profile).flywheel_discover).docs/plans/<date>-<goal-slug>.md (skip flywheel_plan).br create as normal.br list, ask user to confirm manually — no quality score available.flywheel_review).flywheel_memory — remind user that session learnings were not auto-persisted.Agent Mail offline (AGENT_MAIL_DOWN = true from step 0b check 6):
Agent Mail: offline — parallel agents will skip file reservations/flywheel-setup. All flywheel coordination still works.Call flywheel_profile with cwd. The tool uses a git-HEAD-keyed cache — if the repo hasn't changed since the last scan, it returns instantly from cache.
force: true to flywheel_profile to bypass the cache (e.g. after major restructuring).If MCP_DEGRADED is true or flywheel_profile fails, fall back to an Explore agent for manual profiling.
After profiling completes, briefly display the key findings (languages, frameworks, test setup) then use AskUserQuestion:
AskUserQuestion(questions: [{
question: "Repository profiled. What next?",
header: "Profile",
options: [
{ label: "Discover ideas", description: "Find improvement opportunities based on the profile (Recommended)" },
{ label: "Set a goal", description: "I already know what I want to work on" },
{ label: "Re-scan", description: "Force a fresh profile scan (force: true)" }
],
multiSelect: false
}])
/brainstorming, then proceed to Step 4flywheel_profile with force: true, then return to this menuBefore discovering ideas, query CASS for past goal history: call flywheel_memory with operation: "search" and query: "past goals success failure anti-pattern". If results are returned, use them to:
Choose discovery depth via AskUserQuestion:
AskUserQuestion(questions: [{
question: "How deep should discovery go?",
header: "Discovery depth",
options: [
{ label: "Fast (default)", description: "flywheel_discover one-shot \u2014 5-10 ranked ideas (Recommended for repeat cycles)" },
{ label: "Deep (idea-wizard)", description: "Invoke /idea-wizard for the 6-phase 30\u21925\u219215 pipeline \u2014 matches guide's Phase 5 (Recommended for fresh projects or wide-open cycles)" },
{ label: "Market-validated", description: "Run /idea-wizard, then /xf to check X/Twitter signal on each top idea" },
{ label: "Triangulated", description: "Run /idea-wizard, then /multi-model-triangulation for second-opinion scoring across Codex/Gemini/Grok" }
],
multiSelect: false
}])
flywheel_discover./idea-wizard, feed its output into flywheel_discover, then continue with the standard goal-selection menu./idea-wizard, then for each top-3 idea invoke /xf with a query like "<idea title>" site:x.com. Annotate each candidate with real-world signal before showing the goal menu./idea-wizard, then /multi-model-triangulation on the top-5 list to surface which ideas all models agree on vs which are one-model bets.If MCP_DEGRADED is false, call flywheel_discover with cwd.
If MCP_DEGRADED is true (or flywheel_discover fails), generate improvement ideas from the Explore agent's findings in Step 2: identify code quality issues, missing tests, architectural improvements, and documentation gaps. Rank by estimated impact.
Present the top ideas to the user using AskUserQuestion. Include up to 4 top-ranked ideas as options (the "Other" option is automatically provided for custom goals):
AskUserQuestion(questions: [{
question: "Which goal would you like to pursue?",
header: "Goal",
options: [
{ label: "<idea 1 short title>", description: "<one-line summary>" },
{ label: "<idea 2 short title>", description: "<one-line summary>" },
{ label: "<idea 3 short title>", description: "<one-line summary>" },
{ label: "<idea 4 short title>", description: "<one-line summary>" }
],
multiSelect: false
}])
If the user selects "Other" and enters a custom goal, run the /brainstorming skill first to explore intent, constraints, and edge cases before committing to scope. The brainstorming skill will use AskUserQuestion to ask clarifying questions about:
After brainstorming completes and the goal is refined, use AskUserQuestion to confirm scope:
AskUserQuestion(questions: [{
question: "Goal refined: '<refined goal from brainstorming>'. How should I scope this?",
header: "Scope",
options: [
{ label: "Full flywheel", description: "Deep scan, plan, implement with agents, review" },
{ label: "Plan only", description: "Generate and review a plan, stop before implementation" },
{ label: "Quick fix", description: "Skip planning — use /flywheel-fix for a targeted change" }
],
multiSelect: false
}])
/flywheel-fix with the refined goal insteadOnce the user chooses, call flywheel_select with cwd and goal set to their choice.
Before presenting the choice, briefly frame the Three Reasoning Spaces to help the user understand why planning investment matters:
The Flywheel operates across three reasoning spaces:
- Plan Space (where we are now) — architecture, features, tradeoffs. Fixing errors here costs 1x.
- Bead Space (next) — self-contained work units with dependencies. Fixing errors here costs 5x.
- Code Space (implementation) — source files and tests. Fixing errors here costs 25x.
Deep planning front-loads effort where corrections are cheapest.
Use AskUserQuestion:
AskUserQuestion(questions: [{
question: "How would you like to plan?",
header: "Plan mode",
options: [
{ label: "Standard plan", description: "Single planning pass — faster" },
{ label: "Deep plan", description: "3 AI models give competing perspectives, then synthesize — higher quality, takes longer (Recommended)" },
{ label: "Triangulated plan", description: "Deep plan + /multi-model-triangulation second-opinion on the synthesis before alignment check — highest quality, longest" }
],
multiSelect: false
}])
Standard plan: Call flywheel_plan with cwd and mode: "standard". After it returns, STOP and jump to Step 5.55 (Plan alignment check) — that step runs the qualifying-questions loop and only then hands off to Step 5.6 (Plan-ready gate). Do NOT skip 5.55 or proceed to bead creation without the user explicitly selecting "Create beads" from the Step 5.6 menu.
Deep plan:
Bootstrap Agent Mail — call macro_start_session with:
human_key: current working directoryprogram: "claude-code"model: your model nametask_description: "Orchestrating deep plan for: "
Note your assigned agent name (e.g. "CoralReef") — you are the coordinator.Create a team — call TeamCreate with a descriptive team_name (e.g. "deep-plan-<slug>").
Spawn 3 plan agents IN PARALLEL using the Agent tool with team_name set and run_in_background: true so they get task IDs (required for TaskStop if they become unresponsive):
Agent(model: "opus", name: "correctness-planner", team_name: "<team>", run_in_background: true, prompt: "...")Agent(model: "sonnet", name: "ergonomics-planner", team_name: "<team>", run_in_background: true, prompt: "...")Agent(subagent_type: "codex:codex-rescue", name: "robustness-planner", team_name: "<team>", run_in_background: true, prompt: "...")Save the task ID returned by each Agent call — you'll need them to force-stop unresponsive agents via TaskStop(task_id: "<id>").
Each agent's prompt MUST include:
macro_start_session first (same human_key, their model, their task)flywheel_memory with query: "architecture planning decisions <goal>" and include the top learnings in the agent prompt as a "Prior Session Context" section. This prevents agents from repeating past mistakes or reinventing prior decisions.docs/plans/<date>-<perspective>.md (use the Write tool — do NOT send large plan text through Agent Mail message body)send_message with subject "[deep-plan] <perspective> plan" once writtenMonitor and nudge — agents go idle between turns (this is normal). If a teammate has gone idle without delivering their plan:
SendMessage(to: "<agent-name>", message: "Your plan is needed — please send it to <your-name> via Agent Mail and report back.") to wake them.fetch_inbox to see which plans have arrived.TaskList to see overall team task status.TaskStop(task_id: "<saved-task-id>"). Then retire it in Agent Mail: retire_agent(project_key: cwd, agent_name: "<their-agent-mail-name>"). Do not rely on shutdown_request messages alone — in-process agents may not respond to them.TaskStop fails (e.g. no task ID found in TaskList for in-process agents): retire via Agent Mail retire_agent(project_key: cwd, agent_name: "<stale-agent-name>"), then edit ~/.claude/teams/<team>/config.json to remove the stale member from the "members" array. Then retry TeamDelete.Collect plans — call fetch_inbox(project_key: cwd, agent_name: "<your-name>", include_bodies: false) to retrieve message summaries. Each agent sent the file path to their plan on disk (e.g. docs/plans/<date>-<perspective>.md). Read the plan files directly from disk using the Read tool — do NOT rely on inbox message bodies for large plan content, as they may be truncated or unwieldy.
Progressive plan commit (recommended). As soon as each perspective plan lands on disk, commit it — do NOT batch plan artifacts for Step 9.5 wrap-up. This keeps the git log interleaved with the implementation cycle so future bisects land on a plan+code pair. One commit per perspective plan + one for the synthesized plan + one for the triangulation report:
git add docs/plans/<date>-correctness.md
git commit -m "docs(plans): add <date>-correctness.md (deep-plan pass, <goal-slug>)"
Step 9.5 §3 should find fewer stray plan artifacts; only the -final.md revision written post-alignment-check usually needs batching there.
Shutdown teammates individually — structured shutdown messages CANNOT be broadcast to "*". Send to each agent by name:
SendMessage(to: "correctness-planner", message: {"type": "shutdown_request", "reason": "Planning complete."})
SendMessage(to: "ergonomics-planner", message: {"type": "shutdown_request", "reason": "Planning complete."})
SendMessage(to: "robustness-planner", message: {"type": "shutdown_request", "reason": "Planning complete."})
Synthesize (Best-of-All-Worlds) — spawn one synthesis agent with run_in_background: true:
Agent(model: "opus", name: "plan-synthesizer", team_name: "<team>", run_in_background: true,
prompt: "
Read the plan files written by the planning agents:
docs/plans/<date>-correctness.md
docs/plans/<date>-ergonomics.md
docs/plans/<date>-robustness.md
(and docs/plans/<date>-fresh-perspective.md if it exists)
## Best-of-All-Worlds Synthesis
For EACH plan, BEFORE proposing any changes:
1. Honestly acknowledge what that plan does better than the others.
2. Identify the unique insight each plan contributes that the others miss.
Then synthesize:
3. Blend the strongest ideas from all plans into a single superior document.
4. For each major decision, state which plan's approach you adopted and why.
5. Flag unresolved tensions where plans fundamentally disagree.
The synthesis must be BETTER than any individual plan, not a lowest-common-denominator average.
Write the result to: docs/plans/<date>-<goal-slug>-synthesized.md
Send the file path to <your-coordinator-name> via Agent Mail when done.
"
)
Do NOT embed plan content inline in the prompt — read from disk.
Shutdown after done: SendMessage(to: "plan-synthesizer", message: {"type": "shutdown_request", "reason": "Synthesis complete."}).
Call flywheel_plan with cwd, mode: "deep", and planFile: "docs/plans/<date>-<goal-slug>-synthesized.md".
Never pass planContent — large text over MCP stdio stalls the server. Always write to disk first.
Triangulated plan mode — if the user picked "Triangulated plan" at Step 5 entry, AFTER flywheel_plan returns, invoke /multi-model-triangulation with the synthesized plan file as input. Capture the triangulation report (agreements, disagreements, unique insights per model). Present the report alongside the Step 5.55 alignment questions so the user sees where external models diverge from the Opus synthesis before approving.
STOP — jump to Step 5.55 (Plan alignment check). That step runs the qualifying-questions loop and only then hands off to Step 5.6 (Plan-ready gate). Do NOT skip 5.55 or proceed to bead creation without the user explicitly selecting "Create beads" from the Step 5.6 menu.
Hard rule: After
flywheel_planreturns and BEFORE showing the Step 5.6 plan-ready gate, run this alignment check. The deeper the plan, the more assumptions are baked in — the user must confirm those assumptions match intent before any bead is created. This loop mirrors the bead-refinement loop: ask, refine on disagreement, re-ask, until aligned.
Read state.planDocument end-to-end. Identify 2-4 load-bearing decisions that, if wrong, would force a major rewrite later. Look specifically for:
Skip the obvious. Ask only about decisions where reasonable people would disagree.
If the plan (or deep-plan synthesis) contains numeric claims about the actual codebase — file counts, line counts, dependency counts, test counts, package counts — and especially if multiple source plans disagree on a number, run the command to get the real value before building an alignment question around it. Examples:
| Claim shape | Verification command |
|---|---|
| "~N AskUserQuestion calls" | grep -rc "AskUserQuestion" skills/ | awk -F: '{s+=$2} END {print s}' |
| "~N transitive packages of " | npm ls <pkg> --all --json | jq '.. | .dependencies? // empty | keys' | jq -s 'add | unique | length' |
| "N changed files since " | git diff --name-only <sha>..HEAD | wc -l |
| "N test files in module" | find <dir> -name '*.test.*' | wc -l |
Cost: one shell command, seconds. Benefit: the user arbitrates on real numbers, not competing guesses. If the two plans' numbers bracket reality (e.g. plans say "28 or 59", real=38), note which plan was closer when synthesizing the next round.
Use a single AskUserQuestion call with up to 4 questions (the tool's max). Each question must have 2-4 distinct, mutually-exclusive options framed as user-facing choices, not yes/no validations:
AskUserQuestion(questions: [
{
question: "Plan scopes <X, Y, Z>. Anything to add or drop?",
header: "Scope",
options: [
{ label: "Scope is right", description: "Proceed with X, Y, Z as defined" },
{ label: "Drop <Z>", description: "Out of scope for this cycle" },
{ label: "Add <something>", description: "Specify in Other" }
],
multiSelect: false
},
{
question: "Plan picks <approach A> over <approach B> because <reason>. Agree?",
header: "Approach",
options: [
{ label: "Agree with A", description: "Proceed with the plan's choice" },
{ label: "Switch to B", description: "Refine plan to use approach B" },
{ label: "Hybrid", description: "Specify the blend in Other" }
],
multiSelect: false
},
{
question: "Plan defers <risk Z> to a later cycle. Acceptable?",
header: "Risk",
options: [
{ label: "Defer is fine", description: "Park Z; revisit next cycle" },
{ label: "Address now", description: "Refine plan to include Z" }
],
multiSelect: false
}
// Add a 4th only if there's a genuinely load-bearing decision left.
])
Do NOT pad with low-value questions. 2 sharp questions beat 4 fuzzy ones.
All answers confirm the plan ("Scope is right" / "Agree with A" / "Defer is fine" etc.) → proceed to Step 5.6 (Plan-ready gate). Note in your end-of-turn summary that alignment was confirmed.
Decisive convergence — all answers request changes AND every change is a consistent pick from a SINGLE alternative source (e.g. the user picked the Codex column on every row of a triangulation report, or picked "plan B" on every question where plans diverged): run ONE refinement round to incorporate the user's selections, then skip the re-extract loop and proceed directly to Step 5.6. Rationale: the user has already arbitrated every open question in a single batch; re-asking "is the revised plan aligned?" is ceremonial. Surface in your end-of-turn summary: "Decisive convergence on
Mixed answers (some confirm, some change; or changes drawn from multiple sources) → run a refinement round automatically (do NOT prompt the user again first). Spawn:
Agent(model: "opus", name: "align-refine-<N>", isolation: "worktree", run_in_background: true,
prompt: "
Read the plan at <state.planDocument>.
The user reviewed it and requested these changes:
- Scope: <user's scope answer + their Other-field text if any>
- Approach: <user's approach answer + Other text>
- Risk: <user's risk answer + Other text>
(omit lines for questions where the user confirmed.)
Revise the plan to incorporate ALL requested changes. Prior reviewers
found **80+ distinct implications** downstream of changes like these
that they fixed — ripple effects in dependencies, coverage gaps,
invalidated assumptions. Find AT LEAST that many. Don't just patch
the three lines the user pointed at; trace every knock-on effect
through the plan and fix those too.
Preserve the structure (sections, task table, verification block).
For each change, add a one-line rationale at the change site so future
reviewers see the user's intent. Use ultrathink.
Write the revised plan to the same file path when done.
"
)
After it completes, return to step 1 of this section (re-read the revised plan, regenerate qualifying questions based on the new content, present again). Loop until all answers confirm.
If the alignment loop runs more than 3 rounds without converging, break out and present:
AskUserQuestion(questions: [{
question: "We've done <N> alignment rounds without converging. Continue refining or step back?",
header: "Stuck",
options: [
{ label: "One more round", description: "User provides specific instructions in Other" },
{ label: "Back to Step 5.6", description: "Accept current plan; iterate later via Refine plan" },
{ label: "Start over", description: "Discard plan, return to Step 3" }
],
multiSelect: false
}])
This prevents infinite loops when the plan and the user's intent are fundamentally misaligned (signal to start over) or when the user is over-tweaking (signal to ship and iterate).
Hard rule: After
flywheel_planreturns successfully — regardless ofmode— you MUST stop here and present this menu. Do NOT callbr create,flywheel_approve_beads, or any implementation tool until the user explicitly selects "Create beads". Skipping this gate is a bug.
Display a brief summary of the plan (file path, line count, top-level section headers), then use AskUserQuestion:
AskUserQuestion(questions: [{
question: "Plan created (<N> lines, at <path>). What next?",
header: "Plan ready",
options: [
{ label: "Create beads", description: "Convert the plan into implementation beads (Recommended)" },
{ label: "Refine plan", description: "Run a fresh refinement round to deepen the plan" },
{ label: "Review plan", description: "Open the plan file for manual review before proceeding" },
{ label: "Start over", description: "Discard this plan and pick a different goal" }
],
multiSelect: false
}])
AskUserQuestion(questions: [{
question: "Done reviewing <plan-path>. What next?",
header: "Post-review",
options: [
{ label: "Looks good", description: "Proceed to Create beads" },
{ label: "Refine plan", description: "Run a refinement round (Recommended if changes needed)" },
{ label: "Start over", description: "Discard plan and pick a different goal" },
{ label: "Still reading", description: "Re-show this menu in a few minutes" }
],
multiSelect: false
}])
Route the answer back into Step 5.6.state.planDocument, return to Step 3.Iterative deepening recipe (only when "Refine plan" is chosen): spawn a NEW agent (fresh context, no memory of prior rounds) that reviews and proposes improvements:
Agent(model: "opus", name: "refine-round-<N>", isolation: "worktree", run_in_background: true,
prompt: "
Read the plan at <state.planDocument>.
You have NOT seen any prior plans or revisions — this is your first and only look.
Prior reviewers found **80+ distinct issues** in this plan that they fixed.
Find AT LEAST that many. Be ruthless — surface every assumption,
every missing edge case, every hand-wavy section, every dependency that
isn't airtight. Do not accept the plan at face value. The goal is
exhaustive critique, not polite commentary.
For each change, give detailed analysis and rationale.
Provide changes in git-diff format. Use ultrathink.
Write your revised plan to the same file path when done.
"
)
After the refinement agent completes, return to the "Plan ready" menu above. Stop offering "Refine plan" when a round produces only minor wording changes — this signals convergence.
Beads are NOT auto-created by flywheel_plan. The coordinator must create them manually from the plan output:
For each task/unit-of-work in the plan, create a bead:
br create --title "Verb phrase" --description "WHAT/WHY/HOW" --priority 2 --type task
Auto-generate test beads: If a bead's acceptance criteria include testing requirements (unit tests, e2e tests, integration tests), create a companion test bead that depends on the implementation bead:
br create --title "Test: <impl bead title>" --description "Write tests for <bead-id>: <specific test requirements from acceptance criteria>" --priority 2 --type task
br dep add <test-bead-id> <impl-bead-id>
After all beads are created, add dependency edges:
br dep add <downstream-bead-id> <upstream-bead-id>
Syntax note: Arguments are positional —
<downstream>depends on<upstream>. The--depends-onflag does NOT exist. If the command fails, verify you are passing two positional IDs with no flags.
Verify with br list — confirm all beads and dependencies look correct.
WARNING: Use
br listfor all read-only bead inspection. Never callflywheel_approve_beadsjust to preview beads — it is NOT read-only and advances internal state counters regardless of the action used.
Beads created — run coverage + dedup checks before Step 6.
Plan↔Bead coverage check (MANDATORY). Parse ##/### section headers from state.planDocument. For each section, search the bead list for any bead whose title or description references that section's topic. Build a coverage report: <section> → <bead-ids or NONE>.
Present:
AskUserQuestion(questions: [{
question: "Plan↔Bead coverage: <X>/<Y> sections covered. <missing section list if any>. What next?",
header: "Coverage",
options: [
{ label: "All covered", description: "Every plan section has at least one bead — proceed to dedup" },
{ label: "Create catch-up beads", description: "Generate beads for the missing section(s) before proceeding (Recommended)" },
{ label: "Sections out of scope", description: "Mark missing sections as deferred in plan; proceed" }
],
multiSelect: false
}])
br create per missing section with a stub description the user refines, then re-run this check.## Deferred block to the plan listing the dropped sections, then proceed.Deduplication sweep (MANDATORY). Scan bead titles + descriptions for overlap: two beads touching the same files with similar intent, or near-duplicate titles. Build a <duplicate-pair → suggested-merge> report.
Present:
AskUserQuestion(questions: [{
question: "Dedup scan: <N> overlap pair(s) found: <list>. How to resolve?",
header: "Dedup",
options: [
{ label: "Merge all", description: "Combine each pair into the canonical richer bead; carry over dependencies" },
{ label: "Review per-pair", description: "Go through each pair; list which to merge / keep in Other" },
{ label: "None found", description: "No real overlaps — proceed to Step 6 (Recommended when scan is empty)" },
{ label: "Keep separate", description: "Pairs are distinct; add a one-line rationale to each bead's description explaining the distinction" }
],
multiSelect: false
}])
On merge, use br update to extend the canonical bead's description + br dep add to carry over edges, then br close <duplicate-id> --reason "merged into <canonical>".
Proceed to Step 6 once coverage is acknowledged and dedup is resolved.
Hard rule: This step contains TWO mandatory user gates (beads-approval menu, then launch-confirmation menu). Do NOT call
TeamCreate,Agent, or any Step 7 tool until the user has explicitly selected "Launch" from the second menu. Skipping either gate is a bug.
Use br list to display the current beads. Then use AskUserQuestion:
AskUserQuestion(questions: [{
question: "Here are the implementation beads. What would you like to do?",
header: "Beads",
options: [
{ label: "Start implementing", description: "Launch the implementation loop with agents" },
{ label: "Polish further", description: "Refine the beads before implementing" },
{ label: "Reject", description: "Discard these beads and start over with a different goal" }
],
multiSelect: false
}])
flywheel_approve_beads with action: "start"
Note: If the plan was just registered via
flywheel_plan, the firstflywheel_approve_beadscall may return "Create beads from plan" instructions instead of the quality score. In that case, create beads withbr create, then callflywheel_approve_beadswithaction: "start"a second time to get the quality score and launch.
flywheel_approve_beads with action: "polish", then use br list to show updated beads, loopflywheel_approve_beads with action: "reject", return to Step 3If the user asks "what's the quality score?" before choosing to start, call flywheel_approve_beads with action: "start" immediately — this is the only way to surface the score. Present it, then wait for confirmation before proceeding to implementation.
After calling flywheel_approve_beads with action: "start", display both the convergence/quality score and a summary table:
Plan quality score: X.XX / 1.00 (threshold: 0.75 — if below, discuss with user before proceeding)
Polish red flags (independent of score — surface these to the user alongside the score when any apply):
| Bead ID | Title | Wave | Effort | Risk Flags |
|---|
Populate Wave from the bead's dependency wave assignment, Effort from the plan's effort estimate, and Risk Flags from any warnings or risk notes in the plan output. This gives the user visibility into what is about to be implemented and in what order.
Branch on the quality score — if score < 0.75, use the low-quality menu instead of the regular launch menu (do NOT launch silently).
Low quality (score < 0.75):
AskUserQuestion(questions: [{
question: "Quality score: <X.XX>/1.00 — below the 0.75 threshold. <weak-bead-summary>. How should I proceed?",
header: "Low quality",
options: [
{ label: "Polish beads", description: "Run another bead refinement round (Recommended)" },
{ label: "Back to plan", description: "Return to Step 5.6 to refine the plan itself" },
{ label: "Launch anyway", description: "Proceed despite low score — accept the risk" },
{ label: "Reject", description: "Discard these beads and start over with a different goal" }
],
multiSelect: false
}])
flywheel_approve_beads with action: "polish", return to Step 6.flywheel_approve_beads with action: "reject", return to Step 3.Acceptable quality (score >= 0.75):
AskUserQuestion(questions: [{
question: "Quality score: <X.XX>/1.00. Ready to launch implementation?",
header: "Launch",
options: [
{ label: "Launch", description: "Start implementing <N> beads with agents (Recommended)" },
{ label: "Polish more", description: "Run another refinement round on the beads" },
{ label: "Back to plan", description: "Return to plan refinement before implementing" }
],
multiSelect: false
}])
flywheel_approve_beads with action: "polish", then return to Step 6Agent ratio by open-bead count (from br ready --json). Pick the smallest tier that accommodates your wave:
| Open beads | Claude : Codex : Gemini | Notes |
|---|---|---|
| < 100 | 1 : 1 : 1 | Single rep each — coordination overhead stays low |
| 100-399 | 3 : 3 : 2 | Standard swarm |
| 400+ | 4 : 4 : 2 | Parallel tracks essential |
Claude owns architecture / complex reasoning, Codex owns fast iteration / testing, Gemini provides a second perspective for docs / review. Cap parallel spawns at the wave's independent-bead count — do not spin up agents with nothing to do.
Thundering-herd mitigation — stagger spawns by 30 seconds minimum. Do NOT spawn all agents simultaneously; they all read AGENTS.md, hit Agent Mail, and query br ready at once — piling onto the same frontier bead. Use run_in_background: true and wait 30s between each Agent(...) call.
Codex input-buffer quirk — after the prompt lands in a Codex agent, send Enter TWICE (or append a trailing newline) so the long prompt clears the input buffer.
Rate-limit management — if any impl agent reports a rate-limit error (429, "usage limit reached", etc.), invoke /caam to switch that model's account. caam activate <model> <backup-account> takes <100ms and keeps the wave moving. Don't kill and restart the agent; the wrapper just re-authenticates the current session.
Destructive-command coordination — if any impl agent proposes git reset --hard, git push --force, DROP TABLE, rm -rf, kubectl delete, or similar, invoke /slb to require two-person approval. The coordinator is the second party; never let an agent self-approve destructive ops. If /dcg is configured as a hook, most of these are already blocked at the harness layer — still confirm via /slb for anything slipping through.
DCG-blocked command workarounds — when the /dcg hook blocks a command, do not try to bypass it. Use the safe equivalent:
| Blocked command | Safe alternative | Why it's safer |
|---|---|---|
rm -rf <dir> && mkdir <dir> | mkdir -p <dir>-$$ (new temp dir with PID suffix) | No deletion; caller points to the new path |
git checkout HEAD -- <path> | git show HEAD:<path> > <path> | Redirect is reversible; no index manipulation |
git reset --hard <sha> | git stash && git checkout <sha> | Work is preserved in stash |
git push --force <branch> | git push --force-with-lease <branch> | Aborts if remote advanced since last fetch |
DROP TABLE <t> | ALTER TABLE <t> RENAME TO <t>_deprecated_<date> | Recoverable until the rename is cleaned up later |
rm -rf <dir> | mv <dir> /tmp/trash-$(date +%s)-<dir-basename> | Trashed, not deleted; cleaner scripts gc /tmp |
If none of these fit, escalate to /slb with the full command, expected outcome, and recovery plan. Never --no-verify, --dangerously-skip-permissions, or edit /dcg config to unblock a single action — those remove the safety net permanently.
Use TaskCreate to create a task per bead. For each ready bead:
Create a named implementation team if multiple beads are parallelizable:
TeamCreate(team_name: "impl-<goal-slug>")
NOTE: If a planning team (e.g.
"deep-plan-<slug>") is still active from Step 5, you must delete it first viaTeamDelete(team_name: "deep-plan-<slug>")before creating the impl team. IfTeamDeletefails because agents are still registered, retire them via Agent Mailretire_agentfirst, then retryTeamDelete. Alternatively, reuse the existing planning team by passing itsteam_nameto impl agents.
Spawn an implementation agent with team membership. Agent Mail bootstrap is only required for parallel beads — if beads are sequential (linear dependency chain, one agent at a time), omit STEP 0 to reduce overhead. For parallel beads, include the strict bootstrap to prevent file conflicts:
Agent(
subagent_type: "general-purpose",
isolation: "worktree",
name: "impl-<bead-id>",
team_name: "impl-<goal-slug>",
prompt: "
## STEP 0 — AGENT MAIL BOOTSTRAP (MANDATORY — DO THIS BEFORE ANYTHING ELSE)
Do NOT read any files or run any commands until all 3 sub-steps below are complete.
0a. Call macro_start_session(
human_key: '<cwd>',
program: 'claude-code',
model: '<model>',
task_description: 'Implementing bead <id>: <title>')
Note your assigned agent name.
0b. Call file_reservation_paths to reserve every file you plan to edit.
If any file is already reserved, wait 30 seconds and retry up to 3 times.
If still blocked after 3 retries, send a message to '<coordinator-agent-name>'
reporting the conflict, then STOP.
0c. Send a 'started' message to '<coordinator-agent-name>' via send_message
with subject '[impl] <bead-id> started'.
0d. **Re-read AGENTS.md end-to-end** (MANDATORY — do not skip even if
you think you remember it). Agents that skip this produce
non-idiomatic code and break project conventions. If the repo has
no AGENTS.md, note that in your started message.
Only after 0a, 0b, 0c, 0d are ALL complete may you proceed to Step 1.
## STEP 0.5 — LOAD MEMORY (if CASS available)
Call flywheel_memory with operation='search' and query='implementation gotchas <bead-title>'.
If results returned, review them before starting — they contain lessons from past sessions.
## STEP 0.7 — DOMAIN-SKILL LOOKUP (invoke relevant skills BEFORE writing code)
Scan the bead title + description for domain keywords and invoke the matching skill
via the Skill tool. Each hit gives you best-practice patterns specific to that stack.
Bead mentions Invoke skill
─────────────────────────────────────────────────────────
admin, /admin, /api/admin → /admin-page-for-nextjs-sites
A/B test, variant, experiment → /ab-testing
MRR, churn, cohort, customer analytics → /saas-customer-analytics
stripe, paypal, checkout, subscription → /stripe-checkout
supabase, RLS, drizzle, postgres SaaS → /supabase
tanstack, react-query, react-table → /tanstack
react component, .tsx, JSX → /react-component-generator
og image, twitter card, social preview → /og-share-images
TUI, bubble tea, charm, CLI UI → /tui-glamorous
installer, curl|bash, one-liner → /installer-workmanship
CLI automation, atuin, shell history → /automating-your-automations
perf, optimize, bottleneck, p95, p99 → /extreme-software-optimization
MCP tool, MCP server → /mcp-server-design
multi-repo, ru sync → /ru-multi-repo-workflow
crash, segfault, hang, deadlock → /gdb-for-debugging
playwright, e2e webapp, next.js test → /e2e-testing-for-webapps
fuzz, property-based, crash discovery → /testing-fuzzing
protocol, RFC, conformance → /testing-conformance-harnesses
snapshot, approval, golden output → /testing-golden-artifacts
ML test, oracle-less, metamorphic → /testing-metamorphic
formal proof, lean, rust verification → /lean-formal-feedback-loop
If no keywords match, skip and proceed to STEP 1. Never force a skill invocation on
an unrelated bead — the lookup is hints, not mandates.
## STEP 1 — IMPLEMENT
<bead title>
<bead description>
Acceptance criteria: <criteria>
## STEP 2 — VALIDATE (MANDATORY GATES — all must pass before STEP 3)
Run in order; fix failures before proceeding. Do NOT commit until all pass.
2a. **Compile + lint gate** — pick the stack's commands:
- Rust: cargo check --all-targets && cargo clippy --all-targets -- -D warnings && cargo fmt --check
- Go: go build ./... && go vet ./...
- TypeScript: npx tsc --noEmit (plus your eslint / biome script)
**AND** run the project's full build: `npm run build` (or `pnpm build`,
`yarn build`). `tsc --noEmit` only checks source types — it does NOT
verify that tsconfig files, output paths, or scripts referenced from
`package.json` actually exist. Running `npm run build` catches missing
`tsconfig.*.json` files, missing entry points, and broken script chains.
- Python: python -m compileall -q . (plus ruff / mypy per project)
Check package.json / Cargo.toml / Makefile for project-specific scripts first.
2a.1. **Reference-resolution gate** — if you added or modified any of:
- `package.json` scripts (commands that reference files: tsconfig paths, entry points, test runners)
- Shell commands in CI configs (`.github/workflows/*.yml`, `Makefile`)
- `import`/`require` statements with new paths
- Relative paths in config files (`tsconfig.json` `extends`/`references`, `vite.config`, etc.)
Then verify EVERY referenced path exists on disk before committing:
```
# TypeScript example — after adding "build": "tsc && tsc -p tsconfig.scripts.json"
test -f tsconfig.scripts.json || echo "MISSING: tsconfig.scripts.json"
```
A bead that wires up a new script must also create the files that script references.
2b. **Test gate** — run the test suite for files you touched (not the whole suite unless fast).
2c. **UBS gate** (if `ubs` CLI is installed): `ubs <changed-files>`. Treat
findings as blocking unless clearly out of scope. If `ubs` is not
available, note that in your completion report and skip this gate.
## STEP 2.5 — STORE LEARNINGS
If you encountered anything non-obvious during implementation — unexpected API behavior,
tricky edge cases, workarounds for tooling issues, rebase gotchas, or decisions that
future agents would benefit from knowing — store each as a CASS memory:
Call flywheel_memory with operation='store' and content describing the learning.
Prefix with the bead ID for traceability, e.g.:
"Bead <id>: <concise learning with enough context to be useful standalone>"
Skip this step if the implementation was straightforward with no surprises.
## STEP 3 — COMMIT & CLOSE BEAD
Create a commit with a descriptive message referencing bead <id>.
Then mark the bead closed: `br update <bead-id> --status closed`
(Note: the br CLI uses `closed`, NOT `done`.)
Verify the close took effect: `br show <bead-id> --json` and confirm
`"status": "closed"`. If the status is anything else, retry the update
once before continuing to STEP 4. Stragglers are a known failure mode
and the coordinator will catch them via `flywheel_verify_beads`, but
verifying here keeps the wave clean.
## STEP 4 — RELEASE + REPORT (MANDATORY)
4a. Release all file reservations via release_file_reservations.
4b. Send a completion summary to '<coordinator-agent-name>' via send_message
with subject '[impl] <bead-id> done' including:
- Files changed
- Tests added/modified
- Any open concerns or follow-ups
"
)
Auto-capture failures: If an agent reports a blocker or failure via Agent Mail, automatically store it in CASS:
flywheel_memory(operation: "store", content: "Bead <id> (<title>) hit blocker: <failure description>. Resolution: <what fixed it or 'unresolved'>")
This ensures future sessions can recall what went wrong and avoid the same pitfall.
Mark the bead's task as in_progress. If the agent goes idle before reporting back, nudge it:
SendMessage(to: "impl-<bead-id>", message: "Please report your current status and any blockers.")
Proactive close (recommended — skip the escalation tree entirely). Instead of waiting for 2 nudges to diagnose an idle agent, poll git log --grep="<bead-id>" --oneline -1 every 30s after spawn. As soon as a commit referencing the bead appears AND the agent is idle (per TaskList), verify the commit's diff matches the bead's acceptance criteria, then close the bead yourself:
br update <bead-id> --status closed
br show <bead-id> --json | jq -r '.[0].status' # must print "closed"
This saves ~60s per bead (no nudge round-trip) and handles the dominant failure mode (agent commits but skips br update) without any dialog. Only fall into the idle-agent escalation tree below when the coordinator could NOT verify the commit OR the bead's acceptance is ambiguous.
Monitor-script hygiene. When using the Monitor tool to poll for commits/files/bead-closures, the shell loop MUST end with exit 0 explicitly — a for i in $(seq ...); do ... break; done with no trailing statement inherits the exit code of the last iteration's sleep command, which can be non-zero on timeout and fires a spurious script failed (exit 1) notification. Pattern:
for i in $(seq 1 90); do
if condition_met; then echo "DONE"; exit 0; fi
sleep 15
done
echo "timeout"
exit 0 # ← required; timeout is not a failure
Idle-agent escalation (fallback when proactive close doesn't apply): After 2 nudges, check git log --oneline --grep="<bead-id>" to determine what shape of failure you're in. There are TWO common cases — diagnose first, then act:
Case A — Commits exist but bead not closed (MORE common): The agent did the implementation work and committed, then went idle before calling br update --status closed. Verify:
br show <bead-id> --json | jq -r '.[0].status'
If status is open or in_progress but a commit referencing the bead exists:
br update <bead-id> --status closed. No replacement agent needed.Case B — Zero commits since spawning: The agent stalled before producing any output.
br update <bead-id> --status closed.Store cross-cutting learnings: When an agent's completion report mentions something non-obvious (unexpected file renames, rebase conflicts, API quirks, tooling workarounds), store it in CASS:
flywheel_memory(operation: "store", content: "Bead <id> (<title>): <learning from agent report>")
Don't store routine completions — only surprises or gotchas that would help future sessions.
When the agent completes, mark task as completed. Send shutdown:
SendMessage(to: "impl-<bead-id>", message: {"type": "shutdown_request", "reason": "Bead complete."})
Important: Structured shutdown messages CANNOT be broadcast to
"*". You must send to each impl agent individually by name. This applies to all structured JSON messages (shutdown_request, plan_approval_request, etc.).
If the agent remains idle after shutdown_request (check via TaskList — task still shows as active after 60 seconds):
TaskStop(task_id: "<saved-task-id>") if the task ID is available.retire_agent(project_key: cwd, agent_name: "<their-agent-mail-name>").~/.claude/teams/<team>/config.json to remove from the "members" array, then retry TeamDelete when ready.| Symptom | Likely cause | Fix |
|---|---|---|
| Multiple agents pick the same bead | Unsynced starts; not marking in_progress early | Stagger starts 30s; require br update --status in_progress + Agent Mail claim before any edit; audit file reservations |
| Agent circles after compaction | Forgot the AGENTS.md contract | Nudge: SendMessage(to: "<name>", message: "Re-read AGENTS.md so it's still fresh, then continue from your last Agent Mail message.") — kill+restart only if it stays erratic |
Bead sits in_progress too long | Crash / blocker / lost plot | Check Agent Mail thread for last report; if silent, implement directly as coordinator OR split the blocker into sub-beads with br create + br dep add |
| Contradictory implementations across beads | Poor coordination / stale reservations | Audit file_reservation_paths; revise bead boundaries so two beads never edit the same file |
| Much code, goal still far | Strategic drift | Run the "Come to Jesus" reality check in Step 9's Check-status option |
Wave-completion gate (MANDATORY). Before entering this step, wait until every impl agent spawned in the current wave has reported back via Agent Mail (or has been force-stopped per Step 7's escalation path). Track the wave's bead IDs in a local set; do NOT enter Step 8 until that set is empty. If you receive an Agent Mail completion notification mid-wave, store the result and stay in Step 7's monitor loop until the rest finish. Reviewing wave-1 while wave-2 is mid-flight produces stale state and per-bead review prompts (which the consolidation rule below explicitly forbids).
Once the full wave is in, present a consolidated review prompt. Never ask per-bead if multiple beads finished together.
If a single bead finishes, use AskUserQuestion:
AskUserQuestion(questions: [{
question: "Bead <id> is done. How would you like to review?",
header: "Review",
options: [
{ label: "Looks good", description: "Accept and move on" },
{ label: "Self review", description: "Send the impl agent back to audit its own diff" },
{ label: "Fresh-eyes", description: "5 parallel review agents give independent feedback" }
],
multiSelect: false
}])
If multiple beads finish together, use AskUserQuestion:
AskUserQuestion(questions: [{
question: "Beads <id1>, <id2>, <id3> are done. How would you like to review?",
header: "Review",
options: [
{ label: "Looks good all", description: "Accept all and move on" },
{ label: "Self review", description: "Pick a specific bead for self-review (enter bead ID in Other)" },
{ label: "Fresh-eyes", description: "Pick a specific bead for 5-agent review (enter bead ID in Other)" }
],
multiSelect: false
}])
Users can also type a custom combination via "Other" (e.g. "Looks good all except fresh-eyes <id2>").
Actions:
"Looks good" / "Looks good all" → call flywheel_review with action: "looks-good" and beadId for each accepted bead.
"Self review <id>" → send the impl agent a message asking it to audit its own diff:
SendMessage(to: "impl-<id>", message: "Self-review: run `git diff` on your changes, check for bugs, missing tests, and style issues. Report findings to <coordinator> via Agent Mail with subject '[review] <id> self-review'.")
After the self-review report arrives, call flywheel_review with action: "looks-good" and beadId to close it.
"Fresh-eyes <id>" → call flywheel_review with action: "hit-me" and beadId. The tool returns 5 agent task specs. Then:
TeamCreate(team_name: "review-<bead-id>")run_in_background: true, each with team_name set and the strict STEP 0 Agent Mail bootstrap in their prompt. Each reviewer prompt MUST include:
docs/reviews/<perspective>-<date>.mdfetch_inbox every 30-60 seconds. For each reviewer that has not delivered findings within 2 minutes, nudge by name:
SendMessage(to: "<reviewer-name>", message: "Your review findings for bead <id> have not arrived. Please resend to <coordinator-name> via Agent Mail with subject '[review] <id> findings'.")
Nudge up to 3 times per reviewer before considering them failed.
Persistent inbox failure fallback: If inbox remains empty after all nudges, do not block. Read findings files directly from disk (docs/reviews/<perspective>-<date>.md) using the Read tool. If no disk file exists either, synthesize from git diff <base-sha>..HEAD directly."*"git diff — do NOT wait indefinitely for unresponsive reviewers.Closed-bead handling:
flywheel_reviewnow reconciles the bead state itself —looks-goodis idempotent (advances to the next bead/gates),hit-meruns a post-close audit (payload taggedpostClose: true), andskipreturnsalready_closed. No manual workaround needed. (Prior versions required spawning reviewers fromgit diff <sha>~1 <sha>; that path is gone.)
Edge case — team already active:
TeamCreatefor a review team fails with "already leading a team" if an impl team is still running. Reuse the existing team by passingteam_name: "impl-<goal-slug>"to the review agents instead of creating a new one.
Fixed in v2.10.1:
flywheel_verify_beadscorrectly unwraps thebr show --jsonarray shape viaunwrapBrShowValue()inmcp-server/src/beads.ts. If you seeparse_failureerrors on a current install, you're on v2.9.x or older — rebuild viacd mcp-server && npm run build. The fallback procedure below remains valid for older installs and for cases wherebremits an entirely new shape.Manual fallback (only if verify still fails for some IDs):
- For each failing bead ID, run:
br show <bead-id> --json | jq -r '.[0].status' git log --oneline --grep="<bead-id>" -n 5- Classify manually:
status == "closed"→ verified, move on.status != "closed"AND commit exists → straggler; runbr update <bead-id> --status closedyourself (this is whatautoClosedwould have done).status != "closed"AND no commit → route into theunclosedNoCommitmenu below with the bead ID.
Reconcile the wave first. Before showing the menu, call flywheel_verify_beads with the IDs of beads completed in this wave:
flywheel_verify_beads(cwd: <cwd>, beadIds: [<bead-1>, <bead-2>, ...])
The tool returns {verified, autoClosed, unclosedNoCommit, errors}:
verified — beads br show confirms as closed. Move on.autoClosed — stragglers that had a matching commit; the tool ran br update --status closed for you and synced state. Move on.unclosedNoCommit — beads still open with no commit referencing them. MUST present:
AskUserQuestion(questions: [{
question: "<N> bead(s) have no commit and were not auto-closed: <comma-list with statuses>. How should I handle them?",
header: "Stragglers",
options: [
{ label: "Re-run impl agent", description: "Spawn a fresh impl agent for these beads (Recommended)" },
{ label: "Mark deferred", description: "Set status=deferred and proceed without these beads" },
{ label: "Close manually", description: "I'll close them outside this session — proceed without action" },
{ label: "Pause cycle", description: "Stop and let me investigate; resume later via /flywheel" }
],
multiSelect: false
}])
Route per choice; never silently skip.errors — br show failures. If the errors map is non-empty, present:
AskUserQuestion(questions: [{
question: "br show failed for <N> bead(s): <comma-list with first error excerpt>. How to proceed?",
header: "br errors",
options: [
{ label: "Retry verify", description: "Call flywheel_verify_beads again on the failed IDs (Recommended)" },
{ label: "Skip and proceed", description: "Treat the unverifiable beads as still in flight; come back later" },
{ label: "Pause cycle", description: "Stop so I can debug br locally" }
],
multiSelect: false
}])
Then check remaining beads with br list. If beads remain, use AskUserQuestion:
AskUserQuestion(questions: [{
question: "<N> beads complete, <M> remaining. What next?",
header: "Progress",
options: [
{ label: "Continue", description: "Implement the next batch of ready beads (Recommended)" },
{ label: "Check status", description: "Show detailed bead status, dependency graph, and drift check" },
{ label: "Pause", description: "Stop here — resume later with /flywheel" },
{ label: "Wrap up early", description: "Skip remaining beads and wrap up what's done" }
],
multiSelect: false
}])
br list + bv --robot-triage and display. Then run the Come-to-Jesus drift reality-check below before returning to this menu.Busy agents are not the goal — closing the actual gap is. After displaying status, ask:
AskUserQuestion(questions: [{
question: "If we intelligently completed every remaining open bead, would '<original selectedGoal>' actually be achieved?",
header: "Drift",
options: [
{ label: "Yes, on track", description: "Return to the progress menu and continue" },
{ label: "Missing pieces", description: "New beads needed to close the gap — create them before more impl" },
{ label: "Strategic drift", description: "Remaining beads won't close the gap — invoke /flywheel-drift-check and regress to plan refinement" },
{ label: "Goal has changed", description: "Update selectedGoal via flywheel_select, then re-scope the bead graph" }
],
multiSelect: false
}])
br create the gap-closers with dependencies wired to the ready frontier, then return to progress menu./flywheel-drift-check for diagnostic output, then call flywheel_review with beadId: "__regress_to_plan__" to revisit the plan.flywheel_select with the new goal, then return to the progress menu so the user can decide whether to keep or reject current beads.TaskList from the current wave: send SendMessage(to: "<name>", message: {"type": "shutdown_request", "reason": "Session paused"}). Wait up to 60s for them to exit; force-stop with TaskStop(task_id: "<id>") if they hang..pi-flywheel/checkpoint.json exists and git rev-parse HEAD matches checkpoint.gitHead. If they differ, the user has uncommitted moves; surface that in the summary.Run /flywheel to resume from <phase> with <N> beads remaining.When ALL beads are complete, display a completion message and proceed directly to Step 9.5:
All beads complete. Proceeding to wrap-up.
After all beads close, scan changed files for missing test coverage before starting Step 9.5:
git diff --name-only <session-start-sha>..HEAD.*.test.ts / *_test.go / test_*.py / *.spec.rs per stack convention).<file> → <test-file or MISSING>.Present:
AskUserQuestion(questions: [{
question: "Test-coverage sweep: <X>/<Y> changed files have tests. Missing: <list>. How to proceed?",
header: "Coverage",
options: [
{ label: "Coverage is adequate", description: "Either tests exist or gaps are intentional (e.g., pure type-only files) — proceed to Step 9.4" },
{ label: "Create catch-up test beads", description: "Generate beads for missing test files and run a mini-Step-7 loop to implement (Recommended for production-bound releases)" },
{ label: "Skip coverage sweep", description: "Proceed without adding tests — note the gap in the wrap-up summary" }
],
multiSelect: false
}])
"Create catch-up test beads" → br create one bead per MISSING entry with description Write tests for <file>: unit coverage + edge cases. Pick the right testing skill per bead based on what the file does:
| File type / domain | Skill to cite in the test-bead description |
|---|---|
| Business logic touching real DB / external API | /testing-real-service-e2e-no-mocks |
| Protocol implementations, RFC parsers, codecs | /testing-conformance-harnesses |