kataster 0.3.0 → 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.
Files changed (59) hide show
  1. package/.claude/THIRD_PARTY_NOTICES.md +69 -0
  2. package/.claude/agents/acceptance-tester.md +7 -2
  3. package/.claude/agents/code-reviewer.md +7 -2
  4. package/.claude/agents/ux-designer.md +43 -38
  5. package/.claude/hooks/validate-docs.ts +2 -1
  6. package/.claude/lib/config.ts +1 -0
  7. package/.claude/lib/discovery.ts +129 -31
  8. package/.claude/lib/engineering.ts +12 -6
  9. package/.claude/package.json +1 -0
  10. package/.claude/settings.json +1 -2
  11. package/.claude/skills/adopt/SKILL.md +5 -3
  12. package/.claude/skills/backlog/SKILL.md +2 -2
  13. package/.claude/skills/bootstrap/SKILL.md +9 -7
  14. package/.claude/skills/domain-model/SKILL.md +1 -1
  15. package/.claude/skills/feature/SKILL.md +37 -11
  16. package/.claude/skills/feature/scripts/intake.ts +1 -1
  17. package/.claude/skills/groom-backlog/SKILL.md +19 -16
  18. package/.claude/skills/implement/SKILL.md +169 -63
  19. package/.claude/skills/implement/scripts/check-scenarios.ts +1 -1
  20. package/.claude/skills/implement/scripts/story-context.ts +1 -1
  21. package/.claude/skills/implement/scripts/verify.ts +1 -1
  22. package/.claude/skills/prototype/LOGIC.md +101 -0
  23. package/.claude/skills/prototype/SKILL.md +85 -0
  24. package/.claude/skills/prototype/UI.md +130 -0
  25. package/.claude/skills/review-stories/SKILL.md +39 -19
  26. package/.claude/skills/shape/SKILL.md +2 -2
  27. package/.claude/skills/user-stories/SKILL.md +109 -51
  28. package/.claude/skills/user-stories/schema/story.schema.json +6 -3
  29. package/.claude/skills/user-stories/scripts/lint-story.ts +56 -0
  30. package/.claude/skills/user-stories/templates/story-template.md +5 -2
  31. package/.claude/skills/ux-design/SKILL.md +30 -5
  32. package/.opencode/agents/acceptance-tester.md +8 -3
  33. package/.opencode/agents/code-reviewer.md +8 -3
  34. package/.opencode/agents/ux-designer.md +44 -39
  35. package/.opencode/commands/bootstrap.md +1 -1
  36. package/.opencode/commands/feature.md +1 -1
  37. package/.opencode/commands/groom-backlog.md +1 -1
  38. package/.opencode/commands/implement.md +1 -1
  39. package/.opencode/commands/review-stories.md +1 -1
  40. package/AGENTS.md +17 -0
  41. package/CHANGELOG.md +38 -0
  42. package/README.md +64 -7
  43. package/guide/brownfield.md +2 -2
  44. package/guide/concepts.md +26 -5
  45. package/guide/greenfield.md +4 -3
  46. package/guide/release.md +1 -1
  47. package/package.json +1 -1
  48. package/src/cli.mjs +42 -4
  49. package/src/install.mjs +62 -6
  50. package/templates/docs/product/ux-guidelines.md +2 -0
  51. package/templates/docs/prototypes/README.md +9 -0
  52. package/templates/docs/stories/README.md +10 -3
  53. package/templates/docs/workflow.md +38 -13
  54. package/.claude/agents/lead-dev.md +0 -50
  55. package/.claude/agents/product-owner.md +0 -39
  56. package/.claude/agents/requirements-engineer.md +0 -44
  57. package/.opencode/agents/lead-dev.md +0 -67
  58. package/.opencode/agents/product-owner.md +0 -59
  59. package/.opencode/agents/requirements-engineer.md +0 -58
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: user-stories
3
- description: Rules, format and splitting patterns for user stories, spikes and tech tasks in docs/stories/ – frontmatter, INVEST, Gherkin, status workflow, and the local mirror when a Jira or GitHub tracker is configured.
3
+ description: Rules, format and splitting patterns for stories, chores, tasks, spikes and tech tasks in docs/stories/ – frontmatter, the 1-command rule, three spec lenses, Gherkin, status workflow, the deterministic spec linter, and the local mirror when a Jira or GitHub tracker is configured.
4
4
  ---
5
5
 
6
6
  # User Stories
@@ -11,6 +11,39 @@ of truth and `docs/stories/` is its local mirror – the `backlog` skill owns th
11
11
  the artifact this skill describes, and `docs/stories/BACKLOG.md` is generated from it by a hook – never edit it
12
12
  manually.
13
13
 
14
+ ## The spec engineer (main session)
15
+
16
+ There is no requirements subagent. The main session writes the stories, because it already holds the grilling, the
17
+ event storming and the user's decisions – handing them to another agent only adds friction and summary loss
18
+ (user, 2026-11-03).
19
+
20
+ While writing, hold **three lenses at once**:
21
+
22
+ 1. **Domain** – is the behaviour unambiguous? One command, one actor, one observable outcome per scenario. No soft
23
+ wording ("fast", "user-friendly"), no hidden second behaviour.
24
+ 2. **Architecture** – does it fit the bounded context, the aggregate and the events in `docs/domain/events.yaml`?
25
+ Does the command belong to the aggregate named in the story? Does it need a new event or invariant first?
26
+ 3. **Testability** – can every scenario become exactly one red → green test named `ST-NNN: <scenario title>`? Is the
27
+ *When* the real entry point and is every *Then* an assertion with a literal from the scenario?
28
+
29
+ If a lens fails, fix the model (`CONTEXT.md`, `events.yaml`, an ADR) before writing the story. A story that hides an
30
+ open decision is a story that will be decided in code.
31
+
32
+ ## The 1-command rule
33
+
34
+ **One story = one command + the events it produces on one aggregate.** Do not merge several domain commands into one
35
+ story to "save a ticket"; that is what made stories unpredictable. A second command is a second story (or a
36
+ dependency), not a second scenario set.
37
+
38
+ Mechanically enforced by the linter for `type: domain`:
39
+
40
+ - `aggregate: AGG-…` and `command: CMD-…` are required and must exist in `events.yaml`;
41
+ - the command must belong to the stated aggregate;
42
+ - `events` must be exactly what that command produces – no more, no fewer.
43
+
44
+ **At most 4 Gherkin scenarios** per domain story: one happy path and up to three edge/error cases. More means the
45
+ story merges commands, restates a UX guideline pattern, or should be split.
46
+
14
47
  ## Derivation from the Event Storming
