Plan Chunks Skill (Orchestrator)
SkillDev toolsThis skill should be used when the user asks to "plan chunks", "break this down", "plan the implementation", or when a story has status planning and needs implementation details before building. Required before any story can be implemented. Transforms story sparks into detailed chunk-by-chunk implementation plans with full technical specifics, file lists, and risk analysis. Supports parallel planning of multiple stories via batch mode.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Plan Chunks Skill (Orchestrator) skill
What this skill tells your AI
The instructions your AI receives, as published by drobins25/craft in skills/plan-chunks/SKILL.md and read by ahel’s review.
You are the orchestrator coordinating story planning. The plan-chunks-agent does the heavy lifting — deep codebase research and detailed chunk planning in one autonomous pass. Your job is to gather context, launch the right agent(s), triage concerns with the user, and write the approved plans to story files.
Single story: Launch one agent, triage interactively, approve, write. Multiple stories: Launch parallel agents, batch triage, approve each, write all.
CRITICAL: Never auto-invoke this skill. The user must have explicitly chosen to plan — via a command, skill, or direct request. If a story needs planning, inform the user and let them decide when to plan.
When This Activates
- During
/craft:cycle-designwhen user chooses to plan a story - During
/craft:story-newwhen user wants full planning - Before
/craft:story-implementif story is stillstatus: planning - User explicitly asks to "plan chunks" or "break this down"
- When
MODE: batchis passed, plans all stories in the cycle in parallel
This skill is REQUIRED before implementation. Stories with status: planning cannot be implemented until this runs.
Orchestrator Context
The orchestrator may pass enriched args with labeled fields. Parse these to skip rediscovery:
STORY:story name — use to locate story file if path ambiguousCYCLE:cycle directory name — skip cycle detectionCYCLE_GOAL:goal from cycle.yaml — include in agent promptSIBLINGS:comma-separated story names — use in Phase 0.1b instead of scanningAPPROACH:implementation approach from discussion — seed agentDECISIONS:key decisions from discussion — seed agentKEY_FILES:important files from discussion — seed agentDEPTH:planning depth (creative/smart/spark) — adjusts triage thoroughnessMODE:batchtriggers multi-story parallel planning
Fallback: Args may be just a file path with no fields. All phases must work without enriched args.
Your Posture: Opinionated Partner
You're a senior engineer advising on implementation, not offering a menu.
Filter your options through:
- What's the correct way to implement this?
- What would a quality-focused team do?
- What serves the end user best?
When presenting approaches:
- If one way is clearly correct → State it. Don't offer inferior alternatives.
- If there are genuine tradeoffs → Present options with your recommendation
- If something is technically possible but compromises quality → Don't offer it
Simple is often correct. Complex isn't better by default. The goal is right, not hard.
Bad: "We could do A (janky) or B (correct). Pick one." Good: "We should do B - here's why. Any concerns?"
The user chose Craft because they want quality. Use your judgment to deliver it.
Phase 0: Gather Context & Determine Mode
0.1 Gather Launch Context
Read the story file path from args or context. Verify the file exists. Identify the cycle directory (if the story is in a cycle) or note it's a backlog story.
Derive project root from the story file path — strip everything after /.craft/. For example:
- Story at
/repo/apps/craftsman/.craft/cycles/01/stories/foo.md→ project root is/repo/apps/craftsman/ - Story at
/repo/.craft/backlog/foo.md→ project root is/repo/
Do NOT use $CRAFT_PROJECT_ROOT as the project root — in monorepos it may point to the monorepo root, not the sub-project containing the story. Always derive from the story file path.
0.1b Gather Sibling Context (Smart)
Skip if: Story is in backlog (no cycle context).
If args include SIBLINGS:, use that list instead of scanning. Read only those named stories for relevance checks.
Otherwise, scan sibling stories in the cycle for relevance (file path overlap, keyword overlap, component overlap). For related siblings, extract files, decisions, and overlap areas. If no relevant siblings, note: "No relevant siblings — stories appear unrelated."
Details: Read
${CLAUDE_PLUGIN_ROOT}/skills/plan-chunks/references/research-integration.mdfor the full sibling context gathering process (relevance heuristics table, extraction template, context block format).
0.2 Determine Planning Mode
Check args and environment to determine which planning path to follow:
Single-story planning (no MODE: batch in args):
- Default for all existing invocations (7+ commands pass single story paths)
- Always uses plan-chunks-agent via Task tool
- Interactive triage with user after agent completes
- → Proceed to Single-Story Planning below
Multi-story parallel planning (MODE: batch in args):
- Triggered by "Plan all stories" option in cycle-design/cycle-start
- Requires
CYCLE:arg — the cycle directory name - Check
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMSenv var for orchestration mode:- If set to
1→ agent teams path (primary) - Otherwise → Task subagent batches (fallback)
- If set to
- Parallelism is determined by the story dependency graph (M-1b) — independent stories plan in parallel, dependent chains plan sequentially
- Log mode: "Planning mode: agent teams" or "Planning mode: subagents (fallback)"
- → Proceed to Multi-Story Planning below
Phase 0.4: Content Spark Prerequisite Check
Skip if: Autonomous mode (invoked from craft:story-implement-auto).
Skip if: Batch mode (MODE: batch) - routes directly to Multi-Story Planning which has its own content-spark check at M-1 step 6.
Read the story file. Check whether a ## Content Direction section exists with non-empty content (not just the heading).
If missing: The story hasn't been through content-spark yet. Use AskUserQuestion:
question: "This story has no Content Direction yet. Content-spark surfaces assumptions before planning - run it first?"
header: "Prerequisite"
options:
- label: "Run content-spark first (Recommended)"
description: "Surfaces content assumptions so chunk planning is grounded"
- label: "Skip and plan anyway"
description: "Plan without content direction - chunks may make content assumptions"
If "Run content-spark first": Read and execute the logic inline (same pattern story-new uses - avoids the chain-break that nested Skill invocation causes):
Read "${CLAUDE_PLUGIN_ROOT}/commands/references/content-spark-inline.md"
Execute the phases described in that file against the current story.
After it completes, continue to Phase 0.45. If "Skip and plan anyway": Continue to Phase 0.45.
If present: Continue to Phase 0.45.
Phase 0.45: Alignment Gate
Skip if: Story frontmatter has alignment: complete AND the story contains an ## Alignment section (the receipt the check writes). If the flag says complete but the receipt is missing, the check was skipped or predates the receipt - treat it as pending.
Skip if: Autonomous mode (invoked from craft:story-implement-auto).
Read the story file's alignment frontmatter field.
If alignment: pending (or field missing): The story hasn't been through the codebase alignment check. This check surfaces product questions that only the user can answer - conflicts with existing code, adjacencies where the user might want the same change applied, and assumptions the codebase contradicts.
Read ${CLAUDE_PLUGIN_ROOT}/commands/references/alignment-check.md and follow the alignment loop:
- Spawn an Explore agent to investigate the codebase
- Surface genuine product questions via AskUserQuestion
- If answers expand scope, use SendMessage to the same agent for follow-up
- Loop until zero unasked product questions remain
- Record the
## Alignmentreceipt in the story and setalignment: completein the frontmatter
Batch mode (MODE: batch): Flag stories with alignment: pending during triage. Ask the user whether to run alignment checks interactively first or let agents proceed with best judgment. See ${CLAUDE_PLUGIN_ROOT}/commands/references/alignment-check.md "Batch Planning" section.
If alignment: complete: Continue to Phase 0.46.
Phase 0.46: Creative Spark Prerequisite Check
Skip if: Autonomous mode (invoked from craft:story-implement-auto).
Skip if: Batch mode (MODE: batch) - batch flow surfaces creative-spark concerns during triage instead.
Skip if: Story already has a populated ## Visual Direction section (creative-spark already ran). For type: ui, "populated" means a populated Element Binding Table — every region named in the wireframe has a row, and no TBD for a token that already exists in tokens.yaml (TBD is allowed only for a token not yet minted) — not merely non-empty prose.
Read the story file's frontmatter type field. Smart-default the prompt based on type:
For type: ui — Recommend running creative-spark (UI stories benefit from visual riffing before chunks lock the implementation):
question: "Want to riff visual options before planning chunks?"
header: "Prerequisite"
options:
- label: "Yes, riff with creative-spark (Recommended)"
description: "Generates 2-3 visual directions with vibe/layout/motion. Grounds chunk planning in a chosen direction."
- label: "Skip - I know what I want"
description: "Plan straight to chunks. Creative-spark is still reachable later at chunk-approval time."
For type: technical, type: content, or any non-UI type (or missing type) — Default to Skip:
question: "Want to riff visual options before planning chunks?"
header: "Prerequisite"
options:
- label: "Skip - not a UI story (Recommended)"
description: "This story is technical/content - visual riffing isn't applicable. Plan straight to chunks."
- label: "Yes, riff anyway"
description: "Some technical stories have UI surface - run creative-spark if relevant."
If "Yes" (either path):
⛔ DO NOT invoke creative-spark via the Skill tool (chain-break risk). Instead, Read and execute the inline reference:
Read "${CLAUDE_PLUGIN_ROOT}/commands/references/creative-spark-inline.md"
Execute the creative-spark logic against the current story file.
After creative-spark completes, the story will have a ## Visual Direction section with the chosen direction's vibe, feel, inspiration, motion, and the Element Binding Table of per-element token assignments. Continue to Phase 0.5.
If "Skip": Continue to Phase 0.5.
Phase 0.5: Direction Confirmation Gate
Skip if: Args contain DIRECTION_CONFIRMED: true (caller already confirmed with user).
Skip if: Autonomous mode (invoked from craft:story-implement-auto).
Otherwise: Read the story file's ## Spark section. Present it to the user:
"Before I plan the implementation, let's confirm the direction:
[Story Title] [Spark content]"
Use AskUserQuestion: question: "Ready to plan this story?" header: "Confirm" options: - label: "Yes, plan this" description: "Direction is right — proceed to chunk planning" - label: "Explore creatively first" description: "I want to explore options before committing to a direction" - label: "Adjust the scope" description: "I want to refine the spark before planning"
If "Yes, plan this": Proceed to planning. If "Explore creatively first": Stop planning. The user will explore on their own terms. If "Adjust the scope": Discuss with the user. When they confirm the revised direction, update the spark and re-present this gate.
Batch mode (MODE: batch): Present all story sparks as a summary table, then one AskUserQuestion for the batch. Same skip logic - if DIRECTION_CONFIRMED: true, skip the gate.
"Planning [N] stories in [Cycle Name]:
Story Spark [name] [first sentence of spark] [name] [first sentence of spark] ..."
Use AskUserQuestion:
question: "Ready to plan all [N] stories?"
options:
- label: "Yes, plan all"
description: "Directions look right - proceed to parallel planning"
- label: "Review individually"
description: "I want to confirm each story's direction separately"
- label: "Exclude some stories"
description: "Remove stories from this planning batch"
If "Review individually": Present Phase 0.5 gate for each story sequentially (single-story pattern). If "Exclude some stories": Ask which to exclude, remove from batch, then proceed with remaining.
Single-Story Planning
This is the default path for all existing invocations. The plan-chunks-agent does research + planning autonomously, writes the story file directly, then returns a lightweight concerns summary. You triage the concerns with the user and approve or adjust the agent-written file.
S-1: Launch Planning Agent
INVOKE the plan-chunks-agent using the Task tool with subagent_type: "craft:plan-chunks-agent".
Agent prompt template: Read
${CLAUDE_PLUGIN_ROOT}/skills/plan-chunks/references/research-integration.mdfor the full agent launch prompt with scope notes.
Include in the prompt:
-
Story file path (full path)
-
Cycle directory (path, or 'backlog' if not in cycle)
-
Project root (derived from story path — parent of
.craft/) -
Plugin root:
PLUGIN_ROOT: ${CLAUDE_PLUGIN_ROOT}— inject the resolved value. This skill body resolves${CLAUDE_PLUGIN_ROOT}; the subagent CANNOT (it is empty in a Task shell), so the agent needs it injected to reach plugin-internal scripts like the Living Map runner. -
FIRST ACTION block (the map, pre-computed) — derive the scope directories yourself at dispatch time: collect the parent directories of the files the story names (Likely Files,
KEY_FILES:, scope section), keep the few most relevant. Emit LITERAL ready-to-run commands directly under the PLUGIN_ROOT line:**FIRST ACTION — before reading any source file, pull your read plan:** [resolved PLUGIN_ROOT]/scripts/map/map-run.sh assemble [dir-1] --root [project root] [resolved PLUGIN_ROOT]/scripts/map/map-run.sh assemble [dir-2] --root [project root] Each slice line ends in [off=N,lim=M] — issue those ranged Reads at the narrowest useful span; never open a whole annotated file. An empty or floored slice for a directory = orient that area normally.Pre-compute everything — resolved paths, real directories. The agent must never have to translate concepts into directories or assemble the command itself; derivation steps are where compliance dies (field-verified 2026-07-03: the map mandate in the agent's own instructions lost to seeded dispatch context; a literal procedure in the dispatch prompt achieved full compliance). If the story names no files at all, omit the block — the agent's own orientation step is the fallback.
-
Sibling context from Phase 0.1b
-
Cycle goal (from
CYCLE_GOAL:arg or read from cycle.yaml) -
Content Direction (if the story has a
## Content Directionsection — read it and include the full text in the agent prompt. This tells the agent WHAT content the feature contains, so chunk planning can reference specific items, labels, and data shapes rather than guessing.)
If args include APPROACH:, DECISIONS:, or KEY_FILES:, add to the agent prompt: "Starting context from orchestrator — validate it THROUGH the map slice's ranged reads, then deepen. Provided context means read NARROWER, never skip orientation — the FIRST ACTION above still runs first:\n APPROACH: [value]\n DECISIONS: [value]\n KEY_FILES: [value]" (KEY_FILES also feed the FIRST ACTION block's directory derivation.)
CRITICAL: Include the scope note: "SCOPE ALL SEARCHES to the project root. Do NOT search the monorepo root or parent directories. Use the project root as the path parameter for ALL Glob and Grep calls."
CRITICAL: Include the story-write instruction: "After planning, WRITE the updated story file directly using the Write tool. Keep status: planning — the orchestrator handles approval. Then return ONLY your concerns summary as your final output. Do NOT include chunks or implementation details in your text output — those are in the file."
S-2: Receive & Validate Agent Output
Step 0 - PLAN FORK check:
If the agent's output is a ## PLAN FORK report instead of a concerns summary, the agent hit a two-plans question only the user can answer. Do NOT validate or triage yet:
- Read
${CLAUDE_PLUGIN_ROOT}/commands/references/auq-grammar.mdand mirror the fork gate it models - the exemplar carries the whole grammar (question field, option shapes, header chip); mirror it rather than reconstructing it. Then surface ONE AskUserQuestion for the fork. - Return the answer to the planning agent. If a visible agent ID is in hand (background spawns surface one in the result), SendMessage it - addressed by that ID, never the description: "Fork resolved: [chosen branch]. Continue planning." A synchronous spawn exposes no address: re-launch S-1 with the fork resolution included in the prompt instead. Never guess at an address.
- When the agent returns its concerns summary, proceed with Step 1 below as normal.
The agent returns a lightweight concerns summary (~200-400 tokens) and has already written the story file with full planning detail. Run the full validation checklist on both artifacts before proceeding to triage.
Step 1 - Validate the concerns summary (agent's text output):
- Output is non-empty
## Overviewsection present with story file path, chunk count, file count## Flagged Concernsand## Decisions Madetables present
Step 2 - Validate story file structure (agent's primary artifact):
Read the story file path from the Story file: field in the Overview. Run ALL checks - do not stop at the first failure. Collect every failure into a numbered list.
| # | Check | How to verify | Failure text |
|---|---|---|---|
| 1 | ## Chunks section exists | Grep for ^## Chunks heading followed by at least one ### Chunk sub-heading | "No ## Chunks section - agent did not write the plan" |
| 2 | chunks_total in frontmatter is 2-7 | Read frontmatter, parse chunks_total as integer, verify 2 <= N <= 7 | "chunks_total is [N] - must be 2-7 (got [actual])" |
| 3 | ## The Pitch section has content + conditions table | Grep for ^## The Pitch heading. Read lines until the next ## heading. Verify a non-empty sell paragraph AND a conditions table (` | Condition |
| 3b | ## Investigation section has content | Grep for ^## Investigation heading. Read lines until the next ## heading. Verify at least 5 non-empty lines of narrative | "## Investigation section is missing or empty - the plan has no research narrative" |
| 4 | ## Acceptance section has detailed criteria | Grep for ^## Acceptance heading. Read lines until the next ## heading. Verify the section contains at least 3 bullet points (lines starting with - ) - rough acceptance from the creative phase typically has 2-3 vague items; a properly refined section has 5+ specific items | "## Acceptance section appears unrefined - only [N] items found (expected 3+)" |
| 5 | Each chunk has required sub-sections | For each ### Chunk N: heading, verify the presence of **Goal:**, **Files:**, **Contracts:**, and **Test cases:** before the next ### Chunk or end of file | "Chunk [N] is missing [Goal/Files/Contracts/Test cases]" |
| 5b | Contract lines carry receipts | For each line under **Contracts:** (lines starting - ), verify it contains a bracketed receipt: [verified:, [owner:, [investigation:, [visual-source:, or [defines] | "Chunk [N] has receipt-less contract lines - every contract carries evidence or goes to the conditions table" |
| 5c | Visual bindings cover the Element Binding Table (UI/styling stories) | If the story changes rendered styling (a chunk's Files include component/style/template files, or frontmatter type: ui), read the ## Visual Direction Element Binding Table. For each non-TBD row, verify some chunk's **Contracts:** carries a [visual-source:] line naming that Part/Role. A story with no styling change is exempt; a styling story with no Element Binding Table, or with a non-TBD row no chunk binds, FAILS this check (as with any structural failure, the user may still choose Proceed anyway at triage) | "Visual binding incomplete - Element Binding Table row(s) [list] are not bound by any chunk's [visual-source:] Contract; the implementer could assign any valid token and pass. Bind each row or mark it TBD" |
| 6 | Each chunk's Done When asserts a green tree | For each ### Chunk N: heading, read the **Done When:** checklist. At least one criterion must assert a compilable, test-passing state ("build passes", "all tests pass", "no compile errors"). Exempt: a chunk whose Files entries are all read-only, or whose Goal explicitly states no source files are modified (docs-only) | "Chunk [N] has no green-tree Done When criterion - every chunk must leave the project compiling with tests passing; a plan that defers compilation across chunk boundaries is invalid" |
| 7 | ## Acceptance Pre-Flight receipt present, no unreachable vehicles | Grep for ^## Acceptance Pre-Flight heading. If the section is entirely absent, fail with the missing-section text. Read its table (` | Acceptance vehicle |
| 8 | Risk tag comments name a mechanism, not a bare threshold | Applies only when the story has a ## Risk Tags section (absent section passes - tags are optional). This is grep+read logic, not a single regex. Within the section's risk_tags: YAML block, take each tag line (starts with - ) and extract ONLY the text after the first # on that line - the comment. Tag names and YAML structure are never scanned. In the extracted comment, detect a threshold token: [0-9]+px / [0-9]+pt / [0-9]+rem, or a comparison (>=, <=, >, <) adjacent to a number. If no threshold token, the line passes regardless of length or wording. If a threshold is present, require at least one mechanism/verification connective in the same comment: via, through, instead of, not min-height, extend/extended, hit area, padding, pseudo-element, verify/verified, or a citation of a project locked rule (cite/rule). Threshold with no connective -> fail. Applies only to plans produced after this gate shipped - legacy plans never re-triage | "Risk tag [tag-name] carries a bare threshold ('[comment text]') - a threshold as the instruction gets implemented in the cheapest literal way; the comment must name the implementation mechanism (or cite a locked rule), with the threshold only as its verification clause (see skills/plan-chunks/references/chunk-format-guide.md, section Risk Tag Authoring Rule)" |
Step 3 - Route based on validation result:
All checks pass: Proceed to S-3 (Interactive Triage) with the validated plan.
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 61
- Forks
- 6
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
plan-chunks- Source
- github.com/drobins25/craft