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
This commit is contained in:
Donchitos
2026-09-29 21:32:19 +10:00
co-authored by Claude Opus 5.5
parent 7ed2c3e9c4
commit b21fa0f7f2
383 changed files with 22888 additions and 10618 deletions
@@ -2,28 +2,37 @@
## Skill Summary
`/create-stories` breaks a single epic into developer-ready story files. It reads
the EPIC.md, the corresponding GDD, governing ADRs, the control manifest, and the
TR registry. Each story gets structured frontmatter including: Title, Epic, Layer,
Priority, Status, TR-ID, ADR references, Acceptance Criteria, and Definition of
Done. Stories are classified by type (Logic / Integration / Visual/Feel / UI /
Config/Data) which determines the required test evidence path.
`/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.
In `full` review mode, a QL-STORY-READY check runs per story after creation. In
`lean` or `solo` mode, QL-STORY-READY is skipped. The skill asks "May I write"
before writing each story file. Stories are written to
`production/epics/[layer]/story-[name].md`.
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)
Verified automatically by `/skill-test static` — no fixture needed.
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, NEEDS WORK
- [ ] Contains "May I write" collaborative protocol language (per-story approval)
- [ ] 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
@@ -32,13 +41,22 @@ Verified automatically by `/skill-test static` — no fixture needed.
## Director Gate Checks
In `full` mode: QL-STORY-READY check runs per story after creation. Stories that
fail the check are noted as NEEDS WORK before the "May I write" ask.
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" per story.
"QL-STORY-READY skipped — Lean mode."
In `solo` mode: QL-STORY-READY is skipped with equivalent notes.
In `solo` mode: QL-STORY-READY is skipped. Output notes:
"QL-STORY-READY skipped — Solo mode."
---
@@ -47,76 +65,95 @@ In `solo` mode: QL-STORY-READY is skipped with equivalent notes.
### Case 1: Happy Path — Epic with 3 stories, all ADRs Accepted
**Fixture:**
- `production/epics/[layer]/EPIC-[name].md` exists with 3 GDD requirements
- Corresponding GDD exists with matching acceptance criteria
- All governing ADRs have `Status: Accepted`
- `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/session-state/review-mode.txt` contains `lean`
- `production/epics/index.md` has a row for the epic with `Not yet created`
**Input:** `/create-stories [epic-name]`
**Input:** `/create-stories combat`
**Expected behavior:**
1. Skill reads EPIC.md, GDD, governing ADRs, control manifest, and TR registry
2. Classifies each requirement into a story type (Logic / Integration / Visual/Feel / UI / Config/Data)
3. Drafts 3 story files with correct frontmatter schema
4. QL-STORY-READY is skipped (lean mode) — noted in output
5. Asks "May I write" before writing each story file
6. Writes all 3 story files after approval
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:**
- [ ] Each story's frontmatter contains: Title, Epic, Layer, Priority, Status, TR-ID, ADR reference, Acceptance Criteria, DoD
- [ ] Story types are correctly classified (at least one Logic type in fixture)
- [ ] "May I write" is asked per story (not once for the entire batch)
- [ ] QL-STORY-READY skip is noted in output
- [ ] All 3 story files are written with correct naming: `story-[name].md`
- [ ] 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 — No epic file found
### Case 2: Failure Path — Named epic does not exist
**Fixture:**
- The epic path provided does not exist in `production/epics/`
- `project.yaml`: `modes.workflow: full`
- `production/epics/` contains other epics but no `nonexistent-epic/` directory
**Input:** `/create-stories nonexistent-epic`
**Expected behavior:**
1. Skill attempts to read the EPIC.md file
2. File not found
3. Skill outputs a clear error with the path it searched
4. Skill suggests checking `production/epics/` or running `/create-epics` first
5. No story files are created
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 the missing file path
- [ ] No story files are written
- [ ] Skill recommends the correct next action (`/create-epics`)
- [ ] Skill does NOT create stories without a valid EPIC.md
- [ ] 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:**
- EPIC.md exists with 2 requirements
- Requirement 1 is covered by an Accepted ADR
- Requirement 2 is covered by an ADR with `Status: Proposed`
- `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-name]`
**Input:** `/create-stories [epic-slug]`
**Expected behavior:**
1. Skill reads the ADR for Requirement 2 and finds Status: Proposed
2. Story for Requirement 2 is drafted with `Status: Blocked`
3. Blocking note references the specific ADR: "BLOCKED: ADR-NNN is Proposed"
4. Story for Requirement 1 is drafted normally with `Status: Ready`
5. Both stories are shown in the draft — user asked "May I write" for both
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:**
- [ ] Story 2 has `Status: Blocked` in its frontmatter
- [ ] Blocking note names the specific ADR number and recommends `/architecture-decision`
- [ ] Story 1 has `Status: Ready` — blocked status does not affect non-blocked stories
- [ ] Blocked status is shown in the draft preview before writing
- [ ] 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)
---
@@ -124,68 +161,164 @@ In `solo` mode: QL-STORY-READY is skipped with equivalent notes.
### Case 4: Edge Case — No argument provided
**Fixture:**
- `production/epics/` directory exists with ≥2 epic subdirectories
- `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 is provided
2. Outputs a usage error: "No epic specified. Usage: /create-stories [epic-name]"
3. Skill lists available epics from `production/epics/`
4. No story files are created
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 outputs a usage error when no argument is given
- [ ] Skill lists available epics to help the user choose
- [ ] No story files are written
- [ ] 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 runs QL-STORY-READY; stories failing noted as NEEDS WORK
### Case 5: Director Gate — Full mode, one story returns GAPS from QL-STORY-READY
**Fixture:**
- EPIC.md exists with 2 requirements
- Both governing ADRs are Accepted
- `production/session-state/review-mode.txt` contains `full`
- QL-STORY-READY check finds one story has ambiguous acceptance criteria
- `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-name]`
**Input:** `/create-stories [epic-slug]`
**Expected behavior:**
1. Both stories are drafted
2. QL-STORY-READY check runs for each story
3. Story 1 passes QL-STORY-READY
4. Story 2 fails QL-STORY-READY — noted as NEEDS WORK with specific feedback
5. Both stories are shown to user with pass/fail status before "May I write"
6. User can proceed (story written as-is with NEEDS WORK note) or revise first
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:**
- [ ] QL-STORY-READY results appear per story in the output
- [ ] Story 2 is flagged as NEEDS WORK with the specific failing criteria
- [ ] Story 1 shows as passing QL-STORY-READY
- [ ] User is given the choice to proceed or revise before writing
- [ ] Skill does NOT auto-block writing of stories that fail QL-STORY-READY without user input
- [ ] `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, TR registry) loaded before drafting stories
- [ ] Story drafts shown in full before any "May I write" ask
- [ ] "May I write" asked per story (not once for the entire batch)
- [ ] 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`
- [ ] 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 ordering (foundational first, UI last) is validated implicitly via
Case 1's multi-story fixture.
- The story sizing rule (splitting large requirement groups) is not tested here
— it is addressed in the `/create-stories` skill's internal logic.
- 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.