15
48
  | Source in `events.yaml` | typically becomes |
16
49
  |---|---|
@@ -18,72 +51,81 @@ manually.
18
51
  | Policy (automatic) | Story from the beneficiary's perspective ("… I am notified when …") |
19
52
  | Read model | Story about finding/seeing information |
20
53
  | Hotspot | Spike (question + timebox) or `[OPEN]` in the story |
21
- | External system | Story or tech task for the integration |
54
+ | External system | Story or task for the integration |
22
55
 
23
- Every story links the affected events (`events: [EVT-…]`). Commands without a story = gap → report it.
56
+ Every domain story links the affected events (`events: [EVT-…]`). Commands without a story = gap → report it.
24
57
 
25
58
  ## File & Frontmatter
26
59
  File: `docs/stories/ST-NNN-short-title.md` (three-digit number, consecutive, never reused).
27
60
  Template: `templates/story-template.md`. Schema: `schema/story.schema.json`.
28
61
 
29
- | Field | Required | Who sets it |
62
+ | Field | Required | Meaning |
30
63
  |---|---|---|
31
- | `id`, `title`, `type`, `context`, `events` | yes | requirements-engineer |
32
- | `priority` (`must/should/could/wont`) | yes | product-owner (initially `should`) |
33
- | `size` (`XS–XL`), `risk`, `depends_on` | before `ready` | lead-dev |
34
- | `labels` | no | anyone (lowercase, e.g. `mvp`, `feature:<slug>`) |
35
- | `status` | yes | see workflow |
64
+ | `id`, `title`, `type`, `status` | yes | identity and workflow state |
65
+ | `priority` (`must/should/could/wont`) | yes | backlog order; starts as `should` |
66
+ | `aggregate` (`AGG-…`), `command` (`CMD-…`) | for `type: domain` | the 1-command rule, cross-checked against `events.yaml` |
67
+ | `events` (`EVT-…`) | for `type: domain` | exactly the command's `produces` |
68
+ | `context` (`BC-…`) | for `type: domain` | the bounded context |
69
+ | `ui` (`true`) | no | story has a frontend part; triggers the on-demand UX utility |
70
+ | `size`, `risk`, `depends_on` | no | optional planning hints; no sizing gate |
71
+ | `labels` | no | lowercase, e.g. `mvp`, `feature:<slug>` |
36
72
  | `external` | with a tracker | backlog sync – never by hand |
37
73
 
38
74
  With `backlog.provider` = `github` or `jira`, `external` holds the tracker key (`external.key`) and URL. The sync writes
39
75
  it; a story must have it before it reaches `ready`. `ST-NNN` stays the stable id – never renumber a story to follow an
40
76
  issue key, and never use a label that starts with the management prefix (`kataster-` by default).
41
77
 
42
- **No implementation foundation inside a domain story** (user, 2026-10-01). A story describes behaviour a person
43
- can observe; technical groundwork that several stories need is its own **tech task**, with its own `depends_on`.
78
+ **No implementation foundation inside a domain story** (user, 2026-10-01). A story describes behaviour a person can
79
+ observe; technical groundwork that several stories need is its own `task`/`tech-task`, with its own `depends_on`.
44
80
  A checklist of files to create, layers to convert or configs to set is an implementation plan, not acceptance
45
81
  criteria – it is neither the user's language nor a testable outcome, and it hides the real size of the story.
46
- *Why this is a rule:* a story once carried a seven-item checklist that converted **every command built so far** to an
47
- event catalogue. That made an M story an L, put a retrofit nine dependencies deep, and the cost grew with every
48
- command built before it. The grooming pulled it out as its own tech task and the story went back to M.
49
- The exception is a tech task or a spike – there a checklist *is* the acceptance criteria.
50
82
 
51
- **The `ui` label** marks every story with a frontend part – a screen, a form, a flow a person walks through.
52
- `/review-stories` and `/groom-backlog` route those to the `ux-designer`, so a missing label means a story nobody
53
- reviews from that side. What such a story has to say about the interface (and what it must not) is in the
54
- `ux-design` skill; the decisions it is measured against are `docs/product/ux-guidelines.md`.
83
+ ## Types: domain, fast lane, tech task, spike
55
84
 
56
- ## Backlog Order
85
+ | `type` | Use for | Path in `/implement` |
86
+ |---|---|---|
87
+ | `domain` (default) | behaviour in the domain model: one command, one aggregate, Gherkin scenarios | full: TDD per scenario, traceability, diff-scaled review |
88
+ | `chore` | UI tweak, refactoring, dependency bump, small cleanup | fast lane: no Gherkin matching, no formal reviews |
89
+ | `task` | setup or a small non-domain change that is not a chore | fast lane (same as `chore`) |
90
+ | `tech-task` | deliberate technical groundwork several stories need, with a checklist | full: checklist evidence + acceptance tester |
91
+ | `spike` | a timeboxed question, checklist of what to answer | no TDD; evidence in the checklist |
57
92
 
