mirror of
https://github.com/Donchitos/Claude-Code-Game-Studios.git
synced 2026-10-16 10:17:06 +00:00
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:
co-authored by
Claude Opus 5.5
parent
7ed2c3e9c4
commit
b21fa0f7f2
@@ -2,37 +2,55 @@
|
||||
|
||||
## Skill Summary
|
||||
|
||||
`/create-control-manifest` reads all Accepted ADRs from `docs/architecture/` and
|
||||
generates a control manifest — a summary document that captures all architectural
|
||||
constraints, required patterns, and forbidden patterns in one place. The manifest
|
||||
is the reference document that story authors use when writing story files, ensuring
|
||||
stories inherit the correct architectural rules without having to read all ADRs
|
||||
individually.
|
||||
`/create-control-manifest` reads the Accepted ADRs in `docs/architecture/` and
|
||||
generates a control manifest — a flat, actionable rules sheet that captures the
|
||||
required patterns, forbidden approaches, performance guardrails and engine API
|
||||
constraints for each architectural layer (Foundation, Core, Feature,
|
||||
Presentation), plus global rules from project config and engine reference docs.
|
||||
Story authors use it so stories inherit the correct architectural rules without
|
||||
reading every ADR.
|
||||
|
||||
The skill only includes Accepted ADRs; Proposed ADRs are excluded and noted. It
|
||||
has no director gates. The skill asks "May I write" before writing
|
||||
`docs/architecture/control-manifest.md`.
|
||||
The skill counts ADRs first, resolves each ADR's `## Status` with a Grep before
|
||||
reading any ADR body, and builds the manifest from the Accepted set only. It
|
||||
previews rule counts per layer, runs the **TD-MANIFEST** director gate when the
|
||||
review mode is `full` (skipped with a note in `solo` and `lean`), then asks
|
||||
"May I write the Control Manifest?" before writing
|
||||
`docs/architecture/control-manifest.md`. Verdicts: COMPLETE on write, BLOCKED
|
||||
when the user declines the write.
|
||||
|
||||
---
|
||||
|
||||
## 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: CREATED, BLOCKED
|
||||
- [ ] Contains "May I write" collaborative protocol language (for control-manifest.md)
|
||||
- [ ] Has a next-step handoff at the end (`/create-epics` or `/create-stories`)
|
||||
- [ ] Contains verdict keywords: COMPLETE, BLOCKED
|
||||
- [ ] Contains "May I write" collaborative protocol language (for the control manifest)
|
||||
- [ ] Has a next-step handoff at the end (`/create-epics` then `/create-stories`)
|
||||
- [ ] Documents that only Accepted ADRs are included (not Proposed)
|
||||
- [ ] Names gate TD-MANIFEST and its solo/lean skip notes
|
||||
|
||||
---
|
||||
|
||||
## Director Gate Checks
|
||||
|
||||
No director gates — this skill spawns no director gate agents. The control
|
||||
manifest is a mechanical extraction from Accepted ADRs; no creative or technical
|
||||
review gate is needed.
|
||||
One gate: **TD-MANIFEST** (`technical-director`,
|
||||
`.claude/docs/director-gates/td-manifest.md`), spawned after the user accepts the
|
||||
Phase 4 rule summary and before the Phase 5 write ask.
|
||||
|
||||
- `full` → spawned; receives the Control Manifest Preview, the ADRs covered, the
|
||||
engine version and any rules sourced from preferences or engine reference docs
|
||||
- `lean` → skipped; output notes "TD-MANIFEST skipped — Lean mode."
|
||||
- `solo` → skipped; output notes "TD-MANIFEST skipped — Solo mode."
|
||||
|
||||
Verdict handling: APPROVE → proceed to the write ask; CONCERNS → `AskUserQuestion`
|
||||
with `Revise flagged rules` / `Accept and proceed` / `Discuss further`; REJECT →
|
||||
the manifest is not written, flagged rules are fixed and the summary re-presented;
|
||||
NOT ASSESSED [missing input] → never read as APPROVE: the missing input is named,
|
||||
then supplied and the gate re-run, or the run goes on with
|
||||
`TD-MANIFEST: NOT ASSESSED — [input]` stated in the output and the Verdict line.
|
||||
|
||||
---
|
||||
|
||||
@@ -41,127 +59,176 @@ review gate is needed.
|
||||
### Case 1: Happy Path — 4 Accepted ADRs create a correct manifest
|
||||
|
||||
**Fixture:**
|
||||
- `docs/architecture/` contains 4 ADR files, all with `Status: Accepted`
|
||||
- Each ADR has a "Required Patterns" and/or "Forbidden Patterns" section
|
||||
- `docs/architecture/` contains `adr-0001-*.md` … `adr-0004-*.md`, each with a
|
||||
`## Status` section reading `Accepted`
|
||||
- Each ADR has `## Decision` (with "must"/"always" statements) and
|
||||
`## Alternatives Considered` (with rejected alternatives)
|
||||
- No existing `docs/architecture/control-manifest.md`
|
||||
- Review mode resolves to `solo`
|
||||
|
||||
**Input:** `/create-control-manifest`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads all ADR files in `docs/architecture/`
|
||||
2. Extracts Required Patterns, Forbidden Patterns, and key constraints from each
|
||||
3. Drafts the manifest with correct section structure
|
||||
4. Shows the draft manifest to the user
|
||||
5. Asks "May I write `docs/architecture/control-manifest.md`?"
|
||||
6. Writes the manifest after approval
|
||||
1. Globs `docs/architecture/adr-*.md` (N = 4), then Greps `^## Status` to resolve
|
||||
the Accepted set before reading any ADR body
|
||||
2. Greps only the Decision / Alternatives Considered / Performance Implications /
|
||||
Engine Compatibility sections of the Accepted ADRs
|
||||
3. Reports "Loaded 4 Accepted ADRs, engine: [name + version]."
|
||||
4. Shows the Control Manifest Preview (rule counts per layer, ADRs covered) and
|
||||
asks "Does this rule summary look complete?"
|
||||
5. Notes "TD-MANIFEST skipped — Solo mode."
|
||||
6. Asks "May I write the Control Manifest?" with option
|
||||
`[A] Yes — write to docs/architecture/control-manifest.md`
|
||||
7. Writes the manifest after approval; Verdict: COMPLETE
|
||||
|
||||
**Assertions:**
|
||||
- [ ] All 4 Accepted ADRs are represented in the manifest
|
||||
- [ ] Manifest includes distinct sections for Required Patterns and Forbidden Patterns
|
||||
- [ ] Manifest includes the source ADR number for each constraint
|
||||
- [ ] "May I write" is asked before writing
|
||||
- [ ] Skill does NOT write without approval
|
||||
- [ ] Verdict is CREATED after writing
|
||||
- [ ] All 4 Accepted ADRs are listed under `ADRs Covered` in the manifest header
|
||||
- [ ] Each layer section has `### Required Patterns` and `### Forbidden Approaches`
|
||||
- [ ] Every rule carries its source — `— source: [ADR-NNNN]` for a layer rule; a global rule names its `project.yaml` / `technical-preferences.md` key or engine-reference file (e.g. `deprecated-apis.md`)
|
||||
- [ ] Preview is shown and "Does this rule summary look complete?" is asked before any write ask
|
||||
- [ ] "TD-MANIFEST skipped — Solo mode." appears; no technical-director is spawned
|
||||
- [ ] Skill does NOT write before the "May I write the Control Manifest?" approval
|
||||
- [ ] Verdict is COMPLETE after writing
|
||||
|
||||
---
|
||||
|
||||
### Case 2: Failure Path — No ADRs found
|
||||
|
||||
**Fixture:**
|
||||
- `docs/architecture/` directory exists but contains no ADR files
|
||||
- `docs/architecture/` directory exists but contains no `adr-*.md` files
|
||||
|
||||
**Input:** `/create-control-manifest`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads `docs/architecture/` and finds no ADR files
|
||||
2. Skill outputs: "No ADRs found. Run `/architecture-decision` to create ADRs before generating the control manifest."
|
||||
3. Skill exits without creating any file
|
||||
4. Verdict is BLOCKED
|
||||
1. Glob returns N = 0
|
||||
2. Skill outputs: "No ADRs found — run `/architecture-decision` before building a
|
||||
control manifest."
|
||||
3. Skill stops — no Status Grep, no preview, no write ask, no file written
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Skill outputs a clear error when no ADRs are found
|
||||
- [ ] No control manifest file is written
|
||||
- [ ] The "No ADRs found" message is printed
|
||||
- [ ] Skill recommends `/architecture-decision` as the next action
|
||||
- [ ] Verdict is BLOCKED (not an error crash)
|
||||
- [ ] No control manifest file is written and no "May I write" ask is shown
|
||||
- [ ] Verdict COMPLETE is NOT emitted (the skill stops at Phase 1)
|
||||
|
||||
---
|
||||
|
||||
### Case 3: Mixed ADR Statuses — Only Accepted ADRs included
|
||||
|
||||
**Fixture:**
|
||||
- `docs/architecture/` contains 3 Accepted ADRs and 2 Proposed ADRs
|
||||
- `docs/architecture/` contains 5 ADRs: 3 with `## Status` Accepted, 2 with
|
||||
`## Status` Proposed (ADR-0004, ADR-0005)
|
||||
|
||||
**Input:** `/create-control-manifest`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads all ADR files and filters by Status: Accepted
|
||||
2. Manifest is drafted from the 3 Accepted ADRs only
|
||||
3. Output notes: "2 Proposed ADRs were excluded: [adr-NNN-name, adr-NNN-name]"
|
||||
4. User sees which ADRs were excluded before approving the write
|
||||
5. Asks "May I write `docs/architecture/control-manifest.md`?"
|
||||
1. N = 5; the `^## Status` Grep returns 5 matches, 3 reading Accepted — the
|
||||
"some Accepted" row applies and the Accepted set A = the 3 ADRs
|
||||
2. Section extraction is filtered to set A
|
||||
3. Preview reports "Loaded 3 Accepted ADRs", `ADRs covered` lists only the 3, and
|
||||
`ADRs excluded` names ADR-0004 (Proposed) and ADR-0005 (Proposed)
|
||||
4. Proceeds without asking about Proposed ADRs (that ask is reserved for the
|
||||
none-Accepted case)
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Only the 3 Accepted ADRs appear in the manifest content
|
||||
- [ ] Excluded Proposed ADRs are listed by name in the output
|
||||
- [ ] User sees the exclusion list before approving the write
|
||||
- [ ] Skill does NOT silently omit Proposed ADRs without noting them
|
||||
- [ ] Status is resolved with the `^## Status` Grep before any ADR section is read
|
||||
- [ ] The preview's `ADRs covered` and the manifest's `ADRs Covered` list exactly the 3 Accepted ADRs
|
||||
- [ ] Both excluded ADRs are named, with their status, in the preview the user sees before approving — the skill does not silently omit them
|
||||
- [ ] No rule in the manifest is sourced from either Proposed ADR
|
||||
- [ ] The "none Accepted — proceed with Proposed or stop?" ask is NOT shown for this fixture
|
||||
|
||||
---
|
||||
|
||||
### Case 4: Edge Case — Manifest already exists
|
||||
### Case 4: Edge Case — Regenerating an existing manifest
|
||||
|
||||
**Fixture:**
|
||||
- `docs/architecture/control-manifest.md` already exists (version 1, dated last week)
|
||||
- `docs/architecture/` contains Accepted ADRs (some new since last manifest)
|
||||
- `docs/architecture/control-manifest.md` already exists with
|
||||
`Manifest Version` and `Last Updated` both dated last week
|
||||
- `docs/architecture/` contains Accepted ADRs, one of them accepted since then
|
||||
- `production/epics/` already holds epics with stories, so the first-run
|
||||
`/create-epics` next step does not apply
|
||||
|
||||
**Input:** `/create-control-manifest`
|
||||
**Input:** `/create-control-manifest update`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill detects existing manifest and reads its version number / date
|
||||
2. Skill offers to regenerate: "control-manifest.md already exists (v1, [date]). Regenerate with current ADRs?"
|
||||
3. If user confirms: skill drafts updated manifest, increments version number
|
||||
4. Asks "May I write `docs/architecture/control-manifest.md`?" (overwrite)
|
||||
5. Writes updated manifest after approval
|
||||
1. Skill rebuilds the manifest from the current Accepted ADRs (same Phases 1–4)
|
||||
2. Asks "May I write the Control Manifest?" before overwriting
|
||||
3. The new manifest's `Manifest Version` and `Last Updated` are both today's date
|
||||
4. After writing, prints "Updated. Recommend notifying the team of changed rules —
|
||||
especially any new Forbidden entries."
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Skill reads and reports the existing manifest version before offering to regenerate
|
||||
- [ ] User is offered a regenerate/skip choice — not auto-overwritten
|
||||
- [ ] Updated manifest has an incremented version number
|
||||
- [ ] "May I write" is asked before overwriting the existing file
|
||||
- [ ] The existing file is not overwritten before "May I write the Control Manifest?" is approved
|
||||
- [ ] The newly accepted ADR appears in `ADRs Covered`
|
||||
- [ ] `Manifest Version` equals `Last Updated` and is the generation date (not a v1→v2 counter)
|
||||
- [ ] The regeneration next-step ("Updated. Recommend notifying the team…") is shown instead of the first-run `/create-epics` handoff
|
||||
|
||||
---
|
||||
|
||||
### Case 5: Director Gate — No gate spawned; no review-mode.txt read
|
||||
### Case 5: Director Gate — TD-MANIFEST in full review mode returns REJECT
|
||||
|
||||
**Fixture:**
|
||||
- 4 Accepted ADRs exist
|
||||
- `production/session-state/review-mode.txt` exists with `full`
|
||||
- Review mode resolves to `full`
|
||||
- TD-MANIFEST returns REJECT, naming one rule that has no source ADR
|
||||
|
||||
**Input:** `/create-control-manifest`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads ADRs and drafts manifest
|
||||
2. Skill does NOT read `production/session-state/review-mode.txt`
|
||||
3. No director gate agents are spawned at any point
|
||||
4. Skill proceeds directly to "May I write" after drafting
|
||||
5. Review mode setting has no effect on this skill's behavior
|
||||
1. Skill shows the Phase 4 preview; user picks
|
||||
`[A] Yes — looks good, run the director review and write the manifest`
|
||||
2. Spawns `technical-director` via `Agent` with gate TD-MANIFEST, passing the
|
||||
preview (full rule list), ADRs covered and engine version
|
||||
3. On REJECT: does not write the manifest; fixes the flagged rule and re-presents
|
||||
the summary
|
||||
4. "May I write the Control Manifest?" is not asked while the REJECT stands
|
||||
|
||||
**Assertions:**
|
||||
- [ ] No director gate agents are spawned (no CD-, TD-, PR-, AD- prefixed gates)
|
||||
- [ ] Skill does NOT read `production/session-state/review-mode.txt`
|
||||
- [ ] Output contains no "Gate: [GATE-ID]" or gate-skipped entries
|
||||
- [ ] The manifest is generated from ADRs alone, with no external gate review
|
||||
- [ ] TD-MANIFEST is spawned only after the Phase 4 summary is accepted
|
||||
- [ ] The gate receives the rule list, ADRs covered and engine version
|
||||
- [ ] On REJECT no manifest file is written
|
||||
- [ ] The flagged rule is revised and the summary re-presented before any write ask
|
||||
- [ ] No "TD-MANIFEST skipped" note appears in `full` mode
|
||||
|
||||
---
|
||||
|
||||
### Case 6: Edge Case — No Accepted ADR, and ADRs with no `## Status`
|
||||
|
||||
**Fixture (none Accepted):**
|
||||
- `docs/architecture/` contains 3 ADRs, each with `## Status` Proposed
|
||||
|
||||
**Fixture (malformed):**
|
||||
- `docs/architecture/` contains 3 ADRs, none with a `## Status` section
|
||||
|
||||
**Input (both fixtures):** `/create-control-manifest`
|
||||
|
||||
**Expected behavior (none Accepted):**
|
||||
1. N = 3; the `^## Status` Grep matches 3, none reading Accepted
|
||||
2. Reports "3 ADRs found, none Accepted. A manifest built from Proposed ADRs would
|
||||
encode decisions that may still change." and asks whether to proceed with the
|
||||
Proposed ADRs or stop
|
||||
|
||||
**Expected behavior (malformed):**
|
||||
1. N = 3; the `^## Status` Grep matches nothing
|
||||
2. Reports "3 ADRs found, none has a `## Status` section — acceptance cannot be
|
||||
determined. Run `/architecture-decision retrofit [file]` on each." and stops
|
||||
|
||||
**Assertions:**
|
||||
- [ ] None Accepted: the ask is shown and no empty manifest is written
|
||||
- [ ] Malformed: the run stops — the ADRs are not treated as Accepted and no manifest is written
|
||||
- [ ] Malformed: the retrofit command reads `/architecture-decision retrofit [file]` — the form that skill parses
|
||||
- [ ] In neither fixture is a rule summary previewed or a "May I write" ask shown before the user proceeds
|
||||
|
||||
---
|
||||
|
||||
## Protocol Compliance
|
||||
|
||||
- [ ] Reads all ADR files before drafting manifest
|
||||
- [ ] Only Accepted ADRs included — Proposed ones noted as excluded
|
||||
- [ ] Manifest draft shown to user before "May I write" ask
|
||||
- [ ] "May I write `docs/architecture/control-manifest.md`?" asked before writing
|
||||
- [ ] No director gates — no review-mode.txt read
|
||||
- [ ] Ends with next-step handoff: `/create-epics` or `/create-stories`
|
||||
- [ ] Counts ADRs and resolves `## Status` before reading ADR sections
|
||||
- [ ] Only Accepted ADRs included, and every excluded ADR is named with its status in the preview; the none-Accepted and no-`## Status` cases stop or ask instead of emitting an empty manifest
|
||||
- [ ] Rule summary shown to user before the gate and before "May I write"
|
||||
- [ ] "May I write the Control Manifest?" asked before writing `docs/architecture/control-manifest.md`
|
||||
- [ ] TD-MANIFEST runs in `full`, is skipped with a named note in `lean`/`solo`
|
||||
- [ ] Ends with next-step handoff: `/create-epics layer: foundation` then `/create-stories [epic-slug]`
|
||||
|
||||
---
|
||||
|
||||
@@ -169,7 +236,9 @@ review gate is needed.
|
||||
|
||||
- The exact section structure of the generated manifest (constraint tables, pattern
|
||||
lists) is defined by the skill body and not re-enumerated in test assertions.
|
||||
- The `version` field incrementing logic (v1 → v2) is tested via Case 4 but exact
|
||||
version numbering format is not fixture-locked.
|
||||
- ADR parsing (extracting Required/Forbidden Patterns) depends on consistent ADR
|
||||
structure — tested implicitly via Case 1's fixture.
|
||||
- What happens after the user proceeds with Proposed ADRs (Case 6) is not
|
||||
fixture-tested.
|
||||
- TD-MANIFEST APPROVE, CONCERNS and NOT ASSESSED paths, and the `lean` skip note,
|
||||
are not separately fixture-tested.
|
||||
- Relevance filtering of `deprecated-apis.md` entries (2D vs 3D scoping) is not
|
||||
covered.
|
||||
|
||||
@@ -2,189 +2,307 @@
|
||||
|
||||
## Skill Summary
|
||||
|
||||
`/create-epics` reads all approved GDDs and translates them into EPIC.md files,
|
||||
one per system. Epics are organized by layer (Foundation → Core → Feature →
|
||||
Presentation) and processed in priority order within each layer. Each EPIC.md
|
||||
includes scope, governing ADRs, GDD requirements, engine risk level, and a
|
||||
Definition of Done. The skill asks "May I write" before creating each EPIC file.
|
||||
`/create-epics` reads in-scope GDDs, the architecture document, Accepted ADRs and
|
||||
the TR registry, and turns each system into one epic mapped to an architectural
|
||||
module. Systems are processed in layer order (Foundation → Core → Feature →
|
||||
Presentation), and within a layer in `systems-index.md` order. Each epic is
|
||||
presented (layer, GDD, architecture module, governing ADRs, engine risk, ADR
|
||||
coverage, untraced requirements) and the user is asked "Shall I create Epic:
|
||||
[name]?" before anything is written.
|
||||
|
||||
In `full` review mode, a PR-EPIC gate (producer) runs after drafting epics and
|
||||
before writing any files. In `lean` or `solo` mode, PR-EPIC is skipped and noted.
|
||||
Epics are written to `production/epics/[layer]/EPIC-[name].md`.
|
||||
Epics are written to `production/epics/[epic-slug]/EPIC.md`, each after its own
|
||||
"May I write `production/epics/[epic-slug]/EPIC.md` and add its row to
|
||||
`production/epics/index.md` (creating it if absent)?" ask, which names the index
|
||||
it then creates or updates. An EPIC.md that already exists
|
||||
is never overwritten: the user chooses update-in-place (its Stories table kept) or
|
||||
skip. In `full` review mode the
|
||||
PR-EPIC gate (producer) runs after all epics for the layer are defined and before
|
||||
any file is written; in `lean` and `solo` it is skipped with a note. Review mode
|
||||
comes from `resolve_config` (`review_mode`), overridable per run with `--review`.
|
||||
Verdicts: COMPLETE (N epics written) or BLOCKED (user declined all epics, stopped
|
||||
at the gate, or no eligible systems found).
|
||||
|
||||
---
|
||||
|
||||
## 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: CREATED, BLOCKED
|
||||
- [ ] Contains verdict keywords: COMPLETE, BLOCKED
|
||||
- [ ] Contains "May I write" collaborative protocol language (per-epic approval)
|
||||
- [ ] Has a next-step handoff at the end (`/create-stories`)
|
||||
- [ ] Has a next-step handoff at the end (`/create-stories [epic-slug]`)
|
||||
- [ ] Documents PR-EPIC gate behavior: runs in full mode; skipped in lean/solo
|
||||
|
||||
---
|
||||
|
||||
## Director Gate Checks
|
||||
|
||||
In `full` mode: PR-EPIC (producer) gate runs after epics are drafted and before
|
||||
any epic file is written. If PR-EPIC returns CONCERNS, epics are revised before
|
||||
the "May I write" ask.
|
||||
In `full` mode: PR-EPIC (`producer`, `.claude/docs/director-gates/pr-epic.md`)
|
||||
runs once all epics for the current layer are defined and before any epic file is
|
||||
written. Verdicts: REALISTIC → proceed to the write asks; CONCERNS →
|
||||
`AskUserQuestion` with `[A] Proceed as planned` / `[B] Revise epic boundaries` /
|
||||
`[C] Stop`; UNREALISTIC → offer to split or merge epics, revise, present the
|
||||
revised epics again, and re-run the gate before writing. CONCERNS `[B]` likewise
|
||||
re-presents the revised epics before the gate re-runs. NOT ASSESSED [missing
|
||||
input] → never read as REALISTIC: the input is supplied and the gate re-run, or
|
||||
the run goes on with `PR-EPIC: NOT ASSESSED — [input]` stated in the output and
|
||||
the Verdict line.
|
||||
|
||||
In `lean` mode: PR-EPIC is skipped. Output notes: "PR-EPIC skipped — lean mode".
|
||||
In `lean` mode: PR-EPIC is skipped. Output notes: "PR-EPIC skipped — Lean mode."
|
||||
|
||||
In `solo` mode: PR-EPIC is skipped. Output notes: "PR-EPIC skipped — solo mode".
|
||||
In `solo` mode: PR-EPIC is skipped. Output notes: "PR-EPIC skipped — Solo mode."
|
||||
|
||||
---
|
||||
|
||||
## Test Cases
|
||||
|
||||
### Case 1: Happy Path — Two approved GDDs create two EPIC files
|
||||
### Case 1: Happy Path — Two approved GDDs create two epics
|
||||
|
||||
**Fixture:**
|
||||
- `design/gdd/systems-index.md` exists with 2 systems listed
|
||||
- Both systems have approved GDDs in `design/gdd/`
|
||||
- `docs/architecture/architecture.md` exists with matching modules
|
||||
- At least one Accepted ADR exists for each system
|
||||
- `production/session-state/review-mode.txt` contains `lean`
|
||||
- `project.yaml`: `engine.name: Godot`, `modes.workflow: full`, `modes.review_mode: lean`
|
||||
- `design/gdd/systems-index.md` lists 2 Foundation systems
|
||||
- Both systems have Approved GDDs in `design/gdd/`, each with a `## Summary`
|
||||
- `docs/architecture/architecture.md` has a module for each system
|
||||
- Accepted ADRs cover every TR-ID for both systems in `docs/architecture/tr-registry.yaml`;
|
||||
the first system has two governing ADRs whose Engine Compatibility rates
|
||||
Knowledge Risk LOW and HIGH
|
||||
- `docs/architecture/control-manifest.md` exists
|
||||
- No `production/epics/` directory
|
||||
|
||||
**Input:** `/create-epics`
|
||||
**Input:** `/create-epics layer: foundation`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads systems index and both GDDs
|
||||
2. Drafts 2 EPIC definitions (layer, GDD path, ADRs, requirements, engine risk)
|
||||
3. PR-EPIC gate is skipped (lean mode) — noted in output
|
||||
4. For each epic: asks "May I write `production/epics/[layer]/EPIC-[name].md`?"
|
||||
5. After approval: writes both EPIC files
|
||||
1. Globs `design/gdd/*.md` (excluding systems-index and other non-system docs)
|
||||
to establish N, then Greps `^## Summary` to scope the Foundation systems
|
||||
2. Reads the 2 in-scope GDDs, `architecture.md`, the Decision / GDD Requirements
|
||||
Addressed / Engine Compatibility sections of the in-scope ADRs, the TR
|
||||
registry and the manifest header; reports "Loaded 2 GDDs, [M] ADRs, engine: …"
|
||||
3. For each system: presents the epic block and asks "Shall I create Epic: [name]?"
|
||||
4. Notes "PR-EPIC skipped — Lean mode."
|
||||
5. For each epic: asks "May I write `production/epics/[epic-slug]/EPIC.md` and
|
||||
add its row to `production/epics/index.md` (creating it if absent)?" and writes
|
||||
both after approval
|
||||
6. Creates or updates `production/epics/index.md`
|
||||
7. Verdict: COMPLETE — 2 epic(s) written; next step `/create-stories [epic-slug]`
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Epic summary is shown before any write ask
|
||||
- [ ] "May I write" is asked per-epic (not once for all epics together)
|
||||
- [ ] Each EPIC.md contains: layer, GDD path, governing ADRs, requirements table, Definition of Done
|
||||
- [ ] PR-EPIC skip is noted in output
|
||||
- [ ] `production/epics/index.md` is updated after writing
|
||||
- [ ] Skill does NOT write EPIC files without per-epic approval
|
||||
- [ ] Each epic block is shown and "Shall I create Epic: [name]?" asked before any write ask
|
||||
- [ ] "May I write" is asked per epic (not once for both)
|
||||
- [ ] Files land at `production/epics/[epic-slug]/EPIC.md`
|
||||
- [ ] Each EPIC.md contains Layer, GDD path, Architecture Module, Governing ADRs table, GDD Requirements table, Definition of Done
|
||||
- [ ] The first epic's Engine Risk is HIGH — the highest among its governing ADRs, not the first or the average
|
||||
- [ ] The Definition of Done asks Logic and Integration stories for passing tests under `tests/` (the Godot test root) and Visual/Feel and UI stories for retained screenshots in `production/qa/evidence/` — each screen touched for UI, plus a lead sign-off for Visual/Feel
|
||||
- [ ] "PR-EPIC skipped — Lean mode." appears; no producer is spawned
|
||||
- [ ] `production/epics/index.md` is created or updated after writing, and only after an ask that named it
|
||||
- [ ] Verdict is COMPLETE and names `/create-stories [epic-slug]`
|
||||
|
||||
---
|
||||
|
||||
### Case 2: Failure Path — No approved GDDs found
|
||||
### Case 2: Failure Path — No system GDDs found
|
||||
|
||||
**Fixture:**
|
||||
- `design/gdd/systems-index.md` exists
|
||||
- No GDDs in `design/gdd/` have approved status (all are Draft or In Progress)
|
||||
- `project.yaml`: `modes.workflow: full`
|
||||
- `design/gdd/` contains only `game-concept.md` and `systems-index.md` (no
|
||||
system GDDs)
|
||||
|
||||
**Input:** `/create-epics`
|
||||
**Input:** `/create-epics all`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads systems index and attempts to find approved GDDs
|
||||
2. No approved GDDs found
|
||||
3. Skill outputs: "No approved GDDs to convert. GDDs must be Approved before creating epics."
|
||||
4. Skill suggests running `/design-system` and completing GDD approval first
|
||||
5. Skill exits without creating any EPIC files
|
||||
1. Globs `design/gdd/*.md` excluding the non-system docs — N = 0
|
||||
2. Reports "No system GDDs found in `design/gdd/` — run `/design-system` first"
|
||||
and stops
|
||||
3. No epic is presented, no gate runs, no file is written
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Skill stops cleanly with a clear message when no approved GDDs exist
|
||||
- [ ] No EPIC files are written
|
||||
- [ ] Skill recommends the correct next action
|
||||
- [ ] Verdict is BLOCKED
|
||||
- [ ] `game-concept.md` and `systems-index.md` are not counted as system GDDs
|
||||
- [ ] The "No system GDDs found … run `/design-system` first" message is printed
|
||||
- [ ] No "Shall I create Epic" or "May I write" ask is shown and no EPIC.md or index.md is written
|
||||
- [ ] Verdict is BLOCKED (no eligible systems found), not COMPLETE
|
||||
|
||||
---
|
||||
|
||||
### Case 3: Director Gate — Full mode spawns PR-EPIC before writing
|
||||
|
||||
**Fixture:**
|
||||
- 2 approved GDDs exist
|
||||
- `production/session-state/review-mode.txt` contains `full`
|
||||
- 2 Approved GDDs, architecture, ADRs, TR registry and control manifest as in Case 1
|
||||
- `project.yaml`: `modes.workflow: full`, `modes.review_mode: full` — the workflow
|
||||
is pinned because an unset one resolves to `minimal`, where the skill reads the
|
||||
brief instead of the GDDs and the gate never comes into play
|
||||
- PR-EPIC returns REALISTIC
|
||||
|
||||
**Input:** `/create-epics layer: foundation`
|
||||
|
||||
**Full mode expected behavior:**
|
||||
1. Skill drafts both epics
|
||||
2. PR-EPIC gate spawns and reviews the epic drafts
|
||||
3. If PR-EPIC returns APPROVED: "May I write" ask proceeds normally
|
||||
1. Both epics are presented and accepted via "Shall I create Epic: [name]?"
|
||||
2. `producer` is spawned via `Agent` with gate PR-EPIC, receiving the epic
|
||||
structure summary, the layer, milestone timeline and team capacity
|
||||
3. On REALISTIC: the per-epic "May I write" asks proceed
|
||||
4. Epic files are written after approval
|
||||
|
||||
**Assertions (full mode):**
|
||||
- [ ] PR-EPIC gate appears in output as an active gate
|
||||
- [ ] PR-EPIC is spawned once, after both epics are defined
|
||||
- [ ] PR-EPIC runs before any "May I write" ask
|
||||
- [ ] Epic files are NOT written before PR-EPIC completes
|
||||
- [ ] No EPIC.md is written before PR-EPIC resolves
|
||||
|
||||
**Fixture (lean mode):**
|
||||
- Same GDDs
|
||||
- `production/session-state/review-mode.txt` contains `lean`
|
||||
**Fixture (per-run override):**
|
||||
- Same project, `modes.workflow: full`, `modes.review_mode: full`
|
||||
- Input: `/create-epics layer: foundation --review lean`
|
||||
|
||||
**Lean mode expected behavior:**
|
||||
1. Epics are drafted
|
||||
**Override expected behavior:**
|
||||
1. `--review lean` overrides the resolved `full`
|
||||
2. PR-EPIC is skipped — noted in output
|
||||
3. "May I write" ask proceeds directly
|
||||
3. "May I write" asks proceed directly
|
||||
|
||||
**Assertions (lean mode):**
|
||||
- [ ] "PR-EPIC skipped — lean mode" appears in output
|
||||
- [ ] Skill proceeds to "May I write" without waiting for PR-EPIC
|
||||
**Assertions (override):**
|
||||
- [ ] "PR-EPIC skipped — Lean mode." appears in output
|
||||
- [ ] No producer agent is spawned and the write asks follow the epic definitions directly
|
||||
|
||||
---
|
||||
|
||||
### Case 4: Edge Case — Epic already exists for a GDD
|
||||
### Case 4: Edge Case — Untraced requirements at full workflow
|
||||
|
||||
**Fixture:**
|
||||
- `production/epics/[layer]/EPIC-[name].md` already exists for one of the approved GDDs
|
||||
- The other GDD has no existing EPIC file
|
||||
- `project.yaml`: `modes.workflow: full`, `modes.review_mode: solo`
|
||||
- One Approved Foundation GDD whose system has 5 TR-IDs in `tr-registry.yaml`;
|
||||
Accepted ADRs cover 3 of them (2 untraced)
|
||||
|
||||
**Input:** `/create-epics`
|
||||
**Input:** `/create-epics [system-name]`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill detects the existing EPIC file for the first system
|
||||
2. Skill offers to update rather than overwrite: "EPIC-[name].md already exists. Update it, or skip?"
|
||||
3. For the second system (no existing file): proceeds normally with "May I write"
|
||||
1. Epic block shows "GDD Requirements Covered by ADRs: 3 / 5" and lists the 2
|
||||
untraced TR-IDs under "Untraced Requirements"
|
||||
2. Warns: "⚠️ 2 requirements in [system] have no ADR. The epic can be created, but
|
||||
`/create-stories` will write their stories with no governing ADR (`ADR: N/A`)
|
||||
and `Status: Ready` — nothing downstream blocks them, so they would be
|
||||
implemented without architectural guidance. Run `/architecture-decision` first
|
||||
if they need a decision, or proceed and accept the gap."
|
||||
3. Asks "Shall I create Epic: [name]?" with `[A] Yes, create it` /
|
||||
`[B] Skip this epic` / `[C] Pause — I need to write ADRs first`
|
||||
4. On [A]: notes "PR-EPIC skipped — Solo mode.", asks "May I write", and the
|
||||
EPIC.md GDD Requirements table marks the 2 rows `❌ No ADR`
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Skill detects existing EPIC files before writing
|
||||
- [ ] User is offered "update" or "skip" options — not auto-overwritten
|
||||
- [ ] The new system's EPIC is created normally without conflict
|
||||
- [ ] Coverage count and the 2 untraced TR-IDs are shown before the create ask
|
||||
- [ ] The untraced-requirements warning names `/architecture-decision` and says what actually happens downstream: the stories are written `Ready` with no governing ADR — it does not claim they will be Blocked
|
||||
- [ ] Option `[C] Pause — I need to write ADRs first` is offered
|
||||
- [ ] The written EPIC.md marks the untraced rows `❌ No ADR` (not silently dropped)
|
||||
|
||||
---
|
||||
|
||||
### Case 5: Director Gate — PR-EPIC returns CONCERNS
|
||||
|
||||
**Fixture:**
|
||||
- 2 approved GDDs exist
|
||||
- `production/session-state/review-mode.txt` contains `full`
|
||||
- PR-EPIC gate returns CONCERNS (e.g., scope of one epic is too large)
|
||||
- 2 Approved GDDs, architecture, ADRs, TR registry and control manifest as in Case 1
|
||||
- `project.yaml`: `modes.workflow: full`, `modes.review_mode: full`
|
||||
- PR-EPIC returns CONCERNS (one epic's scope is too large)
|
||||
|
||||
**Input:** `/create-epics`
|
||||
**Input:** `/create-epics layer: foundation`
|
||||
|
||||
**Expected behavior:**
|
||||
1. PR-EPIC gate spawns and returns CONCERNS with specific feedback
|
||||
2. Skill surfaces the concerns to the user before any write ask
|
||||
3. User is given options: revise epics, accept concerns and proceed, or stop
|
||||
4. If user revises: updated epic drafts are shown before the "May I write" ask
|
||||
5. Skill does NOT write epics while CONCERNS are unaddressed
|
||||
1. PR-EPIC is spawned and returns CONCERNS with specific feedback
|
||||
2. Skill presents the producer's assessment before any write ask
|
||||
3. `AskUserQuestion`: "Producer raised concerns about the epic structure. How do
|
||||
you want to proceed?" with `[A] Proceed as planned — I accept the producer's
|
||||
concerns` / `[B] Revise epic boundaries — split or merge as recommended` /
|
||||
`[C] Stop — I want to reconsider the scope`
|
||||
4. [B]: epic definitions are revised from Step 4 and PR-EPIC is re-run
|
||||
5. [C]: stops with Verdict: BLOCKED — user wants to reconsider epic scope
|
||||
|
||||
**Assertions:**
|
||||
- [ ] CONCERNS from PR-EPIC are shown to the user before writing
|
||||
- [ ] Skill does NOT auto-write epics when CONCERNS are returned
|
||||
- [ ] User is given a clear choice to revise, proceed, or stop
|
||||
- [ ] Revised epic drafts are re-shown after revision before final approval
|
||||
- [ ] The producer's CONCERNS are shown to the user before any "May I write" ask
|
||||
- [ ] Skill does NOT write epics while the gate is unresolved
|
||||
- [ ] All three options ([A] proceed / [B] revise / [C] stop) are offered
|
||||
- [ ] Choosing [B] re-presents the revised epics and re-runs PR-EPIC before any write ask
|
||||
- [ ] Choosing [C] ends with Verdict: BLOCKED and no files written
|
||||
|
||||
---
|
||||
|
||||
### Case 6: Edge Case — An EPIC.md already exists for one system
|
||||
|
||||
**Fixture:**
|
||||
- As Case 1 (`modes.workflow: full`, `modes.review_mode: lean`)
|
||||
- `production/epics/[first-slug]/EPIC.md` already exists, with
|
||||
`**Stories**: 3 stories` in its header and a 3-row `## Stories` table;
|
||||
`production/epics/index.md` has its row with `3 stories`
|
||||
- The second system has no EPIC.md
|
||||
|
||||
**Input:** `/create-epics layer: foundation`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Both epics are presented and accepted via "Shall I create Epic: [name]?"
|
||||
2. For the first system the skill does not overwrite: it asks "An EPIC.md already
|
||||
exists for [name]. Update it in place, or skip it?" with `[A] Update in place —
|
||||
keep its Stories table` / `[B] Skip this epic`; the user picks [A]
|
||||
3. The update rewrites the header fields other than `Stories`, the Overview,
|
||||
Governing ADRs, GDD Requirements and Definition of Done, and leaves the
|
||||
`**Stories**` line and the `## Stories` table as they were
|
||||
4. For the second system the normal "May I write `…/EPIC.md` and add its row to
|
||||
`production/epics/index.md`…?" ask follows
|
||||
5. `production/epics/index.md` keeps one row for the first epic, still `3 stories`,
|
||||
and gains a row for the second
|
||||
|
||||
**Assertions:**
|
||||
- [ ] The existing file is detected before any write, and update / skip is offered — it is not overwritten
|
||||
- [ ] After the update, the `**Stories**` header line and all 3 `## Stories` rows are unchanged
|
||||
- [ ] The index has no duplicate row for the first epic and does not reset it to `Not yet created`
|
||||
- [ ] The second system's EPIC.md is written only after its own "May I write" ask
|
||||
|
||||
---
|
||||
|
||||
### Case 7: Standard tier — GDDs without `## Summary`, one untraced non-critical requirement
|
||||
|
||||
**Fixture:**
|
||||
- `project.yaml`: `modes.workflow: standard`, `modes.review_mode: solo`
|
||||
- `design/gdd/systems-index.md` lists one Foundation and one Core system; both
|
||||
GDDs predate `## Summary` (the Summary scan matches none of them)
|
||||
- `docs/architecture/architecture.md` has a module for each system, and
|
||||
`docs/architecture/tr-registry.yaml` holds both systems' TR-IDs
|
||||
- The Foundation system's TR-IDs are covered by an Accepted Foundation-layer ADR;
|
||||
one of the Core system's TR-IDs has no ADR
|
||||
- `docs/architecture/control-manifest.md` does not exist
|
||||
|
||||
**Input:** `/create-epics all`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Globs `design/gdd/*.md` for N = 2; the `^## Summary` scan returns 0 matches
|
||||
2. Notes once: "No `## Summary` sections found across 2 GDDs — scoping from
|
||||
`systems-index.md` instead of Summary." and full-reads both in-scope GDDs
|
||||
3. Proceeds without the control manifest (read if present, not required at
|
||||
`standard`)
|
||||
4. The Core epic lists its untraced TR-ID under "Untraced Requirements" as
|
||||
information only — no ⚠️ untraced-requirements warning, nothing blocked
|
||||
5. Notes "PR-EPIC skipped — Solo mode."; each epic is written after its own ask
|
||||
|
||||
**Assertions:**
|
||||
- [ ] A zero-match Summary scan is reported as such and both systems stay in scope — it is not read as "nothing in scope"
|
||||
- [ ] The missing control manifest does not stop the run at `standard`
|
||||
- [ ] The untraced non-critical requirement is listed, but the ⚠️ warning is not emitted
|
||||
- [ ] Both epics are written, each after its own "May I write" ask
|
||||
|
||||
---
|
||||
|
||||
## Protocol Compliance
|
||||
|
||||
- [ ] Epic drafts shown to user before any "May I write" ask
|
||||
- [ ] "May I write" asked per-epic, not once for the entire batch
|
||||
- [ ] Epic definitions shown to user before any "May I write" ask
|
||||
- [ ] "May I write" asked per epic, not once for the entire batch
|
||||
- [ ] An existing EPIC.md is updated in place or skipped by the user's choice — never overwritten
|
||||
- [ ] PR-EPIC gate (if active) runs before write asks — not after
|
||||
- [ ] Skipped gates noted by name and mode in output
|
||||
- [ ] EPIC.md content sourced only from GDDs, ADRs, and architecture docs — nothing invented
|
||||
- [ ] Ends with next-step handoff: `/create-stories [epic-slug]` per created epic
|
||||
- [ ] Never creates stories; ends with next-step handoff `/create-stories [epic-slug]` per created epic
|
||||
|
||||
---
|
||||
|
||||
## Coverage Notes
|
||||
|
||||
- Processing of Core, Feature, and Presentation layers follows the same per-epic
|
||||
pattern as Foundation — layer-specific ordering is not independently tested.
|
||||
- Engine risk level assignment (LOW/MEDIUM/HIGH) from governing ADRs is
|
||||
validated implicitly via Case 1's fixture structure.
|
||||
- The `layer: [name]` and `[system-name]` argument modes follow the same approval
|
||||
pattern as the default (all systems) mode.
|
||||
- Feature and Presentation layers follow the same per-epic pattern as Foundation
|
||||
and Core — layer-specific ordering is not independently tested.
|
||||
- The `minimal` tier (optional; decomposes from `design/game-brief.md`, stops
|
||||
without one) is not given a fixture.
|
||||
- The `## Summary` partial-adoption row (0 < M < N) is not separately tested; the
|
||||
zero-match row is Case 7.
|
||||
- PR-EPIC UNREALISTIC handling (revise, present the revised epics again, re-run
|
||||
the gate), a NOT ASSESSED gate answer, and the no-argument "Which layer or
|
||||
system…" ask are not separately tested.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -2,127 +2,204 @@
|
||||
|
||||
## Skill Summary
|
||||
|
||||
`/dev-story` reads a story file, loads all required context (referenced ADR,
|
||||
TR-ID from the registry, control manifest, engine preferences), implements the
|
||||
story, verifies that all acceptance criteria are met, and marks the story
|
||||
Complete. The skill routes implementation to the correct specialist agent based
|
||||
on the engine and file type — it does not write source code directly.
|
||||
`/dev-story` implements one story. It finds the story (argument, else the active
|
||||
story in `production/session-state/active.md`), resolves the workflow tier for the
|
||||
story's system, verifies required inputs per tier (TR registry, governing ADR,
|
||||
control manifest), reads the ADR's `## Status`, `## Last Verified` and `## Date` in
|
||||
one grep — a `Proposed`, `Deprecated` or `Superseded` status blocks the story at
|
||||
every tier, while a story whose ADR field reads `N/A` references none — and checks ADR
|
||||
freshness by comparing the story's `ADR Version` with the ADR's current version
|
||||
(`Last Verified`, else `Date`, else `unversioned` — the rule `/create-stories`
|
||||
stamps with). It checks the story's `Manifest Version` and its dependencies, asks
|
||||
to mark the story `In Progress`, and routes implementation to a programmer agent
|
||||
plus the project's engine specialist. It does not write source code itself, and
|
||||
every file it does write — story fields, `sprint-status.yaml`, a dependency's
|
||||
`Status`, a Config/Data file, Unity's `ScreenshotOnArg.cs` — follows an ask that
|
||||
names it; only the session-state checkpoint is written without one.
|
||||
|
||||
In `full` review mode, an LP-CODE-REVIEW gate runs before marking the story
|
||||
Complete. In `lean` or `solo` mode, LP-CODE-REVIEW is skipped and the story is
|
||||
marked Complete after the user confirms all criteria are met. The skill asks
|
||||
"May I write" before updating story status and before writing code files.
|
||||
After the agent returns it verifies the agent finished, runs the engine parse
|
||||
check, launches the build to observe anything player-visible (`Run result:`
|
||||
line), prints an "Implementation Complete" summary and overwrites the CHECKPOINT
|
||||
block in `active.md`, whose **Next step** follows the result: `/story-done` after
|
||||
Implementation Complete, `/dev-story` to resume after INCOMPLETE, the unblocking
|
||||
action after BLOCKED. It never closes the story it implements — `/story-done`
|
||||
does that; `/code-review` is recommended first at `standard`/`full`. At
|
||||
`qa.level: minimal` a Logic or Integration story's test requirement is waived and
|
||||
the waiver is printed; a UI or Visual/Feel story's screenshot is never waived, and
|
||||
the run-and-observe step runs at every level.
|
||||
|
||||
---
|
||||
|
||||
## 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, IN PROGRESS, NEEDS CHANGES
|
||||
- [ ] Contains "May I write" collaborative protocol language (story status + code files)
|
||||
- [ ] Has a next-step handoff at the end (`/story-done`)
|
||||
- [ ] Documents LP-CODE-REVIEW gate: active in full mode, skipped in lean/solo
|
||||
- [ ] Contains status keywords: BLOCKED, INCOMPLETE, In Progress, NOT VERIFIED
|
||||
- [ ] Contains "May I write" collaborative protocol language (its own asks for the files it writes; source and tests delegated to sub-agents)
|
||||
- [ ] Has a next-step handoff at the end (`/story-done`, with `/code-review` first at standard/full)
|
||||
- [ ] Documents per-tier input requirements (`full` / `standard` / `minimal`)
|
||||
- [ ] Notes that implementation is delegated to specialist agents (not done directly)
|
||||
|
||||
---
|
||||
|
||||
## Director Gate Checks
|
||||
|
||||
In `full` mode: LP-CODE-REVIEW gate runs after implementation is complete and all
|
||||
criteria are verified, before marking the story Complete.
|
||||
|
||||
In `lean` mode: LP-CODE-REVIEW is skipped. Output notes:
|
||||
"LP-CODE-REVIEW skipped — lean mode". Story is marked Complete after user confirms.
|
||||
|
||||
In `solo` mode: LP-CODE-REVIEW is skipped with equivalent notes.
|
||||
No director gates. `/dev-story` spawns implementation agents (a primary programmer
|
||||
and the engine specialist), not director review gates, and does not resolve
|
||||
`review_mode`. Code review is the separate `/code-review` skill, named as the next
|
||||
step at `standard`/`full`.
|
||||
|
||||
---
|
||||
|
||||
## Test Cases
|
||||
|
||||
### Case 1: Happy Path — Story implemented and marked Complete (full mode)
|
||||
### Case 1: Happy Path — Logic story implemented at full workflow
|
||||
|
||||
**Fixture:**
|
||||
- A story file exists at `production/epics/[layer]/story-[name].md` with:
|
||||
- `Status: Ready`
|
||||
- A TR-ID referencing a registered requirement
|
||||
- At least 2 Given-When-Then acceptance criteria
|
||||
- A test evidence path
|
||||
- Referenced ADR has `Status: Accepted`
|
||||
- `docs/architecture/control-manifest.md` exists
|
||||
- `.claude/docs/technical-preferences.md` has engine and language configured
|
||||
- `production/session-state/review-mode.txt` contains `full`
|
||||
- `project.yaml`: `engine.name: Godot`, `specialists.code: godot-gdscript-specialist`,
|
||||
`modes.workflow: full`, `qa.level: standard`
|
||||
- `production/epics/combat/story-001-damage-calc.md`: `Status: Ready`, Layer Core,
|
||||
Type Logic, `Requirement: TR-combat-001`, `ADR Governing Implementation: ADR-0003`,
|
||||
an `ADR Version` equal to ADR-0003's `## Last Verified` date, a `Manifest Version`
|
||||
equal to the manifest header date, Dependencies None, Test Evidence
|
||||
`tests/unit/combat/combat_damage_calc_test.gd`
|
||||
- `docs/architecture/tr-registry.yaml` has `TR-combat-001`; ADR-0003 exists and is
|
||||
Accepted; `docs/architecture/control-manifest.md` exists
|
||||
- `production/sprint-status.yaml` does not exist
|
||||
|
||||
**Input:** `/dev-story production/epics/[layer]/story-[name].md`
|
||||
**Input:** `/dev-story production/epics/combat/story-001-damage-calc.md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads the story file and all referenced context
|
||||
2. Skill verifies the ADR is Accepted (no block)
|
||||
3. Skill routes implementation to the correct specialist agent
|
||||
4. All acceptance criteria are verified as met
|
||||
5. LP-CODE-REVIEW gate spawns and returns APPROVED
|
||||
6. Skill asks "May I update story status to Complete?"
|
||||
7. Story status is updated to Complete
|
||||
1. Reads the story and greps `id: TR-combat-001` from the registry
|
||||
2. Greps ADR-0003's `^## (Status|Last Verified|Date)` — Status is Accepted and its
|
||||
current version (the `Last Verified` date) matches the story, so the ADR is not read
|
||||
3. Greps `^## Core Layer Rules` from the manifest; Manifest Version matches, no ask
|
||||
4. Asks "May I mark this story In Progress?", naming the story file (and not the
|
||||
absent `sprint-status.yaml`); on yes sets the story's `Status:` to `In Progress`
|
||||
and its `Last Updated:`; prints "Sprint status not updated:
|
||||
production/sprint-status.yaml absent"
|
||||
5. Spawns `gameplay-programmer` with `godot-gdscript-specialist` as secondary,
|
||||
briefing the story path, TR-ID lookup, the story's ADR Decision Summary and
|
||||
Implementation Notes inline, the Core layer rules, and the test file path
|
||||
with the test requirement
|
||||
6. Confirms the agent finished, runs the Godot parse check and reports its exit code
|
||||
7. Prints "Implementation Complete: [title]" with files, test function count,
|
||||
Verification and a `Run result:` line; next step `/code-review` then `/story-done`
|
||||
8. Overwrites the `<!-- CHECKPOINT -->` block in `active.md`
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Skill reads story before spawning any agent
|
||||
- [ ] ADR status is checked before implementation begins
|
||||
- [ ] Implementation is delegated to a specialist agent (not done inline)
|
||||
- [ ] All acceptance criteria are confirmed before LP-CODE-REVIEW
|
||||
- [ ] LP-CODE-REVIEW appears in output as a completed gate
|
||||
- [ ] Story status is updated to Complete only after gate approval and user consent
|
||||
- [ ] Test file is written as part of implementation (not deferred)
|
||||
- [ ] ADR-0003 is not read in full when its `Last Verified` matches the story's `ADR Version`
|
||||
- [ ] The In Progress ask names the story file; `Status:` becomes `In Progress` only after it and before any agent is spawned, and the sprint-status-absent line is printed
|
||||
- [ ] Primary is `gameplay-programmer`; secondary comes from `specialists.code`, not the roster table
|
||||
- [ ] The ADR guidance is passed inline, not as the ADR path
|
||||
- [ ] The brief names `tests/unit/combat/combat_damage_calc_test.gd` (`[system]_[feature]_test.gd`) and requires one test per acceptance criterion
|
||||
- [ ] The parse check's command and exit code are reported, and exactly one `Run result:` line appears
|
||||
- [ ] Story is NOT marked Complete; the handoff is `/code-review` then `/story-done`
|
||||
- [ ] The CHECKPOINT block in `active.md` is overwritten, not appended to
|
||||
|
||||
---
|
||||
|
||||
### Case 2: Failure Path — Referenced ADR is Proposed
|
||||
|
||||
**Fixture:**
|
||||
- A story file exists with `Status: Ready`
|
||||
- The story's TR-ID points to a requirement covered by an ADR with `Status: Proposed`
|
||||
- `project.yaml`: `modes.workflow: standard`
|
||||
- Story file with `Status: Ready` and `ADR Governing Implementation: ADR-0005`
|
||||
- `docs/architecture/adr-0005-*.md` exists with `## Status` Proposed
|
||||
|
||||
**Input:** `/dev-story production/epics/[layer]/story-[name].md`
|
||||
**Input:** `/dev-story production/epics/[epic-slug]/story-[NNN]-[slug].md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads the story file
|
||||
2. Skill resolves the TR-ID and reads the governing ADR
|
||||
3. ADR status is Proposed — skill outputs a BLOCKED message
|
||||
4. Skill names the specific ADR blocking the story
|
||||
5. Skill recommends running `/architecture-decision` to advance the ADR
|
||||
6. Implementation does NOT begin
|
||||
1. Skill reads the story and resolves the `standard` tier
|
||||
2. Skill determines that the referenced ADR-0005 is Proposed
|
||||
3. Story is set BLOCKED in session state; no programmer agent is spawned
|
||||
4. Output names ADR-0005 and recommends `/architecture-decision accept ADR-0005`
|
||||
5. A partial report is produced; the story file's `Status:` is not changed
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Skill does NOT begin implementation with a Proposed ADR
|
||||
- [ ] BLOCKED message names the specific ADR number and title
|
||||
- [ ] Skill recommends `/architecture-decision` as the next action
|
||||
- [ ] Story status remains unchanged (not set to In Progress or Complete)
|
||||
- [ ] The Proposed status is read from ADR-0005's `## Status` section, not inferred
|
||||
- [ ] No programmer or engine-specialist agent is spawned
|
||||
- [ ] Output names ADR-0005 and recommends `/architecture-decision`
|
||||
- [ ] The story header stays `Status: Ready`, and no "May I mark this story In Progress?" ask is shown
|
||||
- [ ] BLOCKED is recorded in session state, and the checkpoint's **Next step** names `/architecture-decision accept ADR-0005` — not `/story-done`
|
||||
|
||||
---
|
||||
|
||||
### Case 3: Ambiguous Acceptance Criteria — Skill asks for clarification
|
||||
### Case 2b: Failure Path — Proposed ADR at the `full` tier
|
||||
|
||||
The `full` column of the file-check table has its own STOP rule, so the
|
||||
`standard` case above does not exercise it.
|
||||
|
||||
**Fixture:**
|
||||
- A story file exists with `Status: Ready`
|
||||
- Referenced ADR is Accepted
|
||||
- One acceptance criterion is ambiguous (not Given-When-Then; uses subjective language like "feels responsive")
|
||||
- `project.yaml`: `modes.workflow: full`
|
||||
- Story file with `Status: Ready`, `ADR Governing Implementation: ADR-0005` and an
|
||||
`ADR Version` older than ADR-0005's `## Last Verified` date
|
||||
- `docs/architecture/adr-0005-*.md` exists with `## Status` Proposed;
|
||||
`docs/architecture/tr-registry.yaml` and the control manifest exist
|
||||
|
||||
**Input:** `/dev-story production/epics/[layer]/story-[name].md`
|
||||
**Input:** `/dev-story production/epics/[epic-slug]/story-[NNN]-[slug].md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads the story and identifies the ambiguous criterion
|
||||
2. Before routing to the specialist, skill asks the user to clarify the criterion
|
||||
3. User provides a concrete, testable restatement
|
||||
4. Skill proceeds with implementation using the clarified criterion
|
||||
5. Skill does NOT guess at the intended behavior
|
||||
1. Skill greps ADR-0005's `^## (Status|Last Verified|Date)` and reads `Proposed`
|
||||
2. It stops before the freshness comparison: "ADR [path] is still Proposed. Accept
|
||||
it with `/architecture-decision accept ADR-0005` before implementing."
|
||||
3. Story is set BLOCKED in session state; no programmer agent is spawned
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Skill surfaces the ambiguous criterion before implementation starts
|
||||
- [ ] Skill asks for user clarification (not auto-interpretation)
|
||||
- [ ] Implementation begins only after clarification is provided
|
||||
- [ ] Clarified criterion is used in the test (not the original vague version)
|
||||
- [ ] The stop happens at `full`
|
||||
- [ ] The Status decides before the freshness check: no ADR-version mismatch prompt is shown although the versions differ, and the ADR is not read beyond the one Grep
|
||||
- [ ] No programmer or engine-specialist agent is spawned, and the story stays `Status: Ready`
|
||||
|
||||
---
|
||||
|
||||
### Case 3: ADR changed since the story was written
|
||||
|
||||
**Fixture:**
|
||||
- `project.yaml`: `engine.name: Godot`, `modes.workflow: full`
|
||||
- Story file with `Status: Ready`, Type Logic, `Requirement: TR-combat-002`,
|
||||
`ADR Governing Implementation: ADR-0004`, an `ADR Version` older than ADR-0004's
|
||||
`## Last Verified` date, a `Manifest Version` equal to the manifest header date,
|
||||
Dependencies None
|
||||
- `docs/architecture/tr-registry.yaml` has `TR-combat-002`; ADR-0004 exists with
|
||||
`## Status` Accepted and is under 50KB; `docs/architecture/control-manifest.md`
|
||||
exists
|
||||
- User picks `[A]` at the prompt
|
||||
|
||||
**Input:** `/dev-story production/epics/[epic-slug]/story-[NNN]-[slug].md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. `Grep "^## (Status|Last Verified|Date)"` on ADR-0004 reads Accepted and a
|
||||
`Last Verified` date different from the story's `ADR Version`
|
||||
2. `AskUserQuestion`: "Story was written against ADR v[story-date]. The ADR is now
|
||||
v[current-date]. Its decision may have changed. How do you want to proceed?"
|
||||
with `[A] Re-read the changed ADR sections…` (naming the refresh of this story's
|
||||
ADR summary and ADR Version) / `[B] Implement from the story's summary…` /
|
||||
`[C] Stop…`
|
||||
3. On [A]: checks the size with `wc -c`; under ~50KB, reads the ADR with one `Read`
|
||||
4. Sets the story's `ADR Version` to ADR-0004's `Last Verified` date and replaces
|
||||
its ADR Decision Summary and Implementation Notes with the re-read guidance
|
||||
5. Spawns the programmer with that guidance inline
|
||||
|
||||
**Assertions:**
|
||||
- [ ] The mismatch prompt is shown before any agent is spawned
|
||||
- [ ] All three options ([A] re-read / [B] accept drift / [C] stop) are offered, and [A] names the story edit it makes
|
||||
- [ ] On [A] the size is checked and a sub-50KB ADR is read in a single `Read`
|
||||
- [ ] The story's `ADR Version` becomes ADR-0004's `Last Verified` date — not today's date — before the programmer is spawned
|
||||
- [ ] The programmer brief carries the freshly read Decision guidance inline, not the summary the story held before [A]
|
||||
|
||||
**Fixture (Date fallback):**
|
||||
- As above, but ADR-0004 has no `## Last Verified` section; its `## Date` equals the
|
||||
story's `ADR Version` (the value `/create-stories` stamped from it)
|
||||
|
||||
**Expected behavior (Date fallback):**
|
||||
1. The same Grep finds no `Last Verified`, so the ADR's current version is its `## Date`
|
||||
2. That matches the story's `ADR Version`: the story is trusted, no prompt is shown,
|
||||
and the ADR is not read
|
||||
|
||||
**Assertions (Date fallback):**
|
||||
- [ ] No mismatch prompt is shown — an ADR stamped from its `## Date` is not treated as stale for lacking `## Last Verified`
|
||||
- [ ] ADR-0004 is not read beyond the one Grep
|
||||
|
||||
---
|
||||
|
||||
@@ -146,60 +223,232 @@ In `solo` mode: LP-CODE-REVIEW is skipped with equivalent notes.
|
||||
- [ ] Skill reads session state when no argument is provided
|
||||
- [ ] Skill confirms the active story with the user before proceeding
|
||||
- [ ] Skill does NOT silently assume the active story without confirmation
|
||||
- [ ] If session state has no active story, skill asks which story to implement
|
||||
|
||||
**Fixture (no active story):**
|
||||
- No argument is provided
|
||||
- `production/session-state/active.md` names no active story
|
||||
- `production/epics/` holds two stories with `Status: Ready` and one `In Progress`
|
||||
|
||||
**Expected behavior (no active story):**
|
||||
1. Skill asks "Which story are we implementing?"
|
||||
2. It globs `production/epics/**/*.md` and lists the two `Status: Ready` stories
|
||||
|
||||
**Assertions (no active story):**
|
||||
- [ ] The question is asked instead of guessing a story
|
||||
- [ ] Only the `Status: Ready` stories are listed
|
||||
|
||||
---
|
||||
|
||||
### Case 5: Director Gate — LP-CODE-REVIEW returns NEEDS CHANGES; lean mode skips gate
|
||||
### Case 5: Minimal tier, Logic story — tests waived
|
||||
|
||||
**Fixture (full mode):**
|
||||
- Story is implemented and all criteria appear met
|
||||
- `production/session-state/review-mode.txt` contains `full`
|
||||
- LP-CODE-REVIEW gate returns NEEDS CHANGES with specific feedback
|
||||
**Fixture:**
|
||||
- `project.yaml`: `engine.name: Godot`, `modes.workflow: minimal`, `qa.level: minimal`
|
||||
- Story Type Logic with `Requirement: Brief MVP feature 1` and ADR fields
|
||||
`N/A (minimal — no ADRs)`
|
||||
- No TR registry, no ADRs, no control manifest
|
||||
- `docs/engine-reference/godot/VERSION.md` rates the pinned version HIGH risk
|
||||
|
||||
**Full mode expected behavior:**
|
||||
1. LP-CODE-REVIEW gate spawns after implementation
|
||||
2. Gate returns NEEDS CHANGES with 2 specific issues
|
||||
3. Story status remains In Progress — NOT marked Complete
|
||||
4. User is shown the gate feedback and asked how to proceed
|
||||
**Input:** `/dev-story production/epics/[slug]/story-001-[slug].md`
|
||||
|
||||
**Assertions (full mode):**
|
||||
- [ ] Story is NOT marked Complete when LP-CODE-REVIEW returns NEEDS CHANGES
|
||||
- [ ] Gate feedback is shown to the user verbatim
|
||||
- [ ] Story status stays In Progress until issues are resolved and gate passes
|
||||
**Expected behavior:**
|
||||
1. Phase 2 does not stop or set BLOCKED for the absent registry, ADR or manifest
|
||||
2. Before spawning, prints a `Briefing omits: …` line naming the TR registry, the
|
||||
ADR guidance and the control manifest
|
||||
3. Spawns `gameplay-programmer` plus the engine specialist (VERSION.md risk HIGH)
|
||||
4. The brief omits the test requirement and tells the agent: "Do not write a test
|
||||
file for this story — test evidence is waived at `qa.level: minimal`."
|
||||
5. Phase 5 is skipped; the summary prints "Test evidence: waived at
|
||||
`qa.level: minimal` — no test was required or written for this story."
|
||||
6. Run-and-observe still runs and prints one `Run result:` line
|
||||
7. Next step is `/story-done [story-path]` directly — no `/code-review`
|
||||
|
||||
**Fixture (lean mode):**
|
||||
- Same story, `production/session-state/review-mode.txt` contains `lean`
|
||||
**Assertions:**
|
||||
- [ ] No STOP or BLOCKED for the absent TR registry, ADR or manifest at `minimal`
|
||||
- [ ] The `Briefing omits:` line names all three dropped inputs, the ADR included
|
||||
- [ ] The engine specialist is spawned because VERSION.md rates the risk HIGH
|
||||
- [ ] The test waiver is stated to the agent and printed in the summary; no tests row or "run your test suite" paragraph appears
|
||||
- [ ] A `Run result:` line is printed — run-and-observe is not waived
|
||||
- [ ] The handoff is `/story-done` with no `/code-review` step
|
||||
|
||||
**Lean mode expected behavior:**
|
||||
1. Implementation completes
|
||||
2. LP-CODE-REVIEW gate is skipped — noted in output
|
||||
3. User is asked to confirm all criteria are met
|
||||
4. Story is marked Complete after user confirmation
|
||||
---
|
||||
|
||||
**Assertions (lean mode):**
|
||||
- [ ] "LP-CODE-REVIEW skipped — lean mode" appears in output
|
||||
- [ ] Story is marked Complete after user confirms criteria (no gate required)
|
||||
- [ ] Skill does NOT block on a gate that is skipped
|
||||
### Case 5b: Minimal tier, UI story — the screenshot is still required
|
||||
|
||||
**Fixture:**
|
||||
- `project.yaml`: `engine.name: Godot`, `modes.workflow: minimal`, `qa.level: minimal`
|
||||
- Story Type UI with `Requirement: Brief MVP feature 2` and ADR fields
|
||||
`N/A (minimal — no ADRs)`
|
||||
- No TR registry, no ADRs, no control manifest
|
||||
|
||||
**Input:** `/dev-story production/epics/[slug]/story-002-[slug].md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Spawns `ui-programmer`; the brief has no test item and no "Do not write a test
|
||||
file" sentence — the test requirement only ever covered Logic and Integration
|
||||
2. The summary prints "Retained screenshot required under
|
||||
`production/qa/evidence/[story-slug]/` before this story can be closed…"
|
||||
3. Run-and-observe retains a screenshot under `production/qa/evidence/[story-slug]/`
|
||||
and prints `Run result: OBSERVED — …` with the path
|
||||
4. Next step is `/story-done [story-path]`
|
||||
|
||||
**Assertions:**
|
||||
- [ ] The UI story is not told its evidence is waived — neither in the brief nor as a "Test evidence: waived" line in the summary
|
||||
- [ ] The screenshot-required line is printed at `qa.level: minimal`
|
||||
- [ ] `Run result: OBSERVED` names a retained screenshot; a `NOT VERIFIED` result would be reported as a blocker, not a note
|
||||
- [ ] The handoff is `/story-done` with no `/code-review` step
|
||||
|
||||
---
|
||||
|
||||
### Case 6: Unity — code under `Assets/`, capture script asked for
|
||||
|
||||
**Fixture:**
|
||||
- `project.yaml`: `engine.name: Unity`, `specialists.code: unity-specialist`,
|
||||
`specialists.ui: unity-ui-specialist`, `commands.smoke` and `commands.run` set,
|
||||
`modes.workflow: minimal`, `qa.level: minimal`
|
||||
- Story Type UI (an inventory screen) with `Requirement: Brief MVP feature 3` and
|
||||
ADR fields `N/A (minimal — no ADRs)`
|
||||
- The project has `Assets/` and no `src/`; no `ScreenshotOnArg.cs` exists under `Assets/`
|
||||
- `docs/engine-reference/unity/VERSION.md` rates the pinned version HIGH risk
|
||||
|
||||
**Input:** `/dev-story production/epics/[slug]/story-003-[slug].md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Spawns `ui-programmer` with `unity-specialist` (`specialists.code`) and
|
||||
`unity-ui-specialist` (`specialists.ui`, for a UI story)
|
||||
2. The brief sends the code to `Assets/Scripts/<System>/`, the Unity code root
|
||||
3. Verification runs `commands.smoke` and reports its exit code
|
||||
4. Before launching, globs `Assets/**/ScreenshotOnArg.cs`, finds none and asks
|
||||
"May I write `Assets/Scripts/ScreenshotOnArg.cs`?"; on yes writes the script
|
||||
verbatim from `.claude/docs/run-and-observe.md`
|
||||
5. Launches the built player with `--scene`/`--screenshot` and prints
|
||||
`Run result: OBSERVED — …` with the retained path
|
||||
|
||||
**Assertions:**
|
||||
- [ ] No file is written under `src/` — the Godot row is not a default
|
||||
- [ ] Both specialists come from the `specialists` block, not the roster table
|
||||
- [ ] `ScreenshotOnArg.cs` is written only after its ask, at `Assets/Scripts/`, exactly as run-and-observe.md gives it
|
||||
- [ ] If the user declines that ask, the result is `Run result: NOT VERIFIED — ScreenshotOnArg.cs not written`, not an observation
|
||||
- [ ] Verification names `commands.smoke` and its exit code
|
||||
|
||||
---
|
||||
|
||||
### Case 7: Engine unset — the code root is unresolved, nothing is written
|
||||
|
||||
**Fixture:**
|
||||
- `project.yaml` has no `engine` block; `.claude/docs/technical-preferences.md`
|
||||
reads `Engine: [TO BE CONFIGURED]`
|
||||
- The project has none of `src/`, `Assets/` or `Source/`
|
||||
- `modes.workflow: minimal`; the story is Type Logic
|
||||
|
||||
**Input:** `/dev-story production/epics/[slug]/story-001-[slug].md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. The code root cannot be resolved (`.claude/docs/code-root-resolution.md`: no
|
||||
`engine.name`, no legacy `Engine:` value, no single unambiguous root in the tree)
|
||||
2. No source file is written, and the output says the code root is unresolved
|
||||
|
||||
**Assertions:**
|
||||
- [ ] No file is created under `src/` or any other guessed root
|
||||
- [ ] The output names the unresolved code root as the reason nothing was written
|
||||
- [ ] "Implementation Complete" is not printed
|
||||
|
||||
---
|
||||
|
||||
### Case 8: Dependency marked Complete through option [C]
|
||||
|
||||
**Fixture:**
|
||||
- `project.yaml`: `engine.name: Godot`, `modes.workflow: minimal`, `qa.level: minimal`
|
||||
- `story-003` lists `story-002` under Dependencies; `story-002` has
|
||||
`Status: In Progress`
|
||||
- At the dependency prompt the user picks `[C]`, then approves the update
|
||||
|
||||
**Input:** `/dev-story production/epics/[slug]/story-003-[slug].md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Reads story-002's `Status:` and asks: "Story '[story-003 title]' depends on
|
||||
'[story-002 title]' which is currently In Progress, not Complete. How do you
|
||||
want to proceed?" with `[A] Proceed anyway` / `[B] Stop` / `[C] The dependency
|
||||
is done but status wasn't updated — mark it Complete and continue`
|
||||
2. On [C] asks "May I update `production/epics/[slug]/story-002-[slug].md` Status
|
||||
to Complete?"
|
||||
3. On yes sets story-002's `Status:` to `Complete`, then continues with story-003
|
||||
|
||||
**Assertions:**
|
||||
- [ ] The dependency prompt comes before any agent is spawned
|
||||
- [ ] story-002 is edited only after the "May I update … Status to Complete?" ask, and only its `Status:` changes
|
||||
- [ ] story-003 itself is not marked Complete — it is set In Progress, after its own ask
|
||||
- [ ] Had the user picked `[B]`, story-003 would be BLOCKED in session state and no agent spawned
|
||||
|
||||
### Case 9: The agent stops early — INCOMPLETE, and the checkpoint says resume
|
||||
|
||||
**Fixture:**
|
||||
- `project.yaml`: `engine.name: Godot`, `modes.workflow: minimal`, `qa.level: minimal`
|
||||
- Story Type Logic, `Status: Ready`, ADR fields `N/A (minimal — no ADRs)`
|
||||
- The programmer agent reports that it hit its turn limit after adding
|
||||
`src/combat/damage.gd`, which calls a helper it never defined
|
||||
|
||||
**Input:** `/dev-story production/epics/[slug]/story-001-[slug].md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Phase 6 treats the story as INCOMPLETE: the headline says so, lists what exists,
|
||||
names the undefined helper, and offers to resume the agent
|
||||
2. "Implementation Complete" is not printed and the story's `Status:` is not advanced
|
||||
3. The checkpoint's **Next step** reads `/dev-story [story-path] — resume: [the
|
||||
undefined helper]`
|
||||
|
||||
**Assertions:**
|
||||
- [ ] No "Implementation Complete" and no `Status:` change past `In Progress`
|
||||
- [ ] The checkpoint's **Next step** is `/dev-story [story-path]` to resume — never `/story-done`, which `/help` reads as "the work is written"
|
||||
|
||||
---
|
||||
|
||||
### Case 10: `full` tier, a story with no governing ADR (`ADR: N/A`)
|
||||
|
||||
**Fixture:**
|
||||
- `project.yaml`: `engine.name: Godot`, `modes.workflow: full`
|
||||
- Story `Status: Ready`, Type Logic, `ADR Governing Implementation: N/A — no
|
||||
architectural pattern required` (what `/create-stories` writes for a
|
||||
requirement `/create-epics` flagged as untraced)
|
||||
- `docs/architecture/tr-registry.yaml` has the story's TR-ID; the control manifest exists
|
||||
|
||||
**Input:** `/dev-story production/epics/[slug]/story-004-[slug].md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Phase 2 reads the ADR field as `N/A`: the story references no ADR, so the `full`
|
||||
column's "ADR file [path] not found" STOP does not fire and no ADR is grepped
|
||||
2. The story is not set BLOCKED; implementation proceeds, with the ADR guidance
|
||||
named in the `Briefing omits:` line
|
||||
|
||||
**Assertions:**
|
||||
- [ ] No STOP and no BLOCKED for the `N/A` ADR field at `full`
|
||||
- [ ] No ADR file is looked up for `N/A`
|
||||
- [ ] Variant — the story names `ADR-0006`, whose `## Status` reads `Superseded by ADR-0009`: the story is BLOCKED at every tier, naming ADR-0009 and saying to edit its ADR field (`/create-stories` never rewrites an existing story)
|
||||
|
||||
---
|
||||
|
||||
## Protocol Compliance
|
||||
|
||||
- [ ] Does NOT write source code directly — delegates to specialist agents
|
||||
- [ ] Reads all context (story, TR-ID, ADR, manifest, engine prefs) before implementation
|
||||
- [ ] "May I write" asked before updating story status and before writing code files
|
||||
- [ ] Skipped gates noted by name and mode in output
|
||||
- [ ] Updates `production/session-state/active.md` after story completion
|
||||
- [ ] Ends with next-step handoff: `/story-done`
|
||||
- [ ] Resolves the workflow tier and verifies required inputs before any agent is spawned
|
||||
- [ ] Mismatch and dependency prompts (`AskUserQuestion`) come before implementation
|
||||
- [ ] Every file the skill itself writes — story fields, `sprint-status.yaml`, a dependency's `Status`, a Config/Data file, `ScreenshotOnArg.cs` — follows an ask that names it; only the `active.md` checkpoint is written without one
|
||||
- [ ] Code is written only under the resolved code root; an unresolved root writes nothing
|
||||
- [ ] Skipped phases and dropped briefing items are announced in the output
|
||||
- [ ] Never emits "Implementation Complete" for an agent that stopped early (INCOMPLETE)
|
||||
- [ ] Overwrites the CHECKPOINT block in `production/session-state/active.md`
|
||||
- [ ] Ends with next-step handoff: `/story-done` (`/code-review` first at standard/full)
|
||||
|
||||
---
|
||||
|
||||
## Coverage Notes
|
||||
|
||||
- Engine routing logic (Godot vs Unity vs Unreal) is not tested per engine —
|
||||
the routing pattern is consistent; engine selection is a config fact.
|
||||
- Visual/Feel and UI story types (no automated test required) have different
|
||||
evidence requirements and are not covered in these cases.
|
||||
- Integration story type follows the same pattern as Logic but with a different
|
||||
evidence path — not independently fixture-tested.
|
||||
- The code root is covered for Godot (`src/`) and Unity (`Assets/`, Case 6) and for
|
||||
an unresolved engine (Case 7). Unreal (`Source/<Module>/<System>/`, with the
|
||||
editor-target build as the parse check) is not given a fixture.
|
||||
- The INCOMPLETE path is Case 9; `parse NOT VERIFIED` when the engine binary is
|
||||
unavailable is not given a fixture.
|
||||
- The Manifest Version mismatch prompt (`[A]` update / `[B]` keep old rules, which
|
||||
records a `Manifest-Note` / `[C]` stop) follows Case 3's ask-before-spawn pattern
|
||||
and is not separately tested.
|
||||
- Config/Data stories (no agent spawned) and `testing.strict` per-type overrides
|
||||
are not covered.
|
||||
|
||||
@@ -2,185 +2,282 @@
|
||||
|
||||
## Skill Summary
|
||||
|
||||
`/map-systems` decomposes a game concept into a systems index. It reads the
|
||||
approved game concept and pillars, enumerates both explicit and implicit systems,
|
||||
maps dependencies between systems, assigns priority tiers (MVP / Vertical Slice /
|
||||
Alpha / Full Vision), and organizes systems into a layered design order
|
||||
(Foundation → Core → Feature → Presentation). The output is written to
|
||||
`design/systems-index.md` after user approval.
|
||||
`/map-systems` decomposes a game concept into a systems index. It reads
|
||||
`design/gdd/game-concept.md` (at `minimal`, `design/game-brief.md`) and the pillars,
|
||||
enumerates explicit and implicit systems, maps dependencies into layers
|
||||
(Foundation → Core → Feature → Presentation → Polish), assigns priority tiers
|
||||
(MVP / Vertical Slice / Alpha / Full Vision), derives a design order, and writes
|
||||
`design/gdd/systems-index.md` from `.claude/docs/templates/systems-index.md` after
|
||||
approval. Each collaborative phase ends with an `AskUserQuestion`.
|
||||
|
||||
This skill is required between game concept approval and per-system GDD creation
|
||||
— it is a mandatory gate in the pipeline. In `full` review mode, CD-SYSTEMS
|
||||
(creative-director) and TD-SYSTEM-BOUNDARY (technical-director) spawn in parallel
|
||||
after the decomposition is drafted. In `lean` or `solo` mode, both gates are
|
||||
skipped. The skill writes to `design/systems-index.md`.
|
||||
Three director gates run in sequence, each in its own phase:
|
||||
TD-SYSTEM-BOUNDARY (technical-director) after the dependency map is approved,
|
||||
PR-SCOPE (producer) after priorities are approved and before the write, and
|
||||
CD-SYSTEMS (creative-director) after the index is written. In `lean` and `solo`
|
||||
each is skipped with a named note. It is required before `/design-system` at
|
||||
`standard`/`full` and optional at `minimal`. Verdicts: COMPLETE (index written) or
|
||||
BLOCKED (user declined the write).
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
- [ ] Contains "May I write" collaborative protocol language (for systems-index.md)
|
||||
- [ ] Contains "May I write" collaborative protocol language (for `design/gdd/systems-index.md`)
|
||||
- [ ] Has a next-step handoff at the end (`/design-system`)
|
||||
- [ ] Documents gate behavior: CD-SYSTEMS + TD-SYSTEM-BOUNDARY in parallel in full mode
|
||||
- [ ] Documents three gates at their phases: TD-SYSTEM-BOUNDARY (Phase 3), PR-SCOPE (Phase 4), CD-SYSTEMS (Phase 5, after the write)
|
||||
|
||||
---
|
||||
|
||||
## Director Gate Checks
|
||||
|
||||
In `full` mode: CD-SYSTEMS (creative-director) and TD-SYSTEM-BOUNDARY
|
||||
(technical-director) spawn in parallel after the systems decomposition is drafted
|
||||
and before `design/systems-index.md` is written.
|
||||
In `full` mode, sequentially:
|
||||
1. **TD-SYSTEM-BOUNDARY** (`technical-director`) — after the dependency ordering is
|
||||
approved, before priority assignment. REJECT → revise boundaries with the user;
|
||||
CONCERNS → noted inline in the index.
|
||||
2. **PR-SCOPE** (`producer`) — after priorities are approved, before the index is
|
||||
written. UNREALISTIC → offer to revise tier assignments before writing;
|
||||
OPTIMISTIC → show the suggested adjustments and ask whether to apply them.
|
||||
3. **CD-SYSTEMS** (`creative-director`) — after the index is written; it receives
|
||||
the index path, the pillars and core fantasy (the brief's pitch and "what they
|
||||
feel" line at `minimal`), every tier's assignments and the high-risk and
|
||||
bottleneck systems. REJECT → revise the system set before GDD authoring;
|
||||
CONCERNS → `AskUserQuestion` (`Revise the system set` / `Accept — record them
|
||||
in the index` / `Discuss further`); on Accept they are recorded as a
|
||||
`> **Creative Director Note** (<tier>): …` directly beneath the
|
||||
`## Priority Tiers` table.
|
||||
|
||||
In `lean` mode: both gates are skipped. Output notes:
|
||||
"CD-SYSTEMS skipped — lean mode" and "TD-SYSTEM-BOUNDARY skipped — lean mode".
|
||||
Any of the three may answer NOT ASSESSED [missing input]; it is never read as
|
||||
approval — the input is supplied and the gate re-run, or the run goes on with
|
||||
`[GATE-ID]: NOT ASSESSED — [input]` recorded in the index.
|
||||
|
||||
In `solo` mode: both gates are skipped with equivalent notes.
|
||||
In `lean` mode each is skipped with a note: "TD-SYSTEM-BOUNDARY skipped — Lean
|
||||
mode.", "PR-SCOPE skipped — Lean mode.", "CD-SYSTEMS skipped — Lean mode."
|
||||
|
||||
In `solo` mode the same three notes appear with "Solo mode."
|
||||
|
||||
---
|
||||
|
||||
## Test Cases
|
||||
|
||||
### Case 1: Happy Path — Game concept exists, 5-8 systems identified
|
||||
### Case 1: Happy Path — Concept decomposed and index written in full review mode
|
||||
|
||||
**Fixture:**
|
||||
- `design/gdd/game-concept.md` exists with Core Mechanics and MVP Definition sections
|
||||
- `design/gdd/game-pillars.md` exists with ≥1 pillar defined
|
||||
- No `design/systems-index.md` exists yet
|
||||
- `production/session-state/review-mode.txt` contains `full`
|
||||
- `project.yaml`: `modes.workflow: standard`, `modes.review_mode: full`
|
||||
- `design/gdd/game-concept.md` exists with Core Mechanics naming combat and an
|
||||
inventory, and an MVP Definition section
|
||||
- `design/gdd/game-pillars.md` exists with 2 pillars
|
||||
- No `design/gdd/systems-index.md` exists yet
|
||||
- TD-SYSTEM-BOUNDARY returns APPROVE, PR-SCOPE returns REALISTIC, CD-SYSTEMS
|
||||
returns APPROVE
|
||||
|
||||
**Input:** `/map-systems`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads game-concept.md and game-pillars.md
|
||||
2. Identifies 5-8 systems (explicit + implicit)
|
||||
3. Maps dependencies between systems and assigns layers
|
||||
4. CD-SYSTEMS and TD-SYSTEM-BOUNDARY spawn in parallel and return APPROVED
|
||||
5. Asks "May I write `design/systems-index.md`?"
|
||||
6. Writes systems-index.md after approval
|
||||
7. Updates `production/session-state/active.md`
|
||||
1. Reads the concept and pillars; globs `design/gdd/*.md`
|
||||
2. Presents systems by category — name, category, one-sentence description,
|
||||
explicit or implicit (e.g. combat implies health, damage calculation, hit
|
||||
detection, combat UI) — and asks about missing / combined / unneeded systems
|
||||
3. Presents the layered dependency map (bottlenecks, leaf nodes, any cycles) and
|
||||
asks "Does this dependency ordering look right?…"
|
||||
4. After approval spawns TD-SYSTEM-BOUNDARY, passing the dependency graph (each
|
||||
system → what it depends on), the layer assignments, the bottleneck systems and
|
||||
any cycles with their proposed resolutions
|
||||
5. Presents priority tiers with reasoning that cites this project's pillars; after
|
||||
approval spawns PR-SCOPE
|
||||
6. Presents the summary (counts by category, MVP count, first 3 in design order,
|
||||
high-risk items) and asks "May I write the systems index to
|
||||
`design/gdd/systems-index.md`?"
|
||||
7. Writes the index, then spawns CD-SYSTEMS with the index path, pillars/core
|
||||
fantasy, every tier's system assignments and the high-risk and bottleneck
|
||||
systems
|
||||
8. Updates `production/session-state/active.md`; Verdict: COMPLETE; offers
|
||||
`/design-system [first-system-in-order]`
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Between 5 and 8 systems are identified (not fewer, not more without explanation)
|
||||
- [ ] CD-SYSTEMS and TD-SYSTEM-BOUNDARY spawn in parallel (not sequentially)
|
||||
- [ ] Both gates complete before the "May I write" ask
|
||||
- [ ] "May I write `design/systems-index.md`?" is asked before writing
|
||||
- [ ] systems-index.md is NOT written without approval
|
||||
- [ ] Session state is updated after writing
|
||||
- [ ] Verdict is COMPLETE
|
||||
- [ ] Implicit systems are inferred and labelled implicit, with the reason given
|
||||
- [ ] TD-SYSTEM-BOUNDARY spawns after the dependency map is approved and before priorities are presented, and is passed the full dependency graph — not a summary
|
||||
- [ ] PR-SCOPE spawns after priorities are approved and before the write ask
|
||||
- [ ] "May I write the systems index to `design/gdd/systems-index.md`?" is asked and nothing is written before approval
|
||||
- [ ] CD-SYSTEMS spawns only after the index is written, and receives all four tiers and the high-risk systems — not the MVP list alone
|
||||
- [ ] The Systems Enumeration table keeps the template's columns (`# / System Name / Category / Priority / Status / Design Doc / Depends On`) — no added column
|
||||
- [ ] `active.md` is updated and the verdict is COMPLETE
|
||||
|
||||
---
|
||||
|
||||
### Case 2: Failure Path — No game concept found
|
||||
|
||||
**Fixture:**
|
||||
- `design/gdd/game-concept.md` does NOT exist
|
||||
- `design/gdd/` directory may be empty or absent
|
||||
- `project.yaml`: `modes.workflow: standard`
|
||||
- Neither `design/gdd/game-concept.md` nor `design/game-brief.md` exists
|
||||
|
||||
**Input:** `/map-systems`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill attempts to read `design/gdd/game-concept.md`
|
||||
2. File not found
|
||||
3. Skill outputs: "No game concept found. Run `/brainstorm` to create one, then return to `/map-systems`."
|
||||
4. Skill exits without creating systems-index.md
|
||||
1. Phase 1 finds no concept
|
||||
2. Skill outputs: "No game concept found. Run `/brainstorm` first to create one,
|
||||
then come back to decompose it into systems."
|
||||
3. Skill stops — no enumeration, no gates, no index
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Skill outputs a clear error naming the missing file path
|
||||
- [ ] The "No game concept found" message is printed
|
||||
- [ ] Skill recommends `/brainstorm` as the next action
|
||||
- [ ] No systems-index.md is created
|
||||
- [ ] Verdict is BLOCKED
|
||||
- [ ] No systems enumeration is presented and no gate is spawned
|
||||
- [ ] No `design/gdd/systems-index.md` is created and Verdict COMPLETE is not emitted
|
||||
|
||||
---
|
||||
|
||||
### Case 3: Director Gate — CD-SYSTEMS returns CONCERNS (missing core system)
|
||||
### Case 3: Director Gate — CD-SYSTEMS returns CONCERNS after the write
|
||||
|
||||
**Fixture:**
|
||||
- Game concept exists
|
||||
- `production/session-state/review-mode.txt` contains `full`
|
||||
- CD-SYSTEMS gate returns CONCERNS: "The [core-system] is implied by the concept but not identified"
|
||||
- Game concept and pillars exist; no index yet
|
||||
- `project.yaml`: `modes.workflow: standard`, `modes.review_mode: full`
|
||||
- TD-SYSTEM-BOUNDARY returns APPROVE, PR-SCOPE returns REALISTIC
|
||||
- CD-SYSTEMS returns CONCERNS: an MVP system implied by the core fantasy is missing
|
||||
- At the CONCERNS question the user picks `Accept — record them in the index`
|
||||
|
||||
**Input:** `/map-systems`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Systems are drafted (5-8 initial systems identified)
|
||||
2. CD-SYSTEMS gate returns CONCERNS naming the missing core system
|
||||
3. TD-SYSTEM-BOUNDARY returns APPROVED
|
||||
4. Skill surfaces CD-SYSTEMS concerns to user
|
||||
5. User is asked: revise systems list to add the missing system, or proceed as-is
|
||||
6. If revised: updated systems list shown before "May I write" ask
|
||||
1. The index is written after "May I write" approval
|
||||
2. CD-SYSTEMS is spawned and returns CONCERNS
|
||||
3. The concerns are shown with `AskUserQuestion`: `Revise the system set` /
|
||||
`Accept — record them in the index` / `Discuss further`
|
||||
4. On Accept, the concern is recorded in the index as
|
||||
`> **Creative Director Note** (MVP): …` directly beneath the `## Priority Tiers`
|
||||
table
|
||||
5. Session state is updated; Verdict: COMPLETE
|
||||
|
||||
**Assertions:**
|
||||
- [ ] CD-SYSTEMS concerns are shown to the user before writing
|
||||
- [ ] Skill does NOT auto-write systems-index.md while CONCERNS are unresolved
|
||||
- [ ] User is given the option to revise or proceed
|
||||
- [ ] Revised systems list is re-shown after revision before final "May I write"
|
||||
- [ ] CD-SYSTEMS is spawned only after the index is written, not before the write ask
|
||||
- [ ] The CONCERNS go to the user as a choice — the index is not edited before the user picks
|
||||
- [ ] Only the Accept choice, which names the edit, leads to the note being written; it sits directly beneath the `## Priority Tiers` table and names the MVP tier
|
||||
- [ ] Had the user picked `Revise the system set`, the affected systems would be reworked with the user and the re-write of the index asked again
|
||||
- [ ] CONCERNS do not trigger a full re-decomposition (that path is REJECT's)
|
||||
- [ ] Verdict is COMPLETE
|
||||
|
||||
---
|
||||
|
||||
### Case 4: Edge Case — systems-index.md already exists
|
||||
### Case 4: Edge Case — Systems index already exists
|
||||
|
||||
**Fixture:**
|
||||
- `project.yaml`: `modes.workflow: standard`
|
||||
- `design/gdd/game-concept.md` exists
|
||||
- `design/systems-index.md` already exists with N systems
|
||||
- `design/gdd/systems-index.md` already exists with 8 systems, 3 of them designed
|
||||
|
||||
**Input:** `/map-systems`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads the existing systems-index.md and presents its current state
|
||||
2. Skill asks: "systems-index.md already exists with [N] systems. Update with new systems, or review and revise priorities?"
|
||||
1. Skill reads the existing index and presents its current status
|
||||
2. Skill asks: "The systems index already exists with 8 systems (3 designed, 5 not
|
||||
started). What would you like to do?" with "Update the index with new systems",
|
||||
"Design the next undesigned system", "Review and revise priorities"
|
||||
3. User chooses an action
|
||||
4. Skill does NOT silently overwrite the existing index
|
||||
4. Skill resumes from the existing index rather than recreating it
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Skill detects and reads the existing systems-index.md before proceeding
|
||||
- [ ] User is offered update/review options — not auto-overwritten
|
||||
- [ ] Existing system count is presented to the user
|
||||
- [ ] Skill does NOT proceed with a full re-decomposition without user choosing to do so
|
||||
- [ ] Skill detects and reads the existing index before proceeding
|
||||
- [ ] The system count with designed / not-started split is presented
|
||||
- [ ] All three options are offered — the index is not auto-overwritten
|
||||
- [ ] Skill does NOT re-run a full decomposition from scratch without the user choosing to
|
||||
|
||||
---
|
||||
|
||||
### Case 5: Director Gate — Lean mode and solo mode both skip gates, noted
|
||||
### Case 5: Director Gate — Lean and solo modes skip all three gates, noted
|
||||
|
||||
**Fixture (lean mode):**
|
||||
- Game concept exists
|
||||
- `production/session-state/review-mode.txt` contains `lean`
|
||||
- `project.yaml`: `modes.workflow: standard`, `modes.review_mode: lean`
|
||||
|
||||
**Lean mode expected behavior:**
|
||||
1. Systems are decomposed and drafted
|
||||
2. Both CD-SYSTEMS and TD-SYSTEM-BOUNDARY are skipped
|
||||
3. Output notes: "CD-SYSTEMS skipped — lean mode" and "TD-SYSTEM-BOUNDARY skipped — lean mode"
|
||||
4. "May I write" ask proceeds directly
|
||||
1. Systems, dependencies and priorities are presented and approved as in Case 1
|
||||
2. Notes "TD-SYSTEM-BOUNDARY skipped — Lean mode." and "PR-SCOPE skipped — Lean
|
||||
mode." at their phases
|
||||
3. "May I write" is asked; the index is written after approval
|
||||
4. Notes "CD-SYSTEMS skipped — Lean mode."
|
||||
5. Session state is updated and Verdict: COMPLETE is printed
|
||||
|
||||
**Assertions (lean mode):**
|
||||
- [ ] Both gate skip notes appear in output
|
||||
- [ ] Skill proceeds to "May I write" without gate approval
|
||||
- [ ] systems-index.md is written after user approval
|
||||
- [ ] All three skip notes appear, each at its own phase
|
||||
- [ ] No director agent is spawned
|
||||
- [ ] The "May I write" ask still precedes the write
|
||||
- [ ] `active.md` is updated and Verdict: COMPLETE is printed even though CD-SYSTEMS was skipped
|
||||
|
||||
**Fixture (solo mode):**
|
||||
- Same game concept, `production/session-state/review-mode.txt` contains `solo`
|
||||
- Same concept, `project.yaml`: `modes.workflow: standard`, `modes.review_mode: full`
|
||||
- Input: `/map-systems --review solo`
|
||||
|
||||
**Solo mode expected behavior:**
|
||||
1. Same decomposition workflow
|
||||
2. Both gates skipped — noted in output with "solo mode"
|
||||
3. "May I write" ask proceeds
|
||||
1. `--review solo` overrides the resolved `full`
|
||||
2. The same three gates are skipped, noted with "Solo mode."
|
||||
|
||||
**Assertions (solo mode):**
|
||||
- [ ] Both skip notes appear with "solo mode" label
|
||||
- [ ] All three skip notes carry the "Solo mode." label
|
||||
- [ ] Behavior is otherwise identical to lean mode for this skill
|
||||
|
||||
---
|
||||
|
||||
### Case 6: Guided mode — a new index is still asked for; an update is not
|
||||
|
||||
**Fixture (new index):**
|
||||
- `project.yaml`: `modes.workflow: standard`, `modes.review_mode: solo`,
|
||||
`modes.automation: guided`
|
||||
- Game concept exists; no `design/gdd/systems-index.md`
|
||||
|
||||
**Fixture (update):**
|
||||
- Same, but `design/gdd/systems-index.md` exists and the user chose "Update the
|
||||
index with new systems"
|
||||
|
||||
**Input (both fixtures):** `/map-systems`
|
||||
|
||||
**Expected behavior:**
|
||||
1. New index: after the summary, asks "May I write the systems index to
|
||||
`design/gdd/systems-index.md`?" and writes only after yes — `guided` asks
|
||||
"May I write?" for new files
|
||||
2. Update: presents the summary, names `design/gdd/systems-index.md`, writes the
|
||||
update without waiting for an explicit yes, and says what it wrote
|
||||
|
||||
**Assertions:**
|
||||
- [ ] New index at `guided`: the write ask is shown and nothing is written before it is answered
|
||||
- [ ] Update at `guided`: no write ask; the summary and destination are shown before the write and the result is reported after it
|
||||
|
||||
---
|
||||
|
||||
### Case 7: Director Gate — TD-SYSTEM-BOUNDARY returns REJECT
|
||||
|
||||
**Fixture:**
|
||||
- `project.yaml`: `modes.workflow: standard`, `modes.review_mode: full`
|
||||
- Game concept and pillars exist; no index yet
|
||||
- TD-SYSTEM-BOUNDARY returns REJECT: two systems share one responsibility and
|
||||
must be merged
|
||||
|
||||
**Input:** `/map-systems`
|
||||
|
||||
**Expected behavior:**
|
||||
1. The dependency map is approved and TD-SYSTEM-BOUNDARY is spawned
|
||||
2. The REJECT is presented, naming the two systems
|
||||
3. The boundaries are revised with the user; the revised dependency map is shown
|
||||
4. Only then are priorities presented and PR-SCOPE spawned
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Priority assignment does not start while the REJECT is unresolved
|
||||
- [ ] The revised boundaries are shown to the user before priorities are presented
|
||||
- [ ] PR-SCOPE is not spawned and nothing is written before the revision
|
||||
- [ ] The REJECT is not recorded as a note and passed over — that handling is CONCERNS'
|
||||
|
||||
---
|
||||
|
||||
## Protocol Compliance
|
||||
|
||||
- [ ] Reads game-concept.md and game-pillars.md before any decomposition
|
||||
- [ ] "May I write `design/systems-index.md`?" asked before writing
|
||||
- [ ] systems-index.md is NOT written without user approval
|
||||
- [ ] CD-SYSTEMS and TD-SYSTEM-BOUNDARY spawn in parallel in full mode
|
||||
- [ ] Reads the game concept (or brief at `minimal`) and pillars before any decomposition
|
||||
- [ ] `AskUserQuestion` at enumeration, dependencies, priorities and the write
|
||||
- [ ] "May I write the systems index to `design/gdd/systems-index.md`?" asked before writing — at `collaborative`, and at `guided` for a new index
|
||||
- [ ] CD-SYSTEMS's CONCERNS reach the written index only through the user's choice; TD-SYSTEM-BOUNDARY's CONCERNS are noted inline in the index
|
||||
- [ ] Gates run sequentially at their own phases in full mode, never before their inputs exist
|
||||
- [ ] Skipped gates noted by name and mode in lean/solo output
|
||||
- [ ] Ends with next-step handoff: `/design-system [next-system]`
|
||||
|
||||
@@ -188,9 +285,12 @@ In `solo` mode: both gates are skipped with equivalent notes.
|
||||
|
||||
## Coverage Notes
|
||||
|
||||
- Circular dependency detection (System A depends on System B which depends on A)
|
||||
is part of the dependency mapping phase — not independently fixture-tested here.
|
||||
- Priority tier assignment (MVP heuristics) is evaluated as part of the Case 1
|
||||
collaborative workflow rather than independently.
|
||||
- The `next` argument mode (handing off the highest-priority undesigned system to
|
||||
`/design-system`) is not tested here — it is a post-index-creation convenience.
|
||||
- Circular dependency detection and its proposed resolutions are part of Phase 3 —
|
||||
not independently fixture-tested here.
|
||||
- PR-SCOPE UNREALISTIC, the CD-SYSTEMS REJECT path and a NOT ASSESSED answer from
|
||||
any of the three gates are not given fixtures.
|
||||
- `autonomous` (records the enumeration via `log_decision` and writes without
|
||||
asking) is not tested.
|
||||
- The `next` and `[system-name]` argument modes (handoff to `/design-system`) are
|
||||
not tested here — they are post-index conveniences.
|
||||
- `docs.density` depth (where per-system prose goes) is not fixture-locked.
|
||||
|
||||
@@ -2,111 +2,156 @@
|
||||
|
||||
## Skill Summary
|
||||
|
||||
`/propagate-design-change` handles GDD revision cascades. When a GDD is updated,
|
||||
the skill traces all downstream artifacts that reference it: ADRs, TR-registry
|
||||
entries, stories, and epics. It produces a structured impact report showing what
|
||||
needs to change and why. The skill does NOT automatically apply changes — it
|
||||
proposes edits for each affected artifact and asks "May I write" per artifact
|
||||
before making any modification.
|
||||
`/propagate-design-change` handles GDD revision cascades into the architecture.
|
||||
Given a changed GDD path, it asks git what changed (`git diff HEAD`, then the last
|
||||
commit), summarises the changed sections, checks the entity registry for
|
||||
downstream GDDs to re-check, then finds every ADR that references the GDD — by
|
||||
scanning `## GDD Requirements Addressed` tables plus a prose grep for the GDD's
|
||||
basename — and reads only that affected set. Each affected ADR is classified
|
||||
Still Valid / Needs Review / Likely Superseded and the full Design Change Impact
|
||||
Report is shown before any action.
|
||||
|
||||
The skill is read-only during analysis and write-gated per artifact during the
|
||||
update phase. It has no director gates — the analysis itself is mechanical
|
||||
tracing, not a creative review.
|
||||
In `full` review mode the TD-CHANGE-IMPACT gate (technical-director) reviews the
|
||||
report before resolution; in `lean`/`solo` it is skipped with a note. The user
|
||||
then decides per ADR (Mark Superseded / Update in place / Keep as-is / Skip), and
|
||||
every file change — an ADR status line, the traceability index, the
|
||||
`docs/architecture/change-impact-[date]-[system].md` report — has its own ask.
|
||||
The cascade scope follows the changed system's workflow tier (`full` all ADRs,
|
||||
`standard` critical ADRs plus those referencing the GDD, `minimal` not applicable).
|
||||
Verdicts: COMPLETE (impact report saved) or BLOCKED (user declined the write).
|
||||
|
||||
---
|
||||
|
||||
## 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, NO IMPACT
|
||||
- [ ] Contains "May I write" collaborative protocol language (per-artifact approval)
|
||||
- [ ] Has a next-step handoff at the end
|
||||
- [ ] Documents that changes are proposed, not applied automatically
|
||||
- [ ] Contains verdict keywords: COMPLETE, BLOCKED
|
||||
- [ ] Contains "May I" ask-before-write language for each file it changes
|
||||
- [ ] Has a next-step handoff at the end (`/architecture-decision`, `/architecture-review`)
|
||||
- [ ] Documents that the impact report is shown before any change is made
|
||||
- [ ] Documents gate TD-CHANGE-IMPACT: runs in full, skipped in lean/solo
|
||||
|
||||
---
|
||||
|
||||
## Director Gate Checks
|
||||
|
||||
No director gates — this skill spawns no director gate agents during analysis.
|
||||
The impact report is a mechanical tracing operation; no creative or technical
|
||||
director review is required at the analysis stage.
|
||||
One gate: **TD-CHANGE-IMPACT** (`technical-director`,
|
||||
`.claude/docs/director-gates/td-change-impact.md`), spawned after the Design
|
||||
Change Impact Report is presented and before the per-ADR resolution workflow.
|
||||
|
||||
- `full` → spawned with the full impact report (change summary, classifications,
|
||||
recommended actions)
|
||||
- `lean` → skipped; output notes "TD-CHANGE-IMPACT skipped — Lean mode."
|
||||
- `solo` → skipped; output notes "TD-CHANGE-IMPACT skipped — Solo mode."
|
||||
|
||||
Verdict handling: APPROVE → resolution workflow; CONCERNS → `AskUserQuestion` with
|
||||
`Revise the impact assessment` / `Accept with noted concerns` / `Discuss further`;
|
||||
REJECT → no resolution; the impact is re-analysed first; NOT ASSESSED [missing
|
||||
input] → never read as APPROVE: the input is supplied and the gate re-run, or the
|
||||
run goes on with `TD-CHANGE-IMPACT: NOT ASSESSED — [input]` stated in the report
|
||||
and the Verdict line.
|
||||
|
||||
---
|
||||
|
||||
## Test Cases
|
||||
|
||||
### Case 1: Happy Path — GDD revision affects 2 stories and 1 epic
|
||||
### Case 1: Happy Path — GDD formula change affects one of two referencing ADRs
|
||||
|
||||
**Fixture:**
|
||||
- `design/gdd/[system].md` exists and has been recently revised (git diff shows changes)
|
||||
- `production/epics/[layer]/EPIC-[system].md` references this GDD
|
||||
- 2 story files reference TR-IDs from this GDD
|
||||
- The changed GDD section affects the acceptance criteria of both stories
|
||||
- `project.yaml`: `modes.workflow: full`, `modes.review_mode: lean`
|
||||
- `design/gdd/combat.md` has an uncommitted edit to a damage formula in its
|
||||
Formulas section
|
||||
- `docs/architecture/` has 4 ADRs; ADR-0003 and ADR-0005 list `combat.md` in
|
||||
`## GDD Requirements Addressed`; ADR-0003's decision assumed the old formula,
|
||||
ADR-0005's decision does not depend on it
|
||||
- `docs/architecture/requirements-traceability.md` exists
|
||||
|
||||
**Input:** `/propagate-design-change design/gdd/[system].md`
|
||||
**Input:** `/propagate-design-change design/gdd/combat.md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads the revised GDD and identifies what changed (git diff or content comparison)
|
||||
2. Skill scans ADRs, TR-registry, epics, and stories for references to this GDD
|
||||
3. Skill produces an impact report: 1 epic affected, 2 stories affected
|
||||
4. Skill shows the proposed change for each artifact
|
||||
5. For each artifact: asks "May I update [filepath]?" separately
|
||||
6. Applies changes only after per-artifact approval
|
||||
1. Verifies the file exists; runs `git diff HEAD -- design/gdd/combat.md` and
|
||||
derives the changed sections from the hunks
|
||||
2. Prints the Change Summary (changed / unchanged sections, key changes)
|
||||
3. Globs the ADRs (N = 4), greps the requirement tables and the `combat`
|
||||
basename, and reports "Loaded 4 ADRs by scan. 2 reference combat.md (…)"
|
||||
4. Reads ADR-0003 and ADR-0005 (size checked with `wc -c` first) and classifies
|
||||
ADR-0003 Needs Review or Likely Superseded, ADR-0005 Still Valid
|
||||
5. Presents the Design Change Impact Report
|
||||
6. Notes "TD-CHANGE-IMPACT skipped — Lean mode."
|
||||
7. Asks "ADR-0003 ([title]) — [status]. What would you like to do?" with the four
|
||||
options; no resolution ask for ADR-0005
|
||||
8. Asks "May I update the traceability index?" and "May I write the change impact
|
||||
report to `docs/architecture/change-impact-[date]-combat.md`?"
|
||||
9. Verdict: COMPLETE — change impact report saved
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Impact report identifies all 3 affected artifacts (1 epic + 2 stories)
|
||||
- [ ] Each affected artifact's proposed change is shown before asking to write
|
||||
- [ ] "May I write" is asked per artifact (not once for all artifacts)
|
||||
- [ ] Skill does NOT apply any changes without per-artifact approval
|
||||
- [ ] Verdict is COMPLETE after all approved changes are applied
|
||||
- [ ] What changed is taken from `git diff`, not from reading two whole documents
|
||||
- [ ] Only the 2 referencing ADRs are full-read; the other 2 are not described as verified unaffected
|
||||
- [ ] The full impact report is shown before any resolution ask or write
|
||||
- [ ] A resolution ask is made per Needs Review / Likely Superseded ADR, one at a time
|
||||
- [ ] Each file change (ADR status, traceability index, impact report) has its own ask
|
||||
- [ ] "TD-CHANGE-IMPACT skipped — Lean mode." appears
|
||||
- [ ] Verdict is COMPLETE after the impact report is written
|
||||
|
||||
---
|
||||
|
||||
### Case 2: No Impact — Changed GDD has no downstream references
|
||||
### Case 2: Zero matches — "no impact" versus "cannot trace"
|
||||
|
||||
**Fixture:**
|
||||
- `design/gdd/[system].md` exists and has been revised
|
||||
- No ADRs, stories, or epics reference this GDD's TR-IDs or GDD path
|
||||
**Fixture (tables present):**
|
||||
- `project.yaml`: `modes.workflow: full`
|
||||
- `design/gdd/combat.md` has an uncommitted edit
|
||||
- 3 ADRs, each with a `## GDD Requirements Addressed` section, none naming
|
||||
`combat.md` in the table or in prose
|
||||
|
||||
**Input:** `/propagate-design-change design/gdd/[system].md`
|
||||
**Input (both fixtures):** `/propagate-design-change design/gdd/combat.md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads the revised GDD
|
||||
2. Skill scans all ADRs, stories, and epics for references
|
||||
3. No references found
|
||||
4. Skill outputs: "No downstream impact found for [system].md — no artifacts reference this GDD."
|
||||
5. No write operations are performed
|
||||
**Expected behavior (tables present):**
|
||||
1. Both scans return 0 with N = 3
|
||||
2. The files-with-matches check for `## GDD Requirements Addressed` is non-empty
|
||||
3. Reports "No ADR references combat.md — no architecture impact."
|
||||
|
||||
**Fixture (tables absent):**
|
||||
- Same GDD edit; 3 ADRs, none containing a `## GDD Requirements Addressed` section
|
||||
and none naming `combat.md`
|
||||
|
||||
**Expected behavior (tables absent):**
|
||||
1. Both scans return 0 with N = 3; the section check is also empty
|
||||
2. Reports "3 ADRs found, none contains a 'GDD Requirements Addressed' section —
|
||||
traceability cannot be computed (a `gate-pre-production` blocker). Run
|
||||
`/architecture-decision retrofit [adr]`."
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Skill outputs the "No downstream impact found" message
|
||||
- [ ] Verdict is NO IMPACT
|
||||
- [ ] No "May I write" asks are issued (nothing to update)
|
||||
- [ ] With tables present, the "no architecture impact" message is printed
|
||||
- [ ] With tables absent, the skill does NOT report "no impact" — it reports that traceability cannot be computed and names `/architecture-decision retrofit [adr]`, the form that skill parses
|
||||
- [ ] No per-ADR resolution ask and no ADR edit happens in either fixture
|
||||
- [ ] Skill does NOT error or crash when no references are found
|
||||
|
||||
---
|
||||
|
||||
### Case 3: In-Progress Story Warning — Referenced story is currently being developed
|
||||
### Case 3: Edge Case — Empty diff on a GDD with history
|
||||
|
||||
**Fixture:**
|
||||
- A story referencing this GDD has `Status: In Progress`
|
||||
- The developer has already started implementing this story
|
||||
- `project.yaml`: `modes.workflow: full`
|
||||
- `design/gdd/combat.md` is committed, has no uncommitted changes, and was not
|
||||
touched by the last commit
|
||||
|
||||
**Input:** `/propagate-design-change design/gdd/[system].md`
|
||||
**Input:** `/propagate-design-change design/gdd/combat.md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill identifies the In Progress story as an affected artifact
|
||||
2. Skill outputs an elevated warning: "CAUTION: [story-file] is currently In Progress — a developer may be working on this. Coordinate before updating."
|
||||
3. The warning appears in the impact report before the "May I write" ask for that story
|
||||
4. User can still approve or skip the update for that story
|
||||
1. `git diff HEAD -- design/gdd/combat.md` is empty
|
||||
2. `git diff HEAD~1 HEAD -- design/gdd/combat.md` is also empty
|
||||
3. Reports "no uncommitted or last-commit changes to `design/gdd/combat.md`" and
|
||||
asks which revision to propagate
|
||||
4. Does not report "no impact" and does not scan ADRs before a revision is chosen
|
||||
|
||||
**Assertions:**
|
||||
- [ ] In Progress story is flagged with an elevated warning (distinct from regular affected-artifact entries)
|
||||
- [ ] Warning appears before the "May I write" ask for that story
|
||||
- [ ] Skill still offers to update the story — the warning does not block the option
|
||||
- [ ] Other (non-In-Progress) artifacts are not affected by this warning
|
||||
- [ ] Both diffs are tried, working tree first, then the last commit
|
||||
- [ ] The "no uncommitted or last-commit changes" report is printed
|
||||
- [ ] The user is asked which revision to propagate
|
||||
- [ ] The empty diff is NOT reported as "no impact"
|
||||
|
||||
---
|
||||
|
||||
@@ -119,57 +164,103 @@ director review is required at the analysis stage.
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill detects no argument is provided
|
||||
2. Skill outputs a usage error: "No GDD specified. Usage: /propagate-design-change design/gdd/[system].md"
|
||||
3. Skill lists recently modified GDDs as suggestions (git log)
|
||||
4. No analysis is performed
|
||||
2. Skill fails with: "Usage: `/propagate-design-change design/gdd/[system].md`
|
||||
Provide the path to the GDD that was changed."
|
||||
3. No diff, scan or analysis is performed
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Skill outputs a usage error when no argument is given
|
||||
- [ ] Usage example is shown with the correct path format
|
||||
- [ ] No impact analysis is performed without a target GDD
|
||||
- [ ] Skill outputs the usage message when no argument is given
|
||||
- [ ] The usage example shows the `design/gdd/[system].md` path format
|
||||
- [ ] No `git diff` or ADR scan is performed without a target GDD
|
||||
- [ ] Skill does NOT silently pick a GDD without user input
|
||||
|
||||
---
|
||||
|
||||
### Case 5: Director Gate — No gate spawned regardless of review mode
|
||||
### Case 5: Director Gate — TD-CHANGE-IMPACT returns CONCERNS in full mode
|
||||
|
||||
**Fixture:**
|
||||
- A GDD has been revised with downstream references
|
||||
- `production/session-state/review-mode.txt` exists with `full`
|
||||
- `project.yaml`: `modes.workflow: full`, `modes.review_mode: full`
|
||||
- A GDD edit that leaves one referencing ADR classified Needs Review
|
||||
- TD-CHANGE-IMPACT returns CONCERNS: a second ADR was under-classified
|
||||
|
||||
**Input:** `/propagate-design-change design/gdd/[system].md`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Skill reads the GDD and traces downstream references
|
||||
2. Skill does NOT read `production/session-state/review-mode.txt`
|
||||
3. No director gate agents are spawned at any point
|
||||
4. Impact report is produced and per-artifact approval proceeds normally
|
||||
1. The Design Change Impact Report is presented
|
||||
2. `technical-director` is spawned via `Agent` with gate TD-CHANGE-IMPACT, passing
|
||||
the full report
|
||||
3. CONCERNS are surfaced, naming the flagged ADR
|
||||
4. `AskUserQuestion`: `Revise the impact assessment` / `Accept with noted concerns`
|
||||
/ `Discuss further`
|
||||
5. The per-ADR resolution workflow starts only after that answer
|
||||
|
||||
**Assertions:**
|
||||
- [ ] No director gate agents are spawned (no CD-, TD-, PR-, AD- prefixed gates)
|
||||
- [ ] Skill does NOT read `production/session-state/review-mode.txt`
|
||||
- [ ] Output contains no "Gate: [GATE-ID]" or gate-skipped entries
|
||||
- [ ] Review mode has no effect on this skill's behavior
|
||||
- [ ] TD-CHANGE-IMPACT is spawned after the impact report is shown and before any resolution ask
|
||||
- [ ] The gate receives the full report (change summary, classifications, recommended actions)
|
||||
- [ ] The CONCERNS name the flagged ADR and all three options are offered
|
||||
- [ ] No ADR, traceability or report file is written before the CONCERNS are answered
|
||||
- [ ] No "TD-CHANGE-IMPACT skipped" note appears in `full` mode
|
||||
|
||||
---
|
||||
|
||||
### Case 6: Workflow tiers — `minimal` stops before the cascade; `standard` narrows it
|
||||
|
||||
**Fixture (minimal):**
|
||||
- `project.yaml` sets no `modes` keys — `modes.rigor` defaults to `minimal`, so
|
||||
the workflow resolves to `minimal`
|
||||
- `design/gdd/loot.md` has an uncommitted edit
|
||||
|
||||
**Fixture (standard):**
|
||||
- `project.yaml`: `modes.workflow: standard`, `modes.review_mode: solo`
|
||||
- `design/gdd/loot.md` has an uncommitted edit
|
||||
- 4 ADRs, by their Engine Compatibility `Layer`: ADR-0001 (Foundation, event bus,
|
||||
no mention of `loot.md`), ADR-0002 (Foundation, save system, lists `loot.md` in
|
||||
`## GDD Requirements Addressed`), ADR-0006 (Feature, loot tables, names `loot.md`
|
||||
in prose only), ADR-0007 (Feature, enemy AI, no mention)
|
||||
|
||||
**Input (both fixtures):** `/propagate-design-change design/gdd/loot.md`
|
||||
|
||||
**Expected behavior (minimal):**
|
||||
1. The diff and Change Summary run as usual
|
||||
2. At the ADR step: "No ADR cascade at minimal workflow — design change recorded;
|
||||
no architecture impact analysis." and the skill stops
|
||||
|
||||
**Expected behavior (standard):**
|
||||
1. The in-scope set is the Foundation ADRs plus any ADR referencing `loot.md`:
|
||||
ADR-0001, ADR-0002 and ADR-0006, so N = 3; ADR-0007 is out of scope
|
||||
2. Reports "Loaded 3 ADRs by scan. 2 reference loot.md (1 via requirements table,
|
||||
1 via prose reference only)."
|
||||
3. Full-reads only ADR-0002 and ADR-0006; notes "TD-CHANGE-IMPACT skipped — Solo mode."
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Minimal: no ADR is globbed or read, no gate is spawned or noted, and no write ask is made
|
||||
- [ ] Standard: ADR-0007 is not counted or read, and neither it nor ADR-0001 is described as verified unaffected
|
||||
- [ ] Standard: the prose-only reference in ADR-0006 is caught by the basename grep
|
||||
- [ ] Standard: the Foundation ADRs are found from the `**Layer**` rows (`Grep pattern="\*\*Layer\*\*" glob="docs/architecture/adr-*.md"`), not guessed from titles
|
||||
- [ ] Variant — ADR-0007 has no `**Layer**` row: it is treated as critical (when in doubt, critical) and joins the in-scope set, so N = 4
|
||||
|
||||
---
|
||||
|
||||
## Protocol Compliance
|
||||
|
||||
- [ ] Reads revised GDD and all potentially affected artifacts before producing impact report
|
||||
- [ ] Impact report shown in full before any "May I write" ask
|
||||
- [ ] "May I write" asked per artifact — never for the entire set at once
|
||||
- [ ] In Progress stories flagged with elevated warning before their approval ask
|
||||
- [ ] No director gates — no review-mode.txt read
|
||||
- [ ] Ends with next-step handoff appropriate to verdict (COMPLETE or NO IMPACT)
|
||||
- [ ] Diffs the GDD and scans ADRs before producing the impact report
|
||||
- [ ] Impact report shown in full before any resolution ask
|
||||
- [ ] Resolution asked per ADR — never one decision for the whole set
|
||||
- [ ] "May I" asked before each file change; ADR content is never deleted, only marked Superseded
|
||||
- [ ] TD-CHANGE-IMPACT runs in `full`, skipped with a named note in `lean`/`solo`
|
||||
- [ ] Ends with follow-up actions matching the resolutions (`/architecture-decision` for Superseded ADRs, `/architecture-review` when many are affected)
|
||||
|
||||
---
|
||||
|
||||
## Coverage Notes
|
||||
|
||||
- ADR impact (when a GDD change requires an ADR update or new ADR) follows the
|
||||
same per-artifact approval pattern as story/epic updates — not independently
|
||||
- A system pinned `minimal` through `system_overrides` on a `standard` project
|
||||
(its change is N/A) is not given its own fixture; Case 6 reaches `minimal`
|
||||
through the project default.
|
||||
- Downstream GDD impact via `design/registry/entities.yaml` is not independently
|
||||
fixture-tested.
|
||||
- TR-registry impact (when changed GDD requires new or updated TR-IDs) is part
|
||||
of the analysis phase but not independently fixture-tested.
|
||||
- The git diff comparison method (detecting what changed in the GDD) is a runtime
|
||||
concern — fixtures use pre-arranged content differences.
|
||||
- A GDD with no git history ("appears to be a new GDD, not a revision") and a
|
||||
path that does not exist are not separately tested.
|
||||
- TD-CHANGE-IMPACT APPROVE, REJECT and NOT ASSESSED paths are not separately tested.
|
||||
- Stories and epics are outside this skill's scope — it cascades into ADRs and the
|
||||
traceability index only.
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
# Skill Test Spec: /vertical-slice
|
||||
|
||||
## Skill Summary
|
||||
|
||||
`/vertical-slice [--review full|lean|solo]` is the Pre-Production validation
|
||||
build: one complete [start → challenge → resolution] loop at near-production
|
||||
quality, answering a falsifiable question about player experience *and* build
|
||||
feasibility. It reads the concept (`design/gdd/game-concept.md`, or
|
||||
`design/game-brief.md` at `rigor: minimal`), the systems index, the architecture
|
||||
and the control manifest, defines the validation question and a 3–5 minute scope,
|
||||
asks to record the plan in `production/session-state/active.md`, then asks "May I
|
||||
create the vertical slice directory at `prototypes/[concept-name]-vertical-slice/`
|
||||
and begin implementation?". Every slice file starts with a
|
||||
`VERTICAL SLICE - NOT FOR PRODUCTION` header in that file's own comment syntax.
|
||||
|
||||
After a one-question-at-a-time debrief it writes
|
||||
`prototypes/[concept-name]-vertical-slice/REPORT.md` (from
|
||||
`.claude/docs/templates/vertical-slice-report.md`) and a `prototypes/index.md`
|
||||
row, one ask naming both. Verdicts are **PROCEED / PIVOT / KILL**, plus
|
||||
**NOT ASSESSED** when nobody has played the loop through from scratch — ranked
|
||||
above PROCEED and below PIVOT and KILL, and never recorded as PROCEED. The verdict
|
||||
feeds `/gate-check production`, which FAILs a built slice with any NO among its
|
||||
Vertical Slice Validation items, so PROCEED is not available after such a NO. In
|
||||
`full` review mode `creative-director` reviews the result via **CD-PLAYTEST**
|
||||
(APPROVE / CONCERNS / REJECT, or NOT ASSESSED): APPROVE keeps the recommendation;
|
||||
CONCERNS go to the user (Revise / Accept / Discuss); REJECT means PROCEED cannot
|
||||
stand — the user chooses PIVOT or KILL and the report records the director's
|
||||
reason. PIVOT writes a `PIVOT-NOTE.md`; KILL runs a five-item soundness check and
|
||||
appends to `prototypes/GRAVEYARD.md`.
|
||||
|
||||
---
|
||||
|
||||
## 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: PROCEED, PIVOT, KILL, NOT ASSESSED
|
||||
- [ ] Contains "May I" language before creating the slice directory and before writing REPORT.md, PIVOT-NOTE.md and GRAVEYARD.md
|
||||
- [ ] Has a next-step handoff per verdict (PROCEED → `/create-epics`, `/create-stories`, `/sprint-plan`, `/gate-check production`; PIVOT → `/design-system`, `/architecture-decision`, `/vertical-slice`; KILL → `/brainstorm` or `/prototype`)
|
||||
- [ ] Documents CD-PLAYTEST: spawned in `full`, skipped with a note in `lean`/`solo`
|
||||
|
||||
---
|
||||
|
||||
## Director Gate Checks
|
||||
|
||||
- **Full mode**: CD-PLAYTEST — `creative-director` receives the REPORT.md content,
|
||||
the validation question and the pillars and core fantasy (from
|
||||
`design/gdd/game-concept.md`, or the pitch and "what they feel" line from
|
||||
`design/game-brief.md`). APPROVE → the recommendation stands; CONCERNS → shown
|
||||
with the recommendation, and the user decides (Revise / Accept / Discuss);
|
||||
REJECT → a PROCEED cannot stand: the user chooses PIVOT or KILL, and REPORT.md
|
||||
records the director's reason (a PIVOT or KILL stands); NOT ASSESSED [missing
|
||||
input] → neither backs nor overturns the recommendation: the input is supplied
|
||||
and the gate re-run, or `CD-PLAYTEST: NOT ASSESSED — [input]` is recorded. Any
|
||||
change to REPORT.md and its `prototypes/index.md` row is asked first. When the
|
||||
slice's own verdict is NOT ASSESSED the gate is skipped: "CD-PLAYTEST skipped —
|
||||
the slice has not been played yet."
|
||||
- **Lean mode**: skipped — "CD-PLAYTEST skipped — Lean mode."
|
||||
- **Solo mode**: skipped — "CD-PLAYTEST skipped — Solo mode."
|
||||
|
||||
---
|
||||
|
||||
## Test Cases
|
||||
|
||||
### Case 1: Happy Path — slice built, played unaided, PROCEED
|
||||
|
||||
**Fixture:**
|
||||
- `project.yaml`: `engine.name: Godot`, `engine.language: GDScript`,
|
||||
`modes.review_mode: solo`
|
||||
- `design/gdd/game-concept.md` (core fantasy, pillars), `design/gdd/systems-index.md`,
|
||||
`docs/architecture/architecture.md` and `docs/architecture/control-manifest.md`
|
||||
exist; `prototypes/` has no `ember-trail-vertical-slice/`
|
||||
- In the debrief the player finished the loop unaided, reached the first meaningful
|
||||
action in 40 seconds, felt the core fantasy and hit no fun blocker; the user
|
||||
answers PROCEED
|
||||
|
||||
**Input:** `/vertical-slice`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Reads the concept, systems index, architecture and manifest; states a
|
||||
validation question covering player experience AND build feasibility
|
||||
2. Presents a 3–5 minute scope and the build plan; the confirmation names
|
||||
`production/session-state/active.md`, and the checkpoint is written there
|
||||
3. Asks "May I create the vertical slice directory at
|
||||
`prototypes/ember-trail-vertical-slice/` and begin implementation?"; every
|
||||
GDScript file it writes starts with `# VERTICAL SLICE - NOT FOR PRODUCTION`
|
||||
4. Iterates with the user until the loop is playable, then asks for the
|
||||
from-scratch playthrough and puts the six debrief questions one at a time
|
||||
5. Drafts the report from `.claude/docs/templates/vertical-slice-report.md` with a
|
||||
day-by-day velocity log; asks "May I write this report to
|
||||
`prototypes/ember-trail-vertical-slice/REPORT.md` and add its row to
|
||||
`prototypes/index.md`?"; writes both
|
||||
6. Notes "CD-PLAYTEST skipped — Solo mode."
|
||||
7. PROCEED routes to `/create-epics layer:foundation`, `/create-epics layer:core`,
|
||||
`/create-stories`, `/sprint-plan` and `/gate-check production`
|
||||
|
||||
**Assertions:**
|
||||
- [ ] The validation question has both a player-experience and a build-feasibility part
|
||||
- [ ] Scope is confirmed, and the checkpoint ask names `active.md`, before any slice file is written
|
||||
- [ ] The directory ask comes before any slice file; each GDScript file's header is a `#` comment, never `//`
|
||||
- [ ] The debrief questions are asked one at a time, after the from-scratch playthrough
|
||||
- [ ] REPORT.md and the `prototypes/index.md` row are written only after one ask naming both; the row records PROCEED
|
||||
- [ ] The formal stage step is `/gate-check production` (Pre-Production → Production), not `/gate-check pre-production`
|
||||
|
||||
---
|
||||
|
||||
### Case 2: Failure Path — a built slice with a NO cannot PROCEED
|
||||
|
||||
**Fixture:**
|
||||
- As Case 1, but in the debrief the player needed the developer to explain the
|
||||
core action (question 1: no)
|
||||
- The user answers PROCEED anyway, then picks PIVOT when asked
|
||||
|
||||
**Input:** `/vertical-slice`
|
||||
|
||||
**Expected behavior:**
|
||||
1. The skill does not record PROCEED: `/gate-check production` FAILs a built slice
|
||||
with any NO among its Vertical Slice Validation items
|
||||
(`.claude/skills/gate-check/references/gate-production.md`)
|
||||
2. It asks the user to choose PIVOT or KILL, naming question 1's answer as the reason
|
||||
3. The user picks PIVOT; REPORT.md is written, after its ask, with verdict PIVOT
|
||||
and the NO named
|
||||
4. The PIVOT route runs: the two carry-forward questions, one at a time, then "May I
|
||||
write this to `prototypes/ember-trail-vertical-slice/PIVOT-NOTE.md`?"
|
||||
|
||||
**Assertions:**
|
||||
- [ ] PROCEED is not written to REPORT.md or `prototypes/index.md` while a validation item is NO
|
||||
- [ ] The user, not the skill, chooses between PIVOT and KILL
|
||||
- [ ] The report names the failed validation item
|
||||
- [ ] PIVOT-NOTE.md is written only after its ask, with what worked, what failed and what the next slice should prove
|
||||
|
||||
---
|
||||
|
||||
### Case 3: Mode Variant — CD-PLAYTEST in full, skipped in lean and solo
|
||||
|
||||
**Fixture:**
|
||||
- A slice has been debriefed with a PROCEED recommendation and REPORT.md written
|
||||
- Run A: `modes.review_mode: full`; CD-PLAYTEST returns APPROVE
|
||||
- Run B: `modes.review_mode: lean`
|
||||
- Run C: `modes.review_mode: full`, input `/vertical-slice --review solo`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Run A: `creative-director` is spawned for CD-PLAYTEST after REPORT.md is
|
||||
written, with the REPORT.md content, the validation question and the pillars
|
||||
and core fantasy; APPROVE leaves PROCEED standing and REPORT.md unchanged
|
||||
2. Run B: no spawn; "CD-PLAYTEST skipped — Lean mode."
|
||||
3. Run C: `--review solo` overrides the resolved `full`; no spawn; "CD-PLAYTEST
|
||||
skipped — Solo mode."
|
||||
|
||||
**Assertions:**
|
||||
- [ ] Run A spawns CD-PLAYTEST only after REPORT.md exists, with the three inputs
|
||||
- [ ] Run A's APPROVE keeps the recommendation and triggers no REPORT.md update ask
|
||||
- [ ] Runs B and C spawn no director and print their skip notes
|
||||
- [ ] No other director gate is spawned in any run
|
||||
|
||||
---
|
||||
|
||||
### Case 4: Edge Case — the slice is built but nobody has played it
|
||||
|
||||
**Fixture:**
|
||||
- The loop became demonstrable, but the user cannot play it through from scratch
|
||||
this session
|
||||
- `modes.review_mode: full`
|
||||
|
||||
**Input:** `/vertical-slice`
|
||||
|
||||
**Expected behavior:**
|
||||
1. The Phase 5 playthrough does not happen, so the verdict is NOT ASSESSED, with
|
||||
the reason
|
||||
2. REPORT.md, after its ask, records the velocity log and NOT ASSESSED; the
|
||||
`prototypes/index.md` row records NOT ASSESSED
|
||||
3. CD-PLAYTEST is not spawned: "CD-PLAYTEST skipped — the slice has not been
|
||||
played yet."
|
||||
4. Next steps: finish the playthrough and debrief from the `active.md` checkpoint,
|
||||
then update REPORT.md after asking; the slice is not taken to
|
||||
`/gate-check production` as if it had passed
|
||||
|
||||
**Assertions:**
|
||||
- [ ] The verdict is NOT ASSESSED — never PROCEED — and its reason is stated
|
||||
- [ ] NOT ASSESSED is ranked above PROCEED and below PIVOT and KILL
|
||||
- [ ] CD-PLAYTEST is not spawned for an unplayed slice, and the skip is announced
|
||||
- [ ] PROCEED's next steps are not offered
|
||||
|
||||
---
|
||||
|
||||
### Case 5: Director Gate — CD-PLAYTEST returns REJECT, CONCERNS or NOT ASSESSED
|
||||
|
||||
**Fixture:**
|
||||
- A slice has been debriefed with a PROCEED recommendation and REPORT.md written;
|
||||
`modes.review_mode: full`; `design/gdd/game-concept.md` holds the pillars
|
||||
- Run A: CD-PLAYTEST returns REJECT — the core fantasy is not present. Asked PIVOT
|
||||
or KILL, the user picks KILL; no playtest session showed an emotional high
|
||||
point, and this is the third slice attempt on the concept
|
||||
- Run B: CD-PLAYTEST returns CONCERNS — the resolution beat undercuts a pillar; the
|
||||
user picks `Accept with noted concerns`
|
||||
- Run C: CD-PLAYTEST returns NOT ASSESSED — the pillars were missing from the
|
||||
context it received
|
||||
|
||||
**Input:** `/vertical-slice`
|
||||
|
||||
**Expected behavior:**
|
||||
1. Run A: the REJECT is read as the gate's word, not as a slice verdict. PROCEED
|
||||
cannot stand: the skill asks the user to choose PIVOT or KILL; the user picks
|
||||
KILL; after "May I update `prototypes/[concept-name]-vertical-slice/REPORT.md`
|
||||
and its `prototypes/index.md` row?" both record KILL and REPORT.md records the
|
||||
director's reason. Phase 8's KILL route runs: two checklist items apply, so the
|
||||
KILL is sound, and it asks "May I append this to `prototypes/GRAVEYARD.md`?"
|
||||
2. Run B: the concerns are shown beside PROCEED with `Revise the recommendation` /
|
||||
`Accept with noted concerns` / `Discuss further`; on Accept, PROCEED stands and,
|
||||
after the update ask, REPORT.md records the concerns
|
||||
3. Run C: the missing input is named; the gate is re-run with the pillars, or
|
||||
`CD-PLAYTEST: NOT ASSESSED — [input]` is recorded after the update ask; PROCEED
|
||||
is neither confirmed nor overturned by it
|
||||
|
||||
**Assertions:**
|
||||
- [ ] The director's answer is read as APPROVE / CONCERNS / REJECT / NOT ASSESSED — never as a PROCEED / PIVOT / KILL of its own
|
||||
- [ ] Run A: PROCEED is not kept after the REJECT; the user chooses PIVOT or KILL, and the director's reason is in REPORT.md
|
||||
- [ ] Run A: the GRAVEYARD.md entry is appended only after its ask, with a specific kill reason
|
||||
- [ ] Run B: the user decides; the recommendation changes only if the user revises it
|
||||
- [ ] Run C: NOT ASSESSED is not treated as APPROVE
|
||||
- [ ] Every REPORT.md / `prototypes/index.md` update follows an ask naming both
|
||||
|
||||
---
|
||||
|
||||
## Protocol Compliance
|
||||
|
||||
- [ ] Reads the concept (or the brief at `minimal`) before defining the validation question
|
||||
- [ ] Confirms scope before building; asks before recording the plan in `active.md` and before creating `prototypes/[concept-name]-vertical-slice/`
|
||||
- [ ] Keeps slice files under `prototypes/`, each with the `VERTICAL SLICE - NOT FOR PRODUCTION` header in its own comment syntax
|
||||
- [ ] Asks before writing REPORT.md (with its `prototypes/index.md` row), PIVOT-NOTE.md, GRAVEYARD.md and any post-gate report update
|
||||
- [ ] Never records PROCEED after a NO validation item, and never for a slice nobody has played
|
||||
- [ ] Applies the review mode before CD-PLAYTEST and prints the skip note when skipped
|
||||
- [ ] Ends with the per-verdict next steps
|
||||
|
||||
---
|
||||
|
||||
## Coverage Notes
|
||||
|
||||
- The multi-turn build loop, the day-3 sunk-cost stop and the day-by-day velocity
|
||||
log need a live run to verify.
|
||||
- Reading a prior `PIVOT-NOTE.md` on a re-run to frame the new validation question
|
||||
is not tested.
|
||||
- The `rigor: minimal` path (the brief's pitch and "what they feel" line in place
|
||||
of pillars) is not given its own fixture.
|
||||
- A KILL whose soundness checklist gives 0–1 items (one targeted PIVOT suggested
|
||||
instead) is not tested.
|
||||
- The networked-game limit (a local slice cannot validate network feel) is
|
||||
advisory text, not tested.
|
||||
Reference in New Issue
Block a user