kataster 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/acceptance-tester.md +7 -2
- package/.claude/agents/code-reviewer.md +7 -2
- package/.claude/agents/ux-designer.md +42 -47
- package/.claude/hooks/validate-docs.ts +2 -1
- package/.claude/lib/config.ts +1 -0
- package/.claude/lib/discovery.ts +129 -31
- package/.claude/lib/engineering.ts +12 -6
- package/.claude/package.json +1 -0
- package/.claude/settings.json +1 -2
- package/.claude/skills/adopt/SKILL.md +5 -3
- package/.claude/skills/backlog/SKILL.md +2 -2
- package/.claude/skills/bootstrap/SKILL.md +9 -7
- package/.claude/skills/domain-model/SKILL.md +1 -1
- package/.claude/skills/feature/SKILL.md +9 -9
- package/.claude/skills/feature/scripts/intake.ts +1 -1
- package/.claude/skills/groom-backlog/SKILL.md +19 -17
- package/.claude/skills/implement/SKILL.md +163 -78
- package/.claude/skills/implement/scripts/check-scenarios.ts +1 -1
- package/.claude/skills/implement/scripts/story-context.ts +1 -1
- package/.claude/skills/implement/scripts/verify.ts +1 -1
- package/.claude/skills/prototype/SKILL.md +1 -1
- package/.claude/skills/review-stories/SKILL.md +39 -19
- package/.claude/skills/shape/SKILL.md +2 -2
- package/.claude/skills/user-stories/SKILL.md +109 -51
- package/.claude/skills/user-stories/schema/story.schema.json +6 -3
- package/.claude/skills/user-stories/scripts/lint-story.ts +56 -0
- package/.claude/skills/user-stories/templates/story-template.md +5 -2
- package/.claude/skills/ux-design/SKILL.md +9 -7
- package/.opencode/agents/acceptance-tester.md +8 -3
- package/.opencode/agents/code-reviewer.md +8 -3
- package/.opencode/agents/ux-designer.md +42 -52
- package/.opencode/commands/bootstrap.md +1 -1
- package/.opencode/commands/feature.md +1 -1
- package/.opencode/commands/groom-backlog.md +1 -1
- package/.opencode/commands/implement.md +1 -1
- package/.opencode/commands/review-stories.md +1 -1
- package/AGENTS.md +17 -0
- package/CHANGELOG.md +24 -0
- package/README.md +31 -6
- package/guide/brownfield.md +2 -2
- package/guide/concepts.md +11 -5
- package/guide/greenfield.md +4 -3
- package/package.json +1 -1
- package/src/cli.mjs +42 -4
- package/src/install.mjs +62 -6
- package/templates/docs/stories/README.md +10 -3
- package/templates/docs/workflow.md +27 -11
- package/.claude/agents/lead-dev.md +0 -52
- package/.claude/agents/product-owner.md +0 -39
- package/.claude/agents/requirements-engineer.md +0 -44
- package/.opencode/agents/lead-dev.md +0 -69
- package/.opencode/agents/product-owner.md +0 -59
- package/.opencode/agents/requirements-engineer.md +0 -58
|
@@ -60,11 +60,11 @@ Do not run an event storming for a bug and do not create a feature slug unless t
|
|
|
60
60
|
Read `docs/product/vision.md`, `CONTEXT.md`, `docs/domain/events.yaml`, `docs/domain/context-map.md`, `docs/architecture/data-model.md`, `docs/adr/`, `docs/stories/BACKLOG.md`. Find out what already exists for this idea (events, stories, hotspots) before asking anything. With an intake result, use its source and matching story instead of searching from scratch. If a linked story exists, pull the tracker first (`/backlog-sync pull`) so the mirror is current.
|
|
61
61
|
|
|
62
62
|
## 2. Grill the idea
|
|
63
|
-
Call the `skill` tool four times, for `grilling`, `domain-model`, `architect` and `ux-design` (the first three are the set of `/grill-with-docs`, which can't be called from a skill). Grill the user until the frontier is empty and they confirm a shared understanding. The grilling carries the three perspectives the
|
|
64
|
-
- **
|
|
65
|
-
- **
|
|
63
|
+
Call the `skill` tool four times, for `grilling`, `domain-model`, `architect` and `ux-design` (the first three are the set of `/grill-with-docs`, which can't be called from a skill). Grill the user until the frontier is empty and they confirm a shared understanding. The grilling carries the three perspectives the spec linter cannot check – product, engineering, UX. With an intake result, the ticket's claims and the intake's `signals` seed the frontier; unresolved comments and contradictions are the first questions. Typical branches:
|
|
64
|
+
- **Product**: Which problem, for which user group, and what value? Measurable outcome? Does it fit the vision, or touch a non-goal? If it changes scope → update `docs/product/vision.md` with the user. Must vs. could – what ships first?
|
|
65
|
+
- **Engineering**: Which existing code, data and stories change? Is there a migration? What is hard to test? Where does it cut into stories – one command per story, at most 4 scenarios?
|
|
66
66
|
- Which existing processes, events and stories does it change? What's explicitly out of scope?
|
|
67
|
-
- **UX – does a person see anything?** Almost always yes – then the UX frontier of `ux-design` belongs in the rounds: entry point, the screen's one job, what is shown before acting, what happens afterwards, the rejected, empty, full and no-permission cases, and the UI wording. A feature whose screens nobody named gets them by accident. Stories with a frontend part get
|
|
67
|
+
- **UX – does a person see anything?** Almost always yes – then the UX frontier of `ux-design` belongs in the rounds: entry point, the screen's one job, what is shown before acting, what happens afterwards, the rejected, empty, full and no-permission cases, and the UI wording. A feature whose screens nobody named gets them by accident. Stories with a frontend part get `ui: true`.
|
|
68
68
|
- **Prototype – is paper enough?** When the UX frontier leaves a structural layout choice, a flow or a state model that cannot be settled in words, the UX lens proposes a prototype: one question, the branch (`ui` or `logic`), the variants or scenarios, and a timebox. The user decides. `--prototype` makes it explicit. Do not propose one for polish or for a question a guideline already answers. If it is agreed, run step 2b before the event storming.
|
|
69
69
|
- New or changed terms → `CONTEXT.md` inline.
|
|
70
70
|
- An architectural trade-off → ADR (`status: proposed`) only if the architect skill's three criteria hold.
|
|
@@ -86,9 +86,9 @@ it. In short:
|
|
|
86
86
|
4. **Capture.** The decision goes to `ux-designer` for `docs/product/ux-guidelines.md` (a G-number when it is
|
|
87
87
|
a recurring rule). Commit `docs/prototypes/<slug>/` on a throwaway branch `prototype/<slug>`, push it only
|
|
88
88
|
if the user wants to share it, then return to the branch you were on. The branch is never merged.
|
|
89
|
-
5. **Into the story.**
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
5. **Into the story.** In section 5 you write the verdict and the branch pointer into the story's `## Context`:
|
|
90
|
+
`Prototype: prototype/<slug> – <question> – <verdict>`, and the scenarios reflect the decision. The
|
|
91
|
+
`ux-designer` never writes the story itself.
|
|
92
92
|
|
|
93
93
|
If the question needs the real application (an existing page, real data), say so: that is an in-app prototype
|
|
94
94
|
and belongs to `/implement`, not to discovery. If the prototype does not answer the question within its
|
|
@@ -103,10 +103,10 @@ Read `.claude/skills/event-storming/SKILL.md` and follow it with the feature as
|
|
|
103
103
|
- A UX decision changes or adds a guideline → delegate to `ux-designer`: write exactly these decisions into `docs/product/ux-guidelines.md`. A prototype verdict is a decision like any other; the branch pointer and the verdict go into the story through step 5. The audit of existing screens belongs to `/groom-backlog`, not to the feature.
|
|
104
104
|
|
|
105
105
|
## 5. Stories
|
|
106
|
-
|
|
106
|
+
Write the stories yourself as the spec engineer (the `user-stories` skill is the method): derive one story per new or changed command, policy or read model; name `aggregate` and `command` (exactly one each), the event/command IDs, `ui: true` for every story with a frontend part, `type: chore`/`task` for non-domain work, the label `feature:<slug>`, the label `bug` for the bug path, the source reference (`Source: <ref> (<url>)`) for every story derived from a ticket, the UX decisions from step 2 (with the G-numbers of the guidelines they reference), the prototype verdict and branch pointer from step 2b, and existing stories that need revising. Do not merge two commands into one story; if the cut needs more than 4 scenarios, split it. Finished stories get `status: review` and are run through the spec linter.
|
|
107
107
|
|
|
108
108
|
## 6. Review
|
|
109
|
-
Read `.claude/skills/review-stories/SKILL.md` and follow it with the story IDs from step 5 as the arguments (only this feature's stories, not everything in `review`). The user
|
|
109
|
+
Read `.claude/skills/review-stories/SKILL.md` and follow it with the story IDs from step 5 as the arguments (only this feature's stories, not everything in `review`). The spec linter must be green before a story reaches `ready-for-human-review`; the user approves every change and every `ready`. There is no separate review subagent.
|
|
110
110
|
|
|
111
111
|
## 7. Wrap-up
|
|
112
112
|
Summarize: the source and the route taken (idea, ticket, existing story or bug), glossary changes, new/changed events, ADRs proposed, a prototype run and its verdict (if any), stories created and their review outcome (`ready` vs. still open), open hotspots/questions. Point to `docs/stories/BACKLOG.md`, where `ready` stories are queued for the engineering workflow. For a bug, say which documented rule was restored, or that the rule changed and became a feature.
|
|
@@ -94,7 +94,7 @@ function storyRef(story: d.Story): StoryRef {
|
|
|
94
94
|
path: d.rel(story.path),
|
|
95
95
|
title: String(story.meta.title ?? ""),
|
|
96
96
|
status: String(story.meta.status ?? ""),
|
|
97
|
-
type: String(story.meta.type ?? "
|
|
97
|
+
type: String(story.meta.type ?? "domain"),
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -15,7 +15,8 @@ every done story, every ADR and every answered open question since then may have
|
|
|
15
15
|
or differently important. Nothing here is a formality – a grooming run that changes nothing was a wasted run or a
|
|
16
16
|
healthy backlog, and you have to be able to say which.
|
|
17
17
|
|
|
18
|
-
Do **not** fix anything yourself. Grooming produces a decision for the user
|
|
18
|
+
Do **not** fix anything yourself. Grooming produces a decision for the user. The main session carries the product and
|
|
19
|
+
engineering lenses; it does not delegate them to simulated roles.
|
|
19
20
|
|
|
20
21
|
## 1. Mechanical health check
|
|
21
22
|
|
|
@@ -39,22 +40,23 @@ rows in `OPEN_QUESTIONS.md`, and the "revisit when …" lines parked in `docs/re
|
|
|
39
40
|
this list to the subagents – they cannot see it, and without it they re-read the same stories that were already
|
|
40
41
|
reviewed once.
|
|
41
42
|
|
|
42
|
-
## 3. Challenge
|
|
43
|
+
## 3. Challenge – two lenses, one pass
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
The main session holds both lenses at once. Write down which one produced each finding; do not average a conflict
|
|
46
|
+
between them away.
|
|
45
47
|
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
-
|
|
48
|
+
- **Value** – is the value still real and still in the vision? Is the story already covered by what was built? Does
|
|
49
|
+
the MVP slice still hold? Which `must` is not a `must` any more, and which `could` turned out to be one? Which
|
|
50
|
+
need from the vision still has no story?
|
|
51
|
+
- **Build** – do `depends_on`, `size` and `risk` still fit **now that the code exists**? Which story has become
|
|
50
52
|
smaller because the foundation is there, which bigger? Which dependency is technical fiction? Which story should
|
|
51
|
-
be split,
|
|
52
|
-
- `ux-designer` – only for stories with the label `ui` (or an obvious frontend part): does the story still match
|
|
53
|
-
`docs/product/ux-guidelines.md`, which one builds a screen that a newer story has replaced, and is there an open
|
|
54
|
-
UX question that needs a prototype (the `prototype` skill) before the story can be reviewed again?
|
|
53
|
+
be split (one command!), re-typed as `chore`/`task`, or dropped?
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
For stories with `ui: true` (or an obvious frontend part), ask the `ux-designer` only when a concrete question needs
|
|
56
|
+
it – component/pattern, an open UX decision, or a prototype. It advises; it does not gate.
|
|
57
|
+
|
|
58
|
+
Do not hand the backlog to subagents: the change list from step 2 is context they cannot see, and re-reading stories
|
|
59
|
+
that were already reviewed once is the cost this workflow removes.
|
|
58
60
|
|
|
59
61
|
## 4. Consolidate
|
|
60
62
|
|
|
@@ -62,22 +64,22 @@ Write `docs/reviews/YYYY-MM-DD-backlog-grooming.md`:
|
|
|
62
64
|
|
|
63
65
|
- the health-check findings with what they turned out to mean
|
|
64
66
|
- per challenged story: keep / revise / split / merge / drop, with the reason and who said it
|
|
65
|
-
- conflicts between the
|
|
67
|
+
- conflicts between the two lenses – name them, don't average them away
|
|
66
68
|
- proposed new stories, and stories proposed for `priority: wont`
|
|
67
69
|
- what explicitly stays as it is, so the next run does not re-litigate it
|
|
68
70
|
|
|
69
71
|
## 5. The user decides
|
|
70
72
|
|
|
71
73
|
Present it in rounds, at most 3 questions at a time, each with a recommended answer. Adopt nothing without consent.
|
|
72
|
-
A disagreement between
|
|
74
|
+
A disagreement between value and build is a question for the user, not something to resolve on their behalf.
|
|
73
75
|
|
|
74
76
|
## 6. Apply
|
|
75
77
|
|
|
76
|
-
- Content changes →
|
|
78
|
+
- Content changes → edit the story in the main session, referencing the grooming file; then re-run the spec linter.
|
|
77
79
|
- **Dropped stories are never deleted**: they get `priority: wont` and keep their file, so the decision stays
|
|
78
80
|
traceable. A story that is wrong rather than unwanted goes back to `status: review` and through `/review-stories`.
|
|
79
81
|
- A `done` story is never reopened – a change to finished behaviour is a new story.
|
|
80
|
-
- New stories from the grooming get `status: draft` and go through `/review-stories` like any other.
|
|
82
|
+
- New stories from the grooming get `status: draft` and go through `/review-stories` like any other (linter → human).
|
|
81
83
|
- With a tracker, push the applied changes (`/backlog-sync push`) before the wrap-up, so Jira/GitHub and the mirror
|
|
82
84
|
agree. A story that is not linked yet stays a local draft until the push creates it.
|
|
83
85
|
|
|
@@ -1,138 +1,223 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: implement
|
|
3
|
-
description: Engineering workflow – implements one story from docs/stories/
|
|
3
|
+
description: Engineering workflow – implements one story from docs/stories/ on its own branch, verifies, reviews scaled to the diff, refactors and hands the pull request to the user; `type: chore`/`task` (or `--fast`) takes the fast lane without Gherkin matching or formal reviews; `--prototype` settles an open UI question first.
|
|
4
4
|
disable-model-invocation: true
|
|
5
|
-
argument-hint: "[ST-NNN – empty = next ready story] [--prototype[=ui|logic]]"
|
|
5
|
+
argument-hint: "[ST-NNN – empty = next ready story] [--fast] [--prototype[=ui|logic]]"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Implement a Story
|
|
9
9
|
|
|
10
|
-
Story: the arguments from the invocation (empty → `node .claude/skills/implement/scripts/next-story.ts`; a story
|
|
10
|
+
Story: the arguments from the invocation (empty → `node .claude/skills/implement/scripts/next-story.ts`; a story
|
|
11
|
+
already `in-progress` is finished first). `--fast` and `--prototype[=ui|logic]` are flags, not the story ID: strip
|
|
12
|
+
them before resolving the story.
|
|
11
13
|
|
|
12
|
-
The main session writes the code; subagents only review
|
|
14
|
+
The main session writes the code; subagents only review, and only in the full domain lane. One checkpoint belongs to
|
|
15
|
+
the user: the **merge** (step 7). Everything before it runs without asking – a `ready` story is good enough to build
|
|
16
|
+
up to the pull request, and the acceptance tester accepts the story, not the user – unless the story turns out to be
|
|
17
|
+
wrong (see *When the story is wrong*), a seam is missing from the catalog (step 2), or the user asked for a prototype
|
|
18
|
+
(step 1b – the verdict is theirs).
|
|
13
19
|
|
|
14
|
-
|
|
20
|
+
## Two lanes
|
|
15
21
|
|
|
16
|
-
|
|
22
|
+
| Lane | Stories | What changes |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| **Domain** (default) | `type: domain` (legacy `story`) | TDD per Gherkin scenario, scenario ↔ test traceability, diff-scaled review, acceptance tester's verdict |
|
|
25
|
+
| **Fast** | `type: chore`, `type: task`, or `--fast` on such a story | branch → implement → lint/typecheck/unit tests → verify → PR; no Gherkin matching, no formal review pass, the user merges |
|
|
26
|
+
|
|
27
|
+
`--fast` on a `type: domain` story is ignored: the story has a command and scenarios, so it takes the domain lane.
|
|
28
|
+
If a "chore" turns out to touch a command, a migration or authorization, stop and say so – risk decides the lane,
|
|
29
|
+
not the label.
|
|
30
|
+
|
|
31
|
+
Engineering conventions: `docs/engineering/conventions.md` – read it if it exists; it describes the module layout,
|
|
32
|
+
how commands and read models are built, and the **seam catalog**.
|
|
33
|
+
|
|
34
|
+
Project profile: `.claude/project.json` – default branch, code roots, commands, preview provider, pull-request tool.
|
|
35
|
+
Read it instead of assuming `main`, `npm` or GitHub.
|
|
17
36
|
|
|
18
37
|
## 1. Prepare
|
|
19
|
-
1. Working tree clean, on the default branch (`repo.defaultBranch`), up to date (`git pull`). Otherwise stop and tell
|
|
38
|
+
1. Working tree clean, on the default branch (`repo.defaultBranch`), up to date (`git pull`). Otherwise stop and tell
|
|
39
|
+
the user.
|
|
20
40
|
2. With a tracker (`backlog.provider` ≠ `local`), pull first (`/backlog-sync pull`) and check that the story has its
|
|
21
41
|
`external` key – an unlinked story never reaches `ready`, so stop and report instead of implementing a stale mirror.
|
|
22
|
-
3. `node .claude/skills/implement/scripts/story-context.ts ST-NNN` – the context pack: story, exact test titles,
|
|
23
|
-
|
|
42
|
+
3. `node .claude/skills/implement/scripts/story-context.ts ST-NNN` – the context pack: story, exact test titles,
|
|
43
|
+
dependencies, events/commands/rules/invariants, glossary, data model, ADRs. Read it completely; it is your
|
|
44
|
+
source, not memory.
|
|
45
|
+
4. `git switch -c st-NNN-<slug>` (slug from the file name), then
|
|
46
|
+
`node .claude/skills/implement/scripts/story-status.ts ST-NNN in-progress` and commit `ST-NNN: start`.
|
|
47
|
+
5. **Pick the lane** and say it in one line: fast lane for `chore`/`task`, domain lane otherwise. The fast lane is
|
|
48
|
+
a shortcut for non-domain work, never a way to skip a risk review.
|
|
24
49
|
|
|
25
50
|
## 1b. Prototype (only when asked)
|
|
26
51
|
|
|
27
|
-
Only with `--prototype`, or when the user explicitly asks during the story. A `ui` story whose screen shape is
|
|
28
|
-
still open was not `ready`; this is the exception that settles it before the test plan. Load the `prototype`
|
|
29
|
-
|
|
52
|
+
Only with `--prototype`, or when the user explicitly asks during the story. A `ui: true` story whose screen shape is
|
|
53
|
+
still open was not `ready`; this is the exception that settles it before the test plan. Load the `prototype` skill and
|
|
54
|
+
follow it.
|
|
30
55
|
|
|
31
|
-
1. **Standalone first.** Delegate to `ux-designer`: question, branch (`ui` or `logic`), variants/scenarios,
|
|
32
|
-
|
|
56
|
+
1. **Standalone first.** Delegate to `ux-designer`: question, branch (`ui` or `logic`), variants/scenarios, timebox,
|
|
57
|
+
target `docs/prototypes/<slug>/`. It writes the self-contained HTML file. The user decides.
|
|
33
58
|
2. **In-app only when the question needs the real page** – an existing route, real data, the real header and
|
|
34
59
|
sidebar. You build the throwaway route or the `?variant=` gate yourself, following the project's routing
|
|
35
|
-
convention; the `ux-designer` defines the question and variants and reviews the result. The prototype stays
|
|
36
|
-
|
|
37
|
-
3. **Capture.** Commit `docs/prototypes/<slug>/` (or the in-app prototype) on `prototype/<slug>`, return to the
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
4. **Then decide.** If the prototype only settles layout and the scenarios still hold, continue with step 2.
|
|
41
|
-
|
|
42
|
-
|
|
60
|
+
convention; the `ux-designer` defines the question and variants and reviews the result. The prototype stays out of
|
|
61
|
+
the production path and is captured on `prototype/<slug>`.
|
|
62
|
+
3. **Capture.** Commit `docs/prototypes/<slug>/` (or the in-app prototype) on `prototype/<slug>`, return to the story
|
|
63
|
+
branch, and write the verdict into the story's `## Context`: `Prototype: prototype/<slug> – <question> – <verdict>`.
|
|
64
|
+
A recurring rule goes to `ux-designer` for `docs/product/ux-guidelines.md`.
|
|
65
|
+
4. **Then decide.** If the prototype only settles layout and the scenarios still hold, continue with step 2. If it
|
|
66
|
+
changes behaviour or a scenario, the story goes back to `review` (see *When the story is wrong*), the main session
|
|
67
|
+
revises it, the spec linter runs and the user approves it again. The branch stays.
|
|
43
68
|
|
|
44
69
|
## 2. Test plan
|
|
45
|
-
|
|
70
|
+
|
|
71
|
+
**Domain lane.** Call the `skill` tool for `tdd` (and `codebase-design` when a new module or interface is involved).
|
|
46
72
|
Show one table and go on to step 3 without waiting:
|
|
47
73
|
|
|
48
74
|
| Scenario (exact test title) | Seam | Test type | Test file |
|
|
49
75
|
|---|---|---|---|
|
|
50
76
|
|
|
51
|
-
-
|
|
52
|
-
- Seams come from the seam catalog in the engineering conventions. A seam not in the catalog is a decision for the
|
|
77
|
+
- One row per Gherkin scenario – at most 4 by the 1-command rule.
|
|
78
|
+
- Seams come from the seam catalog in the engineering conventions. A seam not in the catalog is a decision for the
|
|
79
|
+
user – the one case where you stop here and ask.
|
|
53
80
|
- Name anything the story leaves open. Don't guess – see *When the story is wrong*.
|
|
54
81
|
|
|
55
82
|
Seams from the catalog are the "confirmed seams" the tdd skill requires; the user approved the catalog.
|
|
56
83
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
84
|
+
**Fast lane.** No scenario table. Name the files or packages you will touch and the unit/integration tests that
|
|
85
|
+
cover them; the story's checklist is the acceptance. If it already has scenarios, keep them as a sanity check but do
|
|
86
|
+
not create `ST-NNN:` test titles.
|
|
87
|
+
|
|
88
|
+
## 3. Red → green (domain) / implement (fast)
|
|
89
|
+
|
|
90
|
+
**Domain lane:**
|
|
91
|
+
- Per row: write the test (title exactly `ST-NNN: <scenario title>`), run it and see it fail for the right reason,
|
|
92
|
+
write the minimal code to pass, run it green. Commit: `ST-NNN: <scenario title>`.
|
|
93
|
+
- Domain IDs in the code: commands, events, read models and policies carry their ID from `events.yaml`
|
|
94
|
+
(`CMD-ReportProblem`, `EVT-ProblemReported`, …). New code uses the words of `CONTEXT.md`; a new term goes into
|
|
95
|
+
`CONTEXT.md` first (domain-model skill).
|
|
96
|
+
- Never weaken or delete an existing test to get green. If a test from an earlier story blocks you, its story and
|
|
97
|
+
this one contradict each other → *When the story is wrong*.
|
|
98
|
+
|
|
99
|
+
**Fast lane:**
|
|
100
|
+
- Implement the task, keep the change as small as the checklist says, and add or update unit tests where the change
|
|
101
|
+
can break behaviour. No test-title matching, no scenario traceability.
|
|
102
|
+
- Tick each checklist item in the story file as it becomes true (`- [x] …`).
|
|
103
|
+
- If the work turns into domain behaviour (a new/changed command, event or invariant), stop: the story is the wrong
|
|
104
|
+
type. Send it back to `review` as a `domain` story instead of deciding it in code.
|
|
105
|
+
|
|
106
|
+
**Both lanes** – hooks help on the way: formatting and lint after every write, the quick gate (type check + related
|
|
107
|
+
tests) before you finish a turn. In a monorepo, run the affected set for the packages you touched before the full
|
|
108
|
+
gate: `node .claude/skills/implement/scripts/affected.ts --changed <files>` (or `--base <defaultBranch>`), then
|
|
109
|
+
execute the printed command. It follows shared-library dependents; `verify.ts` still runs everything at the end.
|
|
65
110
|
|
|
66
111
|
## 4. Verify
|
|
67
|
-
`node .claude/skills/implement/scripts/verify.ts` (with `--e2e` when browser tests exist) must be green: lint incl.
|
|
112
|
+
`node .claude/skills/implement/scripts/verify.ts` (with `--e2e` when browser tests exist) must be green: lint incl.
|
|
113
|
+
module boundaries, type check, tests, events and stories valid, scenario ↔ test and domain ID traceability. Language
|
|
114
|
+
warnings: fix or justify.
|
|
68
115
|
|
|
69
|
-
The full `--e2e` run happens **once, before the push**. During red → green run only the spec you are working on;
|
|
116
|
+
The full `--e2e` run happens **once, before the push**. During red → green run only the spec you are working on;
|
|
117
|
+
after the refactor (step 6) run `verify.ts` without `--e2e` plus the specs the refactor touched – CI runs every
|
|
118
|
+
browser test on the pull request anyway (check `e2e`).
|
|
70
119
|
|
|
71
|
-
## 5. Review (
|
|
72
|
-
Push the branch (`git push -u origin st-NNN-<slug>`) so a preview deployment exists, when the project has one
|
|
73
|
-
(`review.preview` in `.claude/project.json`: `vercel`, `netlify`, … – use the provider's MCP or CLI, or the pull
|
|
74
|
-
request's preview comment). Otherwise there is no preview and the reviewers work from the code.
|
|
120
|
+
## 5. Review (domain lane only, scaled to the diff)
|
|
75
121
|
|
|
76
|
-
|
|
122
|
+
**Fast lane: skip this step.** No `code-reviewer`, no `acceptance-tester`, no review file. The gate is step 4 plus
|
|
123
|
+
the user's merge. If the diff touches authorization, input handling, a migration or security headers, say so and offer
|
|
124
|
+
the normal review anyway – the lane follows the risk, not the label.
|
|
77
125
|
|
|
78
|
-
**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
126
|
+
**Domain lane.** Push the branch (`git push -u origin st-NNN-<slug>`) so a preview deployment exists, when the project
|
|
127
|
+
has one (`review.preview` in `.claude/project.json`: `vercel`, `netlify`, … – use the provider's MCP or CLI, or the
|
|
128
|
+
pull request's preview comment). Otherwise there is no preview and the reviewers work from the code.
|
|
129
|
+
|
|
130
|
+
Pick the lane from the **diff**, not from a size label:
|
|
131
|
+
|
|
132
|
+
**Light lane** – all of these hold: the diff is texts, layout, styles, links or docs; no command or route added or
|
|
133
|
+
changed; no input handling (no request handler, form action); no migration; no new dependency.
|
|
134
|
+
- Only `acceptance-tester` – task: story ID, base ref, the preview URL (if known), and: *also check the diff briefly
|
|
135
|
+
against the engineering conventions (texts from the catalogs, the shared page frames, domain language) and list
|
|
136
|
+
deviations as minors.* Writes `docs/reviews/ST-NNN-acceptance.md`.
|
|
82
137
|
- No `code-reviewer`, no extra code or security pass.
|
|
83
138
|
|
|
84
139
|
**Normal lane** – everything else. Start in **one** message:
|
|
85
140
|
- `code-reviewer` – task: story ID, base ref, the context pack command. Writes `docs/reviews/ST-NNN-code-review.md`.
|
|
86
141
|
- `acceptance-tester` – task: story ID, base ref, the preview URL (if known). Writes `docs/reviews/ST-NNN-acceptance.md`.
|
|
87
|
-
- Only
|
|
88
|
-
-
|
|
142
|
+
- Only when the **diff** touches the command layer or other shared platform code: ask the `code-reviewer` for a
|
|
143
|
+
second, bug-focused pass over the diff.
|
|
144
|
+
- Only when the **diff** touches input handling, login/roles/session, uploads or files, or security headers/CSP: ask
|
|
145
|
+
the `code-reviewer` for a security-focused pass.
|
|
89
146
|
|
|
90
|
-
|
|
147
|
+
Both reviewers report findings and never create stories. A finding is **fixed in this story** or becomes an open
|
|
148
|
+
question to the developer (step 6) – there is no follow-up ticket.
|
|
91
149
|
|
|
92
|
-
|
|
150
|
+
Say which lane you picked and why in one line.
|
|
93
151
|
|
|
94
152
|
## 6. Refactor
|
|
95
|
-
- Fix all blockers and majors **inside this story**, and the minors you agree with; say which minors you skip and why.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
153
|
+
- Fix all blockers and majors **inside this story**, and the minors you agree with; say which minors you skip and why.
|
|
154
|
+
Where a finding offers options, apply the recommended one without asking; ask only when no option is recommended.
|
|
155
|
+
- **No follow-up stories from reviews.** A finding that is too large for this story is either:
|
|
156
|
+
1. a **question to the developer** in the review file and in the wrap-up (with evidence and options), or
|
|
157
|
+
2. a line in `## Out of Scope` / a row in `OPEN_QUESTIONS.md` when it is a real decision for the user.
|
|
158
|
+
Only the main session and the user decide whether it becomes a new story; the reviewers never do.
|
|
159
|
+
- Refactor only with green tests; the tests must not change unless they were wrong (then say so). Run `affected.ts`
|
|
160
|
+
for the touched packages, then `node .claude/skills/implement/scripts/verify.ts` again (without `--e2e`) plus the
|
|
161
|
+
browser specs the refactor touched – see step 4.
|
|
162
|
+
|
|
163
|
+
## 7. Done, acceptance and merge → user checkpoint
|
|
164
|
+
|
|
165
|
+
**Fast lane:** tick the last checklist item, then
|
|
166
|
+
`node .claude/skills/implement/scripts/story-status.ts ST-NNN done` (it refuses while a checklist item is open).
|
|
167
|
+
Commit `ST-NNN: done`, push, open the pull request.
|
|
168
|
+
|
|
169
|
+
**Domain lane:** the **acceptance tester's verdict is the acceptance**: the story is `done` in the pull request, so
|
|
170
|
+
the user only merges.
|
|
171
|
+
1. After the refactor, check the verdict in `docs/reviews/ST-NNN-acceptance.md`. `accepted` or `accepted with
|
|
172
|
+
remarks` → continue. `not accepted` → fix the gaps in the story and run the `acceptance-tester` again, until it
|
|
173
|
+
accepts. Only when something goes badly wrong – the verdict stays `not accepted` after a second round, a scenario
|
|
174
|
+
can't be met as written, the preview shows a defect the tester couldn't see – ask the user, the way *When the story
|
|
175
|
+
is wrong* describes.
|
|
176
|
+
2. `node .claude/skills/implement/scripts/story-status.ts ST-NNN done` – refuses unless every scenario has its test
|
|
177
|
+
(domain) or every checklist item is ticked (chore/task/tech task/spike) and all dependencies are done. Commit
|
|
178
|
+
`ST-NNN: done`, push.
|
|
111
179
|
- GitHub: the status change closes the linked issue.
|
|
112
|
-
- Jira: `story-status.ts` prints the transition it could not make (MCP is agent-only). Run
|
|
113
|
-
`jira_transition_issue` on the printed key, then push the story body once
|
|
114
|
-
|
|
115
|
-
|
|
180
|
+
- Jira: `story-status.ts` prints the transition it could not make (MCP is agent-only). Run
|
|
181
|
+
`jira_get_transitions` + `jira_transition_issue` on the printed key, then push the story body once
|
|
182
|
+
(`/backlog-sync push`).
|
|
183
|
+
|
|
184
|
+
**Both lanes – the pull request:**
|
|
185
|
+
3. Title `ST-NNN: <story title>`, body = the scenarios as a checklist (domain) or the task checklist (fast lane),
|
|
186
|
+
links to the story and the review files (if any), the acceptance verdict (domain), the preview URL, remaining
|
|
187
|
+
minors/questions, and anything the user must approve (a conventions change). (No `gh` CLI, or it isn't
|
|
188
|
+
authenticated: push and give the user the compare URL `git push` prints.)
|
|
189
|
+
4. **The user merges** – on the preview if they want to look first. Afterwards: back to the default branch and
|
|
190
|
+
`git pull`.
|
|
116
191
|
|
|
117
192
|
## 8. Wrap-up
|
|
118
|
-
Summarize in a few lines: scenarios implemented, review findings fixed/skipped,
|
|
119
|
-
|
|
120
|
-
-
|
|
193
|
+
Summarize in a few lines: lane taken, scenarios implemented or task completed, review findings fixed/skipped, open
|
|
194
|
+
questions handed to the developer, glossary/ADR changes. Then:
|
|
195
|
+
- Suggest `/improve-codebase-architecture` after the foundation stories, when a bounded context is complete, or about
|
|
196
|
+
every 8–10 done stories.
|
|
197
|
+
- Name the next story (`node .claude/skills/implement/scripts/next-story.ts`) and tell the user to start it in a fresh
|
|
198
|
+
session (`/new`, then `/implement`): every turn re-reads the whole session, so a second story in the same one costs
|
|
199
|
+
several times the first.
|
|
121
200
|
|
|
122
201
|
## Spikes
|
|
123
202
|
A spike answers its **Question** within its **Timebox** – no test plan, no TDD for throwaway experiments.
|
|
124
|
-
- A UX or state-model spike is a prototype: load the `prototype` skill, keep the question and timebox in the
|
|
125
|
-
|
|
126
|
-
- Before starting, tell the user the timebox and what will be kept (skeleton code that becomes the application gets
|
|
127
|
-
|
|
203
|
+
- A UX or state-model spike is a prototype: load the `prototype` skill, keep the question and timebox in the story,
|
|
204
|
+
and capture the verdict the same way (step 1b).
|
|
205
|
+
- Before starting, tell the user the timebox and what will be kept (skeleton code that becomes the application gets
|
|
206
|
+
tests and passes verify).
|
|
207
|
+
- Tick each checklist item in the story file as it is answered; write results where the item says (an ADR's
|
|
208
|
+
consequences, `OPEN_QUESTIONS.md`). A new decision → ADR with `status: proposed` (architect skill); the user accepts.
|
|
128
209
|
- Timebox exhausted → stop, document what is known, and ask the user how to continue.
|
|
129
210
|
- Review: `code-reviewer` only for code that is kept; `acceptance-tester` checks the checklist evidence.
|
|
130
211
|
|
|
131
212
|
## When the story is wrong
|
|
132
|
-
Never guess. When a scenario contradicts another story, a rule or an ADR, can't be tested as written, or leaves a
|
|
213
|
+
Never guess. When a scenario contradicts another story, a rule or an ADR, can't be tested as written, or leaves a
|
|
214
|
+
decision open:
|
|
133
215
|
1. Stop implementing that part. Mark it `[OPEN]` in the story and add a row to `docs/stories/OPEN_QUESTIONS.md`.
|
|
134
|
-
2. `node .claude/skills/implement/scripts/story-status.ts ST-NNN review` and tell the user. The fix goes through
|
|
135
|
-
|
|
216
|
+
2. `node .claude/skills/implement/scripts/story-status.ts ST-NNN review` and tell the user. The fix goes through
|
|
217
|
+
discovery in the main session: revise the story, run the spec linter, and let the user approve it again
|
|
218
|
+
(`/review-stories`). Work already done on the branch stays.
|
|
219
|
+
3. New domain term → `CONTEXT.md` (domain-model skill). Architecture deviation → a `proposed` ADR (architect skill).
|
|
220
|
+
An accepted ADR is never edited; the hooks block it.
|
|
136
221
|
4. A `done` story is never reopened – a change to finished behaviour is a new story.
|
|
137
222
|
|
|
138
223
|
## Foundation stories
|
|
@@ -36,7 +36,7 @@ for (const [id, scenarios] of superseded) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
for (const [id, s] of stories) {
|
|
39
|
-
if (only ? id !== only : !["in-progress", "done"].includes(s.meta.status) || s.meta
|
|
39
|
+
if (only ? id !== only : !["in-progress", "done"].includes(s.meta.status) || !d.isDomain(s.meta)) continue;
|
|
40
40
|
const { covered, missing: untested } = e.scenarioCoverage(s, titles);
|
|
41
41
|
const missing = untested.filter((sc) => !superseded.get(id)?.has(sc));
|
|
42
42
|
for (const sc of missing) {
|
|
@@ -40,7 +40,7 @@ const out: string[] = [`# Context pack – ${id}: ${story.meta.title}`, ""];
|
|
|
40
40
|
|
|
41
41
|
// Story
|
|
42
42
|
out.push("## Story file", "", `\`${d.rel(story.path)}\``, "", "````markdown", storyText.trimEnd(), "````", "");
|
|
43
|
-
if (story.meta
|
|
43
|
+
if (d.isDomain(story.meta)) {
|
|
44
44
|
out.push("## Test titles (exact)", "", "Every scenario gets one test with exactly this title:", "");
|
|
45
45
|
for (const sc of e.scenarioTitles(story)) out.push(`- \`${e.testTitle(id, sc)}\``);
|
|
46
46
|
out.push("");
|
|
@@ -70,7 +70,7 @@ for (const s of appSteps.filter((s) => !commands[s] && !scripts[s])) {
|
|
|
70
70
|
const node = process.execPath;
|
|
71
71
|
const disc = join(here, "..", "..");
|
|
72
72
|
run("events.yaml", node, [join(disc, "event-storming", "scripts", "validate-events.ts")]);
|
|
73
|
-
run("stories", node, [join(disc, "user-stories", "scripts", "validate-stories.ts")]);
|
|
73
|
+
run("stories + spec linter", node, [join(disc, "user-stories", "scripts", "validate-stories.ts")]);
|
|
74
74
|
// The map is generated; staleness is a warning (adoption may not have run yet), not a failed gate.
|
|
75
75
|
run("repository map", node, [join(disc, "adopt", "scripts", "repo-map.ts"), "--check"], true);
|
|
76
76
|
run("path-scoped rules", node, [join(disc, "adopt", "scripts", "rule-doc.ts"), "--check"], true);
|
|
@@ -77,7 +77,7 @@ with a clearly marked throwaway route. The same capture rules apply.
|
|
|
77
77
|
|
|
78
78
|
- **`/feature`** – the UX lens proposes a prototype when the frontier leaves a structural UI, flow or state
|
|
79
79
|
question. The user decides. `--prototype[=ui|logic]` makes it explicit. The verdict goes to the
|
|
80
|
-
`ux-designer` (guidelines) and
|
|
80
|
+
`ux-designer` (guidelines) and into the story's `## Context` in the main session, before the stories are reviewed.
|
|
81
81
|
- **`/implement`** – only when the user asks (`--prototype`) or a spike's question is a UX/state question. A
|
|
82
82
|
`ui` story whose screen shape is still open was not `ready`; the prototype settles it, then the story goes
|
|
83
83
|
back to `review` if its behaviour changed. The engineering rule holds: never decide a story in the code.
|
|
@@ -1,31 +1,51 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: review-stories
|
|
3
|
-
description:
|
|
3
|
+
description: Runs the deterministic spec linter on finished stories, fixes mechanical gaps, moves green stories to ready-for-human-review and guides the user to approval (status ready). No subagent review pass.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
argument-hint: "[ST-IDs, empty = all with status review]"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Story Review
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
There is no simulated role play. The domain, architecture and testability decisions were made in the grilling and
|
|
11
|
+
the event storming; the **spec linter** now checks mechanically that the story carries them. The user approves; the
|
|
12
|
+
agent does not approve on their behalf.
|
|
12
13
|
|
|
13
14
|
1. **Selection**: Stories from the invocation arguments, or all with `status: review` in `docs/stories/`. With a
|
|
14
15
|
tracker (`backlog.provider` ≠ `local`), pull first (`/backlog-sync pull`) so the review sees the tracker's state.
|
|
15
16
|
None found → report and stop.
|
|
16
|
-
2. **
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
5.
|
|
17
|
+
2. **Lint first** – this is the gate, not a suggestion:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
node .claude/skills/user-stories/scripts/lint-story.ts ST-NNN
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Errors are the agent's to fix in the story: a missing `aggregate`/`command`, a command that belongs to another
|
|
24
|
+
aggregate, events that are not exactly what the command produces, a missing `Given/When/Then`, more than 4
|
|
25
|
+
scenarios, duplicate titles, a broken reference. Do not weaken a check to get green – if the model is missing the
|
|
26
|
+
event or aggregate, fix `docs/domain/events.yaml` (event-storming/domain-model skill) first.
|
|
27
|
+
3. **Warnings that matter**: a `ui: true` story with no empty/rejection case, a legacy `type: story`, a scenario that
|
|
28
|
+
reads like a UX guideline restated. Fix what is clearly right; leave the rest as a note in the review summary.
|
|
29
|
+
This is not a second discovery – adopt nothing that changes a decision from the grilling without asking.
|
|
30
|
+
4. **Tracker link**: with a tracker, push unlinked stories (`/backlog-sync push ST-001 …`) **before** setting
|
|
31
|
+
`ready` – the push creates the issue and writes `external`; without it the validator refuses `ready`.
|
|
32
|
+
5. **Linter green → `ready-for-human-review`**:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
node .claude/skills/implement/scripts/story-status.ts ST-NNN ready-for-human-review
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The script validates the file and refuses on any lint error.
|
|
39
|
+
6. **The user approves** – present one short table (ID, title, type, command/aggregate, scenario count, warnings) and
|
|
40
|
+
ask for approval. On approval:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
node .claude/skills/implement/scripts/story-status.ts ST-NNN ready
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
With a tracker, push again so body, labels and status agree. If the user declines, the story goes back to
|
|
47
|
+
`review` or `draft` with their reason.
|
|
48
|
+
7. **UX on demand only**: a story with `ui: true` may get a component/Figma proposal from the `ux-designer`, but
|
|
49
|
+
only when the user asks. It is advice, never a gate – do not wait for it.
|
|
50
|
+
8. Wrap-up: run `node .claude/skills/user-stories/scripts/lint-story.ts`, show the status overview and point to
|
|
51
|
+
`docs/stories/BACKLOG.md` (regenerated automatically), where `ready` stories are queued for engineering.
|