From deep-plan
This skill should be used when the user asks to 'deep plan', 'plan a phase deeply', 'run deep-plan', or wants CE-quality implementation planning after /gsd-discuss-phase. Bridges GSD context with code-grounded research, implementation units, test scenarios, and optional feasibility review. Produces GSD-compatible PLAN.md files.
How this skill is triggered — by the user, by Claude, or both
Slash command
/deep-plan:deep-planThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
<purpose>
fixtures/caveman/01-chat-fragment.mdfixtures/caveman/02-write-artifact.mdfixtures/caveman/03-feasibility-high.mdfixtures/caveman/04-askuserquestion-block.mdfixtures/caveman/05-mid-flight-pivot.mdfixtures/caveman/06-routing-decision.mdfixtures/scoring/01-haiku-small.mdfixtures/scoring/02-quality-bias.mdfixtures/scoring/03-opus-large.mdfixtures/scoring/04-borderline-equal.mdfixtures/scoring/05-advisory-trigger.mdfixtures/scoring/06-signals-override.mdfixtures/scoring/07-reduced-confidence.mdfixtures/scoring/08-borderline-hint.mdreferences/caveman-rule.mdreferences/ce-prompts.mdreferences/config.mdreferences/handoff-schema.mdreferences/intel-distill.mdreferences/intel-sources.mdUse this instead of /gsd-plan-phase when you want deeper code analysis before planning.
<when_to_use>
/gsd-discuss-phase has produced a CONTEXT.md for the target phaseStep 1 detects caveman and builds an override map for three v2 signals forcing full prose (see references/caveman-rule.md).
Caveman: optional plugin by Julius Brussee (MIT), installed separately.
<progress_protocol>
Deep-plan must be visually distinguishable from GSD and CE throughout execution. Follow these patterns at every step.
Opening banner — Display after phase is confirmed (end of Step 2). Open-bordered style matches GSD (no right border to misalign with long phase names):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Deep Plan — Phase {N}: {phase_name}
GSD context → CE research → Implementation plan
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Step headers — Display at the start of every step:
── deep-plan [{current}/{total}] {Step Name} ──────────
Total = 12 with --review, 11 without (feasibility review skipped). Both fractional steps (3.5 already-done check and 9.5 routing decision) are each counted as one task; their announce headers read [3.5/{total}] and [9.5/{total}]. Steps that announce headers: 3, 3.5, 4, 5, 6, 7, 8, 9, 9.5, 10, 11, 12 (skip 11 when --review is absent). Step 1 (Caveman Setup) and Step 2 (Parse Arguments) do their setup work silently and do not announce.
Detail lines — 1-2 lines after each header showing what was found/done. Use ✓/✗ for availability.
Task tracking — After phase confirmation, use TaskCreate to create all step tasks upfront (prefixed "Deep Plan:"). Mark each in_progress when starting, completed when done.
Subagent attribution — Before CE agent calls, state what deep-plan pre-fed and what CE will focus on. After return, summarize new findings count.
See references/progress-templates.md for full output examples per step.
</progress_protocol>
Detect caveman deterministically — do not guess from context:
CAVEMAN_INSTALLED=$(claude plugin list 2>/dev/null | grep -q "caveman@caveman" && echo yes || echo no)
If CAVEMAN_INSTALLED=yes, read references/caveman-rule.md and build an override map for four v2 signals requiring full prose: HIGH feasibility findings, AskUserQuestion blocks, mid-flight scope pivots, and routing-decision banner output (Step 9.5). If no, skip silently — no override map, no further caveman references this run.
Resolve deep_plan.model_routing config — once per run, fall back to defaults silently when absent and with a banner notice when malformed:
PLANNING_EXISTS=$(test -d .planning && echo yes || echo no)
GSD_TOOLS_EXISTS=$(test -f "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" && echo yes || echo no)
CONFIG_HAS_MODEL_ROUTING=$(node -e "
const fs = require('fs');
const path = process.cwd() + '/.planning/config.json';
try {
if (!fs.existsSync(path)) {
process.stdout.write('no');
process.exit(0);
}
const c = JSON.parse(fs.readFileSync(path, 'utf8'));
const block = c?.deep_plan?.model_routing;
process.stdout.write(block && typeof block === 'object' && !Array.isArray(block) ? 'yes' : 'no');
} catch (e) {
process.stdout.write('error');
}
" 2>/dev/null)
CONFIG_READ=$(node -e "
const fs = require('fs');
const path = process.cwd() + '/.planning/config.json';
const typeOf = (x) => x === null ? 'null' : (Array.isArray(x) ? 'array' : typeof x);
try {
if (!fs.existsSync(path)) {
console.log('{}');
console.log('');
process.exit(0);
}
const c = JSON.parse(fs.readFileSync(path, 'utf8'));
const block = c?.deep_plan?.model_routing ?? {};
if (block && typeof block === 'object' && !Array.isArray(block)) {
console.log(JSON.stringify(block));
console.log('');
} else {
console.log('{}');
console.log('config: used defaults for deep_plan.model_routing (malformed: expected object, got ' + typeOf(block) + ')');
}
} catch (e) {
console.log('{}');
console.log('config: malformed JSON, using all defaults');
}
" 2>/dev/null)
CONFIG_BLOCK=$(printf '%s\n' "$CONFIG_READ" | sed -n '1p')
CONFIG_READ_NOTICE=$(printf '%s\n' "$CONFIG_READ" | sed -n '2p')
If PLANNING_EXISTS=yes, GSD_TOOLS_EXISTS=yes, and CONFIG_HAS_MODEL_ROUTING=no, the model_routing block is missing. Read references/setup-wizard.md for: the inline missing-config trigger, the six-question first-run flow, text-mode fallback prompts, GSD profile verification, structured JSON write helper, and the exact deep_plan.model_routing schema to write. Run the inline setup wizard before resolving config for the rest of this deep-plan invocation. After the wizard writes .planning/config.json, re-run the CONFIG_READ snippet above so CONFIG_BLOCK reflects the newly written block.
If PLANNING_EXISTS=no or GSD_TOOLS_EXISTS=no, skip the inline wizard entirely and let Step 2's prerequisite gate print the existing actionable error. Do not create .planning/config.json outside an initialized GSD project.
If CONFIG_HAS_MODEL_ROUTING=error, do not run the wizard automatically. Preserve Phase 9 lenient behavior: use all defaults, keep CONFIG_READ_NOTICE, and point the user at /deep-plan-doctor for repair.
Read references/config.md for: the JSON schema, default values sourced from references/scoring.md, the deep-merge rules per D-08, lenient field-level fallback narrative per D-09, and the resolved-config object shape per D-12.
Apply the resolution algorithm from references/config.md: deep-merge CONFIG_BLOCK into the defaults sourced from references/scoring.md; include CONFIG_READ_NOTICE first when present; for each malformed field or out-of-range numeric override, fall back to the default and append a one-line banner notice (cap at 3 lines, summarize remainder as +N more, see /deep-plan-doctor). Compute _source per the rule in references/config.md ## Resolved-Config Object Shape: "defaults" when no schema leaves came from config, "config" when every schema leaf was provided and validated cleanly, "merged" when the user provided some fields and defaults backfilled the rest (or any field was rejected via lenient fallback).
Hold the resolved-config object in skill scope as resolved_config. Downstream steps consume it:
resolved_config.bias for the threshold map.resolved_config.weight_overrides.{formula, signals} and resolved_config.context_thresholds for any user-overridden scoring math.resolved_config.gsd_profile_at_setup for PLAN.md frontmatter.resolved_config.gsd_profile_at_setup to detect drift against current GSD profile.When resolved_config.pin is non-null, Step 9.5 bypasses scoring entirely (D-02) — the routing banner reads model={pin} pinned=true (scoring skipped) instead of the score breakdown.
Banner notices (one line per malformed field, max 3) ride the existing routing-decision banner exemption from caveman compression — no new caveman v2 signal is needed.
Enforced at: questions (Steps 2, 7), pivots (Step 8), routing decision (Step 9.5), feasibility (Step 11).
## Step 2: Parse Arguments and Auto-Detect PhaseBefore anything else in this step, check prerequisites:
Run three checks via Bash (run all three, collect failures, report together):
test -f "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs"claude plugin list 2>&1 | grep -q compound-engineering.planning/ exists: test -d .planning/If any failed, print every failure with its fix command.
Error format (only print lines for missing prerequisites):
deep-plan requires GSD. Install: see GSD Discord #getting-started
deep-plan requires Compound Engineering. Install: claude plugin marketplace add EveryInc/compound-engineering-plugin && claude plugin install compound-engineering
No .planning/ directory found. Run /gsd-new-project to initialize.
If GSD is missing, do not hard-stop immediately. GSD is commonly installed in another shell while the Claude Code session remains open.
Ask:
GSD is required before deep-plan can read phase context.
1. I installed GSD — retry checks
2. Show install steps and stop
3. Run /deep-plan-doctor --install after I fix it
When AskUserQuestion is available, use equivalent options:
Run: /deep-plan-doctor --install and stopIf the user chooses retry, re-run all three checks. If they now pass, continue silently. If GSD is still missing, show the same recovery prompt again, up to 3 retry attempts, then stop with the install note.
If CE or .planning/ is missing but GSD is present, stop after printing the missing prerequisite lines; those fixes have their own explicit commands/workflows and should not be retried inside /deep-plan.
If all pass, continue silently.
Extract from the invocation:
phase — the phase number (e.g., "18", "11.1")--review flag — run feasibility review after planning--skip-research flag — skip CE repo-research-analyst--text flag — use plain-text numbered lists instead of AskUserQuestionText mode detection (runs once, applies to all prompts):
Text mode is active if either condition is true:
--text flag was passed in argumentsworkflow.text_mode is true in GSD config:
TEXT_MODE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.text_mode 2>/dev/null)
Store result as text_mode (boolean). When active, all user prompts in this session use plain-text numbered lists instead of AskUserQuestion.
If no phase argument provided, auto-detect:
ROADMAP_STATE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" roadmap analyze 2>/dev/null)
Find the best candidate phase by priority:
If no candidate matches either priority, all phases already have plans:
All phases in roadmap have plans. Nothing to plan. Run /gsd-add-phase to add new work.
Stop execution.
Detection priority — why this order:
Has CONTEXT.md but no PLAN.md wins because the user explicitly ran discuss-phase to lock decisions; the next step is planning, and that's exactly what deep-plan does.No CONTEXT.md, no PLAN.md is the fallback for phases that need discuss-phase first; deep-plan suggests running it rather than planning blind.--review or /gsd-execute-phase to proceed.Scope-mismatch check (runs when phase was auto-detected):
Compute task_hint: any free-text args not consumed by phase number or known flags (--review, --skip-research, --text). Empty string if none.
Fire the scope-check if the phase was auto-detected AND (task_hint is non-empty OR the detected phase has no CONTEXT.md). Skip it otherwise (explicit phase arg, or happy path with CONTEXT.md and no hint) — fall straight through to the existing three-option prompt below.
If text_mode is active, present as a plain-text numbered list:
Detected Phase {N}: {phase_name}. Your request mentions: "{task_hint}"
How should this be scoped?
1. Plan Phase {N} as detected
2. Expand Phase {N} scope to include this work (runs /gsd-discuss-phase)
3. Insert a decimal hotfix phase like {N}.1 (runs /gsd-add-phase)
4. Route to /gsd-quick (tactical fix, no phase needed)
Type a number to choose. Parse response (number or free text). If invalid, re-prompt.
Otherwise, use AskUserQuestion with four options mirroring the list above.
Routing:
Run: /gsd-discuss-phase {N} "{task_hint}" and stop (no banner, no TaskCreate, no state writes)Run: /gsd-add-phase (decimal hotfix flow) and stopRun: /gsd-quick "{task_hint}" and stopIf text_mode is active, present as a plain-text numbered list instead of AskUserQuestion:
1. Yes, plan Phase {N}
2. Different phase
3. Run /gsd-discuss-phase {N} first
Type a number to choose:
Parse the user's response (number or free text describing their choice). If invalid, re-prompt.
Otherwise, use AskUserQuestion with options:
After phase confirmed:
--review, 12 with --review. The denominator counts every step that announces a [N/{total}] header: 3, 3.5, 4, 5, 6, 7, 8, 9, 9.5, 10, 12 (11 entries) without --review; add 11 (feasibility review) for the 12-entry --review total. Step 1 (Caveman Setup) and Step 2 (Parse Arguments) run silently and are not counted.
Announce: ── deep-plan [3/{total}] Loading GSD context ──
After reading, detail: CONTEXT.md {✓/✗} | RESEARCH.md {✓/✗} | ROADMAP.md {✓/✗}
INIT=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init plan-phase "$PHASE" 2>/dev/null)
Parse the JSON output for: phase_dir, padded_phase, phase_slug, has_context, has_research, context_path, research_path.
Required: Read CONTEXT.md from the phase directory. If CONTEXT.md does not exist:
Phase {N} has no CONTEXT.md. Run `/gsd-discuss-phase {N}` first to gather
implementation decisions, then re-run `/deep-plan {N}`.
Stop.
Optional reads (if they exist):
.planning/ROADMAP.md (goals, requirements, success criteria).planning/REQUIREMENTS.md for requirement definitionsCheck for existing plans: If PLAN.md files already exist for this phase:
If text_mode is active, present as a plain-text numbered list instead of AskUserQuestion:
1. Add another plan (increment plan number)
2. Replan from scratch (overwrite)
3. Cancel
Type a number to choose:
Parse the user's response (number or free text describing their choice). If invalid, re-prompt.
Otherwise, use AskUserQuestion with options:
Announce: ── deep-plan [3.5/{total}] Checking if work is already done ──
This step skips planning when the phase's success criteria are already satisfied by existing code (LIFE-02). Saves users from re-planning work that was implemented ad-hoc via /quick or other entry points.
Skip conditions:
has_plans=true from Step 2's init data → skip silently (already planned).roadmap get-phase is empty → skip silently (nothing to check against).Evidence gathering (per criterion):
met (all evidence found), partial (some evidence), not met (no evidence).Routing:
met: present summary table. Ask via AskUserQuestion (or numbered list in text_mode):
Yes, mark complete / No, plan anyway (work may be redundant) / Show evidence firstYes: Edit .planning/ROADMAP.md to flip [ ] → [x] for the phase line. Log: [step 3.5] Phase {N} marked complete based on existing code evidence. Exit deep-plan with handoff message.No: continue to Step 4.Show evidence first: print the evidence table, then re-prompt with first two options only.partial or not met: log [step 3.5] {met}/{total} criteria show evidence — continuing to plan and proceed to Step 4. Do not prompt.Caveman override: the AskUserQuestion in this step is a v2 signal — output the summary table and prompt in full prose regardless of caveman level. (Step 1 override map.)
## Step 4: Gather GSD IntelligenceAnnounce: ── deep-plan [4/{total}] Gathering codebase intelligence ──
After gathering, detail: Intel: {found_list} ({N}/5 files, {fresh/stale/none}) | Research: {found_list} ({warm/cold} start)
Read references/intel-sources.md for the full source list (intel/ files, research/ files, scope boundaries), staleness rules, the no-analysis fallback prompt, and the gsd_knowledge composition spec.
Check each source in order. Read what exists, skip what doesn't. If neither .planning/intel/ nor .planning/research/ exist, prompt the user per the reference (Continue anyway / Run /gsd-scan first).
After gathering, build the gsd_knowledge block per the schema in the reference. This block feeds Step 6 (CE warm-start prompt).
Announce: ── deep-plan [5/{total}] Building planning brief ──
After composing, detail: Locked decisions: {N} | Open questions: {N} | Seed files: {N}
Transform GSD artifacts into a structured planning brief. This brief serves two purposes: (1) it becomes context for CE research, and (2) it frames the implementation units.
From CONTEXT.md:
<domain> section → Problem frame and scope boundaries<decisions> locked items → Resolved questions (carry forward as-is)<decisions> "Claude's Discretion" items → Open questions for research to inform<code_context> → Seed files for repo-research-analyst<specifics> → Constraints and examples<deferred> → Explicit non-goals (scope boundaries)From phase RESEARCH.md (if exists):
From ROADMAP.md phase section:
Compose a 2-3 paragraph planning brief summarizing:
Announce: ── deep-plan [6/{total}] CE deep research ({warm/cold} start) ──
Pre-fed: {summary} → CE focusing on: integration points, gaps, risksNo GSD intel to pre-feed → CE exploring from scratchIf --skip-research was passed, skip to Step 7.
Decide warm vs cold: if gsd_knowledge block from Step 4 is non-empty → warm-start. Otherwise → cold-start.
Read references/ce-prompts.md for the full Task spawn body (warm + cold variants), confidence-tag rules, merge rules, and post-CE announce templates. Substitute {N}, {phase_name}, {planning_brief}, {gsd_knowledge block from Step 3}, and {files from code_context} from in-memory state, then spawn the agent.
After CE returns: apply the confidence tags + merge rules from the reference. Display the post-CE announce line per warm/cold variant.
## Step 7: Resolve Planning QuestionsAnnounce: ── deep-plan [7/{total}] Resolving planning questions ──
After resolving, detail: Auto-resolved: {N} | Asking user: {N} | Deferred: {N}
Build a question list from:
For each question:
If text_mode is active, present each question as a plain-text numbered list instead of AskUserQuestion. For fixed-option questions:
{Question text}
1. {option 1}
2. {option 2}
...
Type a number to choose:
For open-ended questions, prompt for free text input. Parse the user's response (number or free text describing their choice). If invalid, re-prompt.
Otherwise, use AskUserQuestion for each question with the appropriate options.
Keep user questions focused and minimal (1-2 max). Don't ask about things the user already decided in CONTEXT.md.
Caveman override: If override map active (Step 1), output question blocks in full prose.
## Step 8: Structure Implementation UnitsAnnounce: ── deep-plan [8/{total}] Structuring implementation units ──
After structuring, detail: Units: {N} | Test scenarios: {N} | Must-haves: {truths}/{artifacts}/{links}
Break the phase work into implementation units. Each unit represents one meaningful atomic change.
For each unit, define:
Generate GSD must_haves from test scenarios:
truths → one truth per critical test scenario ("User can X", "Y produces Z")artifacts → one artifact per created/modified file with a searchable contains tokenkey_links → traceability from source to destination with search patternsOrdering: Dependencies first. Pure functions/constants before stateful units (hooks, classes, services) before composition layers (components, handlers, modules). Infrastructure before features.
Caveman override: If scope pivot detected (Step 1 override map), output pivot reasoning in full prose.
## Step 9: Write GSD PLAN.mdRead references/plan-template.md for: numeric plan-numbering rules, the file-path convention, substitution-variable table, and the full PLAN.md template body (frontmatter + objective + execution_context + context + tasks + threat_model + verification + success_criteria + output).
Substitute live values per the variable table in the reference. Write to .planning/phases/{padded_phase}-{slug}/{padded_phase}-{MM}-PLAN.md.
For executor_model and model_recommendation placeholders, write the frontmatter block in the template shape but leave routing values for Step 9.5 to fill. Step 9.5 owns the routing decision and must replace those placeholders before Step 10 validation.
Path-portability rule: tilde paths only (@~/...); never @$HOME/... (PORT-01).
Announce: ── deep-plan [9/{total}] Plan written ──
Detail: .planning/phases/{phase_dir}/{padded_phase}-{MM}-PLAN.md — Units: {N} | Test scenarios: {N} | Must-haves: {truths} truths, {artifacts} artifacts, {links} links
Read references/scoring.md for: signal extraction heuristics, the three perspective formulas, the byte-ratio table, the threshold map, the half-up rounding helper with Number.EPSILON correction, the banner format with machine-readable trailer, and the worked-examples / golden-fixture index.
This step always runs, including when --skip-research was passed. Missing CE-derived signals fall back to 0 per D-08 — novel and unknown_deps default to 0 when feasibility/research output is absent, and the banner appends (reduced confidence: --skip-research used).
Extract the 8 signals from in-memory pipeline state:
units array produced by Step 8 and the must_haves object produced by Step 8.references/scoring.md ## Signal Extraction:
files_modified, deduplicate paths across all unit.files arrays (D-15) — same file referenced by 3 units counts once.checkpoints, parse CONTEXT.md for the <questions> block. If absent, default to 0 and remember to annotate the banner.<signals> override block (D-13). Parse the block by locating <signals> and </signals> markers in the body (NOT in frontmatter) and iterating flat key: value lines between them — DO NOT reuse the frontmatter-only yaml_get from tests/eval-caveman-rule.sh or tests/eval-scoring.sh. That helper is gated on --- fences (it tracks a frontmatter state machine and exits at the second ---), so it returns empty for any key inside a body-level <signals> block. Use a dedicated extractor: capture lines between the <signals> and </signals> markers, then split each line on the first : and trim. Validate each value matches ^[0-9]+$ (non-negative integer); reject non-numeric or negative values per signal and remember to annotate the banner with (<signals> override rejected for {key}: not a non-negative integer).<signals> REPLACES the auto value; missing keys leave the auto value in place.Compute the three perspectives and the combined score per the formulas in references/scoring.md. Do NOT inline the formulas here — call them out by name (volume, structure, risk, combined) and trust the reference doc for the math.
Apply the threshold map from references/scoring.md to the rounded combined score to determine the recommended model. Use >= comparison (locked rule from Pitfall 4 mitigation). Read resolved_config.bias from the resolved-config object set in Step 1 (per references/config.md ## Resolved-Config Object Shape) — defaults to balanced when config is absent (_source: "defaults").
Estimate input tokens by walking the deduplicated files_modified set, calling wc -c (or equivalent) on each path, and dividing by the per-extension byte ratio from the table in references/scoring.md. Sum the per-file estimates. The default ratio for unknown extensions is 3.0 — conservative high, biases toward triggering the advisory rather than missing it.
Determine the phase-split advisory: strict AND gate (D-01) — input_tokens > 180000 AND combined >= opus_thresholds[bias]. Determine the borderline hint (D-12): if combined is within ±10% of either threshold, prepare the appropriate bias-bump suggestion.
Build the in-memory routing-decision object (D-06) with snake_case field names per the convention in references/scoring.md:
volume_score, structure_score, risk_score, combined_score — rounded to 1 decimal via the half-up helperrecommended_model — one of opus, sonnet, haikubias — the active bias used for threshold mappingthreshold — the threshold value compared against (e.g., 12 for opus/balanced)input_tokens_estimate — integeradvisory — booleanborderline_hint — string or nullreduced_confidence — boolean (true when --skip-research was passed)executor_model — the model downstream executors should use after pins and auto-mode budget caps are appliedselection_reason — one of recommended, pinned, gsd_profile_cap, or no_gsd_profilesignals — the merged signal values (post-override)signal_overrides_rejected — array of any <signals> keys whose values were rejected for invalidityDetermine executor_model from the same routing decision object:
resolved_config.pin is non-null, set executor_model = resolved_config.pin and selection_reason = "pinned".resolved_config.mode = "auto", read the current GSD profile:
GSD_PROFILE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get workflow.profile 2>/dev/null)
Apply the budget-cap map exactly: quality -> opus, balanced -> sonnet, budget -> sonnet.
GSD_PROFILE is empty, keep executor_model = recommended_model and set selection_reason = "no_gsd_profile".recommended_model is above the mapped cap, set executor_model to the cap and selection_reason = "gsd_profile_cap".recommended_model is at or below the cap, keep executor_model = recommended_model and selection_reason = "recommended".executor_model = recommended_model and selection_reason = "recommended".Use model ordering haiku < sonnet < opus for cap comparison. A cap never upgrades a lower recommendation.
Hold this object in scope. Do NOT write it to a sidecar file (D-06). Immediately update the PLAN.md written in Step 9 so its frontmatter contains:
executor_model: "{executor_model}"
model_recommendation:
recommended_model: "{recommended_model}"
executor_model: "{executor_model}"
selection_reason: "{selection_reason}"
bias: "{bias}"
threshold: {threshold}
scores:
volume: {volume_score}
structure: {structure_score}
risk: {risk_score}
combined: {combined_score}
input_tokens_estimate: {input_tokens_estimate}
advisory: {advisory}
reduced_confidence: {reduced_confidence}
The frontmatter block and the routing banner must be sourced from the same in-memory routing decision. Step 10 validation runs only after this frontmatter update.
Append routing telemetry after the frontmatter update succeeds. Use structured JSON parse/update/write on .planning/config.json; never overwrite unrelated keys. Append one object to _telemetry.decisions[] and preserve all existing entries:
{
"timestamp": "{ISO-8601 timestamp}",
"phase_id": "{padded_phase}-{slug}",
"plan_path": "{path to written PLAN.md}",
"recommended_model": "{recommended_model}",
"executor_model": "{executor_model}",
"selection_reason": "{selection_reason}",
"override_flag": {override_flag},
"scores": {
"volume": {volume_score},
"structure": {structure_score},
"risk": {risk_score},
"combined": {combined_score}
},
"bias": "{bias}",
"threshold": {threshold},
"input_tokens_estimate": {input_tokens_estimate},
"advisory": {advisory},
"reduced_confidence": {reduced_confidence}
}
If .planning/config.json is malformed, do not rewrite it. Emit a warning that telemetry was skipped and point the user at /deep-plan-doctor. Missing _telemetry or _telemetry.decisions should be created; existing decision entries must remain intact.
Emit the banner using the format specified in references/scoring.md ## Banner Format. The banner has 3 required lines plus optional advisory / borderline / reduced-confidence lines plus the machine-readable trailer comment. The full banner is reproduced below for verification (per success criterion #5 — three perspective scores visible):
── deep-plan [9.5/{total}] Routing decision ──
Volume: {V.V} | Structure: {S.S} | Risk: {R.R} → Combined: {C.C}
Recommendation: {model} ({bias} bias, threshold {T})
{advisory line if D-01 triggered}
{borderline hint if D-12 triggered}
{(reduced confidence: --skip-research used) if applicable}
<!-- DEEP_PLAN_ROUTING: model={model} combined={C.C} volume={V.V} structure={S.S} risk={R.R} bias={bias} threshold={T} advisory={true|false} -->
Phase-split advisory mode-aware behavior (D-02):
When advisory: true, behavior depends on the active mode (locked for Phase 9 to provide; default confirm until then):
If mode: auto, render the advisory line as part of the banner and continue planning uninterrupted.
If text_mode is active (per Step 2 detection), present as a plain-text numbered list:
{advisory message — D-03 diagnostic detail with input tokens, combined score, top 2 contributing signals by weighted contribution}
1. Continue with current scope
2. Stop and split this phase manually
Type a number to choose. Parse response (number or free text). If invalid, re-prompt.
Otherwise (mode: confirm, no --text flag), use AskUserQuestion with two options mirroring the list above.
If the user chooses "Stop and split this phase manually", print Run: /gsd-add-phase to split this phase and stop the deep-plan run cleanly. The PLAN.md from Step 9 has already been written — the user can revisit it after splitting.
Announce: ── deep-plan [9.5/{total}] Routing decision ──
Detail: Volume: {V} | Structure: {S} | Risk: {R} → Combined: {C} | Model: {model} ({bias} bias){advisory_suffix}
Caveman override: routing-decision banner is always full prose regardless of caveman mode (Step 1 override map). New v2 signal — see references/caveman-rule.md Signal: Routing Decision Banner.
Announce: ── deep-plan [10/{total}] Validating plan structure ──
Detail: Spawning plan-validator against PLAN.md...
This step always runs. It catches format errors that would break gsd-executor — frontmatter schema, task XML structure, must_haves validity, and @-reference resolution.
Validation lifecycle: deep-plan validates plans twice when --review is active:
Read references/validation-flow.md for the full Task spawn body, FAIL/WARN/PASS result routing, and retry semantics. Substitute {path to written PLAN.md} and {project root path} from in-memory state.
Announce (after validation): ── deep-plan [10/{total}] Validation complete ──
Detail: Result: {PASS/WARN/FAIL} | Errors: {N} | Warnings: {N}
Announce (before review): ── deep-plan [11/{total}] Feasibility review ──
Detail: Launching feasibility-reviewer against PLAN.md...
If --review flag was passed:
Select the feasibility reviewer model explicitly:
feasibility_model="opus"
Explicit --review always forces the feasibility reviewer model to opus regardless of inherited model, executor_model, or GSD profile cap. Quality wins because the user opted into a feasibility pass. If a future non-explicit feasibility path is added, it may set feasibility_model="$executor_model" from the Step 9.5 routing decision instead.
Spawn the CE feasibility reviewer with the Agent tool's model parameter:
Agent(
subagent_type="compound-engineering:ce-feasibility-reviewer",
model: "$feasibility_model",
description="Feasibility review for {path to written PLAN.md}",
prompt="Review this plan for feasibility — will the proposed technical approach survive contact with reality?
Plan: {path to written PLAN.md}
Codebase: {project root}
Focus on:
1. Will the implementation order work given actual code dependencies?
2. Are there build/deployment issues the plan misses?
3. Are file paths and code references accurate?
4. Are the risks realistic and mitigations sufficient?
Be critical. Flag anything that would fail during implementation."
)
Route findings by severity:
HIGH severity findings — auto-revise:
The user already opted into --review; HIGH findings exist precisely to trigger revision. Skip the permission prompt and revise automatically.
[step 11] HIGH finding(s) detected — auto-revising plan: {brief summary}pre_revision_plan variable before the Edit call so revert is possible if validation persistently fails.[step 11] Auto-revision validated — proceeding.MODERATE severity findings — surface as warnings, do not block:
[step 11] {N} MODERATE finding(s) — surfaced as warnings, not blocking.LOW severity findings — summarize briefly:
Announce (after review): ── deep-plan [11/{total}] Feasibility review complete ──
Detail: {N} findings: {high} HIGH | {moderate} MODERATE | {low} LOW
Caveman override: If any HIGH finding present (Step 1 override map), output entire feasibility review in full prose.
## Step 12: HandoffAnnounce: ── deep-plan [12/{total}] Complete ──
Mark all remaining Deep Plan tasks as completed.
Display summary:
## Deep Plan Complete
**Phase:** {N} — {phase_name}
**Plan:** {padded_phase}-{MM}-PLAN.md
**Units:** {count} implementation units
**Test scenarios:** {count} across all units
**Must-haves:** {truths_count} truths, {artifacts_count} artifacts, {links_count} key links
**Validation:** {PASS/WARN/FAIL} ({error_count} errors, {warning_count} warnings)
{if review: **Feasibility:** {findings_summary}}
**Next:** Run `/gsd-execute-phase {N}` to execute this plan.
<success_criteria>
── deep-plan [N/M] header with detail linesProvides a checklist for code reviews covering functionality, security, performance, maintainability, tests, and quality. Use for pull requests, audits, team standards, and developer training.
npx claudepluginhub schylerchase/deep-plan-plugin --plugin deep-plan