| name | start |
| description | This skill should be used when the user asks to "start:", "start a feature", "build a feature", "implement a feature", "new feature", "start working on", "I want to build", "let's build", "add a feature", or at the beginning of any non-trivial development work. It orchestrates the full lifecycle from idea to PR, invoking the right skills at each step. |
| tools | Read, Glob, Grep, Write, Edit, Bash, Task, AskUserQuestion, Skill |
Start — Lifecycle Orchestrator
Guide development work through the correct lifecycle steps, invoking the right skill at each stage. This is the single entry point for any non-trivial work.
Announce at start: "Starting the feature lifecycle. Analyzing your project to recommend the right tool..."
Triage
Before brainstorming, analyze your project description to determine the correct path: quick (bounded trivial edit confirmed by code), feature-flow (standard lifecycle), or GSD (multi-feature project).
Step 1: Check if tool selection is enabled
Read .feature-flow.yml and look for tool_selector.enabled:
- If
enabled: false → skip tool selection, proceed directly to brainstorming
- If
enabled: true or missing → continue to step 2
Step 2: Check for command-line overrides
Did the user include --feature-flow, --gsd, or --no-quick flag?
- If
--feature-flow present → remove flag from description, skip detection, use feature-flow
- If
--gsd present → remove flag from description, skip detection, launch GSD
- If
--no-quick present → remove flag from description, record no_quick_override = true, continue to step 3 (Quick-Path Confirmation will be skipped; heuristic scoring runs normally)
- If
--quick or any other --foo token is present that is NOT in --feature-flow / --gsd / --no-quick → surface: "Unknown flag --foo. Quick path is opt-out only (--no-quick); there is no --quick flag. Continuing with auto-detection." Strip the token from description and continue to step 3.
- If no flags → continue to step 3
Step 3: Quick-Path Confirmation
Quick path is available when tool_selector.quick_path.enabled is true (default) and no_quick_override is not set (see Step 2 — set by the --no-quick flag). If either condition is false, skip this step entirely and continue to Step 4.
Run gates in strict order 0 → 4. First failure short-circuits immediately — do not run later gates. Pass budget: ≤5 Bash/Grep/Read/Glob tool calls total across all gates. In-process AST tokenization and byte-range overlap checks are free (do not count). If you reach 5 tool calls before all gates pass, abort confirmation and fall through silently.
Once a file is Read (1 budget call), Claude may reason over its contents freely for Gate 3 and Gate 4 without further cost — but re-reading the same file counts as an additional call.
| # | Gate | Pass condition | Fail surface |
|---|
| 0 | Clean working tree | git status --porcelain returns empty | Surface to user: "Working tree is dirty — running normal lifecycle to avoid trampling in-progress work." Then fall through to heuristic scoring. |
| 1 | Concrete target identifiable | Description names a file path, function name, symbol, or string literal | Surface to user: "No specific target named — running normal lifecycle. If you meant a specific file, say start: fix typo in X.ts line 42." Then fall through. |
| 2 | Bounded file count | Target resolves to ≤ max_files files (default 3) | Silent fallthrough |
| 3 | No exported-declaration overlap | The edit's byte range does not overlap any export / export default / module.exports AST node. Check is mechanical byte-range overlap — not a "flows outward" semantic analysis. Edits to the body of a re-exported internal symbol pass Gate 3 (byte range does not overlap the export node itself); Gate 4 catches such edits via identifier-position exclusion. | Silent fallthrough |
| 4 | Lexical-region rule | Every proposed old_string byte range sits entirely inside one of: (a) Markdown prose outside ``` fences; (b) a string literal node in a code file that is not a syntactic argument to a log.* / logger.* / console.* call expression (walk up to nearest CallExpression or TaggedTemplateExpression; if callee root identifier matches case-insensitively, fail); (c) a line or block comment node. Identifiers, keywords, imports, type annotations, decorators, numeric/boolean literals, operators always fail. Unsupported languages (not Markdown/TypeScript/JavaScript/Python) conservatively fail. Multiple old_string ranges: all must pass individually. | Silent fallthrough |
Gate 4 log-call exclusion detail: From the matched string-literal node, walk up to the nearest enclosing CallExpression or TaggedTemplateExpression. Resolve the callee to its root identifier (the leftmost name in a.b.c.d(...) is a; for this.x.y(...), the root is this — in which case look one level in: x). If the root identifier (case-insensitive) is exactly log, logger, or console → Gate 4 fails. Does NOT match logging (Python stdlib) — Python's logging module is a separate exclusion documented under Gate 4 edge cases below.
Python logging.* exclusion: Python logging.* calls (e.g. logging.info(...), logging.warning(...)) are also excluded via the same CallExpression ancestor walk — if the root identifier case-insensitively equals logging, Gate 4 fails.
Gate 4 whitespace tolerance: If a proposed old_string region, extended by leading/trailing whitespace to the nearest non-whitespace character, would cross out of the confirmed lexical region, Gate 4 fails (fail-closed).
Edge cases — Gate 4 fails when in doubt. The following all fail Gate 4 regardless of surface appearance: (a) TypeScript type-position string literals (const x: "foo" = ... — the first "foo" is a type, not a value); (b) expressions inside f-strings / template literals (f"hello {user.name}", `hello ${user.name}` — the {user.name} / ${user.name} region is an expression, not string content); (c) JSX attribute values that are identifiers or expressions rather than string literals; (d) any string-like syntax Claude cannot confidently classify to an AST node kind in a single pass. When the region kind is not unambiguously string-literal / comment / MD-prose, Gate 4 fails.
Budget exhaustion: If the 5-tool-call budget is reached before all gates finish evaluating, silently fall through to heuristic scoring. The change is not quick by definition.
On all-pass: Set quick_path_confirmed = true. Record confirmed scope: the set of file paths and their confirmed lexical regions (held in working context only — no state file). Jump to Step 7 quick-path execution branch.
On any fail or skip: Continue to Step 4.
Step 4: Run heuristic detection
Analyze user's project description using heuristics:
- Extract feature count (using regex for action verbs)
- Check for scope keywords ("from scratch", "complete app", etc.)
- Parse timeline mentions ("hours" vs "weeks/months")
- Detect complexity patterns (multiple stacks, microservices, explicit counts)
Calculate weighted confidence score (0.0–1.0) using scoring table.
Step 5: Check confidence threshold
If quick_path_confirmed is set (from Step 3), skip this step entirely and proceed to Step 6. Confidence threshold applies only to the heuristic-scoring path.
Read tool_selector.confidence_threshold from .feature-flow.yml (default: 0.7):
- If calculated_confidence < threshold → skip recommendation, proceed with feature-flow
- If calculated_confidence >= threshold → continue to step 6
Step 6: Display recommendation
Show recommendation based on path or confidence band:
Step 7: Execute user choice
If quick_path_confirmed is set (from Step 3 Quick-Path Confirmation): Execute the quick-path flow below. Do not prompt the user for a choice — the confirmation gates already verified the scope.
Quick-Path Execution (8-step flow)
-
The announcement has already been emitted at Step 6. Step 7 step 1 is a reference-only placeholder; do not re-emit.
-
Record confirmed scope — note the set of confirmed file paths and their confirmed lexical regions in working context. No state file. No .feature-flow/session-state.json. Scope set lifetime is this single skill invocation.
-
Edit the file(s) in the confirmed set via the Edit tool.
-
Run Stop-hook checks (tsc, lint, type-sync). Stop hook may auto-format / auto-fix, changing diff size.
-
Post-hook pre-commit budget check: run git diff --numstat summed across confirmed files (added + removed lines). If total > max_changed_lines (default 10) → escape hatch (step 6). This runs after Stop hook so auto-format changes are included.
-
Hard-assertion escape hatch: If the edit touched any file outside the confirmed set, introduced a new exported symbol, exceeded max_changed_lines, or the Stop hook failed → hard stop. Run:
git clean -f -- <all confirmed file paths>
git checkout -- <all confirmed file paths>
git clean first removes untracked (newly-created) files; git checkout then restores tracked modifications. Multi-file atomic across both cases because Gate 0 proved the pre-state clean.
(Safe because Gate 0 guarantees the tree was clean before quick path wrote anything — this only discards what quick path itself wrote. Restore is multi-file atomic: all confirmed files, even if only one was edited.) Then tell the user:
⚠ Quick path misclassified this change (<reason>). No commit made, working tree restored. Re-run with \start: ` for the full lifecycle.`
Stop. Do not commit, do not fall through.
-
Commit. Check git log --oneline -10 to observe the project's existing commit prefix style (e.g., docs:, fix:, feat:, refactor:). Write the commit message in imperative mood, following that style. Include the actual post-edit line count in the message body (N lines changed). No Claude co-author trailer — quick-path commits are deterministic, top-to-bottom model edits, not human-model collaborations; adding a co-author trailer would misrepresent their authorship.
-
Skip everything else. No design doc, no design verification, no implementation plan, no acceptance criteria doc, no handoff. The commit and the auditable announcement line are the only artifacts.
Interrupted-turn recovery. Scope set lives in working context only (no state file, by design). If the turn is interrupted between step 3 (edit applied) and step 6 (escape-hatch assertion) — e.g., context overflow, user Ctrl+C, mid-hook error — the scope set is lost and edits remain on disk. No automatic cleanup runs. The next start: invocation's Gate 0 check will detect the dirty tree and route to normal lifecycle; the user can commit or revert manually from there. This is the documented recovery path.
If quick_path_confirmed is not set (normal paths):
- If user chooses "Use feature-flow" → proceed with brainstorming
- If user chooses "Launch GSD" → execute GSD handoff (see below)
- If
auto_launch_gsd: true → skip user choice, execute GSD handoff automatically
GSD Handoff Execution
When launching GSD:
- Extract metadata from
.feature-flow.yml (stack, database, etc.)
- Create
.gsd-handoff.json with:
- original_description (from start command)
- stack, database, repo info
- features_detected, recommendation_confidence
- detected_features, detected_scope, recommended_tool_reason
- Launch GSD:
npx get-shit-done-cc@latest --handoff-from-feature-flow
- Handle errors:
- If GSD not installed → show install instructions, offer to continue with feature-flow
- If handoff file write fails → launch GSD normally (user re-explains)
- If user cancels GSD → ask "return to feature-flow or exit?"
- Cleanup: Delete
.gsd-handoff.json after GSD exits
Pre-Flight Check
Before starting, build the plugin registry by scanning installed plugins.
Read references/plugin-scanning.md for the full scanning process, keyword classification, and registry management.
Dynamic Plugin Registry
At Step 0, feature-flow scans ~/.claude/plugins/cache/ to discover all installed plugins. It reads each plugin's plugin.json manifest and component metadata, classifies capabilities via keyword matching into 8 lifecycle roles, and persists the results in .feature-flow.yml under plugin_registry.
Base plugins (superpowers, context7, pr-review-toolkit, feature-dev, backend-api-security) are always present with hardcoded known roles. Discovered plugins extend beyond the base set. If a base required plugin (superpowers, context7) is missing, stop the lifecycle with an installation message. If a recommended plugin is missing, warn and continue.
After scanning, run fallback validation: verify base plugins are actually loaded in the current session via namespace-prefix detection in the skill/tool list.
Pre-Flight Reviewer Audit, Marketplace Discovery & Install
Read references/step-lists.md — "Pre-Flight Reviewer Audit", "Marketplace Discovery", and "Install Missing Plugins Prompt" sections after completing the registry scan above. The audit now reads from plugin_registry in .feature-flow.yml instead of individual hardcoded checks.
Tool Parameter Types
Reminder: Tool parameters must use correct types. Wrong types cause cascading failures.
| Parameter | Tool | Correct type | Wrong type (do NOT use) |
|---|
replace_all | Edit | boolean — true or false | 'true' / 'false' (string) |
offset | Read | number — e.g. 100 | '100' (string) |
limit | Read | number — e.g. 50 | '50' (string) |
Command-Line Flag Parsing
The start: command accepts optional flags to override tool selection:
Usage:
start: <description> [--feature-flow | --gsd | --no-quick]
Parsing logic:
- Extract user input after
start: keyword
- Check for
--feature-flow, --gsd, or --no-quick flags at the end
- If flag found, remove it from description and set override
- If no flag, proceed with automatic detection
Flag: --no-quick — disables quick-path confirmation for this invocation. Quick-Path Confirmation (Step 3) is skipped entirely; the lifecycle falls directly into heuristic scoring. There is no --quick flag — quick path is opt-out, not opt-in.
Examples:
start: add logout button --feature-flow → description: "add logout button", override: feature-flow
start: build complete app --gsd → description: "build complete app", override: gsd
start: fix typo in README.md --no-quick → quick path disabled for this run, normal lifecycle
start: build payments system → description: "build payments system", override: none (auto-detect)
Priority (highest to lowest):
--gsd (highest — existing)
--feature-flow (existing)
--no-quick (new — disables quick path for this invocation)
- Config file
tool_selector.quick_path.enabled
- Automatic heuristic detection / built-in default (
enabled: true)
--no-quick × quick_path.enabled: false is a documented no-op: the CLI flag confirms the config. No error.
If flag is present, skip all other logic and use that flag's value.
Configuration Loading
The start skill reads tool_selector config from .feature-flow.yml:
Precedence (highest to lowest):
- Command-line flags (
--feature-flow or --gsd) if provided
- Config file values from
.feature-flow.yml → tool_selector section
- Built-in defaults (enabled: true, threshold: 0.7, auto_launch: false)
Reading config:
- Extract tool_selector section from .feature-flow.yml
- Parse enabled, confidence_threshold, auto_launch_gsd values
- Use defaults if section or keys missing
Config values:
-
tool_selector.enabled (boolean, default: true)
- If false: Skip tool selection entirely, proceed with feature-flow
- If true: Run detection and show recommendation if confident
-
tool_selector.confidence_threshold (float 0-1, default: 0.7)
- Only show recommendation if calculated confidence >= threshold
- Example: score 0.65 with threshold 0.7 → no recommendation shown
-
tool_selector.auto_launch_gsd (boolean, default: false)
- If true: Launch GSD automatically when GSD is recommended
- If false: Ask user "Launch GSD or use feature-flow?" first
-
tool_selector.quick_path.enabled (boolean, default: true)
- If false: Quick-Path Confirmation is skipped for all invocations (same effect as always passing
--no-quick)
- If true: Quick-Path Confirmation runs before heuristic scoring
-
tool_selector.quick_path.max_confirmation_tool_calls (integer ≥ 1, default: 5)
- Maximum Bash/Grep/Read/Glob tool calls during Quick-Path Confirmation. In-process AST work does not count.
- If budget is exhausted before all gates pass, fall through silently.
-
tool_selector.quick_path.max_files (integer ≥ 1, default: 3)
- Gate 2 passes if the target resolves to ≤ this many files.
- Default 3 (not 1) so multi-file prose fixes like "fix typos in README and CHANGELOG" can take the quick path.
-
tool_selector.quick_path.max_changed_lines (integer ≥ 1, default: 10)
- Post-hook pre-commit budget: total added + removed lines across confirmed files must be ≤ this value.
- Measured after the Stop hook runs (catches auto-format expansion).
- The stronger scale guardrail — binds total edit size regardless of file count.
Default values:
tool_selector:
enabled: true
confidence_threshold: 0.7
auto_launch_gsd: false
quick_path:
enabled: true
max_confirmation_tool_calls: 5
max_files: 3
max_changed_lines: 10
Defaults if the quick_path sub-section is missing: all four keys use the values above. Quick path is on out of the box.
Recommendation Display
Display recommendation to user with confidence level:
If tool_selector.enabled = false:
Skip display entirely, proceed directly with feature-flow.
If confidence < threshold:
Show quiet notification:
✅ This looks like feature-flow work. Starting...
If confidence in band 🟡 (0.4–0.7):
✅ Project Analysis:
• Features detected: 4
• Scope: "complete SaaS from scratch"
• Timeline: weeks/months
• Confidence: 65%
🟡 Recommendation: This could be a GSD project.
GSD handles multiple features through parallel execution and wave-based delivery.
Feature-flow excels at single features with deep verification and thorough testing.
Which would you prefer?
[Launch GSD] [Use feature-flow anyway]
If confidence in band 🔴 (0.7+):
✅ Project Analysis:
• Features detected: 5
• Scope: "build from scratch"
• Timeline: 2+ months
• Confidence: 82%
🔴 Recommendation: This is a GSD project.
Multiple independent features work best in parallel. Feature-flow is built for
focused single-feature development with thorough testing.
Which would you prefer?
[Launch GSD (Recommended)] [Use feature-flow anyway]
User interaction:
- If tool_selector.auto_launch_gsd = true: Auto-launch GSD without prompt
- If tool_selector.auto_launch_gsd = false: Show buttons, wait for user choice
Output clarity:
- Use emoji indicators (🟢/🟡/🔴) for confidence level
- List detected features and scope for transparency
- Explain WHY each tool is recommended
- Keep explanations brief (2-3 sentences max)
GSD Handoff Mechanism
When user chooses "Launch GSD", prepare context handoff:
Step 1: Extract project metadata
Read from .feature-flow.yml:
- stack (node-js, react, python, etc.)
- database (postgres, mongodb, etc.)
- Any other project context
Step 2: Generate handoff payload
Create .gsd-handoff.json in repo root:
{
"source": "feature-flow",
"timestamp": "2026-03-09T14:30:00Z",
"original_description": "build complete SaaS with payments, billing, analytics",
"stack": "node-js/react/typescript",
"database": "postgres",
"repo_url": "current working directory path",
"repo_state": "clean",
"metadata": {
"features_detected": 4,
"recommendation_confidence": 0.8,
"detected_features": ["payments", "invoicing", "billing", "analytics"],
"detected_scope": "from scratch",
"recommended_tool_reason": "4+ features detected + 'from scratch' + weeks timeline"
}
}
Step 3: Launch GSD
npx get-shit-done-cc@latest --handoff-from-feature-flow
GSD detects .gsd-handoff.json and:
- Reads the
original_description
- Skips "what are you building?" questions
- Jumps to "Let me clarify scope..." phase
Step 4: Cleanup
After GSD exits (success or cancel):
- Delete
.gsd-handoff.json
- Return control to user or shell
Error handling:
- If GSD not installed: Show install command, offer to continue with feature-flow
- If handoff file can't be written: Launch GSD normally (user pastes description again)
- If user cancels GSD: Ask "return to feature-flow or exit?"
Tool Selector Heuristic Detection
Six heuristic detection functions inform the "which tool" decision in start Step 1. These signals combine into a confidence score (0.0–1.0) that recommends either feature-flow or GSD.
Feature Count Detection
Extract distinct features from user description:
- Pattern: Look for action verbs followed by nouns: "add X", "build Y", "implement Z"
- Use regex: \b(add|build|implement|create|develop|design|make|write)\s+([a-z\s]+?)(?=and|,|then|\s+with|\s+for|$)
- Split by "and", count distinct items
- Examples:
- "add a logout button" → 1 feature
- "build payments and invoicing" → 2 features
- "create payments, billing, analytics, dashboards" → 4 features
Scoring:
- 1 feature: +0 (neutral baseline)
- 2-3 features: +0.1
- 4+ features: +0.3
Scope Keyword Detection
Search for high-confidence GSD indicators:
- Keywords: "from scratch", "complete app", "full system", "entire", "build everything"
- Keywords: "multiple independent", "parallel execution", "separate services"
- Keywords: "full project", "entire product"
Scoring:
- 1+ keyword found: +0.4 (high weight)
- No keywords: +0 (neutral)
Timeline Detection
Parse time estimates:
- Feature-flow signals: "1-2 hours", "a few hours", "today", "this afternoon"
- GSD signals: "1-2 weeks", "several weeks", "a month", "a sprint", "2-3 months"
Scoring:
- GSD timeline (weeks+): +0.2
- Feature-flow timeline (hours): -0.1 (slightly reduces GSD score)
- No timeline: +0 (neutral)
Complexity Pattern Detection
Detect architectural complexity:
- Multiple tech stack mentions (e.g., "React frontend AND Node backend AND PostgreSQL")
- Microservices references: "services", "distributed", "microservice", "API gateway"
- Explicit numbers: "50+ tasks", "10+ pages", "20+ endpoints"
Scoring:
- Complexity pattern found: +0.2
- No pattern: +0 (neutral)
Recommendation Scoring
Combine all signals into a single confidence score (0.0–1.0):
| Signal | Weight | Condition |
|---|
| 4+ features | +0.3 | Feature count >= 4 |
| 2-3 features | +0.1 | Feature count = 2-3 |
| Scope keyword | +0.4 | 1+ keyword found |
| GSD timeline | +0.2 | "weeks", "months", etc. |
| Feature-flow timeline | -0.1 | "hours", "today", etc. |
| Complexity pattern | +0.2 | Multiple stacks or microservices |
Final score bands:
- 🟢 feature-flow (0.0–0.4): Small, 1-2 features, hours-scale
- 🟡 GSD-recommended (0.4–0.7): Multi-feature, weeks-scale
- 🔴 GSD-strongly-recommended (0.7+): Large, 5+ features, "from scratch"
Purpose
Ensure the lifecycle is followed from start to finish. Track which steps are complete, invoke the right skill at each stage, and do not advance until the current step is done.
Process
Step 0: Load or Create Project Context
Read references/project-context.md for full Step 0 details. Summary of substeps:
- YOLO/Express trigger phrase detection (word-boundary matching on
--yolo, yolo mode, --express, etc.)
- Load or create
.feature-flow.yml (version drift check, stack cross-check, auto-detection)
- Base branch detection (cascade:
.feature-flow.yml → git config → develop/staging → main/master)
- Session model check
- Notification preference (macOS-only, saved to
.feature-flow.yml)
- YOLO stop_after reading (from
.feature-flow.yml)
- Opportunistic cleanup pre-flight. Invoke
feature-flow:cleanup-merged with no argument to reclaim worktrees, branches, and handoff files for any PRs that have merged since the last start: session. This step:
- Runs for all scopes including Quick fix.
- Is silent on no-op (no handoff files found, or all found PRs are still open).
- Announces cleaned PRs on success:
Pre-flight: cleaned up PR #N (slug-a3f2), PR #M (slug-b742)
- Non-blocking: does not block the lifecycle if cleanup fails — log the failure and continue.
- Invocation:
Skill(skill: "feature-flow:cleanup-merged", args: "") wrapped in try/catch; any exception logs Pre-flight cleanup failed: <error> — continuing. and proceeds.
Reference Loading Strategy
This table is the authoritative contract for which references to load and when. The always-loaded group (pre-flight + Step 0 rows) is loaded during pre-flight and Step 0, before scope is known. The scope-conditional group is applied after Step 1 determines scope — read only the references marked for the current scope and mode.
Counting rule: "Read instructions before lifecycle execution" counts every **Read \references/X.md`** instruction in this file that appears before the inline-step section headings (### Copy Env Files Step` and onward). The 11 point-of-use reads in those sections are already lazy and are not counted here.
| Reference | Quick fix | Small enh (fast-track) | Small enh (standard) | Feature | Major feature |
|---|
plugin-scanning.md (pre-flight) | ✓ always | ✓ always | ✓ always | ✓ always | ✓ always |
step-lists.md pre-flight sections | ✓ always | ✓ always | ✓ always | ✓ always | ✓ always |
project-context.md (Step 0) | ✓ always | ✓ always | ✓ always | ✓ always | ✓ always |
step-lists.md step-list sections (Step 2) | ✓ always | ✓ always | ✓ always | ✓ always | ✓ always |
orchestration-overrides.md | — | — | ✓ (brainstorm runs) | ✓ | ✓ |
yolo-overrides.md full file | if YOLO/Express | if YOLO/Express | if YOLO/Express | if YOLO/Express | if YOLO/Express |
yolo-overrides.md quality sections | ✓ if not already loaded | ✓ if not already loaded | ✓ if not already loaded | ✓ if not already loaded | ✓ if not already loaded |
model-routing.md | ✓ always | ✓ always | ✓ always | ✓ always | ✓ always |
code-review-pipeline.md (lazy) | — | ✓ at point-of-use | ✓ at point-of-use | ✓ at point-of-use | ✓ at point-of-use |
inline-steps.md per-step sections (lazy) | ✓ at point-of-use | ✓ at point-of-use | ✓ at point-of-use | ✓ at point-of-use | ✓ at point-of-use |
"If not already loaded" idiom: When an instruction says Read references/X.md if not already loaded, treat the read as a no-op when the file is already in the orchestrator's working context. The quality-sections row above is the canonical example: in YOLO/Express mode the full yolo-overrides.md is loaded by the ### YOLO/Express Overrides instruction below, so the quality-sections read in ### Quality Context Injections finds the file already in context and is a no-op. In Interactive mode the full file is not loaded, so the quality-sections read fires and loads only those three sections.
Rationale for always-loaded group: Pre-flight and Step 0 run before scope is determined — those references cannot be deferred. model-routing.md and the quality sections of yolo-overrides.md apply to every scope because every scope dispatches subagents via superpowers:subagent-driven-development for its Implement step (per the Skill Mapping table's Implement row — applies to Quick fix's "Implement fix (TDD)" wording too).
Rationale for scope-conditional group:
orchestration-overrides.md: contains only brainstorming interview format and Express design-approval checkpoint. Quick fix has neither a brainstorming step nor a design document; Small enhancement fast-track explicitly skips both. So neither code path inside orchestration-overrides.md ever fires for those two scope/mode combinations.
yolo-overrides.md full file: only the YOLO/Express overrides for writing-plans, git-worktrees, finishing-branch, and subagent-driven-development matter when YOLO or Express mode is active. Interactive sessions never need the full file (they still need the quality sections — see row above).
Step 1: Determine Scope
Ask the user what they want to build. Then classify the work.
Issue reference detection: Before classifying scope, check if the user's request references an existing GitHub issue. Look for patterns: #N, issue #N, implement issue #N, issue/N, or a full GitHub issue URL (e.g., https://github.com/.../issues/N).
If an issue reference is found:
- Extract the issue number
- Fetch the issue body and title:
gh issue view N --json title,body,comments --jq '{title, body, comments: [.comments[].body]}'
- Store the issue number as lifecycle context (pass to subsequent steps)
- Announce: "Found issue #N: [title]. I'll use this as context for brainstorming and update it after design."
- Pass the issue body + comments as initial context to the brainstorming step
If no issue reference is found, proceed as before.
Issue richness scoring (when an issue is linked):
Assess the linked issue for context richness. Count the following signals:
- Has acceptance criteria or clear requirements sections
- Has resolved discussion in comments (answered questions)
- Has concrete examples, mockups, or specifications
- Body is >200 words with structured content (headings, lists, tables)
A score of 3+ means the issue is "detailed."
Inline context richness:
If the user's initial message (not the issue) contains detailed design decisions — specific approach descriptions, UX flows, data model specifics, or concrete behavior specifications — treat this as equivalent to a detailed issue for recommendation purposes.
Fast-track detection (small enhancement only):
This check runs only after scope has been classified as "small enhancement" in the table below. After scoring issue richness and evaluating inline context, check if the small enhancement qualifies for a fast-track lifecycle:
- Condition: Scope is classified as "small enhancement" AND either:
- Issue richness score is 3+ (detailed issue), OR
- Inline context provides equivalent detail (specific approach, file references, acceptance criteria)
- If fast-track qualifies:
- Set
fast_track flag for step list building
- Announce activation:
- YOLO/Express:
"YOLO: start — Small enhancement fast-track → Activated (issue #N richness: [score]/4). Skipping: brainstorming, design document, verify-plan-criteria." (for Express mode, substitute Express: for YOLO: in the announcement)
- Interactive:
"Issue #N has detailed requirements (richness: [score]/4). Fast-tracking: skipping brainstorming, design document, and verify-plan-criteria. The issue content serves as the design."
- If fast-track does not qualify: Use the standard 17-step small enhancement list. No announcement needed.
Fast-track detection runs after scope classification and before the combined scope + mode prompt. The step count in the prompt reflects the fast-track status: 14 steps if fast-track qualifies, 17 steps otherwise.
Scope classification:
| Scope | Description | Example |
|---|
| Quick fix | Single-file bug fix, typo, config change | "Fix the null check in the login handler" |
| Small enhancement | 1-3 files, well-understood change, no new data model | "Add a loading spinner to the search page" |
| Feature | Multiple files, new UI or API, possible data model changes | "Add CSV export to the results page" |
| Major feature | New page/workflow, data model changes, external API integration, pipeline changes | "Build a creative domain generator with LLM" |
See references/scope-guide.md for detailed criteria, examples, and edge cases.
Smart recommendation logic:
Determine the recommended mode using three signals:
| Scope | Default | With detailed issue | With detailed inline context |
|---|
| Quick fix | YOLO | YOLO | YOLO |
| Small enhancement | YOLO | YOLO | YOLO |
| Feature | Interactive | YOLO (override) | YOLO (override) |
| Major feature | Interactive | Express | Express |
Context pressure estimates (scope × mode):
| Scope | Interactive | Express | YOLO |
|---|
| Quick fix (7 steps) | Low | Low | Low |
| Small enhancement (14-17 steps) | Medium | Low | Low |
| Feature (21 steps) | High | Medium | Medium |
| Major feature (22 steps) | Very High | High | High |
Combined scope + mode prompt:
Present the classification AND mode recommendation to the user in a single AskUserQuestion. The question text includes the scope, step count, and (if applicable) issue context summary.
Question format:
This looks like a **[scope]** ([N] steps).
[If issue linked: "Found issue #N: [title] — [richness summary]."]
Run mode?
Context warning (conditional):
When the recommended mode is Interactive AND the context pressure for Interactive at the current scope is High or Very High, add a context note line to the question text:
This looks like a **[scope]** ([N] steps).
[If issue linked: "Found issue #N: [title] — [richness summary]."]
Context note: Interactive mode at this scope involves extended conversation. Express auto-selects decisions while preserving design approval checkpoints.
Run mode?
When to show the context note:
- Feature + sparse context (High pressure in Interactive) → show note
- Major feature + sparse context (Very High pressure in Interactive) → show note
- All other cases → no context note (either pressure is Low-Medium, or the recommended mode already accounts for context pressure)
Option ordering depends on recommendation:
YOLO recommended (quick fix, small enhancement, or feature with detailed context):
- Option 1: "YOLO — fully unattended, no pauses" with description: "Recommended — [reasoning]"
- Option 2: "Express — I'll auto-select decisions but pause for design approval"
- Option 3: "Interactive — I'll interview you to address outstanding design questions"
Interactive recommended (feature/major without detailed context):
- Option 1: "Interactive — I'll interview you to address outstanding design questions" with description: "Recommended — [reasoning]"
- Option 2: "Express — I'll auto-select decisions but pause for design approval"
- Option 3: "YOLO — fully unattended, no pauses"
Express recommended (major feature with detailed issue or detailed inline context):
- Option 1: "Express — I'll auto-select decisions but pause for design approval" with description: "Recommended — detailed requirements cover design decisions; Express auto-selects while preserving design approval gate."
- Option 2: "Interactive — I'll interview you to address outstanding design questions"
- Option 3: "YOLO — fully unattended, no pauses"
Footnote (always shown after the options): "Express pauses at design approval. Interactive pauses for each design question."
The recommended option always appears first in the list. Each option's description includes italicized reasoning when a recommendation is made.
Scope correction: If the user believes the scope is misclassified, they can select "Other" on the AskUserQuestion and state their preferred scope. The lifecycle will adjust the step list and checkpoint rules accordingly.
YOLO behavior (trigger phrase activated): If YOLO was already activated by a trigger phrase in Step 0, skip this question entirely. Auto-classify scope and announce: YOLO: start — Scope + mode → [scope], YOLO (trigger phrase)
Express behavior (trigger phrase activated): If Express was already activated by a trigger phrase in Step 0, skip this question entirely. Auto-classify scope and announce: Express: start — Scope + mode → [scope], Express (trigger phrase)
Express behavior: If the user selects "Express", set Express mode active. All YOLO auto-selection overrides apply for skill invocations, but design approval checkpoints are shown instead of suppressed.
Step 2: Build the Step List
Based on scope AND platform, determine which steps apply. Read references/step-lists.md — "Step Lists" section for the step list for each scope (quick fix, small enhancement standard/fast-track, feature, major feature) and mobile platform adjustments.
Use the TaskCreate tool to create a todo item for each step. Call all TaskCreate tools in a single parallel message.
Step 3: Execute Steps in Order
For each step, follow this pattern:
- Announce the step: "Step N: [name]. Invoking [skill name]."
- Mark in progress (conditional): Only set
in_progress via TaskUpdate before starting steps where the work is extended and the user benefits from an active status indicator. Steps that keep in_progress: study existing patterns, implementation, self-review, code review, generate CHANGELOG entry, final verification, documentation lookup. Steps that skip in_progress: brainstorming, design document, design verification, create/update issue, implementation plan, verify plan criteria, worktree setup, copy env files, commit and PR, post implementation comment. Note: sub-step 5 (completed) is always retained — it is the turn-continuity bridge. Skipping in_progress does not affect YOLO Execution Continuity. Note: YOLO propagation (prepending yolo: true) applies only to Skill() invocations, not to Task() dispatches.
- Invoke the skill using the Skill tool (see mapping below and
../../references/tool-api.md — Skill Tool for correct parameter names)
- Confirm completion: Verify the step produced its expected output. (Turn Bridge Rule — include any confirmation notes alongside the
TaskUpdate call in step 5, not as a separate text-only response.)
- Mark complete: Update the todo item to
completed — always call TaskUpdate here. (Turn Bridge Rule — this call keeps your turn alive.) Batching optimization: When the next step (N+1) is in the in_progress-eligible list (study existing patterns, implementation, self-review, code review, generate CHANGELOG entry, final verification, documentation lookup), send both TaskUpdate calls as a single parallel message: [TaskUpdate(N, completed), TaskUpdate(N+1, in_progress)]. This saves one API round-trip per eligible step transition. If N is the final lifecycle step, no N+1 exists — skip the batch and call only TaskUpdate(N, completed) as usual. In-progress step update (paired with TaskUpdate): After (or alongside) TaskUpdate(N, completed), update the in-progress state file at .feature-flow/handoffs/in-progress-<slug>.yml in the base repo: set current_step to the next step's step-id (or handoff if N is the final step), last_completed_step to the just-completed step's step-id, and updated_at to the current ISO UTC timestamp. Use the helper pattern below — python3 + yaml.safe_load/yaml.dump so phase_summaries entries written by phase-boundary writes are preserved. Pass values via env vars, not inline string interpolation — values like current_step are safe (kebab-case enums) but the same pattern is reused for free-text fields elsewhere, and consistent env-var passing means apostrophes in values cannot terminate the python -c argument early. If the in-progress file does not exist (initial write failed), skip silently. Helper:
BASE_REPO=$(cd "$(git rev-parse --git-common-dir)/.." && pwd)
F="${BASE_REPO}/.feature-flow/handoffs/in-progress-${SLUG}.yml"
[ -f "$F" ] && F="$F" NEXT="<next-step-id>" PREV="<completed-step-id>" TS="$(date -u +%Y-%m-%dT%H:%M:%SZ)" python3 -c '
import os, yaml
f = os.environ["F"]
d = yaml.safe_load(open(f)) or {}
d["current_step"] = os.environ["NEXT"]
d["last_completed_step"] = os.environ["PREV"]
d["updated_at"] = os.environ["TS"]
yaml.dump(d, open(f, "w"), default_flow_style=False, allow_unicode=True)
'
Runs inline as a Bash call paired with the TaskUpdate. The $(cd "$(git rev-parse --git-common-dir)/.." && pwd) idiom resolves the base repo from both base-repo and worktree CWDs (--show-toplevel returns the worktree path when invoked from inside a worktree — wrong location).
6. Announce next step and loop: "Step N complete. Next: Step N+1 — [name]." Then immediately loop back to sub-step 1 (Announce the step) for the next lifecycle step.
YOLO Execution Continuity (CRITICAL): In YOLO mode, the execution loop must be uninterrupted. After completing one step, proceed directly to the next step in the same turn — do NOT end your turn between steps. The most common failure mode is: a skill outputs text (e.g., brainstorming decisions table), the assistant's turn ends because there are no pending tool calls, and the user must type "continue" to resume — this defeats the purpose of YOLO ("fully unattended, no pauses"). To prevent this: apply the Turn Bridge Rule (below) after every step, then continue to step 7 and loop back to step 1 for the next step.
Turn Bridge Rule: After outputting results for any inline step, immediately call TaskUpdate to mark that step complete in the same response — do not end your turn with only text output. A text-only response ends your turn and forces the user to type "continue" to resume, which breaks YOLO continuity. The TaskUpdate tool call is the bridge that keeps your turn alive between lifecycle steps.
YOLO Propagation: When YOLO mode is active, prepend yolo: true. scope: [scope]. to the args parameter of every Skill invocation. Scope context is required because design-document uses it to determine checkpoint behavior.
YOLO Model Routing (CRITICAL): In YOLO mode, brainstorming and design document phases MUST be dispatched as Task calls with explicit model params — not as inline Skill calls. This gives full per-phase model control regardless of the orchestrator's model. Planning is also dispatched as a Task with model: "sonnet".
Subagent dispatch patterns A and B (CRITICAL — applies in ALL modes, not just YOLO): Some lifecycle phases are dispatched as Task() subagents per #251's subagent-driven phase architecture, regardless of mode. These dispatches are for context isolation (the orchestrator never sees the skill's intermediate work — only a structured return contract written to the in-progress state file), not for model routing. Two patterns are in use:
- Pattern A (wrap): orchestrator dispatches one Task subagent that invokes the phase skill and returns a structured contract. Used for phases that do NOT internally fan out subagents.
- Pattern B (hoist + consolidator): orchestrator dispatches the parallel fanout itself (subagents cannot dispatch sub-subagents per #251 Q1), then dispatches a single consolidator subagent that ingests fanout results, runs the rest of the skill, and returns a structured contract. Used for phases that DO internally fan out.
Currently converted: verify-plan-criteria (Pattern A — see "Verify Plan Criteria — Pattern A Dispatch" subsection below), design-document (Pattern B — see "Design Document — Pattern B Dispatch" subsection below), verify-acceptance-criteria (Pattern B — see "Verify Acceptance Criteria — Pattern B Dispatch" subsection below), code-review (Pattern B — see "Code Review — Pattern B Dispatch" subsection below). Skipped by design analysis: merge-prs (no orchestrator-side benefit; see issue #251 comment). Future conversions: implementation per #251's conversion order. Each converted phase has its own wrapper subsection documenting the dispatch shape, return-contract validation, and inline-fallback path. In Express and Interactive modes, Pattern A and Pattern B still apply — the skills being wrapped do not require user interaction at the points where dispatch happens, so subagent isolation is safe in all modes.
Why: The Skill tool has no model parameter — it inherits the parent model. The Task tool has an explicit model parameter. In YOLO mode there is no user interaction, so running skills inside a Task subagent works identically to running them inline. The /model command must NEVER be used — it writes to ~/.claude/settings.json (a global config file) and affects all other terminal windows and tmux panes.
YOLO mode invocations:
# Brainstorming — Opus for creative reasoning
Task(subagent_type: "general-purpose", model: "opus", description: "YOLO brainstorming",
prompt: "Invoke Skill(skill: 'superpowers:brainstorming', args: 'yolo: true. scope: [scope]. [context args]'). Return the complete brainstorming output including all self-answered design decisions.")
# Design document — Pattern B (hoist + consolidator). See "Design Document — Pattern B Dispatch" subsection below for the full dispatch shape.
# (The pre-#251 single-Task wrapper at this location was latently broken: subagents cannot dispatch sub-subagents,
# so the inner Explore fanout inside design-document silently failed. Pattern B fixes this.)
# Implementation planning — Sonnet for structured task decomposition
Task(subagent_type: "general-purpose", model: "sonnet", description: "YOLO implementation plan",
prompt: "Invoke Skill(skill: 'superpowers:writing-plans', args: 'yolo: true. scope: [scope]. [context args]'). Return the plan file path and task summary.")
Verify Plan Criteria — Pattern A Dispatch
Note: INLINE-FALLBACK IS A ROLLOUT-ONLY FEATURE.
Applies in ALL modes (YOLO, Express, Interactive — see the "Pattern A subagent dispatch" CRITICAL block above). verify-plan-criteria is the first lifecycle phase converted to Pattern A subagent dispatch (per issue #251). The orchestrator dispatches a Task() subagent with explicit model, the subagent invokes the skill which writes a structured return contract to the in-progress state file, and the orchestrator validates the contract before proceeding to the next step. The orchestrator never sees the skill's intermediate file reads or report text — only the validated contract object.
# Step: Verify plan criteria (Pattern A)
BASE_REPO=$(cd "$(git rev-parse --git-common-dir)/.." && pwd)
SLUG=<slug-from-session-context>
STATE_FILE="${BASE_REPO}/.feature-flow/handoffs/in-progress-${SLUG}.yml"
PLAN_PATH=<absolute-path-to-plan-file>
Task(
subagent_type: "general-purpose",
model: "sonnet",
description: "verify-plan-criteria Pattern A",
prompt: "MUST invoke Skill(skill: 'feature-flow:verify-plan-criteria', args: 'yolo: true. plan_file: ${PLAN_PATH}. write_contract_to: ${STATE_FILE}. phase_id: plan'). Do NOT improvise the contract — Step 7 of the skill writes it for you. Required field values verbatim (no paraphrasing): phase MUST be \"verify-plan-criteria\" (not \"plan\"); status MUST be one of \"success\"|\"partial\"|\"failed\" (not \"passed\"|\"ok\"|\"complete\"); schema_version MUST be 1; plan_path, criteria_total, criteria_machine_verifiable, criteria_added_by_agent, tasks_missing_criteria all required (see hooks/scripts/validate-return-contract.js SCHEMAS map for the locked schema). Return the state-file path and a one-line summary of the contract."
)
Why phase_id: plan (not verify-plan-criteria): phase_id names the state-file bucket in phase_summaries — one of the four fixed keys (brainstorm, design, plan, implementation). The verify-plan-criteria lifecycle step lives in the plan bucket. The contract's own phase field stays "verify-plan-criteria" per #251's locked spec. Two distinct concepts, same word "phase" — don't confuse them.
Why model: "sonnet": verify-plan-criteria is read-heavy (one plan file + multiple grep checks) with structured output. Sonnet handles the criteria-drafting Step 4 logic well; haiku is too brittle for ambiguous criterion classification; opus is over-spec for mechanical validation.
Post-dispatch sequence (orchestrator-side):
- Read state file and extract
phase_summaries.plan.return_contract:
python3 -c "import json, yaml; d = yaml.safe_load(open('${STATE_FILE}')); rc = (d.get('phase_summaries', {}).get('plan') or {}).get('return_contract'); json.dump(rc, open('/tmp/ff-return-contract-${SLUG}.json','w')) if rc else None; print('missing' if not rc else 'ok')"
If output is missing → trigger inline-fallback (case 2 below).
- Validate the contract:
node hooks/scripts/validate-return-contract.js /tmp/ff-return-contract-${SLUG}.json
Exit 0 → proceed. Non-zero → trigger inline-fallback (case 3 below).
- Proceed to next lifecycle step (Copy env files / Study existing patterns / Implement).
Inline-fallback path (rollout-only — three failure cases):
| Case | Trigger | Announce | Next |
|---|
| 1 | Task() dispatch fails (timeout, tool error, refusal) | verify-plan-criteria Pattern A: dispatch failed (<reason>). Falling back to inline Skill(). | Run inline Skill(skill: "feature-flow:verify-plan-criteria", args: "yolo: true. plan_file: <path>") |
| 2 | Subagent completes but return_contract field is null/absent in state file | verify-plan-criteria Pattern A: subagent did not write return_contract. Falling back to inline Skill(). | Same inline invocation |
| 3 | validate-return-contract.js exits non-zero | verify-plan-criteria Pattern A: contract validation failed (<error from validator>). Falling back to inline Skill(). | Same inline invocation |
The inline path runs the existing skill with no write_contract_to arg — Step 7 of the skill is skipped, the skill behaves identically to its pre-#251 form, and the orchestrator captures its report from the Skill tool result text directly.
Design Document — Pattern B Dispatch
Note: INLINE-FALLBACK IS A ROLLOUT-ONLY FEATURE.
Applies in ALL modes (YOLO, Express, Interactive — see the "Subagent dispatch patterns A and B" CRITICAL block above). design-document is the first lifecycle phase converted to Pattern B subagent dispatch (per issue #251). Because the skill internally fans out 3-4 Explore agents (which subagents cannot do per #251 Q1), the orchestrator hoists the fanout to itself, then dispatches a single consolidator subagent that runs the rest of the skill (Steps 2-7) in isolation. The orchestrator never sees the consolidator's intermediate work — only the validated return contract.
Sub-step 1 — Hoisted parallel Explore fanout (orchestrator-side):
The orchestrator dispatches 3-4 Explore agents in parallel (single message), one per area. Models per #251: model: "haiku" (cheap, parallelizable, structured findings).
# Hoisted from skills/design-document/SKILL.md Step 1
Task(subagent_type: "Explore", model: "haiku", description: "Format patterns",
prompt: "Read existing design docs in docs/plans/ and extract document structure, section patterns, and conventions. Read-only. Return JSON: {area: 'format', findings: [string, ...]}.")
Task(subagent_type: "Explore", model: "haiku", description: "Stack & dependencies",
prompt: "Examine dependency files (package.json, config files), project structure, and tech stack conventions. Return JSON: {area: 'stack', findings: [string, ...]}.")
Task(subagent_type: "Explore", model: "haiku", description: "Relevant code",
prompt: "Search for and read source files related to the feature being designed. Feature description: <inherited from lifecycle context>. Return JSON: {area: 'code', findings: [string, ...]}.")
# Documentation agent (conditional — only if .feature-flow.yml has context7 field, Context7 MCP is available, and no documentation lookup ran earlier)
Task(subagent_type: "Explore", model: "haiku", description: "Documentation (Context7)",
prompt: "Query Context7 libraries from .feature-flow.yml `context7` field for current patterns the design should follow. Return JSON: {area: 'docs', findings: [string, ...]}.")
Sub-step 2 — Consolidate findings into a JSON file (so the consolidator subagent can read them via findings_path):
BASE_REPO=$(cd "$(git rev-parse --git-common-dir)/.." && pwd)
SLUG=<slug-from-session-context>
FINDINGS="/tmp/ff-design-findings-${SLUG}.json"
python3 -c "
import json
agents = [<list of {area, findings} dicts collected from the parallel Task() returns above>]
json.dump({'agents': agents}, open('${FINDINGS}', 'w'))
"
Sub-step 3 — Consolidator dispatch:
ISSUE=<linked-issue-number>
STATE_FILE="${BASE_REPO}/.feature-flow/handoffs/in-progress-${SLUG}.yml"
Task(
subagent_type: "general-purpose",
model: "sonnet",
description: "design-document Pattern B consolidator",
prompt: "Invoke Skill(skill: 'feature-flow:design-document', args: 'yolo: true. scope: [scope]. issue: ${ISSUE}. design_issue: ${ISSUE}. findings_path: ${FINDINGS}. write_contract_to: ${STATE_FILE}. phase_id: design'). Return the state-file path and a one-line summary of the contract."
)
Why phase_id: design (not design-document): phase_id names the state-file bucket in phase_summaries — one of the four fixed keys (brainstorm, design, plan, implementation). The design-document lifecycle step lives in the design bucket. The contract's own phase field stays "design-document" per #251's locked spec. Two distinct concepts, same word "phase" — don't confuse them. (This bug bit PR #262 self-review for verify-plan-criteria; same trap applies here.)
Why model: "sonnet" for the consolidator: design-document Steps 2-7 do non-trivial writing (synthesizing brainstorm decisions + Explore findings into structured Markdown sections, then merging into the GitHub issue body). Sonnet handles the writing well. Haiku is too brittle for cross-section coherence; opus is over-spec for structured Markdown synthesis where the inputs are already gathered.
Why model: "haiku" for the Explore fanout: each agent's job is a focused read-and-summarize; haiku is the cost-optimal choice for parallel structured retrieval. Matches the existing design-document skill's recommendation.
Post-dispatch sequence (orchestrator-side):
- Read state file and extract
phase_summaries.design.return_contract:
python3 -c "import json, yaml; d = yaml.safe_load(open('${STATE_FILE}')); rc = (d.get('phase_summaries', {}).get('design') or {}).get('return_contract'); json.dump(rc, open('/tmp/ff-return-contract-${SLUG}.json','w')) if rc else None; print('missing' if not rc else 'ok')"
If output is missing → trigger inline-fallback (case 3 below).
- Validate the contract:
node hooks/scripts/validate-return-contract.js /tmp/ff-return-contract-${SLUG}.json
Exit 0 → proceed. Non-zero → trigger inline-fallback (case 4 below).
- Proceed to next lifecycle step (Design verification / Implementation plan).
Inline-fallback path (rollout-only — four failure cases):
| Case | Trigger | Announce | Next |
|---|
| 1 | One or more Explore agents fail/timeout AND the failure leaves <2 successful agents | design-document Pattern B: Explore fanout failed (<reason>). Falling back to inline Skill(). | Run inline Skill(skill: "feature-flow:design-document", args: "yolo: true. scope: <scope>. issue: <N>") (no findings_path — the skill runs its own Step 1) |
| 2 | Consolidator Task() dispatch fails (timeout, tool error, refusal) | design-document Pattern B: consolidator dispatch failed (<reason>). Falling back to inline Skill(). | Same inline invocation |
| 3 | Consolidator completes but return_contract field is null/absent in state file | design-document Pattern B: consolidator did not write return_contract. Falling back to inline Skill(). | Same inline invocation |
| 4 | validate-return-contract.js exits non-zero | design-document Pattern B: contract validation failed (<error from validator>). Falling back to inline Skill(). | Same inline invocation |
The inline-fallback target is the bare Skill() form (Interactive/Express equivalent), NOT the pre-#251 YOLO Task() wrapper at line ~688. The pre-#251 wrapper is latently broken — it dispatched feature-flow:design-document inside a general-purpose subagent which then attempted recursive Explore fanout (forbidden per #251 Q1). The bare Skill() invocation runs in the orchestrator's own context where the Explore fanout works.
Interactive/Express mode continues to use inline Skill calls for brainstorming (unchanged — inherits the parent model, which should be Opus at session start). design-document now uses Pattern B in all modes (the YOLO Task() wrapper at line ~688 is replaced by the Pattern B sub-steps above; the Interactive/Express bare Skill() invocations below are the inline-fallback path only). This applies to model-routing-driven dispatches only — Pattern A and Pattern B subagent dispatches still use Task() in Interactive/Express modes because their rationale is context isolation, not model routing.
Skill(skill: "superpowers:brainstorming", args: "yolo: true. scope: [scope]. [original args]")
# Note: design-document is dispatched via Pattern B above. The bare Skill() form below is the inline-fallback only.
# Skill(skill: "feature-flow:design-document", args: "yolo: true. scope: [scope]. [original args]") -- fallback path
Express Propagation: When Express mode is active, prepend express: true. scope: [scope]. to the args parameter of every Skill invocation. Express inherits all YOLO auto-selection overrides — skills that check for yolo: true should also check for express: true and behave the same way (auto-select decisions). The only difference is at the orchestrator level where checkpoints are shown instead of suppressed. Express mode uses inline Skill calls (not Task dispatch) for the brainstorming phase to preserve the user's ability to interact at checkpoints:
Skill(skill: "superpowers:brainstorming", args: "express: true. scope: [scope]. [original args]")
# Note: design-document is dispatched via Pattern B above. The bare Skill() form below is the inline-fallback only.
# Skill(skill: "feature-flow:design-document", args: "express: true. scope: [scope]. [original args]") -- fallback path
For inline steps (CHANGELOG generation, self-review, code review, study existing patterns), the mode flag is already in the conversation context — no explicit propagation is needed.
Verify Acceptance Criteria — Pattern B Dispatch
Note: INLINE-FALLBACK IS A ROLLOUT-ONLY FEATURE.
Applies in ALL modes (YOLO, Express, Interactive — see the "Subagent dispatch patterns A and B" CRITICAL block above). verify-acceptance-criteria is the second Pattern B conversion (per #251 Wave 3 phase 4). Because the skill internally dispatches a single task-verifier subagent at Step 3 (which subagents cannot do per #251 Q1 — recursive dispatch silently fails), the orchestrator hoists the task-verifier dispatch to itself, then dispatches a single consolidator subagent that runs the rest of the skill (Steps 4-6) in isolation. The orchestrator never sees the plan content, the extracted criteria, or the detailed verification report — only the validated return contract.
Why skip the state-file bucket (architectural deviation from design-document Pattern B): the four phase_summaries buckets (brainstorm, design, plan, implementation) are all claimed by phase-boundary writes. Verify-acceptance-criteria runs inside the Final Verification inline step, well after the implementation phase boundary; it is a verification step within the implementation phase, not a phase that owns a bucket. Reusing phase_summaries.implementation.return_contract would collide with the future Phase 6 (subagent-driven-development) Pattern B contract. The contract is consumed once by the orchestrator's validator and discarded — no cross-compaction reader needs it from the state file. Writing directly to a tmp JSON file avoids the collision and avoids a schema_version bump.
Sub-step 1 — Hoisted task-verifier dispatch (orchestrator-side):
The orchestrator dispatches the feature-flow:task-verifier subagent directly. The task-verifier reads the plan, extracts criteria, runs verifications, and writes the detailed Markdown report to a tmp path. Model per #251: model: "haiku" (focused mechanical verification — matches the existing inline-skill dispatch).
SLUG=<slug-from-session-context>
REPORT_PATH="/tmp/ff-verify-ac-report-${SLUG}.md"
PLAN_FILE="<absolute path to plan>"
Task(
subagent_type: "feature-flow:task-verifier",
model: "haiku",
description: "verify-acceptance-criteria task-verifier",
prompt: "Read the implementation plan at ${PLAN_FILE}. Extract every \`**Acceptance Criteria:**\` section and its \`- [ ]\` items (or for XML plans, every \`<criterion>\` element). Verify each criterion against the codebase per agents/task-verifier.md Steps 1-3 (categorize, execute, diagnose). Write the detailed Markdown report (Results table + Summary + Verdict) to ${REPORT_PATH}. Then return ONLY a short JSON summary: {\"report_path\": \"${REPORT_PATH}\", \"verdict\": \"VERIFIED|INCOMPLETE|BLOCKED\", \"pass_count\": <int>, \"fail_count\": <int>, \"failed_criteria\": [{\"task_id\": \"Task N\", \"criterion\": \"<text>\", \"reason\": \"<one-line evidence>\"}, ...]}."
)
Sub-step 2 — Consolidator dispatch:
CONTRACT_PATH="/tmp/ff-verify-ac-contract-${SLUG}.json"
Task(
subagent_type: "general-purpose",
model: "sonnet",
description: "verify-acceptance-criteria Pattern B consolidator",
prompt: "Invoke Skill(skill: 'feature-flow:verify-acceptance-criteria', args: 'plan_file: ${PLAN_FILE}. verifier_report_path: ${REPORT_PATH}. write_contract_to: ${CONTRACT_PATH}'). The skill will skip Step 3 (already run by orchestrator), present the report from Step 4, optionally update plan checkboxes in Step 5, and write the return contract in Step 6. Return the contract path and a one-line summary."
)
Why model: "sonnet" for the consolidator: Steps 4-5 do summary writing + checkbox edits across potentially many criteria; Sonnet handles the structured presentation without missing edge cases. Haiku is too brittle for the diagnose/present split; Opus is over-spec for what is mostly bookkeeping over an already-produced report.
Why model: "haiku" for the task-verifier: Mechanical verification (file existence, grep, exit codes) plus pattern-matching diagnosis is exactly Haiku's wheelhouse. This matches the existing inline-skill choice for task-verifier dispatch.
Post-dispatch sequence (orchestrator-side):
- Verify the contract file was written:
[ -f "${CONTRACT_PATH}" ] && echo ok || echo missing
If missing → trigger inline-fallback (case 3 below).
- Validate the contract:
node hooks/scripts/validate-return-contract.js "${CONTRACT_PATH}"
Exit 0 → proceed. Non-zero → trigger inline-fallback (case 4 below).
- Read pass/fail counts from the validated contract and sum them (
pass_count + fail_count) to derive the acceptance_criteria_count metadata-block field. Proceed to next lifecycle step (Sync with base branch / Commit and PR).
Inline-fallback path (rollout-only — four failure cases):
| Case | Trigger | Announce | Next |
|---|
| 1 | Sub-step 1 task-verifier dispatch fails (timeout, tool error, refusal) | verify-acceptance-criteria Pattern B: task-verifier dispatch failed (<reason>). Falling back to inline Skill(). | Run inline Skill(skill: "feature-flow:verify-acceptance-criteria", args: "plan_file: <path>") (no verifier_report_path — the skill runs its own Step 3) |
| 2 | Consolidator Task() dispatch fails (timeout, tool error, refusal) | verify-acceptance-criteria Pattern B: consolidator dispatch failed (<reason>). Falling back to inline Skill(). | Same inline invocation |
| 3 | Consolidator completes but write_contract_to JSON file is missing or empty | verify-acceptance-criteria Pattern B: consolidator did not write contract. Falling back to inline Skill(). | Same inline invocation |
| 4 | validate-return-contract.js exits non-zero | verify-acceptance-criteria Pattern B: contract validation failed (<error from validator>). Falling back to inline Skill(). | Same inline invocation |
The inline-fallback target is the bare Skill() form (the pre-#251 path). This is safe — verify-acceptance-criteria's pre-#251 inline form ran in the orchestrator's own context, where the task-verifier Task() dispatch works. (Unlike design-document's pre-#251 YOLO Task() wrapper which was latently broken; this skill never had a YOLO Task() wrapper to begin with — it was always invoked inline from the Final Verification step.)
Call site: the Pattern B wrapper is invoked from the Final Verification inline step (skills/start/references/inline-steps.md "Final Verification Step" section). The "Always run verify-acceptance-criteria" rule there now resolves to "Always run verify-acceptance-criteria via Pattern B dispatch" — see that section for integration with the quality-gate-skip logic.
Code Review — Pattern B Dispatch
Note: INLINE-FALLBACK IS A ROLLOUT-ONLY FEATURE.
Applies in ALL modes (YOLO, Express, Interactive — see the "Subagent dispatch patterns A and B" CRITICAL block above) at every scope where the existing pipeline runs (Small enhancement, Feature, Major feature — Quick fix is already skipped per skills/start/references/code-review-pipeline.md "Quick fix guard"). code-review is the third Pattern B conversion (per #251 Wave 3 phase 5). The pipeline internally fans out the parallel reviewer dispatches across Phase 1a (pr-review-toolkit), Phase 1b (report-only agents), and Phase 1c (senior panel). Subagents cannot recursively dispatch (#251 Q1), so the orchestrator continues to dispatch those reviewer fanouts itself, then dispatches a single consolidator subagent that runs Phases 2-5 in isolation: conflict detection, fix application, targeted re-verification, report assembly, and contract write. The orchestrator never sees the reviewer findings list, the conflict-resolution decisions, or the fix-application diff — only the validated return contract.
Why skip the state-file bucket (architectural deviation — same rationale as verify-acceptance-criteria): the four phase_summaries buckets (brainstorm, design, plan, implementation) are all claimed by phase-boundary writes. Code-review is a verification step within the implementation phase, not a phase that owns a bucket. Reusing phase_summaries.implementation.return_contract would collide with the future Phase 6 (subagent-driven-development) Pattern B contract. The contract is consumed once by the orchestrator's validator and discarded — no cross-compaction reader needs it from the state file. Writing directly to a tmp JSON file avoids the collision and avoids a schema_version bump.
Sub-step 1 — Phase 0 deterministic pre-filter (orchestrator-side, unchanged):
The orchestrator runs the existing Phase 0 logic from skills/start/references/code-review-pipeline.md — detect TypeScript / ESLint / Biome, run them in parallel, fix deterministic findings, build the exclusion-context summary. No subagent dispatch yet. Phase 0 is fast (linters) and produces a small text output; isolating it in a subagent is not load-bearing.
Sub-step 2 — Phase 1a/1b/1c parallel reviewer dispatches (orchestrator-side, unchanged):
The orchestrator dispatches the existing reviewers per the existing rules in skills/start/references/code-review-pipeline.md — Phase 1a pr-review-toolkit subagent (gated, sequential pre-pass), then Phase 1b report-only agents in parallel with Phase 1c senior panel (Major-feature only). These dispatches MUST stay orchestrator-side because subagents cannot recursively dispatch (#251 Q1). The orchestrator collects each reviewer's structured output (Phase 1a Auto-Fixed/Critical/Important/Minor sections; Phase 1b structured findings; Phase 1c findings + persona/finding_type fields).
Sub-step 3 — Consolidator dispatch:
SLUG=<slug-from-session-context>
LIFECYCLE_SESSION=<lifecycle-session-slug-from-.feature-flow/session.txt>
CONTRACT_PATH="/tmp/ff-code-review-contract-${SLUG}.json"
REPORT_PATH="/tmp/ff-code-review-report-${SLUG}.md"
PLAN_FILE="<absolute path to plan>"
Task(
subagent_type: "general-purpose",
model: "sonnet",
description: "code-review Pattern B consolidator",
prompt: "Run Phases 2-5 of the code-review pipeline per `skills/start/references/code-review-pipeline.md`. You are receiving the parallel reviewer outputs from the orchestrator (which already executed Phases 0, 1a, 1b, 1c).
Inputs:
- Phase 1a pr-review-toolkit summary: <inline structured summary OR null if Phase 1a was skipped>
- Phase 1b structured findings: <inline list per agent>
- Phase 1c senior panel findings: <inline list OR empty list when scope < Major feature OR null when Phase 1c failed>
- Lifecycle session slug: ${LIFECYCLE_SESSION}
- Plan file (for the verdict-honesty constraint context): ${PLAN_FILE}
- Report path to write: ${REPORT_PATH}
- Contract path to write: ${CONTRACT_PATH}
Execute Phase 2 (merge / dedupe / conflict-detect), Phase 3 (apply rule-based fixes via Edit/Write/Bash and commit), Phase 4 (targeted re-verification — for any agent re-dispatch row that triggers, write a deferred[] entry instead per the Pattern B agent-re-dispatch rule in code-review-pipeline.md), Phase 5 (write the report to ${REPORT_PATH} with [session:${LIFECYCLE_SESSION}] correlation tokens on every entry, then write the return contract to ${CONTRACT_PATH} per the Phase 5 'Contract Write' subsection). Return the contract path and a one-line verdict summary."
)
Why model: "sonnet": consolidation requires structured-output discipline (deduplication, conflict detection, contract field assembly) plus mechanical edits (Phase 3 fix application). Sonnet handles both well; Haiku is too brittle for the conflict-resolution heuristics; Opus is over-spec for what is mostly bookkeeping over already-produced findings. Senior-panel dispatches (Phase 1c) already use Opus at the orchestrator level; the consolidator does not need to re-decide architectural questions, only consolidate.
Post-dispatch sequence (orchestrator-side):
- Verify the contract file was written:
[ -f "${CONTRACT_PATH}" ] && echo ok || echo missing
If missing → trigger inline-fallback (case 3 below).
- Validate the contract:
node hooks/scripts/validate-return-contract.js "${CONTRACT_PATH}"
Exit 0 → proceed. Non-zero → trigger inline-fallback (case 4 below).
- Read
verdict from the validated contract and feed the lifecycle decision:
verdict: "approve" → continue normally to next lifecycle step (Generate CHANGELOG entry / Final verification).
verdict: "needs_changes" → continue but flag the PR; the post-implementation comment and PR body should reflect that critical/important findings remain. The lifecycle does not auto-halt — the user makes the merge decision.
verdict: "blocked" → halt the lifecycle. Surface the contract's deferred[] entries to the user and stop. Do not proceed to commit/PR.
Inline-fallback path (rollout-only — four failure cases):
| Case | Trigger | Announce | Next |
|---|
| 1 | Sub-step 2 reviewer dispatch failure (existing per-reviewer handlers retained — this row covers cascading failures only) | code-review Pattern B: reviewer dispatch failed (<reason>). Continuing inline at orchestrator level. | Run Phases 2-5 inline at the orchestrator level per skills/start/references/code-review-pipeline.md |
| 2 | Consolidator Task() dispatch fails (timeout, tool error, refusal) | code-review Pattern B: consolidator dispatch failed (<reason>). Falling back to inline pipeline. | Run Phases 2-5 inline at the orchestrator level (orchestrator can do agent re-dispatch in Phase 4 — no deferred[] mapping needed in fallback path) |
| 3 | Consolidator completes but write_contract_to JSON file is missing or empty | code-review Pattern B: consolidator did not write contract. Falling back to inline pipeline. | Same inline pipeline path |
| 4 | validate-return-contract.js exits non-zero | code-review Pattern B: contract validation failed (<error from validator>). Falling back to inline pipeline. | Same inline pipeline path |
The inline-fallback target is the existing in-place pipeline — Phases 2-5 run at the orchestrator level identically to the pre-#251 behavior. Phase 4 agent re-dispatch works in the inline path (orchestrator CAN dispatch agents); no deferred[] entries are written in fallback mode.
Call site: the Pattern B wrapper is invoked from the Code Review Pipeline Step (skills/start/SKILL.md "Code Review Pipeline Step" section, which itself defers to skills/start/references/code-review-pipeline.md). The "Quick fix guard" at the top of that pipeline doc still applies — Quick fix scope skips both Pattern B and the inline pipeline.
Lifecycle Context Object: As the lifecycle executes, maintain a context object that accumulates artifact paths as they become known. Include all known paths in the args of every subsequent Skill invocation, after the mode flag and scope:
| Path key | When it becomes available |
|---|
base_branch | Step 0 — base branch detection |
feature_context | Step 0 — knowledge base pre-flight (null if no FEATURE_CONTEXT.md found). File is session-local (not committed). |
issue | Step 1 — when an issue number is linked |
design_issue | After create-issue step — integer issue number containing the design (set by create-issue; design-document edits the body) |
plan_file | After implementation plan step (the absolute path of the saved plan file) |
worktree | After worktree setup (the absolute path to the created worktree) |
pr | After "Commit and PR" step (the PR number extracted from the superpowers:finishing-a-development-branch output) |
Include only paths that are known at the time of each invocation — do not include paths for artifacts that haven't been created yet. Example invocations showing progressive accumulation:
# YOLO mode — brainstorming and design doc via Task dispatch with explicit model:
Task(subagent_type: "general-purpose", model: "opus", description: "YOLO brainstorming",
prompt: "Invoke Skill(skill: 'superpowers:brainstorming', args: 'yolo: true. scope: [scope]. base_branch: main. issue: 119. [original args]'). Return the complete output.")
# YOLO mode — planning via Task dispatch with explicit model:
Task(subagent_type: "general-purpose", model: "sonnet", description: "YOLO implementation plan",
prompt: "Invoke Skill(skill: 'superpowers:writing-plans', args: 'yolo: true. scope: [scope]. base_branch: main. issue: 119. design_issue: 119. [original args]'). Return the plan file path.")
# Interactive/Express mode — inline Skill calls (inherit parent model):
Skill(skill: "superpowers:brainstorming", args: "yolo: true. scope: [scope]. base_branch: main. issue: 119. [original args]")
Skill(skill: "superpowers:writing-plans", args: "yolo: true. scope: [scope]. base_branch: main. issue: 119. design_issue: 119. [original args]")
# During and after implementation (all paths known, all modes):
Skill(skill: "superpowers:subagent-driven-development", args: "yolo: true. scope: [scope]. plan_file: /abs/path/plan.md. design_issue: 119. worktree: /abs/path/.worktrees/feat-xyz. base_branch: main. issue: 119. [original args]")
Skill(skill: "feature-flow:verify-acceptance-criteria", args: "plan_file: /abs/path/plan.md. [original args]")
Do not skip steps. If the user asks to skip a step, explain why it matters and confirm they want to skip. If they insist, mark it as skipped and note the risk.