kataster 0.3.1 → 0.6.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/THIRD_PARTY_NOTICES.md +4 -0
- package/.claude/agents/acceptance-tester.md +7 -2
- package/.claude/agents/code-reviewer.md +7 -2
- package/.claude/agents/domain-architect.md +7 -3
- package/.claude/agents/researcher.md +77 -0
- package/.claude/agents/ux-designer.md +42 -47
- package/.claude/hooks/validate-docs.ts +17 -1
- package/.claude/lib/architecture.ts +3 -33
- package/.claude/lib/backlog.ts +2 -0
- package/.claude/lib/config.ts +49 -0
- package/.claude/lib/discovery.ts +200 -32
- package/.claude/lib/engineering.ts +18 -6
- package/.claude/lib/gaps.ts +179 -0
- package/.claude/lib/glob.ts +39 -0
- package/.claude/lib/repo.ts +143 -19
- package/.claude/lib/research.ts +303 -0
- package/.claude/lib/slices.ts +529 -0
- package/.claude/package.json +1 -0
- package/.claude/settings.json +2 -2
- package/.claude/skills/adopt/SKILL.md +111 -34
- package/.claude/skills/adopt/scripts/gap-register.ts +61 -0
- package/.claude/skills/adopt/scripts/repo-map.ts +34 -2
- package/.claude/skills/adopt/scripts/slice-doc.ts +117 -0
- package/.claude/skills/adopt/scripts/slice.ts +163 -0
- package/.claude/skills/adopt/templates/context-map.as-is.md +22 -0
- package/.claude/skills/architect/SKILL.md +6 -1
- package/.claude/skills/backlog/SKILL.md +2 -2
- package/.claude/skills/bootstrap/SKILL.md +9 -7
- package/.claude/skills/domain-model/CONTEXT-FORMAT.md +1 -1
- package/.claude/skills/domain-model/SKILL.md +24 -4
- package/.claude/skills/event-storming/SKILL.md +3 -2
- package/.claude/skills/event-storming/schema/events.schema.json +2 -0
- package/.claude/skills/event-storming/templates/events.example.yaml +6 -0
- package/.claude/skills/feature/SKILL.md +16 -13
- package/.claude/skills/feature/scripts/intake.ts +1 -1
- package/.claude/skills/grilling/SKILL.md +15 -0
- package/.claude/skills/groom-backlog/SKILL.md +19 -17
- package/.claude/skills/implement/SKILL.md +199 -78
- package/.claude/skills/implement/scripts/characterize.ts +252 -0
- package/.claude/skills/implement/scripts/check-scenarios.ts +1 -1
- package/.claude/skills/implement/scripts/story-context.ts +65 -1
- package/.claude/skills/implement/scripts/verify.ts +4 -1
- package/.claude/skills/improve-codebase-architecture/SKILL.md +4 -1
- package/.claude/skills/prototype/SKILL.md +1 -1
- package/.claude/skills/research/SKILL.md +149 -0
- package/.claude/skills/research/scripts/research-check.ts +105 -0
- package/.claude/skills/research/templates/research.md +29 -0
- package/.claude/skills/review-stories/SKILL.md +49 -19
- package/.claude/skills/shape/SKILL.md +26 -7
- package/.claude/skills/tdd/SKILL.md +10 -0
- package/.claude/skills/user-stories/SKILL.md +128 -51
- package/.claude/skills/user-stories/schema/story.schema.json +10 -3
- package/.claude/skills/user-stories/scripts/lint-story.ts +56 -0
- package/.claude/skills/user-stories/templates/story-template.md +6 -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/domain-architect.md +7 -3
- package/.opencode/agents/researcher.md +91 -0
- package/.opencode/agents/ux-designer.md +42 -52
- package/.opencode/commands/adopt.md +1 -1
- 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/research.md +7 -0
- package/.opencode/commands/review-stories.md +1 -1
- package/.opencode/commands/shape.md +1 -1
- package/AGENTS.md +30 -0
- package/CHANGELOG.md +73 -0
- package/README.md +108 -24
- package/guide/brownfield.md +41 -12
- package/guide/concepts.md +23 -6
- package/guide/greenfield.md +4 -3
- package/package.json +1 -1
- package/src/cli.mjs +42 -4
- package/src/detect.mjs +9 -0
- package/src/install.mjs +66 -6
- package/templates/docs/domain/context-map.md +5 -1
- package/templates/docs/domain/events.yaml +3 -0
- package/templates/docs/research/README.md +70 -0
- package/templates/docs/stories/README.md +12 -3
- package/templates/docs/workflow.md +76 -19
- 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
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# As-is context map – {{project}}
|
|
2
|
+
|
|
3
|
+
> Recovered from code by `/adopt` on {{date}} at {{commit}}. This is **not a target**.
|
|
4
|
+
> Target: [context-map.md](context-map.md) · Gap register: [gap-register.md](gap-register.md).
|
|
5
|
+
|
|
6
|
+
<!--
|
|
7
|
+
One section per recovered bounded context. Use `### BC-… – <name>` so gap-register.ts can link to it.
|
|
8
|
+
Evidence is a table, a service method or a path; no target statements, no invented terms.
|
|
9
|
+
-->
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
flowchart LR
|
|
13
|
+
%% BC-ExampleA -->|recovered dependency| BC-ExampleB
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Contexts
|
|
17
|
+
|
|
18
|
+
### BC-Example – <name>
|
|
19
|
+
Purpose (as recovered): …
|
|
20
|
+
Core terms: …
|
|
21
|
+
Evidence: `<path:line>`, `<table>`, `<service method>`.
|
|
22
|
+
Boundaries: …
|
|
@@ -21,10 +21,15 @@ Domain language (the glossary in `CONTEXT.md`), bounded contexts, aggregates and
|
|
|
21
21
|
├── architecture/
|
|
22
22
|
│ └── data-model.md ← logical data model (domain-model skill)
|
|
23
23
|
└── domain/
|
|
24
|
-
├── context-map.md
|
|
24
|
+
├── context-map.md ← target map
|
|
25
|
+
├── context-map.as-is.md ← as-is snapshot, written only by /adopt
|
|
26
|
+
├── gap-register.md ← as-is ↔ target gaps (generated rows + decisions)
|
|
25
27
|
└── events.yaml
|
|
26
28
|
```
|
|
27
29
|
|
|
30
|
+
`docs/domain/context-map.md` is the target; `context-map.as-is.md` is the snapshot recovered by `/adopt`. Do not
|
|
31
|
+
write the as-is map from an architecture session – a target decision belongs in the target map.
|
|
32
|
+
|
|
28
33
|
Once code exists and contexts live in separate modules, context-specific decisions may move next to the code (`src/<context>/docs/adr/`); system-wide decisions stay in `docs/adr/`.
|
|
29
34
|
|
|
30
35
|
## During the session
|
|
@@ -155,8 +155,8 @@ silently – ask the user.
|
|
|
155
155
|
|
|
156
156
|
## When to sync
|
|
157
157
|
|
|
158
|
-
- after
|
|
159
|
-
- after `
|
|
158
|
+
- after the main session created or changed stories (spec engineer) → `push`
|
|
159
|
+
- after `priority`, `size`, `risk` or `depends_on` changed → `push`
|
|
160
160
|
- before `/review-stories` → `pull`, then review, then `push` the approved stories
|
|
161
161
|
- before `/implement` → `pull`; after each status change the workflow updates the tracker (GitHub directly, Jira by
|
|
162
162
|
the printed MCP transition), and after `done` → `push`
|
|
@@ -77,24 +77,26 @@ and reason. Do not let it become a mood board.
|
|
|
77
77
|
|
|
78
78
|
## Phase 5 – Foundation stories and the first slice
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
Write the stories yourself as the spec engineer (the `user-stories` skill is the method), in two parts:
|
|
81
81
|
|
|
82
82
|
1. **Foundation tech tasks** – what every later story relies on: repository skeleton, the single quality command
|
|
83
83
|
(`verify`), CI, the test harness and test data approach, auth/roles if the vision needs them, deployment.
|
|
84
84
|
Each is a tech task with a checklist and `depends_on`, not a domain story. Keep them minimal: foundation just
|
|
85
85
|
in time, not a platform project.
|
|
86
86
|
2. **The first vertical slice** – the smallest set of stories that delivers one real end-to-end path from the
|
|
87
|
-
vision (e.g. "report → triage → resolve"), each a story with Gherkin scenarios, `ui` where a person sees
|
|
87
|
+
vision (e.g. "report → triage → resolve"), each a story with Gherkin scenarios, `ui: true` where a person sees
|
|
88
88
|
something.
|
|
89
89
|
|
|
90
|
-
Rules: at most
|
|
91
|
-
`events`; `status: draft`, then `review` when
|
|
90
|
+
Rules: one story = one command + its events on one aggregate, at most 4 scenarios; no implementation plan inside a
|
|
91
|
+
domain story; every domain story links `aggregate`, `command` and its `events`; `status: draft`, then `review` when
|
|
92
|
+
finished. The spec linter must be green before `ready-for-human-review`.
|
|
93
|
+
|
|
92
94
|
|
|
93
95
|
## Phase 6 – Review
|
|
94
96
|
|
|
95
|
-
Read `.claude/skills/review-stories/SKILL.md` and follow it with the story IDs from Phase 5. The
|
|
96
|
-
every `ready`. Fix what
|
|
97
|
-
|
|
97
|
+
Read `.claude/skills/review-stories/SKILL.md` and follow it with the story IDs from Phase 5. The spec linter is the
|
|
98
|
+
gate; the user approves every `ready`. Fix what it finds in the story (or in the model, when an event or aggregate
|
|
99
|
+
is missing) – never work around a lint error.
|
|
98
100
|
|
|
99
101
|
## Phase 7 – Wrap-up
|
|
100
102
|
|
|
@@ -42,6 +42,6 @@ _Avoid_: Fix, service
|
|
|
42
42
|
|
|
43
43
|
## Single vs multi-context
|
|
44
44
|
|
|
45
|
-
During discovery there is one root `CONTEXT.md`, grouped by bounded context; the relationships between contexts are in `docs/domain/context-map.md
|
|
45
|
+
During discovery there is one root `CONTEXT.md`, grouped by bounded context; the relationships between contexts are in `docs/domain/context-map.md` (target). `/adopt` records what the code does today in `docs/domain/context-map.as-is.md` – not a target.
|
|
46
46
|
|
|
47
47
|
When code exists and contexts become separate modules, the glossary may be split: a root `CONTEXT-MAP.md` lists the contexts and links to one `CONTEXT.md` per module (e.g. `src/workshop/CONTEXT.md`). Only split when the code is actually structured that way – decide it via ADR.
|
|
@@ -15,7 +15,9 @@ Architecture decisions (ADRs, tech stack) belong to the `architect` skill. The d
|
|
|
15
15
|
|---|---|
|
|
16
16
|
| Glossary (ubiquitous language) | `CONTEXT.md` at the repo root – format: [CONTEXT-FORMAT.md](./CONTEXT-FORMAT.md) |
|
|
17
17
|
| Event storming model incl. `bounded_contexts`, `aggregates` | `docs/domain/events.yaml` |
|
|
18
|
-
|
|
|
18
|
+
| Target context map | `docs/domain/context-map.md` – where the domain is going |
|
|
19
|
+
| As-is context map | `docs/domain/context-map.as-is.md` – recovered from code, written only by `/adopt` |
|
|
20
|
+
| Gap register | `docs/domain/gap-register.md` – links as-is and target, generated rows + user decisions |
|
|
19
21
|
| Logical data model | `docs/architecture/data-model.md` – template: `templates/data-model.md` |
|
|
20
22
|
|
|
21
23
|
## 1. Language (during every session)
|
|
@@ -30,7 +32,7 @@ When the user uses vague or overloaded terms, propose a precise canonical term.
|
|
|
30
32
|
When domain relationships are being discussed, stress-test them with specific scenarios. Invent scenarios that probe edge cases and force the user to be precise about the boundaries between concepts. "A customer reports the same problem on an item that already has an open case – a new case or the same one?"
|
|
31
33
|
|
|
32
34
|
### Cross-reference with docs and code
|
|
33
|
-
When the user states how something works, check whether `docs/domain/events.yaml`, the stories (and the code, once it exists) agree. If you find a contradiction, surface it.
|
|
35
|
+
When the user states how something works, check whether `docs/domain/events.yaml`, the stories (and the code, once it exists) agree. If you find a contradiction, surface it. A source that contradicts the model is a grilling question, not a silent rewrite of the model (see the `research` skill).
|
|
34
36
|
|
|
35
37
|
### Update CONTEXT.md inline
|
|
36
38
|
When a term is resolved, update `CONTEXT.md` right there. Don't batch these up: capture them as they happen. `CONTEXT.md` is totally devoid of implementation details. It is a glossary and nothing else – not a spec, not a scratch pad.
|
|
@@ -39,7 +41,8 @@ Same word, different meaning in two places → a hint at a bounded context bound
|
|
|
39
41
|
|
|
40
42
|
## 2. Bounded Contexts & Context Map
|
|
41
43
|
- Draw boundaries along language (same word, different meaning → different context) and responsibility (who decides?).
|
|
42
|
-
- `docs/domain/context-map.md
|
|
44
|
+
- `docs/domain/context-map.md` is the **target** map: per context its purpose, core terms, owner role. Relationships as a Mermaid `flowchart` using the patterns Customer/Supplier, Conformist, Anti-Corruption Layer, Shared Kernel, Published Language.
|
|
45
|
+
- `docs/domain/context-map.as-is.md` is the **as-is** snapshot: what the code does today, with evidence. Only `/adopt` writes it; every other discovery path writes the target. The gap register links both.
|
|
43
46
|
- 2–4 contexts are typical for a small system. More only with justification.
|
|
44
47
|
- Maintain them in `events.yaml` under `bounded_contexts`, and group the terms in `CONTEXT.md` by context.
|
|
45
48
|
|
|
@@ -47,9 +50,26 @@ Same word, different meaning in two places → a hint at a bounded context bound
|
|
|
47
50
|
- An aggregate protects invariants that must be consistent **immediately**. Everything else is eventually consistent via events/policies.
|
|
48
51
|
- Keep them small. Reference other aggregates by ID only.
|
|
49
52
|
- Per aggregate in `events.yaml`: `context`, `invariants` (as testable statements). Assign commands and events via `aggregate`.
|
|
50
|
-
- **An invariant is stated once, on the aggregate** (user, 2026-10-01). A command's `rules` list only what it adds beyond them: defaults, actor permissions no invariant carries, required input, checks across aggregate or context boundaries, and consequences of the transition. Everything the stored state has to satisfy is an invariant, not a rule – the
|
|
53
|
+
- **An invariant is stated once, on the aggregate** (user, 2026-10-01). A command's `rules` list only what it adds beyond them: defaults, actor permissions no invariant carries, required input, checks across aggregate or context boundaries, and consequences of the transition. Everything the stored state has to satisfy is an invariant, not a rule – the spec engineer reads both when deriving scenarios.
|
|
51
54
|
- Sign of a wrong aggregate: a command needs data from several aggregates to check a rule.
|
|
52
55
|
|
|
56
|
+
### Aggregate status: target, as-is, unresolved
|
|
57
|
+
Every aggregate carries a status; a missing `status` means `target`, so existing models stay valid.
|
|
58
|
+
|
|
59
|
+
| Status | Meaning | Rule |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `target` | The boundary the project wants. The default in greenfield and in a confirmed target model. | Only a user decision makes an inferred boundary `target`. |
|
|
62
|
+
| `as-is` | The factual consistency boundary recovered from code. | Requires `evidence`: the table, service method or path that marks it. |
|
|
63
|
+
| `unresolved` | The boundary is unclear. | Requires an open hotspot (`refs: [AGG-…]`) and grilling. No story on it can become ready. |
|
|
64
|
+
|
|
65
|
+
**Prefer `as-is` or `unresolved` over an invented aggregate.** `/adopt` never writes `target` for something it
|
|
66
|
+
inferred from code. If you cannot name the table, method or path that holds the boundary together, it is not
|
|
67
|
+
`as-is` – it is `unresolved`. After changing a status or evidence, refresh the gap register:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
node .claude/skills/adopt/scripts/gap-register.ts
|
|
71
|
+
```
|
|
72
|
+
|
|
53
73
|
## 4. Logical Data Model (`docs/architecture/data-model.md`)
|
|
54
74
|
- Per aggregate: root entity, entities, value objects, attributes with **domain** types (e.g. `SerialNumber`, `Money`, `Timestamp`), required/optional.
|
|
55
75
|
- Lifecycle as a Mermaid `stateDiagram-v2` (derive states from the events).
|
|
@@ -12,7 +12,8 @@ Focus of this session: the arguments from the invocation (empty = big picture ac
|
|
|
12
12
|
|
|
13
13
|
## Preparation
|
|
14
14
|
1. Call the `skill` tool for `grilling` and `domain-model`. Grilling sets how you ask questions; domain-model sets how you guard the language in `CONTEXT.md`.
|
|
15
|
-
2. Read `docs/product/vision.md`, `CONTEXT.md`, `docs/domain/events.yaml`, `docs/domain/context-map.md
|
|
15
|
+
2. Read `docs/product/vision.md`, `CONTEXT.md`, `docs/domain/events.yaml`, `docs/domain/context-map.md` (target),
|
|
16
|
+
`docs/domain/context-map.as-is.md` and `docs/domain/gap-register.md` when they exist.
|
|
16
17
|
3. Format reference: `templates/events.example.yaml` in this skill folder (unrelated example domain – copy the format only, no content).
|
|
17
18
|
|
|
18
19
|
## Facilitation Rules
|
|
@@ -33,7 +34,7 @@ Focus of this session: the arguments from the invocation (empty = big picture ac
|
|
|
33
34
|
4. **Commands & actors** – What triggers each event, and who does it? Capture external systems (`EXT-`). Business rules of the command go into `rules` – only what the command adds beyond the `invariants` of its aggregate, which are stated once, there (user, 2026-10-01).
|
|
34
35
|
5. **Policies** – "Whenever <event>, then <command>". Include time-triggered ones (event with `origin: time`) and manual routines.
|
|
35
36
|
6. **Read models** – What information does an actor need to trigger the command? (`fed_by`, `used_by`, `fields`)
|
|
36
|
-
7. **Aggregates (proposal)** – Which rules must be protected consistently? Rough assignment of commands/events. Detailed work is done by `domain-architect`.
|
|
37
|
+
7. **Aggregates (proposal)** – Which rules must be protected consistently? Rough assignment of commands/events. Detailed work is done by `domain-architect`. Every aggregate gets `status: target` in greenfield; a boundary the user cannot settle becomes `status: unresolved` with an open hotspot. When adopting existing code, the status is `as-is` (with evidence) or `unresolved`, never an invented `target`.
|
|
37
38
|
8. **Bounded contexts (proposal)** – Where do language or responsibility change? Propose rough boundaries.
|
|
38
39
|
|
|
39
40
|
When focusing on a single process: phases 0–6 for that process (phase 0 only for what the vision doesn't cover yet), 7–8 only if something new emerges.
|
|
@@ -51,6 +51,8 @@
|
|
|
51
51
|
"id": { "type": "string", "pattern": "^AGG-[A-Za-z0-9]+$" },
|
|
52
52
|
"name": { "$ref": "#/$defs/text" },
|
|
53
53
|
"context": { "type": "string" },
|
|
54
|
+
"status": { "enum": ["target", "as-is", "unresolved"] },
|
|
55
|
+
"evidence": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/text" } },
|
|
54
56
|
"invariants": { "type": "array", "items": { "$ref": "#/$defs/text" } },
|
|
55
57
|
"description": { "type": "string" }
|
|
56
58
|
}
|
|
@@ -24,12 +24,18 @@ aggregates:
|
|
|
24
24
|
- id: AGG-Bike
|
|
25
25
|
name: Bike
|
|
26
26
|
context: BC-Rental
|
|
27
|
+
status: target
|
|
27
28
|
invariants:
|
|
28
29
|
- A bike can only be rented out once at a time
|
|
29
30
|
- A bike marked as damaged cannot be rented out
|
|
30
31
|
- id: AGG-RepairOrder
|
|
31
32
|
name: Repair order
|
|
32
33
|
context: BC-Workshop
|
|
34
|
+
# status: as-is # factual boundary recovered from code; add evidence below
|
|
35
|
+
# evidence:
|
|
36
|
+
# - repair_orders table (db/schema.sql:40)
|
|
37
|
+
# - RepairOrderService.open() (src/services/repairOrderService.ts:22)
|
|
38
|
+
# status: unresolved # boundary unclear; add an open hotspot with refs: [AGG-RepairOrder]
|
|
33
39
|
|
|
34
40
|
events:
|
|
35
41
|
- id: EVT-BikeRented
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: feature
|
|
3
|
-
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 instead; `--prototype` adds a throwaway prototype before the stories.
|
|
3
|
+
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 instead; `--prototype` adds a throwaway prototype before the stories; `--research` forces the research step for a cross-cutting question.
|
|
4
4
|
disable-model-invocation: true
|
|
5
|
-
argument-hint: "<idea | ST-NNN | #issue | PROJ-123 | URL> [--prototype[=ui|logic]]"
|
|
5
|
+
argument-hint: "<idea | ST-NNN | #issue | PROJ-123 | URL> [--prototype[=ui|logic]] [--research]"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# New Feature
|
|
@@ -11,6 +11,8 @@ The argument is a feature idea, an existing story or a ticket. Empty → ask the
|
|
|
11
11
|
Pick a short kebab-case slug for it (e.g. `order-photos`); stories get the label `feature:<slug>`.
|
|
12
12
|
`--prototype[=ui|logic]` is a flag, not part of the idea: strip it before resolving a reference. It asks for a
|
|
13
13
|
prototype before the stories are written; without a branch the `prototype` skill picks it from the question.
|
|
14
|
+
`--research` is a flag too: strip it before resolving a reference. It forces the research step for a topic the
|
|
15
|
+
trigger list in step 2 does not catch.
|
|
14
16
|
|
|
15
17
|
## 0. Intake – when the argument is a reference
|
|
16
18
|
|
|
@@ -57,14 +59,15 @@ ADRs and `docs/product/ux-guidelines.md` first.
|
|
|
57
59
|
Do not run an event storming for a bug and do not create a feature slug unless the rule changes.
|
|
58
60
|
|
|
59
61
|
## 1. Preparation
|
|
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.
|
|
62
|
+
Read `docs/product/vision.md`, `CONTEXT.md`, `docs/domain/events.yaml`, `docs/domain/context-map.md` (target), `docs/domain/context-map.as-is.md`, `docs/domain/gap-register.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
63
|
|
|
62
64
|
## 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
|
-
- **
|
|
65
|
+
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:
|
|
66
|
+
- **Research – does the idea rest on an external fact?** Auth/identity, security, payment, privacy/data protection, accessibility, performance, a new library or technology, or `--research`: load the `research` skill before grilling the affected branch. Check `docs/research/` first; a trigger is not a mandate, and one run covers a topic, not a story. Findings enter the round as cited recommendations – evidence, not decisions.
|
|
67
|
+
- **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?
|
|
68
|
+
- **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
69
|
- 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
|
|
70
|
+
- **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
71
|
- **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
72
|
- New or changed terms → `CONTEXT.md` inline.
|
|
70
73
|
- An architectural trade-off → ADR (`status: proposed`) only if the architect skill's three criteria hold.
|
|
@@ -86,9 +89,9 @@ it. In short:
|
|
|
86
89
|
4. **Capture.** The decision goes to `ux-designer` for `docs/product/ux-guidelines.md` (a G-number when it is
|
|
87
90
|
a recurring rule). Commit `docs/prototypes/<slug>/` on a throwaway branch `prototype/<slug>`, push it only
|
|
88
91
|
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
|
-
|
|
92
|
+
5. **Into the story.** In section 5 you write the verdict and the branch pointer into the story's `## Context`:
|
|
93
|
+
`Prototype: prototype/<slug> – <question> – <verdict>`, and the scenarios reflect the decision. The
|
|
94
|
+
`ux-designer` never writes the story itself.
|
|
92
95
|
|
|
93
96
|
If the question needs the real application (an existing page, real data), say so: that is an in-app prototype
|
|
94
97
|
and belongs to `/implement`, not to discovery. If the prototype does not answer the question within its
|
|
@@ -103,10 +106,10 @@ Read `.claude/skills/event-storming/SKILL.md` and follow it with the feature as
|
|
|
103
106
|
- 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
107
|
|
|
105
108
|
## 5. Stories
|
|
106
|
-
|
|
109
|
+
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 research files they cite (`sources: [docs/research/<topic>.md]`) with adopted/rejected findings and their reasons in `## Context`, 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
110
|
|
|
108
111
|
## 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
|
|
112
|
+
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
113
|
|
|
111
114
|
## 7. Wrap-up
|
|
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.
|
|
115
|
+
Summarize: the source and the route taken (idea, ticket, existing story or bug), glossary changes, new/changed events, ADRs proposed, research files created or refreshed and the findings the user adopted or rejected, 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
|
|
|
@@ -27,4 +27,19 @@ Each round the user answers reshapes the tree: settled decisions push the fronti
|
|
|
27
27
|
|
|
28
28
|
Finding _facts_ is your job, never the user's. When a frontier question needs a fact from the environment (filesystem, tools, etc.), dispatch a sub-agent to find it; don't ask the user for anything you could look up yourself. Don't block on it: a running exploration is an unsettled prerequisite, so only the questions downstream of it wait for the sub-agent to report; ask the rest of the frontier now. The _decisions_ are the user's: put each to them and wait.
|
|
29
29
|
|
|
30
|
+
## Research before a round
|
|
31
|
+
|
|
32
|
+
When a frontier question depends on an external fact – authentication/identity, security, payment, privacy/data
|
|
33
|
+
protection, accessibility, performance, a new library or technology – load the `research` skill before the round. A
|
|
34
|
+
trigger is **not a mandate**: if `CONTEXT.md`, `docs/domain/events.yaml`, an accepted ADR, the UX guidelines, the
|
|
35
|
+
conventions or a valid research file already answers it, run nothing. One run per topic, not per story.
|
|
36
|
+
|
|
37
|
+
- The recommendation cites the finding and its source: `➡️ … (RFC 9700 §2.1.1; F1 in docs/research/oauth-pkce.md)`.
|
|
38
|
+
- Only a confirmed recommendation becomes a Gherkin scenario or checklist item with an observable threshold – never
|
|
39
|
+
"follow best practices". A finding that cannot be tested is context or a guideline, not an acceptance criterion.
|
|
40
|
+
- Rejected options are recorded with the reason in the story's `## Context` / `## Out of Scope` (or the ADR /
|
|
41
|
+
initiative). The research file stays evidence and is not rewritten into a decision log.
|
|
42
|
+
- A finding that contradicts `CONTEXT.md`, `events.yaml`, an accepted ADR or the UX guidelines is a grilling
|
|
43
|
+
question. Never edit the model to match the source silently.
|
|
44
|
+
|
|
30
45
|
The session is done when the frontier is empty: every branch of the design tree visited, nothing left silently assumed. Do not act on it until the user confirms you have reached a shared understanding.
|
|
@@ -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
|
|