58
- `docs/stories/BACKLOG.md` is generated (`scripts/render-backlog.ts`) and the order is **derived on every render,
59
- never stored**. `backlogOrder` in `.claude/lib/discovery.ts` sorts:
93
+ `chore` and `task` have a `## Task` section and acceptance as a short checklist (`- [ ] …`) or, if they really have
94
+ observable behaviour, at most 4 scenarios. They do not need `aggregate`, `command`, `context` or `events`.
60
95
 
61
- 1. by `priority` – `must`, `should`, `could`, `wont`;
62
- 2. within the same priority **by story ID, ascending**;
63
- 3. then dependencies first – a story that a listed story depends on is pulled in front of it.
96
+ `story` is the legacy name of `domain` and still validates. The linter reports it as a warning and relaxes the strict rules
97
+ (missing `aggregate`/`command`, more than 4 scenarios) so an upgrade does not turn an existing backlog red – new work
98
+ uses `domain`.
64
99
 
65
- What follows from that, and has caught us out before (story review 2026-09-29):
100
+ ## The `ui` flag
66
101
 
67
- - **Numbers decide within a priority.** A story with a higher ID never overtakes a lower one, so a new tech task
68
- always lands *behind* the older stories it is meant to precede. Raising it to `must` does not help when those
69
- are `must` too.
70
- - **`depends_on` is the only thing that really moves a story forward** – and it is for real dependencies, not
71
- for planning wishes. Do not invent one to force an order.
72
- - **So say it out loud when a story is built out of turn**: `/implement ST-NNN` with the ID, never the bare
73
- `/implement` (which follows this very order via `next-story.ts`), and record the intended order in the
74
- story's Notes so the next person sees why.
102
+ `ui: true` marks a story with a frontend part – a screen, a form, a flow a person walks through. It is the **only**
103
+ trigger for the on-demand `ux-designer`: component/layout proposals, Figma/design-token logic or a prototype. The UX
104
+ utility never gates the story; a missing decision comes back as a proposal, not as a blocker.
75
105
 
76
- There is no script that re-sorts the backlog, because there is nothing to sort – only story files and this rule.
106
+ The old `labels: [ui]` is still recognised as equivalent. New stories set the flag.
77
107
 
78
108
  ## Status Workflow
79
- `draft` (in progress) → `review` (finished, waiting for the story review) → `ready` (after user approval; `size` set, no `[OPEN]`) → `in-progress` → `done`.
80
-
81
- Discovery ends at `ready`. The engineering workflow (`/implement`) sets `in-progress` and `done` with `node .claude/skills/implement/scripts/story-status.ts`; the validation hook enforces the same rules when the file is edited directly:
109
+ `draft` (in progress) → `review` (written, waiting for the linter) → `ready-for-human-review` (spec linter green) →
110
+ `ready` (the user approved it) → `in-progress` → `done`.
111
+
112
+ - **The linter is the gate**: `node .claude/skills/user-stories/scripts/lint-story.ts <file>`. Only when it is green
113
+ does the story move to `ready-for-human-review`; there is no LLM review pass before implementation.
114
+ - **`ready` is the user's decision**, not the agent's.
115
+ - Discovery ends at `ready`. The engineering workflow (`/implement`) sets `in-progress` and `done` with
116
+ `node .claude/skills/implement/scripts/story-status.ts`; the validation hook enforces the same rules when the file
117
+ is edited directly.
82
118
  - `in-progress` and `done` need all `depends_on` stories `done`.
83
- - `done` needs a test titled `ST-NNN: <scenario title>` for every scenario (story), or every checklist item ticked `- [x]` (spike, tech task).
84
- - A story that turns out wrong during implementation goes from `in-progress` (or `ready`) back to `review`, with `[OPEN]` + an entry in `OPEN_QUESTIONS.md`; it is revised and approved again.
119
+ - `done` for a domain story needs a test titled `ST-NNN: <scenario title>` for every scenario; for a chore, task,
120
+ tech task or spike every checklist item is ticked `- [x]`.
121
+ - A story that turns out wrong during implementation goes from `in-progress` (or `ready`) back to `review`, with
122
+ `[OPEN]` + an entry in `OPEN_QUESTIONS.md`; the main session revises it and the linter/approval runs again.
85
123
  - `done` is final. A change to finished behaviour is a new story.
86
- - `superseded` – a story that is not built as written, before it was started: its work was done elsewhere (a direct change, another story), or a new planning replaces it. Set from `draft`, `review` or `ready`, never from `in-progress`. Its first paragraph says where the work went or what replaces it; the file stays as the record other documents link to. Final like `done`, listed in its own section of the backlog and counted in no progress (user, 2026-10-25). Set it with `node .claude/skills/implement/scripts/story-status.ts ST-NNN superseded`.
124
+ - `superseded` – a story that is not built as written, before it was started: its work was done elsewhere (a direct
125
+ change, another story), or a new planning replaces it. Set from `draft`, `review`, `ready-for-human-review` or
126
+ `ready`, never from `in-progress`. Its first paragraph says where the work went or what replaces it; the file stays
127
+ as the record other documents link to. Final like `done`, listed in its own section of the backlog and counted in
128
+ no progress (user, 2026-10-25).
87
129
 
88
130
  ## Body Structure
89
131
  ```
@@ -110,26 +152,42 @@ Scenario: <Error or edge case>
110
152
  ## Out of Scope
111
153
  ## Open Questions
112
154
  ```
113
- Scenario titles are unique within a story and become test titles (`ST-NNN: <scenario title>`). Renaming a scenario of an `in-progress` or `done` story breaks that link – the test must be renamed too (`verify.ts` reports it).
155
+ Scenario titles are unique within a story and become test titles (`ST-NNN: <scenario title>`). Renaming a scenario
156
+ of an `in-progress` or `done` story breaks that link – the test must be renamed too (`verify.ts` reports it).
114
157
 
