一键导入
create-plan
Produce a technical implementation plan (design-focused), optionally interviewing the user, then run multi-model generator and plan review gate
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Produce a technical implementation plan (design-focused), optionally interviewing the user, then run multi-model generator and plan review gate
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Ask the Cerberus model panel an arbitrary question
Interview the user to produce a feature spec, then run multi-model generator and spec review gate
Iterative code review with external reviewers
Iterative plan review with external reviewers
Iterative spec review with external reviewers
Verify epic acceptance criteria against the codebase with multi-model consensus
基于 SOC 职业分类
| name | create-plan |
| disable-model-invocation | true |
| description | Produce a technical implementation plan (design-focused), optionally interviewing the user, then run multi-model generator and plan review gate |
| argument-hint | [--mode <name>] [--max-rounds <N>] [--from-spec <path/to/spec.md>] [--skip-interview] <feature or plan summary> |
Before running any Bash snippet in this skill, run the shared Cerberus resolver below. It lazily builds and executes bin/cerberus from the configured plugin root.
# --- shared resolver (canonical body; identical across all callers) ---
set +u
if [ -n "${CODEX_THREAD_ID:-}" ] || [ -n "${PLUGIN_ROOT:-}" ]; then
host=codex
elif [ -n "${CLAUDE_SESSION_ID}" ] || [ -n "${CLAUDE_PLUGIN_ROOT}" ] || [ -n "${CLAUDE_SKILL_DIR}" ]; then
host=claude
else
host="${CERBERUS_HOST:-}"
if [ "$host" = claude-code ]; then
host=claude
fi
fi
root="${CERBERUS_ROOT:-}"
if [ -z "$root" ] && [ "$host" = codex ]; then
root="${PLUGIN_ROOT:-}"
fi
if [ -z "$root" ] && [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then
cache_home="${HOME:-}"
[ -n "$cache_home" ] || cache_home="${USERPROFILE:-}"
if [ -n "$cache_home" ]; then
cache_file="$cache_home/.codex/cerberus/sessions/$CODEX_THREAD_ID/plugin-root"
if [ -r "$cache_file" ]; then
IFS= read -r root < "$cache_file" || true
fi
fi
fi
if [ -z "$root" ] && [ "$host" != codex ]; then
root="${CLAUDE_PLUGIN_ROOT}"
[ -n "$root" ] || root="${PLUGIN_ROOT:-}"
fi
if [ -z "$root" ] && [ "$host" != codex ]; then
skill_dir="${CLAUDE_SKILL_DIR}"
if [ -n "$skill_dir" ]; then
root="$(cd "$skill_dir/../.." && pwd)"
fi
fi
[ -n "$root" ] || { echo "cerberus: plugin root not set; set CERBERUS_ROOT and retry" >&2; exit 127; }
bin="$root/bin/cerberus"
export CERBERUS_ROOT="$root"
claude_session="${CLAUDE_SESSION_ID}"
if [ "$host" = claude ]; then
export CERBERUS_HOST=claude
elif [ "$host" = codex ]; then
export CERBERUS_HOST=codex
fi
if [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then
export CERBERUS_HOST=codex CERBERUS_SESSION_ID="$CODEX_THREAD_ID"
elif [ "$host" = claude ] && [ -n "$claude_session" ]; then
export CERBERUS_HOST=claude CERBERUS_SESSION_ID="${CERBERUS_SESSION_ID:-$claude_session}"
fi
command -v make >/dev/null 2>&1 || { echo "cerberus: make not found on PATH; install make and retry." >&2; exit 127; }
if ! make -q -C "$root" build >/dev/null 2>&1; then
command -v go >/dev/null 2>&1 || { echo "cerberus: Go >= 1.22 not found on PATH; install Go and retry." >&2; exit 127; }
echo "cerberus: building... (this happens once after clone or upgrade)" >&2
start=$(date +%s)
make -C "$root" build >&2 || exit $?
end=$(date +%s)
echo "cerberus: build complete in $((end-start))s" >&2
fi
# --- shared resolver above; per-caller exec below (allowed to diverge) ---
exec "$bin" "$@"
Use bin/cerberus through the configured plugin root when invoking Cerberus commands below.
Turn a spec or vague feature idea into a design-focused implementation plan by combining codebase research (including file existence checks), either a targeted implementation-focused interview or an autonomous decision pass, multi-model generation, and a plan review gate.
Note: This command produces a design plan (architecture, constraints, approach). Task breakdown is handled separately by
/create-tasks, which reads this plan and outputs to Beads issues (--beads) or TODO.md.
You MUST follow these phases in order. Skipping phases is NOT ALLOWED, except that --skip-interview replaces the interactive interview portion of Phase 2 with an autonomous decision pass:
[TBD] placeholders to a file (this becomes the canonical doc)[TBD] placeholders, or if --skip-interview is set, make and document autonomous decisions for those placeholdersHard Rules:
[TBD] markers in Phase 1c--skip-interview is set--skip-interview is set--skip-interview is set, you MUST NOT ask plan-generation clarifying questions; instead, make safe decisions from the spec, codebase evidence, and existing project patterns, then document every decision and rationale in the plan--skip-interview, explain the workflow and proceed with skeleton + interview✅ Produce skeleton with [TBD] placeholders in Phase 1c — The initial plan file must contain unfilled placeholders, not completed content.
✅ Run at least one interview batch in Phase 2 unless --skip-interview is set — Use AskUserQuestion to confirm assumptions, even if the spec seems complete.
✅ Honor --skip-interview explicitly — Do not ask clarifying questions; fill placeholders through documented autonomous decisions and mark unsafe/product-owned decisions as Open Questions.
✅ Follow the workflow when user asks to skip without the flag — If user says "just generate the plan" but did not pass --skip-interview, explain the workflow and proceed with skeleton + interview.
✅ Write generator drafts to files — Call cerberus generate, which writes drafts to disk; pass file paths to the synthesis subagent.
✅ Delegate synthesis to a subagent — Use the Task tool for synthesis to preserve your main context for the review gate.
Modes only select a model panel from config.yaml. Mode names do not alter interview depth, priority scope, or refinement policy, so custom modes behave exactly like built-in modes.
Use soft budgets and exit early when the plan is decision-complete. With --skip-interview, apply the same completeness standard to the autonomous decision pass instead of asking questions.
Override: --max-rounds <N> sets the review round cap explicitly, overriding defaults.max_rounds. Accepts any integer >= 0; 0 runs the initial review once and disables refinement respawns.
Soft budget rules:
The user provides either:
--from-spec path/to/spec.md--skip-interview to skip user questions and have the command make and document its own implementation decisionsBefore Phase 0, parse command arguments:
MODE only when an explicit --mode <name> flag is present; otherwise leave it unset so config.yaml can supply defaults.mode.MAX_ROUNDS only when an explicit --max-rounds <N> flag is present; otherwise leave it unset so the runtime defaults remain authoritative.SKIP_INTERVIEW=true only when the explicit --skip-interview flag is present.SKIP_INTERVIEW unset or set it to false; command examples must check [[ "${SKIP_INTERVIEW:-false}" == "true" ]] before forwarding the flag.--skip-interview from the feature summary before writing the plan.--mode <name> from the feature summary before writing the plan.--skip-interview is not present, free-text phrases like "skip the interview" or "just generate it" are not enough to enter autonomous mode; follow the normal interview workflow.--from-spec is not provided and --skip-interview is set, treat the remaining feature summary as the starting artifact instead of asking whether a spec exists.Before deep research, establish what you're planning against:
Detect a spec (if any):
--from-spec is provided, use that path.--skip-interview is set, do not ask; record spec_path as N/A and use the user's feature summary as the starting artifact.Ingest starting artifacts:
Document:
spec_path (if any)Before asking implementation questions, understand how and where the work will land:
Identify relevant areas:
Note existing patterns:
Find integration points & constraints:
Capture key files/modules:
Ownership hints:
Goal: Identify existing infrastructure to extend BEFORE proposing new components.
This phase prevents the common failure mode of proposing parallel/duplicate systems when the codebase already has mechanisms that should be extended.
If a spec exists: Honor any integration constraints from the spec (e.g., "Must reuse existing auth pipeline"). If the plan needs to deviate from spec constraints, explicitly call out the tradeoff and risk.
Identify existing mechanisms that could serve this feature:
For each existing mechanism, evaluate:
Build an Integration Decision Table:
| Existing Mechanism | Could Serve Feature? | Extend vs New | Rationale |
|--------------------|---------------------|---------------|-----------|
| src/config/loader.ts | Yes | Extend | Already handles all component config |
| src/plugins/registry.ts | Partial | Extend + Add | Has plugin loading, needs config hooks |
| N/A - no existing auth middleware | No | New | Nothing exists for this concern |
Default to extension: If an existing mechanism can serve the feature with reasonable modifications, the plan MUST propose extending it rather than creating a parallel system. Creating new infrastructure requires explicit justification:
Red flags to catch yourself:
Plans must not hallucinate existing files. Explicitly verify file existence:
Collect candidate paths from:
Check each candidate path:
Build a verification table for context:
- src/auth/middleware.ts — Exists
- src/auth/session_rotation.ts — New (to be created)
- tests/auth/session_rotation.test.ts — New (test file to add)
Create a skeleton of the plan with placeholders based on research and spec. This drives targeted interviewing.
IMPORTANT: When you finish Phase 1c:
docs/YYYY-MM-DD-FEATURE-plan.md) — this becomes the canonical doc[TBD] placeholders — fill them only during Phase 2 from user answers or documented autonomous decisions--skip-interview is not set, present the skeleton and your first batch of interview questions via AskUserQuestion--skip-interview is set, do not present interview questions; immediately proceed to the Phase 2 autonomous decision passPHASE 2 GATE: If --skip-interview is not set, after sending Interview Batch 1, end your turn immediately. Do not proceed to Phase 3+ until the user answers or issues a stop signal. This gate is mandatory for interactive mode.
# Implementation Plan: [Short Name]
## Context & Goals
- **Spec**: [spec_path or "N/A — derived from user description"]
- [TBD: 1-3 bullets summarizing the feature]
## Scope & Non-Goals
- **In Scope**
- [Pre-fill from spec if available, else TBD]
- **Out of Scope (Non-Goals)**
- [Pre-fill from spec if available, else TBD]
## Assumptions & Constraints
- [TBD or pre-fill from research]
### Implementation Constraints
- [TBD: architectural constraints]
### Testing Constraints
- [TBD: coverage requirements]
### Decision Log
| Decision | Rationale | Evidence | Tradeoff / Risk / Follow-up |
|----------|-----------|----------|------------------------------|
| [TBD: decisions made during interview or autonomous mode] | [TBD] | [TBD] | [TBD] |
## Integration Analysis
### Existing Mechanisms Considered
[Pre-fill from Phase 1a Integration Decision Table]
| Existing Mechanism | Could Serve Feature? | Decision | Rationale |
|--------------------|---------------------|----------|-----------|
| [path/to/mechanism] | Yes/Partial/No | Extend/New | [Why] |
### Integration Approach
[TBD: How this feature hooks into existing infrastructure. If creating new infrastructure, justify why existing mechanisms are insufficient.]
## Prerequisites
- [ ] [TBD: access, approvals, infra]
## High-Level Approach
[TBD: 1-2 paragraphs describing the technical approach, phases, and key decisions]
## Technical Design
### Architecture
[TBD: How components fit together, data flow, key boundaries]
### Data Model
[TBD: Entities, relationships, state transitions — or "N/A" if not applicable]
### API/Interface Design
[TBD: Key interfaces, contracts, protocols — or "N/A" if not applicable]
### File Impact Summary
[Pre-fill from Phase 1b verification table]
| Path | Status | Description |
|------|--------|-------------|
| `src/auth/middleware.ts` | Exists | Modify existing middleware |
| `src/auth/session.ts` | **New** | Create session helper |
| `tests/auth/session.test.ts` | **New** | Add tests |
## Risks, Edge Cases & Breaking Changes
### Edge Cases & Failure Modes
- [TBD or pre-fill from spec Edge Cases]
### Breaking Changes & Compatibility
- **Potential Breaking Changes**: [TBD]
- **Mitigations**: [TBD]
## Testing & Validation Strategy
- [TBD: Types of tests needed (unit, integration, e2e)]
- [TBD: Coverage requirements]
- [TBD: Manual validation steps]
### Acceptance Criteria Coverage
| Spec AC | Approach |
|---------|----------|
| [Pre-fill from spec if available] | [How this plan addresses it] |
## Spec/Legacy Fidelity
[If a spec/legacy doc exists, confirm the plan matches it. Any deviations must be explicit.]
### Deviation Log
| Source | Deviation | Rationale | Approved? |
|--------|-----------|-----------|-----------|
| None | — | — | — |
## Open Questions
- [List unknowns from research]
## Next Steps
After this plan is approved, run `/create-tasks` to generate:
- `--beads` → Beads issues with dependencies for multi-agent execution
- (default) → TODO.md checklist for simpler tracking
Skeleton rules:
[TBD] or [TBD: hint]Prerequisites: Phase 1c skeleton MUST exist before starting Phase 2.
--skip-interview)If SKIP_INTERVIEW=true, replace the interactive interview with this pass:
AskUserQuestion for plan-generation clarification. The flag is the user's explicit delegation signal.[TBD] from evidence where possible using the spec, codebase research, integration table, verified file list, and established project patterns.### Decision Log with rationale, evidence, tradeoff, and risk/follow-up. Also mirror durable assumptions in ## Assumptions & Constraints.## Open Questions and design the plan so implementation can pause at that boundary.[TBD] placeholders except intentionally retained Open Questions.When citing evidence in the plan, use durable references such as file paths, module names, spec IDs, or section names. Do not include file line numbers or #L... anchors.
Treat these as unsafe unknowns unless directly specified by the spec or strongly established by codebase patterns:
For unsafe unknowns, do not ask the user in skip-interview mode and do not silently choose. List the item in Open Questions and design the implementation so work can pause before the unsafe boundary.
After this pass, proceed directly to Phase 3 in the same turn.
If SKIP_INTERVIEW=false, run the interview below.
Load the interview engine: Read ${CLAUDE_PLUGIN_ROOT}/prompts/interview-engine.md for the full mechanism. Key principles below.
IMPORTANT: Use the AskUserQuestion tool for ALL interview questions. Put coverage + numbered questions + off-ramp in a single tool call. Plain text questions are not interactive.
Ask questions in order of priority (P0-P3) and depth (L0-L3), with breadth across topics before depth in any single topic.
| Priority | What | Examples |
|---|---|---|
| P0 | Blockers / correctness | Scope, backwards compatibility, data loss, testing baseline |
| P1 | Major design | Architecture, API contracts, ownership, rollout strategy |
| P2 | Edge cases | Failure modes, migrations, observability |
| P3 | Polish | Optimizations, refactors, minor improvements |
| Depth | Scope | Examples |
|---|---|---|
| L0 | Vision / outcome | What spec? What MVP? What's excluded? |
| L1 | Architecture | Boundaries, data flow, API direction, test strategy |
| L2 | Components | File targets, endpoints, modules, test layers |
| L3 | Implementation | Exact files, schemas, algorithms, test cases |
Anti-deep-dive rule: Don't ask L2 for Topic A until all P0 topics have L1 coverage.
| Signal Type | Trigger Phrases | Action |
|---|---|---|
| Global stop | "enough detail", "that's enough", "stop here", "we're good", "ship it" | End interview, remaining TBDs → Open Questions |
| Depth cap | "keep it high-level", "stop at L1", "no deep dive", "details later" | Set max_depth, continue within cap |
| Priority cap | "skip P2/P3", "just blockers", "P0/P1 only" | Set max_priority, lower items → Open Questions |
| Per-topic stop | "enough about testing", "park observability", "skip migrations" | Mark topic capped, continue others |
| Per-question skip | "skip this one", "next question" | Mark TBD as Open Question, no follow-ups |
| Delegation | "you decide", "whatever's standard" | Pick safe default, record in Assumptions & Constraints |
| Uncertainty | "I don't know" | Offer 2-3 options; if declined → Open Question |
Present questions with context and an explicit off-ramp:
**Interview Batch [N]** (Priority: P0, Depth: L1)
Current coverage: [P0 complete through L0, now at L1]
Questions (answer any, skip any):
1. [Topic: Architecture] How should data flow between components?
- Options: [A] Sync via API, [B] Event-driven, [C] You decide
- Evidence: I see pub/sub in `services/events/` — should we use that?
2. [Topic: Testing] What test types are required?
- Options: [A] Unit only, [B] Unit + integration, [C] Full pyramid
3. [Topic: Compatibility] Are there existing clients to maintain?
- Evidence: Found API v2 consumers in `clients/`
---
Reply using `1: <answer> 2: <answer>` format (skip numbers to leave as Open Questions).
Or say "enough detail" to stop, "keep it high-level" to cap depth.
Phase 2 Rules:
[TBD] placeholders in the skeletonP0/L0-L1 (always cover):
P1/L1-L2 (cover when applicable):
P2/L2-L3 (cover for high-risk or complex work):
| User says... | You should... |
|---|---|
| "You decide" | Choose safe, conventional pattern; record in Assumptions & Constraints |
| "I don't know" | Propose 2–3 concrete strategies with tradeoffs |
| "Whatever's standard" | Use existing codebase patterns; say so explicitly |
| "Skip this" | Record under Non-Goals or Open Questions |
| Stop signal | End interview or cap depth immediately |
Gate Check — You MUST NOT proceed to Phase 3 until:
--skip-interview is set and the autonomous decision pass is completeCreate a compact context block for generators:
Context Checklist — Ensure plan file has:
Create, populate, and remember a temporary prompt file:
CRITICAL: Tool/Bash calls do not share exported variables. Do not create PROMPT_TMP in one Bash call and then use $PROMPT_TMP in a later Bash call unless you explicitly re-export the printed literal path in that same later call. Prefer the single Bash block below, which keeps creation and population in one shell process.
CRITICAL: The command MUST start with an executable, NOT a bare variable assignment. Variable assignments trigger permission prompts.
env bash -lc 'set -euo pipefail
PROMPT_TMP="$(mktemp "${TMPDIR:-/tmp}/create-plan-prompt-XXXXXX")"
test -f "$PROMPT_TMP"
set +u
if [ -n "${CODEX_THREAD_ID:-}" ] || [ -n "${PLUGIN_ROOT:-}" ]; then host=codex; elif [ -n "${CLAUDE_SESSION_ID}" ] || [ -n "${CLAUDE_PLUGIN_ROOT}" ] || [ -n "${CLAUDE_SKILL_DIR}" ]; then host=claude; else host="${CERBERUS_HOST:-}"; if [ "$host" = claude-code ]; then host=claude; fi; fi; root="${CERBERUS_ROOT:-}"; if [ -z "$root" ] && [ "$host" = codex ]; then root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then cache_home="${HOME:-}"; [ -n "$cache_home" ] || cache_home="${USERPROFILE:-}"; if [ -n "$cache_home" ]; then cache_file="$cache_home/.codex/cerberus/sessions/$CODEX_THREAD_ID/plugin-root"; if [ -r "$cache_file" ]; then IFS= read -r root < "$cache_file" || true; fi; fi; fi; if [ -z "$root" ] && [ "$host" != codex ]; then root="${CLAUDE_PLUGIN_ROOT}"; [ -n "$root" ] || root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" != codex ]; then skill_dir="${CLAUDE_SKILL_DIR}"; if [ -n "$skill_dir" ]; then root="$(cd "$skill_dir/../.." && pwd)"; fi; fi; [ -n "$root" ] || { echo "cerberus: plugin root not set; set CERBERUS_ROOT and retry" >&2; exit 127; }
cat "$root/prompts/generators/create-plan.md" > "$PROMPT_TMP"
cat >> "$PROMPT_TMP" <<'"'"'EOF'"'"'
## Context
EOF
printf "PROMPT_TMP=%s\n" "$PROMPT_TMP"'
This creates a unique temp file like /tmp/create-plan-prompt-abc123. Do not use a top-level PROMPT_TMP=$(mktemp ...) assignment, and do not add a suffix like .md; BSD/macOS mktemp only replaces trailing X characters.
Record the printed PROMPT_TMP=... value. In subsequent Bash calls, substitute the actual printed path (for example /tmp/create-plan-prompt-abc123) or start that same call with export PROMPT_TMP='/tmp/create-plan-prompt-abc123' && .... Never assume $PROMPT_TMP still exists from an earlier tool call.
Now append the Phase 3 context (skeleton + findings + user answers or autonomous decisions) to the actual prompt file path printed above. Substitute the printed path in this same Bash call:
: "${PROMPT_TMP:=<paste the printed /tmp/create-plan-prompt-... path here>}" && export PROMPT_TMP && cat >> "$PROMPT_TMP" <<'EOF'
[Paste Phase 3 context here]
EOF
Spawn generators with the mode flag. The cerberus generate subcommand requires an output directory as the first argument, resolves the selected panel from config.yaml, and writes drafts to files, returning their paths.
If --skip-interview was passed to this command, add --skip-interview to the cerberus generate invocation so the model drafts also make and document autonomous decisions instead of asking clarifying questions.
CRITICAL: The command MUST start with an executable, NOT a variable assignment. Variable assignments trigger permission prompts.
: "${PROMPT_TMP:=<paste the printed /tmp/create-plan-prompt-... path here>}" && export PROMPT_TMP && export OUTPUT_PARENT="${REVIEW_DIR:-${TMPDIR:-/tmp}}" && mkdir -p "$OUTPUT_PARENT" && export OUTPUT_DIR="$(mktemp -d "$OUTPUT_PARENT/create-plan-drafts-XXXXXX")" && test -d "$OUTPUT_DIR" && printf 'OUTPUT_DIR=%s\n' "$OUTPUT_DIR" && MODE_ARGS=() && if [ -n "${MODE:-}" ]; then MODE_ARGS=(--mode "$MODE"); fi && if [[ "${SKIP_INTERVIEW:-false}" == "true" ]]; then set +u; if [ -n "${CODEX_THREAD_ID:-}" ] || [ -n "${PLUGIN_ROOT:-}" ]; then host=codex; elif [ -n "${CLAUDE_SESSION_ID}" ] || [ -n "${CLAUDE_PLUGIN_ROOT}" ] || [ -n "${CLAUDE_SKILL_DIR}" ]; then host=claude; else host="${CERBERUS_HOST:-}"; if [ "$host" = claude-code ]; then host=claude; fi; fi; root="${CERBERUS_ROOT:-}"; if [ -z "$root" ] && [ "$host" = codex ]; then root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then cache_home="${HOME:-}"; [ -n "$cache_home" ] || cache_home="${USERPROFILE:-}"; if [ -n "$cache_home" ]; then cache_file="$cache_home/.codex/cerberus/sessions/$CODEX_THREAD_ID/plugin-root"; if [ -r "$cache_file" ]; then IFS= read -r root < "$cache_file" || true; fi; fi; fi; if [ -z "$root" ] && [ "$host" != codex ]; then root="${CLAUDE_PLUGIN_ROOT}"; [ -n "$root" ] || root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" != codex ]; then skill_dir="${CLAUDE_SKILL_DIR}"; if [ -n "$skill_dir" ]; then root="$(cd "$skill_dir/../.." && pwd)"; fi; fi; [ -n "$root" ] || { echo "cerberus: plugin root not set; set CERBERUS_ROOT and retry" >&2; exit 127; }; bin="$root/bin/cerberus"; export CERBERUS_ROOT="$root"; claude_session="${CLAUDE_SESSION_ID}"; if [ "$host" = claude ]; then export CERBERUS_HOST=claude; elif [ "$host" = codex ]; then export CERBERUS_HOST=codex; fi; if [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then export CERBERUS_HOST=codex CERBERUS_SESSION_ID="$CODEX_THREAD_ID"; elif [ "$host" = claude ] && [ -n "$claude_session" ]; then export CERBERUS_HOST=claude CERBERUS_SESSION_ID="${CERBERUS_SESSION_ID:-$claude_session}"; fi; command -v make >/dev/null 2>&1 || { echo "cerberus: make not found on PATH; install make and retry." >&2; exit 127; }; if ! make -q -C "$root" build >/dev/null 2>&1; then command -v go >/dev/null 2>&1 || { echo "cerberus: Go >= 1.22 not found on PATH; install Go and retry." >&2; exit 127; }; echo "cerberus: building... (this happens once after clone or upgrade)" >&2; start=$(date +%s); make -C "$root" build >&2 || exit $?; end=$(date +%s); echo "cerberus: build complete in $((end-start))s" >&2; fi; "$bin" generate "$OUTPUT_DIR" --type create-plan "${MODE_ARGS[@]}" --prompt-file "$PROMPT_TMP" --skip-interview; else set +u; if [ -n "${CODEX_THREAD_ID:-}" ] || [ -n "${PLUGIN_ROOT:-}" ]; then host=codex; elif [ -n "${CLAUDE_SESSION_ID}" ] || [ -n "${CLAUDE_PLUGIN_ROOT}" ] || [ -n "${CLAUDE_SKILL_DIR}" ]; then host=claude; else host="${CERBERUS_HOST:-}"; if [ "$host" = claude-code ]; then host=claude; fi; fi; root="${CERBERUS_ROOT:-}"; if [ -z "$root" ] && [ "$host" = codex ]; then root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then cache_home="${HOME:-}"; [ -n "$cache_home" ] || cache_home="${USERPROFILE:-}"; if [ -n "$cache_home" ]; then cache_file="$cache_home/.codex/cerberus/sessions/$CODEX_THREAD_ID/plugin-root"; if [ -r "$cache_file" ]; then IFS= read -r root < "$cache_file" || true; fi; fi; fi; if [ -z "$root" ] && [ "$host" != codex ]; then root="${CLAUDE_PLUGIN_ROOT}"; [ -n "$root" ] || root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" != codex ]; then skill_dir="${CLAUDE_SKILL_DIR}"; if [ -n "$skill_dir" ]; then root="$(cd "$skill_dir/../.." && pwd)"; fi; fi; [ -n "$root" ] || { echo "cerberus: plugin root not set; set CERBERUS_ROOT and retry" >&2; exit 127; }; bin="$root/bin/cerberus"; export CERBERUS_ROOT="$root"; claude_session="${CLAUDE_SESSION_ID}"; if [ "$host" = claude ]; then export CERBERUS_HOST=claude; elif [ "$host" = codex ]; then export CERBERUS_HOST=codex; fi; if [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then export CERBERUS_HOST=codex CERBERUS_SESSION_ID="$CODEX_THREAD_ID"; elif [ "$host" = claude ] && [ -n "$claude_session" ]; then export CERBERUS_HOST=claude CERBERUS_SESSION_ID="${CERBERUS_SESSION_ID:-$claude_session}"; fi; command -v make >/dev/null 2>&1 || { echo "cerberus: make not found on PATH; install make and retry." >&2; exit 127; }; if ! make -q -C "$root" build >/dev/null 2>&1; then command -v go >/dev/null 2>&1 || { echo "cerberus: Go >= 1.22 not found on PATH; install Go and retry." >&2; exit 127; }; echo "cerberus: building... (this happens once after clone or upgrade)" >&2; start=$(date +%s); make -C "$root" build >&2 || exit $?; end=$(date +%s); echo "cerberus: build complete in $((end-start))s" >&2; fi; "$bin" generate "$OUTPUT_DIR" --type create-plan "${MODE_ARGS[@]}" --prompt-file "$PROMPT_TMP"; fi
Record the printed OUTPUT_DIR=... value, then read the draft.md paths cerberus generate prints to stdout — one line per drafter that succeeded. The panel comes from the selected mode in config.yaml (falling back to claude + codex + gemini), so the set of directories is dynamic: each drafter writes to $OUTPUT_DIR/<label>/draft.md, where <label> is the provider name, with additional same-provider instances suffixed (for example codex and codex-2). Use exactly the paths printed; do not assume a fixed list. Do not pass literal $OUTPUT_DIR/... paths to a subagent unless you have replaced $OUTPUT_DIR with the actual printed directory.
IMPORTANT: The tool result contains only file paths, not the full draft content. This preserves your context window.
You MUST use a subagent (Task tool) to synthesize drafts. This preserves your main context for the review gate phase.
Use the Task tool with a prompt like:
Synthesize the following generator drafts into the plan file.
Draft files to read:
[Paste the actual draft.md paths printed by `cerberus generate` — one per successful drafter. The panel is whatever the selected `config.yaml` mode resolves to; the example shape below may differ from your run.]
- /actual/output/dir/claude/draft.md
- /actual/output/dir/codex/draft.md
- /actual/output/dir/codex-2/draft.md
Plan file to update: docs/YYYY-MM-DD-FEATURE-plan.md
Synthesis rules:
1. Use the existing plan file as the canonical structure. Preserve its section order, but add any missing required sections from the create-plan template rather than dropping generator content.
2. Identify common structure and tasks — higher confidence where drafts agree
3. Resolve conflicts using the spec and codebase patterns
4. Fill remaining [TBD] placeholders with synthesized content
5. Mark unresolved items as Open Questions
6. Respect file existence: label new files as "New: path/to/file"
7. Preserve and complete the Decision Log; if `--skip-interview` was used, include every autonomous decision with rationale, evidence, tradeoff, and risk/follow-up
8. Ensure all template sections are complete:
- Context & Goals, Scope & Non-Goals, Assumptions & Constraints
- Prerequisites, High-Level Approach, Technical Design (architecture/data/interfaces)
- Risks/Edge Cases, Testing & Validation, Open Questions
Update the plan file in place with the synthesized content.
Return a summary of key decisions made during synthesis.
The subagent will:
Delegate draft reading to the subagent — reading drafts yourself would consume your context. The subagent reads drafts, synthesizes, and returns a summary.
The subagent updated the plan file in Phase 5. Confirm the [TBD] placeholders have been filled.
If --skip-interview was used, also confirm ### Decision Log documents the autonomous decisions, their rationale, supporting evidence, tradeoffs, and risk/follow-up.
Spawn external reviewers on the plan file. Forward --max-rounds only when the user supplied an explicit command-level override:
--max-rounds <N> was passed to this command, forward that N.config.yaml and the CLI defaults remain authoritative for built-in and custom modes.CERBERUS_HOST=codex and CERBERUS_SESSION_ID=$CODEX_THREAD_ID are exported before spawning if the host variables are not already set; the command below does this automatically when CODEX_THREAD_ID is present and CERBERUS_HOST is unset or already codex.set +u; if [ -n "${CODEX_THREAD_ID:-}" ] || [ -n "${PLUGIN_ROOT:-}" ]; then host=codex; elif [ -n "${CLAUDE_SESSION_ID}" ] || [ -n "${CLAUDE_PLUGIN_ROOT}" ] || [ -n "${CLAUDE_SKILL_DIR}" ]; then host=claude; else host="${CERBERUS_HOST:-}"; if [ "$host" = claude-code ]; then host=claude; fi; fi; root="${CERBERUS_ROOT:-}"; if [ -z "$root" ] && [ "$host" = codex ]; then root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then cache_home="${HOME:-}"; [ -n "$cache_home" ] || cache_home="${USERPROFILE:-}"; if [ -n "$cache_home" ]; then cache_file="$cache_home/.codex/cerberus/sessions/$CODEX_THREAD_ID/plugin-root"; if [ -r "$cache_file" ]; then IFS= read -r root < "$cache_file" || true; fi; fi; fi; if [ -z "$root" ] && [ "$host" != codex ]; then root="${CLAUDE_PLUGIN_ROOT}"; [ -n "$root" ] || root="${PLUGIN_ROOT:-}"; fi; if [ -z "$root" ] && [ "$host" != codex ]; then skill_dir="${CLAUDE_SKILL_DIR}"; if [ -n "$skill_dir" ]; then root="$(cd "$skill_dir/../.." && pwd)"; fi; fi; [ -n "$root" ] || { echo "cerberus: plugin root not set; set CERBERUS_ROOT and retry" >&2; exit 127; }; bin="$root/bin/cerberus"; export CERBERUS_ROOT="$root"; claude_session="${CLAUDE_SESSION_ID}"; if [ "$host" = claude ]; then export CERBERUS_HOST=claude; elif [ "$host" = codex ]; then export CERBERUS_HOST=codex; fi; if [ "$host" = codex ] && [ -n "${CODEX_THREAD_ID:-}" ]; then export CERBERUS_HOST=codex CERBERUS_SESSION_ID="$CODEX_THREAD_ID"; elif [ "$host" = claude ] && [ -n "$claude_session" ]; then export CERBERUS_HOST=claude CERBERUS_SESSION_ID="${CERBERUS_SESSION_ID:-$claude_session}"; fi; command -v make >/dev/null 2>&1 || { echo "cerberus: make not found on PATH; install make and retry." >&2; exit 127; }; if ! make -q -C "$root" build >/dev/null 2>&1; then command -v go >/dev/null 2>&1 || { echo "cerberus: Go >= 1.22 not found on PATH; install Go and retry." >&2; exit 127; }; echo "cerberus: building... (this happens once after clone or upgrade)" >&2; start=$(date +%s); make -C "$root" build >&2 || exit $?; end=$(date +%s); echo "cerberus: build complete in $((end-start))s" >&2; fi; MODE_ARGS=(); if [ -n "${MODE:-}" ]; then MODE_ARGS=(--mode "$MODE"); fi; ROUND_ARGS=(); if [ -n "${MAX_ROUNDS:-}" ]; then ROUND_ARGS=(--max-rounds "$MAX_ROUNDS"); fi; "$bin" spawn-plan-review "${MODE_ARGS[@]}" "${ROUND_ARGS[@]}" docs/YYYY-MM-DD-FEATURE-plan.md
CRITICAL: After running the spawn command, STOP IMMEDIATELY. Do NOT poll, sleep, wait, or run any further commands. The Stop hook will automatically wait for reviewers and present their findings when you stop. Any attempt to manually check reviewer status will fail.
--skip-interview only skips Phase 0 spec-path questioning and the Phase 2 implementation interview. It does not skip the review gate.
During review refinement in skip-interview mode:
AskUserQuestion if the review gate cannot proceed without a human decision.IMPORTANT: Use the AskUserQuestion tool for ALL clarifying questions during review. Put findings + options in a single tool call. Plain text questions are not interactive.
Treat reviewer findings as a queue. Process in priority-first, breadth-first order:
Priority definitions:
**Review Findings Batch [N]** (Priority: P0)
Reviewers found 2 P0 issues and 4 P1 issues. Addressing P0s first:
1. [Section: Architecture] Unclear ownership boundary between services
- Options: [A] Service A owns, [B] Service B owns, [C] Shared ownership
2. [Section: Testing] No verification for backwards compatibility
- Options: [A] Add integration tests, [B] Manual verification, [C] Skip (accept risk)
---
Reply "enough detail" to stop, or "skip P2/P3" to focus only on blockers.
| Signal | Action |
|---|---|
| "enough detail" / "that's good" | Stop asking, mark remaining as Open Questions |
| "skip P2/P3" / "just fix blockers" | Only address P0/P1 |
| "you decide" | Pick safe fix, record in Assumptions & Constraints |
DO:
#L... anchors.Always ask for user input on:
OK to silently fix: Typos, formatting, and purely mechanical issues.
Use the gate's resolved round cap from explicit --max-rounds <N> or config.yaml/CLI defaults. Process findings in priority order regardless of mode name. If the cap is reached, record unresolved findings as Open Questions. --max-rounds 0 runs the initial review once, records its unresolved findings, and performs no refinement respawn.
When the plan passes review:
/create-tasks to generate execution artifacts:
--beads → Create Beads issues with dependencies for multi-agent parallelization