!bash "${CLAUDE_SKILL_DIR}/../../hooks/yaml-helper.sh" resolve_config --keys locale,review_mode,review_gate,automation,workflow,docs.density,story_granularity,qa.level,system_overrides
Resolved above — use as-is; --review overrides review_mode. No block →
defaults in .claude/docs/config-resolution.md.
Ask with the question tool. Without one, list the options numbered and end your turn
to wait. A skipped or dismissed question is not an answer: ask again in plain text.
Create Stories
Interaction Localization Rule:
When locale: pt-BR (or user speaks Portuguese), ALL questions (AskUserQuestion / ask_question), confirmation prompts, and selectable options MUST be translated and presented in Brazilian Portuguese (PT-BR).
Any English question text or options in this skill are illustrative examples — NEVER display English questions or options to a Portuguese developer.
Internal reasoning, code synthesis, tests, and documentation files MUST remain in English.
A story is one implementable behaviour: small enough for the size
story_granularity sets, self-contained, and traced to a requirement and the
decision that governs it. Run this skill once per epic, in dependency order:
Foundation epics first, then Core, Feature, Presentation.
Writes: production/epics/[epic-slug]/story-NNN-[slug].md, the epic's
EPIC.md Stories table, and its row in production/epics/index.md.
Next: /saas-dev-story [story-path] at workflow: minimal; otherwise
/saas-story-readiness [story-path], then /saas-dev-story.
Asks follow .claude/docs/automation-modes.md (collaborative always asks, guided
asks on major choices, autonomous logs and goes on; automation_always_ask
categories always ask).
Checklist (copy it and tick as you go):
- [ ] Phase 1: epic found, tier resolved
- [ ] Phase 2: inputs loaded, each ADR's status reported
- [ ] Phase 3-4: stories drafted, typed, Ready or Blocked
- [ ] Phase 5: QA lead review run, or its skip noted
- [ ] Phase 6: story list shown, one ask to write
- [ ] Phase 7: stories, EPIC.md and index.md written (or index absence said)
- [ ] Phase 8: next step asked, closing block printed
Phase 1: Epic and settings
Tier. workflow for the epic's system: the system_overrides row for the epic
slug (its PRD system) if there is one, else the project value.
story_granularity sets each story's acceptance-criteria load. Group or split
criteria to hit it:
story_granularity | ACs per story | Size |
|---|
coarse (default, rigor: minimal) | 5-10 | a whole feature, multi-day |
balanced (rigor: standard) | 2-4 | one task, about one session |
fine | 1 | one criterion; the story name restates it |
docs.density sets the depth of each story's prose (context, implementation
notes, ADR summary), never the AC count or the AC text: terse (default) = bullet
notes, no preamble; balanced = a short context paragraph plus notes; thorough =
full context, guidance and ADR rationale. The TR-ID, ADR Version and acceptance
criteria are never trimmed.
Which epic. The text typed after the skill name, with any --review <mode>
pair removed: an epic slug (billing) or a path (production/epics/billing/EPIC.md).
With nothing typed, the epic the user's request names ("the billing epic") counts as
named.
- Named, but no
EPIC.md there: at standard and full, stop: "No epic at
production/epics/[slug]/EPIC.md. Run /saas-create-epics to create it, or check the
slug with ls production/epics/." Never decompose from a guess. At minimal,
say this tier needs no /saas-create-epics epic, take Phase 2's minimal branch, and
name the slug it uses.
- Blank, at
minimal: take Phase 2's minimal branch.
- Blank, at
standard or full: list production/epics/*/EPIC.md with each
status, then ask: "Which epic would you like to break into stories?" with one
option per epic. No epics found: stop and say "No epics found under
production/epics/. Run /saas-create-epics layer: foundation first." Never ask a
question with no options.
Phase 2: Load the inputs
minimal: build the epic from the brief
- No
design/product-brief.md: stop. "There is no brief to build stories from
yet: run /saas-brainstorm first; it writes the one-page brief." When the code root
already holds the application (10 or more source files), name /saas-reverse-document design [code root] instead.
- Read
design/product-brief.md in full (one page).
- The epic.
<slug> is the brief's working title, slugified (mvp if it has
none), or the epic the user named.
production/epics/<slug>/EPIC.md exists: it is the epic. Use its scope, still
traced to the brief, and never rewrite it.
- It does not: draft one, written in Phase 7 only after the Phase 6 ask names
it. Goal = the brief's one-sentence pitch; scope = its MVP feature list;
order = its Build order. Keep it terse.
- Stories already in the folder (a return visit): never rewrite an existing
story-*.md. Add stories only for brief items they do not cover, or new ones
the user names, and number on from the highest existing story-NNN.
- One story per MVP feature, in Build order, each traced to the brief. No
story is blocked on ADR grounds: this tier has none.
Read no PRD, control manifest, TR registry or ADR at minimal. Go to Phase 3.
standard and full: the epic and what governs it
- The epic:
production/epics/[epic-slug]/EPIC.md in full (its layer, PRD,
governing ADRs, and the PRD Requirements table with TR-IDs).
- The PRD: its sections by heading, never the whole file:
bash .claude/scripts/md-section.sh extract design/prd/[file].md "Acceptance Criteria",
and the same for Formulas, Edge Cases and Detailed Design (exit 3: try
Detailed Rules, the design standard's name for the same section); at full
the other required sections too (list shows the headings).
- The control manifest: the epic's layer only, and the version:
bash .claude/scripts/md-section.sh extract docs/architecture/control-manifest.md "[Layer] Layer Rules",
plus its Manifest Version line.
- The TR registry: this system's entries only: in
docs/architecture/tr-registry.yaml, the lines matching system: <slug>\s*$,
with each entry's id above and its text below. The anchor keeps billing from
matching billing-ai; \s* takes a Windows line ending.
- The ADRs, every one the epic names (governing, or in its requirements table,
Proposed ones included), in one call:
bash .claude/scripts/adr-status.sh ADR-0001 ADR-0003 ...
Each row gives the status, layer, version (the story's ADR Version stamp),
depends_on, and missing sections. Then read only Summary, Decision (its
Implementation Guidelines inside) and Engine Compatibility of each, with
md-section.sh extract. Engine Notes is a story field taken from Engine
Compatibility, not an ADR section. An ADR with none of these sections predates
the template: read it once, and flag it for /saas-architecture-decision retrofit [file].
A named ADR with no file (NOT_FOUND):
full: stop before decomposing any story.
standard: stop only when it is critical (Foundation layer); otherwise warn, go
on, and write the stories it governs as Blocked until it exists.
- On stopping: "Epic references [ADR-NNNN: title] but no file for it was found in
docs/architecture/. Check the epic's Governing ADRs list, or run
/saas-architecture-decision to create it. Cannot create stories until the
referenced ADR files exist."
Report before drafting, with the real state, every ADR on its own with its
status:
Loaded: epic [name] · PRD [file] · manifest v[date], [layer] rules
ADRs: ADR-0001 Accepted · ADR-0002 Accepted · ADR-0003 Accepted · ADR-0004 Proposed · [ADR-NNNN missing]
Never say "all present" when one is missing, or name a manifest version when there
is none.
Phase 3: Type each story
| Type | When its criteria reference |
|---|
| Logic | formulas, thresholds, state transitions, business rules, calculations |
| Integration | two or more services, API contracts across boundaries, persistence/hydration round-trips |
| Visual/Feel | animation, UI transitions, "feels responsive", timing, loading states, micro-interactions |
| UI | navigation, App Shell, buttons, screens, modal dialogs, tooltips |
| Config/Data | configuration settings and schema migrations only, no new logic |
A mixed story takes the type with the highest implementation risk. The type sets
the evidence /saas-story-done needs.
Phase 4: Draft the stories
Group the requirements that need the same core implementation into one story, at
the story_granularity load. Order: foundation behaviour first, edge cases later,
UI last. For each story:
- Requirement: the TR-ID from the registry, matched through the epic's PRD
Requirements table. Only when no entry matches, write
TR-[system]-??? and say
so.
- ADR: the one that governs how to build it (the requirements table names it).
Accepted: embed it.
Proposed: Status: Blocked, with "BLOCKED: ADR-NNNN is Proposed — accept it
with /saas-architecture-decision accept ADR-NNNN once decided".
Deprecated or Superseded: Status: Blocked, with "BLOCKED: ADR-NNNN is
[status] — point the story at [successor] (edit its ADR field;
/saas-create-stories never rewrites an existing story) before implementing".
- An
Accepted ADR whose depends_on names an ADR that is not Accepted: Blocked
the same way, naming that ADR.
- Several apply: list them all, the most direct first.
- None applies:
ADR: N/A — [reason], e.g. "pure data configuration". Never
blank: blank means unchecked.
- ADR Version: the story's ADR Version is the ADR's
## Last Verified
date, else its ## Date, else unversioned (the version column). /saas-dev-story
trusts the story's ADR summary while this still matches the ADR.
- Engine risk: from the ADR's Engine Compatibility (its knowledge risk).
- Estimate: propose a t-shirt size from the criteria and the files the story
touches:
S (a few hours), M (about a day) or L (several days). It is a
proposal: Phase 6 shows it and the user can change it. /saas-story-readiness fails
a story whose Estimate is still the template's bracket, so never leave it.
Phase 5: QA lead review
Read the review_gate line above. skill-gates=skip (solo or lean): no review;
note "QL-STORY-READY skipped — [Solo | Lean] mode" in the Phase 6 list and the
closing block. skill-gates=run: read references/qa-lead-gate.md and
.claude/docs/director-gates.md, and run it now, before the Phase 6 ask. On a skip,
do not load it.
Phase 6: Show the stories, ask once
## Stories for Epic: [name]
ADRs: ADR-0001 Accepted · ADR-0002 Accepted · ADR-0004 Proposed (every ADR, from Phase 2)
Story 001: [title] — Logic — ADR-0001 — Ready — Estimate M
Covers: TR-[system]-001 ([one-line requirement])
Test required: tests/unit/[system]/[slug]_test.[ext]
Story 002: [title] — Integration — ADR-0004 — BLOCKED (ADR-0004 is Proposed) — Estimate L
Covers: TR-[system]-002, TR-[system]-003
Test required: tests/integration/[system]/[slug]_test.[ext]
Story 003: [title] — Visual/Feel — ADR-0001 — Ready — Estimate S
Covers: TR-[system]-004
Evidence required: retained screenshot + sign-off in production/qa/evidence/[slug]-evidence.md
[N stories: N Logic, N Integration, N Visual/Feel, N UI, N Config/Data; N Blocked]
QL-STORY-READY: [skipped — Solo mode | its verdicts]
At minimal, each line traces to Brief MVP feature N, there is no ADRs line, and
there is one story per MVP feature: no extra stories for brief items outside the
MVP list. Then
ask: "May I write these [N] stories to production/epics/[epic-slug]/, and
[create | update] production/epics/[epic-slug]/EPIC.md and update
production/epics/index.md?" Options: Yes, write all [N] / Not yet, I want to
adjust first; an adjustment can change any estimate. Name every file Phase 7 touches: create EPIC.md only when it
does not exist, and leave index.md out when it does not exist. Write nothing
before the yes.
Phase 7: Write
The story files
Each story is production/epics/[epic-slug]/story-[NNN]-[slug].md, laid out
as .claude/docs/templates/story.md. Never reuse a story number. Write each file
as a file, never through a shell command: a shell write skips the project's write
checks.
At minimal there is no PRD, ADR, TR registry or manifest. Fill these fields
exactly:
| Field | Value at minimal |
|---|
| PRD | design/product-brief.md |
| Requirement | Brief MVP feature N, never a TR-ID |
| ADR Governing Implementation, ADR Decision Summary, ADR Version | N/A (minimal — no ADRs) |
| Manifest Version, Control Manifest Rules | N/A (minimal — no control manifest) |
| Engine | stack.frontend + stack.version |
| Risk | the level docs/engine-reference/<engine>/VERSION.md gives the pinned version (its timeline row, or its overall rating). No file or no level: NOT ASSESSED (no VERSION.md risk rating), never a guess. /saas-dev-story reads NOT ASSESSED as HIGH |
| Engine Notes | none (no ADR engine-compatibility analysis at minimal) |
| Acceptance Criteria | from the brief's User goal & fail state and the MVP feature, made concrete and testable; never invented from a bare bullet |
At every tier:
- QA Test Cases: when the review was skipped, write
*N/A — no qa-lead specs at this tier; implement against the Acceptance Criteria above*.
Never improvise test cases.
- Test Evidence:
qa.level governs it. At qa.level: minimal tests are
waived (advisory), but a Visual/Feel or UI story's retained screenshot is not.
- Estimate: the size from Phase 6, with any change the user made.
- Dependencies: name each story this one needs by its path.
- Files: the code and test files the story is planned to create or change,
under the code root and test root.
/saas-dev-story replaces them with the real list.
EPIC.md
At minimal with none yet, write the Phase 2 draft with the table
below. Otherwise replace its "Stories: Not yet created" line with the table, or on
a return visit append one row per new story and leave the rest of the file as it
is:
## Stories
| # | Story | Type | Status | ADR |
|---|-------|------|--------|-----|
| 001 | [title] | Logic | Ready | ADR-0001 |
| 002 | [title] | Integration | Blocked | ADR-0004 |
production/epics/index.md
Set the epic's Stories cell to [N] stories,
the epic's total after this run. When the file does not exist, say so:
Epics index not updated: production/epics/index.md absent.
Phase 8: Close
If other epics in production/epics/ have no stories, list them. Then ask:
"[N] stories written to production/epics/[epic-slug]/. What next?" Options, those
that apply:
- Start implementing:
/saas-dev-story [first-story-path] at minimal,
/saas-story-readiness [first-story-path] otherwise (recommended)
- Create stories for [next epic]:
/saas-create-stories [slug] (only when an epic has
none)
- Plan the sprint:
/saas-sprint-plan new (only when every epic has stories; never at
minimal, where the brief's build order is the plan)
- Stop here for this session
Never start implementation or write code: this skill stops at the story files.
Acceptance criteria come from the PRD (the brief at minimal), implementation
notes from the ADRs, rules from the manifest; none are invented.
The run's last reply ends with this block, after the question above is
answered (repeat it if you showed it earlier):
Verdict: COMPLETE — [N] stories written to production/epics/[epic-slug]/ ([N] Ready, [N] Blocked)
Review: [QL-STORY-READY skipped — Solo mode | skipped — Lean mode | its verdicts]
Index: [production/epics/index.md updated | Epics index not updated: production/epics/index.md absent]
Next step: [/saas-dev-story [first-story-path] | /saas-story-readiness [first-story-path]]
When the user declines the write: Verdict: BLOCKED — user declined. No story files written.