115
- Spikes: `## Question`, `## Timebox`, `## Acceptance Criteria` (checklist `- [ ] …`).
116
- Tech tasks: `## Task`, `## Acceptance Criteria` (checklist).
158
+ Chore/task/tech-task: `## Task`, `## Acceptance Criteria` (checklist `- [ ] …`).
159
+ Spike: `## Question`, `## Timebox`, `## Acceptance Criteria` (checklist).
117
160
 
118
161
  ## Quality Rules
119
162
  - **INVEST**: independent, negotiable, valuable, estimable, small, testable.
120
- - Gherkin in English (`Given / When / Then / And / But`). At least a happy path + one error/edge case.
163
+ - Gherkin in English (`Given / When / Then`); every scenario has all three steps. At least a happy path + one
164
+ error/edge case, at most 4 scenarios.
121
165
  - Scenarios describe **behavior**, not UI details ("clicks the blue button" ✗) and not technology.
122
- - **At most 10 scenarios** per story – each one is a red → green cycle in `/implement`. Spend them on domain behavior and real rejections. A pattern `docs/product/ux-guidelines.md` already defines (grouping, collapsing, kept choices after a rejection) is a G-number in the Context, tested once where the pattern is built, not restated as scenarios. More left → split (patterns below). The validator warns in `draft` and refuses `review`.
166
+ - Spend the scenarios on domain behavior and real rejections. A pattern `docs/product/ux-guidelines.md` already
167
+ defines (grouping, collapsing, kept choices after a rejection) is a G-number in the Context, tested once where the
168
+ pattern is built, not restated as scenarios.
123
169
  - Measurable outcomes: "Then the item has the status 'out of order'" instead of "Then it works".
124
170
  - Non-functional requirements as concrete scenarios or checklist items with a number.
125
171
  - Terms exactly as in the glossary `CONTEXT.md`; never use an `_Avoid_` synonym.
126
172
 
127
- ## Splitting Patterns (if larger than M)
128
- By workflow step · by business rule · happy path first, special cases later · by data variant · by role · "manual first, automated later".
173
+ ## Splitting Patterns (one command per story)
174
+ By command · by business rule · happy path first, special cases later · by data variant · by role ·
175
+ "manual first, automated later". If two commands share a screen, that is two stories and one `depends_on`, not one
176
+ story with two `When`s.
177
+
178
+ ## Validation (deterministic, no LLM)
179
+ The spec linter is the gate before `ready-for-human-review`:
180
+
181
+ ```bash
182
+ node .claude/skills/user-stories/scripts/lint-story.ts # all stories
183
+ node .claude/skills/user-stories/scripts/lint-story.ts ST-012 # one story
184
+ kataster lint-story docs/stories/ST-012-*.md # from the CLI
185
+ ```
186
+
187
+ It checks frontmatter syntax and required fields, the aggregate/command/event cross-check against
188
+ `docs/domain/events.yaml`, Gherkin `Given/When/Then`, at most 4 scenarios and unique scenario titles. A PostToolUse
189
+ hook runs the same rules after every write and regenerates `BACKLOG.md`; `verify.ts` runs them for the whole backlog.
129
190
 
130
- ## Validation
131
- A hook checks every written story automatically and regenerates `BACKLOG.md`. Full check of all stories:
132
- `node .claude/skills/user-stories/scripts/validate-stories.ts`
133
191
  After deleting or renaming story files, regenerate the backlog:
134
192
  `node .claude/skills/user-stories/scripts/render-backlog.ts`
135
193
 
@@ -3,12 +3,15 @@
3
3
  "title": "Story frontmatter (docs/stories/ST-NNN-*.md)",
4
4
  "type": "object",
5
5
  "additionalProperties": false,
6
- "required": ["id", "title", "type", "context", "priority", "status"],
6
+ "required": ["id", "title", "type", "priority", "status"],
7
7
  "properties": {
8
8
  "id": { "type": "string", "pattern": "^ST-[0-9]{3,}$" },
9
9
  "title": { "type": "string", "minLength": 5, "maxLength": 120 },
10
- "type": { "enum": ["story", "spike", "tech-task"] },
10
+ "type": { "enum": ["domain", "chore", "task", "tech-task", "spike", "story"] },
11
11
  "context": { "type": "string", "pattern": "^BC-[A-Za-z0-9]+$" },
12
+ "aggregate": { "type": "string", "pattern": "^AGG-[A-Za-z0-9]+$" },
13
+ "command": { "type": "string", "pattern": "^CMD-[A-Za-z0-9]+$" },
14
+ "ui": { "type": "boolean" },
12
15
  "priority": { "enum": ["must", "should", "could", "wont"] },
13
16
  "size": { "enum": ["XS", "S", "M", "L", "XL", null] },
14
17
  "risk": { "enum": ["low", "medium", "high", null] },
@@ -34,6 +37,6 @@
34
37
  "url": { "type": "string" }
35
38
  }
36
39
  },
37
- "status": { "enum": ["draft", "review", "ready", "in-progress", "done", "superseded"] }
40
+ "status": { "enum": ["draft", "review", "ready-for-human-review", "ready", "in-progress", "done", "superseded"] }
38
41
  }
39
42
  }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The story spec linter – deterministic, no LLM, no tokens.
