Fix release for 1.1.1: the minimal path end to end, engine commands that run on Godot, Unity and Unreal, hook warnings you can see, and verdicts that say when they could not check. Details in CHANGELOG.md; upgrade steps in UPGRADING.md (v1.1.1 → v1.1.2). Fixes #67 Fixes #131 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WuJn2FdynEybfL5KC697nJ
16 KiB
Skill Test Spec: /create-stories
Skill Summary
/create-stories breaks a single epic into developer-ready story files. At
standard/full workflow it reads production/epics/[epic-slug]/EPIC.md, the
epic's GDD, the governing ADRs (section-bounded reads, never unbounded), this
layer's rules from the control manifest and this system's entries in the TR
registry. At minimal it synthesizes an implicit epic from
design/game-brief.md instead, and writes that epic's EPIC.md only after the
write ask names it.
Each story is classified by type (Logic / Integration / Visual/Feel / UI /
Config/Data), which fixes its required test evidence. A story governed by a
Proposed ADR is set Status: Blocked. In full review mode qa-lead is spawned
once with gate QL-STORY-READY (verdicts ADEQUATE / GAPS / INADEQUATE) and
returns test-case specs for ADEQUATE stories; GAPS go to the user (Revise /
Accept / Discuss), INADEQUATE blocks the story until it is revised; in
lean/solo the gate is skipped with a note. All stories are presented in one
summary and the skill asks once — "May I write these [N] stories to
production/epics/[epic-slug]/, and update production/epics/[epic-slug]/EPIC.md
and production/epics/index.md?" — then writes story-NNN-[slug].md files and
updates the epic's EPIC.md and production/epics/index.md. Verdicts: COMPLETE
or BLOCKED (user declined).
Static Assertions (Structural)
Checked against the SKILL.md by /skill-test spec — no fixture needed.
- Has required frontmatter fields:
name,description,argument-hint,user-invocable,allowed-tools - Has ≥2 phase headings
- Contains verdict keywords: COMPLETE, BLOCKED
- Contains "May I write" collaborative protocol language (one approval for the full story set)
- Has a next-step handoff at the end (
/story-readiness,/dev-story) - Documents story Status: Blocked when governing ADR is Proposed
- Documents QL-STORY-READY gate: active in full mode, skipped in lean/solo
Director Gate Checks
In full mode: qa-lead is spawned once via Agent with gate QL-STORY-READY
after all stories are decomposed and before the write ask. It returns a verdict per
story (ADEQUATE / GAPS / INADEQUATE) plus Given/When/Then specs (Logic,
Integration) or manual verification steps (Visual/Feel, UI) for ADEQUATE stories.
GAPS → AskUserQuestion with Revise flagged criteria / Accept and proceed /
Discuss further — nothing is revised before the user chooses. INADEQUATE →
blocking: the story is revised with the user (or dropped and named) before the
write ask. NOT ASSESSED [missing input] → never read as ADEQUATE: the input is
supplied and the verdict re-requested, or the story is written without qa-lead
specs and marked QL-STORY-READY: NOT ASSESSED — [input] in the story list.
In lean mode: QL-STORY-READY is skipped. Output notes:
"QL-STORY-READY skipped — Lean mode."
In solo mode: QL-STORY-READY is skipped. Output notes:
"QL-STORY-READY skipped — Solo mode."
Test Cases
Case 1: Happy Path — Epic with 3 stories, all ADRs Accepted
Fixture:
project.yaml:engine.name: Godot,modes.workflow: full,modes.review_mode: lean,modes.story_granularity: fine(one story per acceptance criterion)production/epics/combat/EPIC.mdexists with 3 GDD requirements and its governing ADRs listed- The epic's GDD exists with exactly one acceptance criterion per requirement (one is a damage formula)
- All governing ADR files exist with
## StatusAccepted docs/architecture/control-manifest.mdexistsdocs/architecture/tr-registry.yamlhas TR-IDs for all 3 requirementsproduction/epics/index.mdhas a row for the epic withNot yet created
Input: /create-stories combat
Expected behavior:
- Reads EPIC.md and the GDD in full; greps this layer's
## <layer> Layer Rulesfrom the manifest and this system's TR-registry entries; loads each ADR by heading map + bounded reads - Reports "Loaded epic [name], GDD [filename], [N] governing ADRs [status], [manifest status]."
- Classifies each story by type (the damage-formula story is Logic)
- Notes "QL-STORY-READY skipped — Lean mode."
- Presents the story list (title, type, ADR, covered TR-IDs, test/evidence path)
- Asks once: "May I write these 3 stories to
production/epics/combat/, and updateproduction/epics/combat/EPIC.mdandproduction/epics/index.md?" - Writes
story-001-[slug].md…story-003-[slug].md, updates the EPIC.md Stories table and the index row to3 stories - Asks what next, recommending
/story-readiness [first-story-path]; Verdict: COMPLETE
Assertions:
- Exactly 3 stories are drafted — one per acceptance criterion at
fine - Each story file has the header fields Epic, Status, Layer, Type, Manifest Version, and a Context block with GDD,
Requirement: TR-[system]-NNN, ADR Governing Implementation, ADR Version, Engine/Risk - Each story has Acceptance Criteria, QA Test Cases, Test Evidence and Dependencies sections
- The formula story is typed Logic with evidence path
tests/unit/[system]/…(the Godot test root) - "QL-STORY-READY skipped — Lean mode." appears and each QA Test Cases section reads "N/A — no qa-lead specs at this tier…" (no improvised test cases)
- "May I write" is asked once, after the full list is shown, and names the 3 stories,
EPIC.mdandproduction/epics/index.md - Files are named
production/epics/combat/story-NNN-[slug].md - Skill does NOT start implementation
Case 2: Failure Path — Named epic does not exist
Fixture:
project.yaml:modes.workflow: fullproduction/epics/contains other epics but nononexistent-epic/directory
Input: /create-stories nonexistent-epic
Expected behavior:
- Skill looks for
production/epics/nonexistent-epic/EPIC.md— not found - Skill outputs a clear error naming that path
- Skill recommends
/create-epics(the Previous step) or checking the slug against the epics underproduction/epics/ - No story files are created and no epic is synthesized from the brief
Assertions:
- Skill outputs a clear error naming
production/epics/nonexistent-epic/EPIC.md - No story files, EPIC.md or index row are written
- Skill recommends
/create-epics - Skill does NOT fall through to the
minimalbrief-synthesis branch atfull
Case 3: Blocked Story — ADR is Proposed
Fixture:
project.yaml:modes.workflow: full,modes.review_mode: solo,modes.story_granularity: fine- EPIC.md exists with 2 requirements, one acceptance criterion each; both governing ADR files exist
- Requirement 1 is governed by an ADR with
## StatusAccepted - Requirement 2 is governed by ADR-0007 with
## StatusProposed
Input: /create-stories [epic-slug]
Expected behavior:
- Both ADR files exist, so the
full-tier existence check passes - Skill reads each governing ADR's status and finds ADR-0007 Proposed
- Story 2 is drafted with
Status: Blockedand the note "BLOCKED: ADR-0007 is Proposed — accept it with/architecture-decision accept ADR-0007once decided" - Story 1 is drafted with
Status: Ready - The blocked story is flagged in the story list before the single "May I write" ask
Assertions:
- The ADR status is taken from the ADR's
## Statussection, not assumed - Story 2 has
Status: Blockedand the note names ADR-0007 and/architecture-decision accept— never a bare/architecture-decision, which starts a new ADR - Variant — ADR-0007's
## StatusreadsSuperseded by ADR-0009: story 2 is stillStatus: Blocked, and its note names ADR-0009 as the ADR to point it at - Story 1 has
Status: Ready— the blocked ADR does not affect it - The blocked story is flagged before write approval, not discovered after writing
- Both story files are written (blocked stories are still written — just flagged)
Case 4: Edge Case — No argument provided
Fixture:
project.yaml:modes.workflow: standardproduction/epics/contains 2 epic subdirectories, each with anEPIC.md
Input: /create-stories (no argument)
Expected behavior:
- Skill detects no argument at
standard - Globs
production/epics/*/EPIC.md - Asks via
AskUserQuestion: "Which epic would you like to break into stories?" with the 2 epics (and their status) as options - Decomposes only the epic the user picks
Assertions:
- Skill asks "Which epic would you like to break into stories?" rather than erroring
- Both epics from the glob are offered as options
- No story files are written before the user picks
- Skill does NOT silently pick an epic without user input
- Skill does NOT take the
minimalbrief-synthesis branch atstandard
Fixture (no epics):
project.yaml:modes.workflow: standardproduction/epics/holds noEPIC.md
Expected behavior (no epics):
- The glob returns nothing, so the skill stops: "No epics found under
production/epics/. Run/create-epics layer: foundationfirst — an epic is what this skill decomposes."
Assertions (no epics):
- No "Which epic…" question is asked with an empty option list
- The stop names
/create-epicsand nothing is written
Case 5: Director Gate — Full mode, one story returns GAPS from QL-STORY-READY
Fixture:
project.yaml:modes.workflow: full,modes.review_mode: full,modes.story_granularity: fine- EPIC.md exists with 2 requirements, one acceptance criterion each; both governing ADRs Accepted
- QL-STORY-READY returns ADEQUATE for story 1 and GAPS for story 2 (one vague acceptance criterion)
- At the GAPS question the user picks
Revise flagged criteria
Input: /create-stories [epic-slug]
Expected behavior:
- Both stories are decomposed
qa-leadis spawned once with QL-STORY-READY for the whole story list- The assessment is presented: story 1 ADEQUATE with its test-case specs; story 2 GAPS naming the vague criterion
AskUserQuestionfor story 2:Revise flagged criteria/Accept and proceed/Discuss further- On Revise: story 2's revised criteria are drafted and shown; specs for story 2 alone are re-requested in one follow-up call
- Once both are ADEQUATE, the story list is presented and the single write ask is made; each story's QA Test Cases section holds the qa-lead specs
Assertions:
qa-leadis spawned once for all stories (not once per story, and not a second time for story 1's specs); the only follow-up call covers story 2 alone- Per-story verdicts use ADEQUATE / GAPS / INADEQUATE and name the failing criterion
- The GAPS verdict goes to the user with the three options — story 2's criteria are not revised before the user chooses
- Story 2's revised criteria are shown before the write ask; it carries no specs until ADEQUATE
- Had the user picked
Accept and proceed, story 2 would be written with its criteria unchanged and its QA Test Cases reading*Test cases not yet defined — run /qa-plan to generate them.* - Story 1's QA Test Cases section contains Given/When/Then (Logic/Integration) or Setup/Verify/Pass condition (Visual/Feel, UI) blocks from the gate
- No "QL-STORY-READY skipped" note appears in
fullmode
Case 6: Minimal tier — epic synthesized from the brief, then a return visit
Fixture:
project.yaml:engine.name: Godot,engine.version: "4.6", and nomodeskeys —modes.rigordefaults tominimal, soworkflow,qa.leveland the review mode resolve tominimal/minimal/solodesign/game-brief.mdwith working title "Lantern Keeper", a Player goal & fail state, 2 MVP features and a Build orderdocs/engine-reference/godot/VERSION.mdis absent- No
production/epics/directory
Input: /create-stories
Expected behavior:
- No argument at
minimaltakes Step 2'sminimalbranch and reads the brief; nothing stops for the absent GDD, ADRs, control manifest or TR registry - Drafts
production/epics/lantern-keeper/EPIC.mdwithout writing it - Notes "QL-STORY-READY skipped — Solo mode."
- Presents 2 stories, one per MVP feature in Build order, and asks once to write
them and create
production/epics/lantern-keeper/EPIC.md(noindex.md— it does not exist) - Writes
EPIC.mdand both stories; printsEpics index not updated: production/epics/index.md absent - Recommends
/dev-story [first-story-path]— no/story-readiness, no/sprint-planoption
Assertions:
- Nothing,
EPIC.mdincluded, is written before the single write ask, and that ask namesEPIC.md - Each story reads
Requirement: Brief MVP feature N,N/A (minimal — no ADRs)in its ADR fields andN/A (minimal — no control manifest)as its Manifest Version - Each story's Risk is
NOT ASSESSED (no VERSION.md risk rating)— never a guessed level - Each QA Test Cases section reads the "N/A — no qa-lead specs at this tier…" line
- The index line names
production/epics/index.md, not the systems index
Fixture (return visit):
- As above after that run:
production/epics/lantern-keeper/holdsEPIC.md(a 2-row Stories table),story-001-…andstory-002-…; the brief now lists a 3rd MVP feature
Expected behavior (return visit):
- Reads the existing stories and
EPIC.md; drafts one story for the new feature - Asks once, naming the new story and the
EPIC.mdupdate; writesstory-003-[slug].mdand appends one row to the Stories table
Assertions (return visit):
story-001andstory-002are unchanged- The new story is numbered 003, on from the highest existing number
EPIC.mdkeeps its two rows and every other section; exactly one row is appended
Fixture (an EPIC.md with no stories yet):
- As the first fixture, but
/create-epicswas run anyway, soproduction/epics/lantern-keeper/EPIC.mdexists (scope from the brief, Stories "Not yet created") and the folder holds no story files
Expected behavior (an EPIC.md with no stories yet):
- The existing
EPIC.mdis the epic: no new one is drafted from the brief - The write ask names the 2 stories and says update
EPIC.md, not create
Assertions (an EPIC.md with no stories yet):
- Every section of the existing
EPIC.mdother than its Stories table is unchanged - The Step 5 ask says update
EPIC.md
Protocol Compliance
- All context (EPIC, GDD, ADRs, manifest layer rules, TR registry entries) loaded before drafting stories
- Story list shown in full before the "May I write" ask
- "May I write" asked once for the full story set, not once per story, naming every file it touches (stories,
EPIC.md,production/epics/index.mdwhen present) - Blocked stories flagged before write approval — not discovered after writing
- TR-IDs reference the registry — requirement text is not embedded inline in story files
- Control manifest rules quoted per-story from the manifest, not invented
- Ends with next-step handoff:
/story-readiness→/dev-story(/dev-storydirectly atminimal)
Coverage Notes
- At
minimal, the "run/brainstormfirst" stop when no brief exists and a named epic slug that does not exist (theminimalbranch is taken instead of/create-epics) are not given fixtures. - The
fullmissing-ADR-file stop and thestandardcritical/non-critical ADR split are not separately tested. - INADEQUATE (the story is revised with the user, or dropped and named) and a NOT ASSESSED gate answer are not given fixtures.
- Integration story test evidence (playtest doc alternative) follows the same approval pattern as Logic stories — not independently fixture-tested.
- Story sizing is pinned to
finein Cases 1, 3 and 5 so the story counts are determinate;coarseandbalancedgrouping, and prose depth perdocs.density, are not fixture-locked. - The existing-QA-plan substitution prompt (Use QA-plan specs / Use qa-lead specs / Skip) is not tested.