Files
Claude-Code-Game-Studios/CCGS Skill Testing Framework/skills/pipeline/create-stories.md
T
DonchitosandClaude Opus 5.5 b21fa0f7f2 Release 1.1.2 — the default path works end to end
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
2026-09-29 21:32:19 +10:00

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.md exists 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 ## Status Accepted
  • docs/architecture/control-manifest.md exists
  • docs/architecture/tr-registry.yaml has TR-IDs for all 3 requirements
  • production/epics/index.md has a row for the epic with Not yet created

Input: /create-stories combat

Expected behavior:

  1. Reads EPIC.md and the GDD in full; greps this layer's ## <layer> Layer Rules from the manifest and this system's TR-registry entries; loads each ADR by heading map + bounded reads
  2. Reports "Loaded epic [name], GDD [filename], [N] governing ADRs [status], [manifest status]."
  3. Classifies each story by type (the damage-formula story is Logic)
  4. Notes "QL-STORY-READY skipped — Lean mode."
  5. Presents the story list (title, type, ADR, covered TR-IDs, test/evidence path)
  6. Asks once: "May I write these 3 stories to production/epics/combat/, and update production/epics/combat/EPIC.md and production/epics/index.md?"
  7. Writes story-001-[slug].md … story-003-[slug].md, updates the EPIC.md Stories table and the index row to 3 stories
  8. 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.md and production/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: full
  • production/epics/ contains other epics but no nonexistent-epic/ directory

Input: /create-stories nonexistent-epic

Expected behavior:

  1. Skill looks for production/epics/nonexistent-epic/EPIC.md — not found
  2. Skill outputs a clear error naming that path
  3. Skill recommends /create-epics (the Previous step) or checking the slug against the epics under production/epics/
  4. 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 minimal brief-synthesis branch at full

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 ## Status Accepted
  • Requirement 2 is governed by ADR-0007 with ## Status Proposed

Input: /create-stories [epic-slug]

Expected behavior:

  1. Both ADR files exist, so the full-tier existence check passes
  2. Skill reads each governing ADR's status and finds ADR-0007 Proposed
  3. Story 2 is drafted with Status: Blocked and the note "BLOCKED: ADR-0007 is Proposed — accept it with /architecture-decision accept ADR-0007 once decided"
  4. Story 1 is drafted with Status: Ready
  5. 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 ## Status section, not assumed
  • Story 2 has Status: Blocked and the note names ADR-0007 and /architecture-decision accept — never a bare /architecture-decision, which starts a new ADR
  • Variant — ADR-0007's ## Status reads Superseded by ADR-0009: story 2 is still Status: 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: standard
  • production/epics/ contains 2 epic subdirectories, each with an EPIC.md

Input: /create-stories (no argument)

Expected behavior:

  1. Skill detects no argument at standard
  2. Globs production/epics/*/EPIC.md
  3. Asks via AskUserQuestion: "Which epic would you like to break into stories?" with the 2 epics (and their status) as options
  4. 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 minimal brief-synthesis branch at standard

Fixture (no epics):

  • project.yaml: modes.workflow: standard
  • production/epics/ holds no EPIC.md

Expected behavior (no epics):

  1. The glob returns nothing, so the skill stops: "No epics found under production/epics/. Run /create-epics layer: foundation first — 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-epics and 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:

  1. Both stories are decomposed
  2. qa-lead is spawned once with QL-STORY-READY for the whole story list
  3. The assessment is presented: story 1 ADEQUATE with its test-case specs; story 2 GAPS naming the vague criterion
  4. AskUserQuestion for story 2: Revise flagged criteria / Accept and proceed / Discuss further
  5. On Revise: story 2's revised criteria are drafted and shown; specs for story 2 alone are re-requested in one follow-up call
  6. 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-lead is 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 full mode

Case 6: Minimal tier — epic synthesized from the brief, then a return visit

Fixture:

  • project.yaml: engine.name: Godot, engine.version: "4.6", and no modes keys — modes.rigor defaults to minimal, so workflow, qa.level and the review mode resolve to minimal / minimal / solo
  • design/game-brief.md with working title "Lantern Keeper", a Player goal & fail state, 2 MVP features and a Build order
  • docs/engine-reference/godot/VERSION.md is absent
  • No production/epics/ directory

Input: /create-stories

Expected behavior:

  1. No argument at minimal takes Step 2's minimal branch and reads the brief; nothing stops for the absent GDD, ADRs, control manifest or TR registry
  2. Drafts production/epics/lantern-keeper/EPIC.md without writing it
  3. Notes "QL-STORY-READY skipped — Solo mode."
  4. Presents 2 stories, one per MVP feature in Build order, and asks once to write them and create production/epics/lantern-keeper/EPIC.md (no index.md — it does not exist)
  5. Writes EPIC.md and both stories; prints Epics index not updated: production/epics/index.md absent
  6. Recommends /dev-story [first-story-path] — no /story-readiness, no /sprint-plan option

Assertions:

  • Nothing, EPIC.md included, is written before the single write ask, and that ask names EPIC.md
  • Each story reads Requirement: Brief MVP feature N, N/A (minimal — no ADRs) in its ADR fields and N/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/ holds EPIC.md (a 2-row Stories table), story-001-… and story-002-…; the brief now lists a 3rd MVP feature

Expected behavior (return visit):

  1. Reads the existing stories and EPIC.md; drafts one story for the new feature
  2. Asks once, naming the new story and the EPIC.md update; writes story-003-[slug].md and appends one row to the Stories table

Assertions (return visit):

  • story-001 and story-002 are unchanged
  • The new story is numbered 003, on from the highest existing number
  • EPIC.md keeps 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-epics was run anyway, so production/epics/lantern-keeper/EPIC.md exists (scope from the brief, Stories "Not yet created") and the folder holds no story files

Expected behavior (an EPIC.md with no stories yet):

  1. The existing EPIC.md is the epic: no new one is drafted from the brief
  2. 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.md other 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.md when 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-story directly at minimal)

Coverage Notes

  • At minimal, the "run /brainstorm first" stop when no brief exists and a named epic slug that does not exist (the minimal branch is taken instead of /create-epics) are not given fixtures.
  • The full missing-ADR-file stop and the standard critical/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 fine in Cases 1, 3 and 5 so the story counts are determinate; coarse and balanced grouping, and prose depth per docs.density, are not fixture-locked.
  • The existing-QA-plan substitution prompt (Use QA-plan specs / Use qa-lead specs / Skip) is not tested.