3
+ *
4
+ * It is the gate before `ready-for-human-review`: a story only leaves `review` when this exits 0.
5
+ * The rules live in `lib/discovery.ts`, so the PostToolUse hook, `validate-stories.ts`, `story-status.ts`
6
+ * and `verify.ts` all enforce the same checks. This script is the human/CI entry point.
7
+ *
8
+ * node .claude/skills/user-stories/scripts/lint-story.ts # every story
9
+ * node .claude/skills/user-stories/scripts/lint-story.ts ST-012 # one story by id
10
+ * node .claude/skills/user-stories/scripts/lint-story.ts docs/stories/ST-012-*.md
11
+ * node .claude/skills/user-stories/scripts/lint-story.ts --json # machine-readable
12
+ *
13
+ * Checks: frontmatter syntax and required fields (`id`, `title`, `type`, `status`; `aggregate` and `command`
14
+ * for `type: domain`), referential integrity against `docs/domain/events.yaml` (aggregate, command, events =
15
+ * what the command produces), Gherkin Given/When/Then, at most 4 scenarios, unique scenario titles.
16
+ */
17
+ import { existsSync } from "node:fs";
18
+ import { basename, resolve } from "node:path";
19
+ import * as d from "../../../lib/discovery.ts";
20
+
21
+ const args = process.argv.slice(2);
22
+ const json = args.includes("--json");
23
+ const target = args.find((a) => !a.startsWith("-"));
24
+
25
+ let only: string | null = null;
26
+ if (target) {
27
+ if (/^ST-\d{3,}$/i.test(target)) {
28
+ const path = d.storyFiles().find((f) => basename(f).toUpperCase().startsWith(target.toUpperCase()));
29
+ if (!path) {
30
+ console.error(`No story file found for '${target}' in docs/stories/.`);
31
+ process.exit(1);
32
+ }
33
+ only = path;
34
+ } else {
35
+ only = resolve(target);
36
+ if (!existsSync(only)) {
37
+ console.error(`Story file not found: ${target}`);
38
+ process.exit(1);
39
+ }
40
+ }
41
+ }
42
+
43
+ const report = new d.Report();
44
+ d.validateStories(report, only);
45
+
46
+ if (json) {
47
+ console.log(JSON.stringify({ ok: report.ok, errors: report.errors, warnings: report.warnings }, null, 2));
48
+ } else {
49
+ for (const line of report.lines()) console.log(line);
50
+ if (report.ok) {
51
+ console.log(`Spec linter OK${only ? ` – ${d.rel(only)}` : ""}${report.warnings.length ? ` (${report.warnings.length} warning(s))` : ""}.`);
52
+ } else {
53
+ console.log(`\nSpec linter FAILED: ${report.errors.length} error(s). Fix the story; it does not reach 'ready-for-human-review' before this is green.`);
54
+ }
55
+ }
56
+ process.exit(report.ok ? 0 : 1);
@@ -1,8 +1,11 @@
1
1
  ---
2
2
  id: ST-001
3
3
  title: Short, domain-level title
4
- type: story
4
+ type: domain
5
5
  context: BC-Example
6
+ aggregate: AGG-Example
7
+ command: CMD-Example
8
+ ui: false
6
9
  priority: should
7
10
  size: null
8
11
  risk: null
@@ -17,7 +20,7 @@ status: draft
17
20
  As a <role>, I want <goal>, so that <benefit>.
18
21
 
19
22
  ## Context
20
- <Trigger, preconditions, business rules>
23
+ <Trigger, preconditions, business rules – from the command's rules and its aggregate's invariants>
21
24
 
22
25
  ## Acceptance Criteria
23
26
 
@@ -38,9 +38,10 @@ Everything else a person triggers has a screen, and if nobody designs it, it get
38
38
  act, and what they see afterwards? If any of the three is unclear, the feature has an open UX question – raise it
39
39
  in the grilling round, don't settle it while writing code.
40
40
 
41
- Stories with a frontend part carry the label **`ui`**. `/review-stories` (the lead-dev's UX lens) and
42
- `/groom-backlog` (the `ux-designer`) pick them by that label, so a missing label means a story nobody looks at from
43
- this side.
41
+ Stories with a frontend part carry **`ui: true`** (the legacy label `ui` is still recognised). It is the trigger for
42
+ the on-demand `ux-designer` – component/layout proposals, Figma/design-token logic, a prototype – and for the UI
43
+ warnings in the spec linter. It is not a gate: a missing flag means a story nobody looks at from this side, not a
44
+ story that cannot ship.
44
45
 
45
46
  ## The UX frontier – what to grill
46
47
 
@@ -70,10 +71,34 @@ cannot be asked before the domain decision it serves.
70
71
  A question whose answer is already in `docs/product/ux-guidelines.md` is not asked again – quote the guideline
71
72
  instead. That is what makes the yardstick pay off.
72
73
 
74
+ ## When paper is not enough – the prototype
75
+
76
+ Most UX questions are settled in words: entry, job, states, wording. A few are not – which of three
77
+ structurally different layouts works, or whether a state model still feels right once it is pushed through the
78
+ awkward cases. For those, propose a **prototype**: the `prototype` skill, owned by the `ux-designer`.
79
+
80
+ Propose it in the grilling round, with a recommended answer, when the question is:
81
+
82
+ - a structural layout choice (not colour, spacing or copy),
83
+ - a state model or a flow that is hard to reason about on paper,
84
+ - a screen that does not exist yet and whose shape decides how the stories are cut.
85
+
86
+ Do not propose one for polish, or for a question a guideline or the vision already answers. State the one
87
+ question, the branch (`ui` or `logic`), the variants or scenarios, and the timebox. The user decides.
88
+
89
+ The verdict goes into `docs/product/ux-guidelines.md` as a G-number when it is a recurring rule, and into the
90
+ story's `## Context` (`Prototype: prototype/<slug> – <question> – <verdict>`). The prototype itself is
91
+ throwaway: it lives under `docs/prototypes/<slug>/`, is captured on a throwaway branch, and is never merged.
92
+ Details: `.claude/skills/prototype/SKILL.md`.
93
+
94
+ At story review, a `ui: true` story whose screen shape is still open is not `ready`: send it back to `/feature` for a
95
+ prototype (or a spike), rather than approving it and deciding it in code. The `ux-designer` advises; the user
96
+ approves.
97
+
73
98
  ## What goes into the story, and what does not
74
99
 
75
- Stories stay at the level of observable behaviour. The `lead-dev` rule holds for UX too: no implementation detail
76
- in a story, no markup, no component names, no pixel values.
100
+ Stories stay at the level of observable behaviour. No implementation detail in a story: no markup, no pixel values.
101
+ Component proposals belong to the `ux-designer` reply and the engineering conventions, not to the story.
77
102
 
78
103
  - **Into the Gherkin**: what a person sees and can do, in terms a test can check. "Then the open cases of the
79
104
  item are listed, newest first" – yes. "Then a card component with a muted description is rendered" – no.
@@ -25,7 +25,7 @@ permissions:
25
25
 
26
26
  Before you start, load the skill `user-stories` with the `skill` tool.
27
27
 
28
- You are the acceptance tester of this project. You check whether **one story** is really done from the user's point of view. You report gaps; you never write or change tests, code or stories – in this project tests are written test-first by whoever implements the story.
28
+ You are the acceptance tester of this project. You check whether **one story** is really done from the user's point of view. You report gaps; you never write or change tests, code or stories – in this project tests are written test-first by whoever implements the story. You never create follow-up stories: a gap is either fixed in this story or handed back as an open question.
29
29
  You have NO context from the main conversation – the task gives you the story ID, the base ref and, if one exists, the preview deployment URL. Write in the artifact language (`languages.artifacts` in `.claude/project.json`, default English).
30
30
 
31
31
  ## Steps
@@ -35,7 +35,7 @@ You have NO context from the main conversation – the task gives you the story
35
35
  - the *Given* is really set up (test data builders, fixed clock for time-based rules),
36
36
  - the *When* goes through the real entry point (the command, the page), not a helper behind it,
37
37
  - every *Then* line is asserted, with expected values taken from the scenario (literals), not recomputed.
38
- 4. **Run the tests** of the story (e.g. `npm test -- -t "ST-NNN"`; browser tests with the project's e2e script, against the preview URL if given). Use the shell only for read-only commands and test runs.
38
+ 4. **Run the tests** of the story (e.g. `npm test -- -t "ST-NNN"`; browser tests with the project's e2e script, against the preview URL if given). Use Bash only for read-only commands and test runs.
39
39
  5. **Definition of done** (`docs/engineering/conventions.md` and `docs/product/ux-guidelines.md`): usable at the
40
40
  project's design size, lists fast with realistic data, every command writes its journal entry, texts from the
41
41
  message catalogs, no personal data in logs, critical security advisories of the stack applied within 48 hours.
@@ -57,8 +57,13 @@ Date: YYYY-MM-DD · Tests run: <command> → <passed/failed counts> · Preview:
57
57
  | Item | Applies | Evidence | OK? |
58
58
 
59
59
  ## Edge cases not covered by the story
60
- | Case | Expected by a rule? (cite) | Recommendation: fix now / new story / question |
60
+ | Case | Expected by a rule? (cite) | Recommendation: fix now / question |
61
61
  ```
62
62
 
63
63
  End with a verdict: `accepted`, `accepted with remarks` or `not accepted` (a scenario without a real test, a failing test, or a violated rule). **Your verdict is the acceptance** (user, 2026-10-27): on `accepted` and `accepted with remarks` the story goes to `done` and the user only merges, so don't accept what you would want the user to look at first.
64
+
65
+ ## Boundaries
66
+ - You never create, split or revise stories, and never delegate to another agent. An uncovered edge case is a **question** for the developer or a line in the review file – not a new ticket.
67
+ - A story the linter accepted is still built as written: if a scenario itself is wrong, say so; the developer sends the story back to `review` instead of deciding it in code.
68
+
64
69
  Reply to the main session with the verdict, the gaps and the file path.
@@ -28,11 +28,11 @@ permissions:
28
28
 
29
29
  Before you start, load the skills `codebase-design` and `tdd` with the `skill` tool.
30
30
 
31
- You are the code reviewer of this project. You review the changes of **one story** against the project's documented decisions and write your findings down. You never change code, tests or stories.
31
+ You are the code reviewer of this project. You review the changes of **one story** against the project's documented decisions and write your findings down. You never change code, tests or stories, and you never create follow-up stories: a finding is either fixed inside this story or handed back as an open question to the developer.
32
32
  You have NO context from the main conversation – the task gives you the story ID, the base ref (usually `main`) and the paths you need. Write in the artifact language (`languages.artifacts` in `.claude/project.json`, default English).
33
33
 
34
34
  ## Inputs
35
- - The diff: `git diff <base>...HEAD` and `git log <base>..HEAD --oneline`. Use the shell only for read-only commands (git, the scripts below, running tests) – never to write files.
35
+ - The diff: `git diff <base>...HEAD` and `git log <base>..HEAD --oneline`. Use Bash only for read-only commands (git, the scripts below, running tests) – never to write files.
36
36
  - The context pack: `node .claude/skills/implement/scripts/story-context.ts ST-NNN` (story, events, commands with rules, aggregates with invariants, glossary, data model, ADRs).
37
37
  - ADRs in `docs/adr/`, glossary in `CONTEXT.md`, the engineering conventions in `docs/engineering/conventions.md` (once it exists – it overrides general preferences).
38
38
 
@@ -63,7 +63,12 @@ Base: <ref> · Commits: <n> · Date: YYYY-MM-DD
63
63
  |---|---|---|---|---|---|---|
64
64
  ```
65
65
 
66
- Severity: **blocker** (violates an ADR, a domain rule, security or a scenario – must be fixed before merge), **major** (should be fixed in this story), **minor** (judgement call, the main session decides), **follow-up** (worth a tech-task story, too big for this one).
66
+ Severity: **blocker** (violates an ADR, a domain rule, security or a scenario – must be fixed before merge), **major** (should be fixed in this story), **minor** (judgement call, the main session decides), **question** (needs a decision the developer must make – no story, no ticket, just the question and the evidence).
67
67
  End with a two-line verdict: `ready to merge` / `fix blockers first`, and the single most important finding.
68
68
 
69
+ ## Boundaries
70
+ - You never create, split, re-scope or revise stories, and never delegate to another agent. A finding that is too big for this story is a **question** in the review file with the evidence and the options – the developer decides whether to widen the story, open a question in `OPEN_QUESTIONS.md`, or fix it now.
71
+ - You review the diff, not the whole codebase. Read the surrounding code only where the diff needs it to be judged.
72
+ - Do not restate what lint, types or tests already enforce. Report what a machine cannot see.
73
+
69
74
  Reply to the main session with the verdict, the counts per severity and the file path.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: UX/UI designer. Reviews stories with a frontend part and existing screens against docs/product/ux-guidelines.md, and maintains those guidelines. Use in backlog grooming for stories labelled `ui`, and when a feature's grilling changed a UX guideline.
2
+ description: On-demand UX utility – component and layout proposals, Figma/design-token logic, UX guidelines and throwaway prototypes. Invoked only when a story carries `ui: true` or while the prototyping phase runs; it never gates a story and never writes stories, tests or production code.
3
3
  mode: subagent
4
4
  color: pink
5
5
  permissions:
@@ -10,7 +10,7 @@ permissions:
10
10
  resource: docs/product/ux-guidelines.md
11
11
  effect: allow
12
12
  - action: edit
13
- resource: docs/reviews/*
13
+ resource: docs/prototypes/**
14
14
  effect: allow
15
15
  - action: shell
16
16
  resource: "*"
@@ -28,56 +28,61 @@ permissions:
28
28
  resource: ux-design
29
29
  effect: allow
30
30
  - action: skill
31
- resource: user-stories
31
+ resource: prototype
32
32
  effect: allow
33
33
  ---
34
34
 
35
- Before you start, load the skills `ux-design` and `user-stories` with the `skill` tool.
35
+ Before you start, load the skills `ux-design` and `prototype` with the `skill` tool.
36
36
 
37
- You are the UX/UI designer of this project, whose interface its users meet in the situations
38
- `docs/product/vision.md` describes. You have NO context from the main conversation – everything relevant is in `docs/` and in the code.
39
- Write in the artifact language (`languages.artifacts` in `.claude/project.json`, default English); the UI texts you propose are in the project UI language (`languages.ui` in `.claude/project.json`).
37
+ You are the UX utility of this project. You are **not a gatekeeper**: a story is never blocked on your review, and
38
+ `/implement` never waits for you. The main session calls you when a story has `ui: true`, when the prototyping phase
39
+ runs, or when the user asks a concrete interface question. You have NO context from the main conversation – everything
40
+ relevant is in `docs/` and in the code. Write in the artifact language (`languages.artifacts` in
41
+ `.claude/project.json`, default English); the UI texts you propose are in the project UI language (`languages.ui`).
40
42
 
41
43
  ## Yardstick
42
- - `docs/product/ux-guidelines.md` – the decisions already made. **Your file.** If it does not exist yet, say so
43
- and propose its first content instead of judging against rules nobody agreed to.
44
+ - `docs/product/ux-guidelines.md` – the decisions already made. **Your file.** If it does not exist yet, say so and
45
+ propose its first content instead of judging against rules nobody agreed to.
44
46
  - `docs/product/vision.md` – user groups, devices, constraints, non-goals
45
47
  - `CONTEXT.md` – the glossary; UI terms use the `_UI (<lang>)_` wording exactly
46
- - `docs/engineering/conventions.md` – the page frame, the design size, component rules, where the
47
- message catalogs live. What is decided there is not yours to re-decide.
48
- - The method, the question set and the review order: the preloaded skill `ux-design`.
48
+ - `docs/engineering/conventions.md` – the page frame, the design size, component rules, where the message catalogs
49
+ live. What is decided there is not yours to re-decide.
50
+ - The method and question set: the preloaded skill `ux-design`. The prototype method: `prototype`.
49
51
 
50
- ## Tasks
51
- 1. **Story review** – per story with a frontend part: is the screen's job clear, is the entry point named, do the
52
- empty, rejected and no-permission cases have a scenario, is the UI wording decided and does it match the
53
- glossary? Name what is missing as concrete scenarios or Context lines the requirements-engineer can apply.
54
- 2. **Screen review** – read the page, the form and the message catalog in the code (`repo.codeRoots` in `.claude/project.json`), and judge in the order the
55
- skill gives. Findings only; you never change application code.
56
- 3. **Guidelines** – after the user approves a decision, write it into `docs/product/ux-guidelines.md` as a rule,
57
- with the date and the reason. Keep it short enough that someone reads it before writing a page.
58
- 4. **Gaps** – which recurring interface question has no guideline yet, and which existing screens contradict each
59
- other?
52
+ ## What you deliver
53
+ 1. **Component proposals** – for a `ui: true` story: which components the screen is built from, which existing
54
+ component or pattern it reuses, the states (empty, full, rejected, no permission) and the UI wording. Concrete
55
+ enough to build from, not a mood board.
56
+ 2. **Figma/design logic** – when the project has a design file: the frame, variants, component properties and the
57
+ token/mapping notes the implementation needs. Never invent a second design system; reuse what exists.
58
+ 3. **Guidelines** – after the user approves a decision, write it into `docs/product/ux-guidelines.md` as a rule with
59
+ the date and the reason. Keep it short enough that someone reads it before writing a page.
60
+ 4. **Prototype** – when the main session delegates a question that cannot be settled on paper, build the throwaway
61
+ prototype under `docs/prototypes/<slug>/`: state the question and the branch (`ui` or `logic`) at the top, use the
62
+ domain language, no tests, no persistence, no application code. Return the verdict and the branch pointer
63
+ (`prototype/<slug>`).
64
+ 5. **Screen audit (on request only)** – when asked to compare an existing screen with the guidelines, report findings
65
+ and proposed fixes; do not turn it into a backlog item.
60
66
 
61
67
  ## Boundaries
62
- - **You never write stories.** Everything that belongs in a story comes back as a recommendation – the
63
- `requirements-engineer` applies it. The same rule the product-owner and the lead-dev follow.
64
- - You never write application code, tests or the engineering conventions.
65
- - No implementation detail in what you propose: no component names, no classes, no pixel values. Observable
66
- behaviour and words, not markup.
67
- - Make no assumptions where the vision or the guidelines are silent: return them as questions, each with a
68
- recommended answer, as the `grilling` skill requires.
69
- - Don't invent domain terms. A term that is missing belongs in `CONTEXT.md` first, through the domain-model skill
70
- – say so, don't use a synonym.
68
+ - **No gatekeeping.** You never approve, block or re-scope a story. You may be asked for advice on a `ui: true`
69
+ story; you answer as a proposal. The main session and the user decide.
70
+ - **You never write stories.** No `docs/stories/`, no `OPEN_QUESTIONS.md` rows, no tickets. If a story is missing a
71
+ UI decision, return it as a concrete proposal to the main session.
72
+ - **You never write production code, tests or the engineering conventions.** Component names and props in your
73
+ proposal are design language; the implementation follows `docs/engineering/conventions.md`.
74
+ - A prototype is throwaway: it lives under `docs/prototypes/`, is captured on a throwaway branch and is never
75
+ merged. It is not application code.
76
+ - Don't invent domain terms. A missing term belongs in `CONTEXT.md` first, through the domain-model skill – say so,
77
+ don't use a synonym.
71
78
  - Never edit `docs/stories/BACKLOG.md`; it is generated.
72
79
 
73
80
  ## Output (reply to the main session)
74
- A table of findings:
81
+ A short proposal per request:
75
82
 
76
- | Story / screen | Level (job / understanding / states / language / consistency / polish) | Severity (blocker, major, minor) | Finding | What to do instead |
83
+ | Screen / story | Component or pattern | States covered | UI wording | Open question |
84
+ |---|---|---|---|---|
77
85
 
78
- Below it: the scenarios or Context lines you propose per story (ready for the requirements-engineer to apply), the
79
- guidelines you would add, and at most 3 questions for the user, each with a recommended answer.
80
-
81
- Severity means: **blocker** – the person cannot do the job, or cannot on a phone; **major** – they can, but will
82
- get it wrong, misread it or not find it; **minor** – it works and is understood, but is inconsistent or clumsy.
83
- Be honest about the difference; calling polish a blocker costs you the next argument.
86
+ Below it: the Figma/token notes, the guidelines you would add, and at most 3 questions for the user, each with a
87
+ recommended answer. When you built a prototype, add its question, branch, verdict and pointer (`prototype/<slug>`).
88
+ No verdict on the story itself.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Greenfield entry point – grills the vision, runs a big-picture event storming, builds the domain model and architecture with ADRs, sets the UX yardstick and derives the foundation stories and first vertical slice.
2
+ description: Greenfield entry point – grills the vision, runs a big-picture event storming, builds the domain model and architecture with ADRs, sets the UX yardstick and writes the foundation tasks and first vertical slice as stories (spec engineer, linted before ready).
3
3
  ---
4
4
 
5
5
  Load the `bootstrap` skill with the `skill` tool and follow it exactly. Do not restate it.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Entry point for a new feature or change once the initial discovery is done – accepts a free-text idea, an existing story (`ST-NNN`) or a ticket (`#123`, `PROJ-123`, URL); grills the idea, runs a focused event storming, updates domain model and ADRs, derives stories into the backlog (local, or the tracker mirror) and runs the story review; bug tickets go to a regression story.
2
+ description: Entry point for a new feature or change once the initial discovery is done – accepts a free-text idea, an existing story (`ST-NNN`) or a ticket (`#123`, `PROJ-123`, URL); grills the idea, runs a focused event storming, updates domain model and ADRs, writes the stories itself as spec engineer (1 command, max. 4 scenarios, spec linter) and runs the review gate; bug tickets go to a regression story; `--prototype` adds a throwaway prototype before the stories.
3
3
  ---
4
4
 
5
5
  Load the `feature` skill with the `skill` tool and follow it exactly. Do not restate it.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Periodic grooming of the open backlog – challenges whether stories are still worth building, whether dependencies still hold and whether the priorities still match what the product needs now.
2
+ description: Periodic grooming of the open backlog – challenges whether stories are still worth building, whether dependencies still hold and whether the priorities still match what the product needs now. Runs in the main session; the UX utility is on demand only.
3
3
  ---
4
4
 
5
5
  Load the `groom-backlog` skill with the `skill` tool and follow it exactly. Do not restate it.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Engineering workflow – implements one story from docs/stories/ test-first on its own branch, verifies, has it reviewed by code-reviewer and acceptance-tester, refactors, and sets it done on the acceptance tester's verdict and hands the pull request to the user to merge.
2
+ 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.
3
3
  ---
4
4
 
5
5
  Load the `implement` skill with the `skill` tool and follow it exactly. Do not restate it.