kataster 0.0.0-stage → 0.2.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 +53 -0
- package/.claude/agents/code-reviewer.md +56 -0
- package/.claude/agents/domain-architect.md +40 -0
- package/.claude/agents/lead-dev.md +50 -0
- package/.claude/agents/product-owner.md +39 -0
- package/.claude/agents/repo-analyst.md +78 -0
- package/.claude/agents/requirements-engineer.md +44 -0
- package/.claude/agents/ux-designer.md +64 -0
- package/.claude/hooks/bash-guard.ts +92 -0
- package/.claude/hooks/code-check.ts +37 -0
- package/.claude/hooks/path-guard.ts +34 -0
- package/.claude/hooks/path-rules.ts +66 -0
- package/.claude/hooks/project-check.ts +108 -0
- package/.claude/hooks/protect-files.ts +55 -0
- package/.claude/hooks/session-start.ts +213 -0
- package/.claude/hooks/stop-gate.ts +56 -0
- package/.claude/hooks/validate-docs.ts +58 -0
- package/.claude/lib/architecture.ts +736 -0
- package/.claude/lib/backlog-github.ts +454 -0
- package/.claude/lib/backlog-jira.ts +347 -0
- package/.claude/lib/backlog-sync.ts +42 -0
- package/.claude/lib/backlog.ts +396 -0
- package/.claude/lib/bazel.ts +212 -0
- package/.claude/lib/config.ts +122 -0
- package/.claude/lib/discovery.ts +821 -0
- package/.claude/lib/engineering.ts +406 -0
- package/.claude/lib/nx.ts +129 -0
- package/.claude/lib/repo.ts +1194 -0
- package/.claude/lib/toolgraph.ts +74 -0
- package/.claude/lib/turbo.ts +166 -0
- package/.claude/package-lock.json +427 -0
- package/.claude/package.json +21 -0
- package/.claude/settings.json +82 -0
- package/.claude/skills/adopt/SKILL.md +283 -0
- package/.claude/skills/adopt/scripts/boundary-check.ts +156 -0
- package/.claude/skills/adopt/scripts/package-doc.ts +71 -0
- package/.claude/skills/adopt/scripts/repo-map.ts +123 -0
- package/.claude/skills/adopt/scripts/rule-doc.ts +80 -0
- package/.claude/skills/architect/ADR-FORMAT.md +97 -0
- package/.claude/skills/architect/SKILL.md +64 -0
- package/.claude/skills/architect/TECH-STACK.md +21 -0
- package/.claude/skills/backlog/SKILL.md +198 -0
- package/.claude/skills/backlog/scripts/backlog-pull.ts +45 -0
- package/.claude/skills/backlog/scripts/backlog-push.ts +38 -0
- package/.claude/skills/backlog/scripts/backlog-status.ts +32 -0
- package/.claude/skills/backlog/scripts/jira-import.ts +40 -0
- package/.claude/skills/backlog/scripts/jira-plan.ts +26 -0
- package/.claude/skills/backlog/scripts/jira-record.ts +41 -0
- package/.claude/skills/bootstrap/SKILL.md +119 -0
- package/.claude/skills/codebase-design/DEEPENING.md +37 -0
- package/.claude/skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
- package/.claude/skills/codebase-design/SKILL.md +114 -0
- package/.claude/skills/domain-model/CONTEXT-FORMAT.md +47 -0
- package/.claude/skills/domain-model/SKILL.md +64 -0
- package/.claude/skills/domain-model/templates/data-model.md +29 -0
- package/.claude/skills/engineering-conventions/SKILL.md +31 -0
- package/.claude/skills/event-storming/SKILL.md +44 -0
- package/.claude/skills/event-storming/schema/events.schema.json +124 -0
- package/.claude/skills/event-storming/scripts/render-event-storming.ts +11 -0
- package/.claude/skills/event-storming/scripts/validate-events.ts +11 -0
- package/.claude/skills/event-storming/templates/events.example.yaml +91 -0
- package/.claude/skills/feature/SKILL.md +86 -0
- package/.claude/skills/feature/scripts/intake.ts +356 -0
- package/.claude/skills/grill-me/SKILL.md +7 -0
- package/.claude/skills/grill-with-docs/SKILL.md +7 -0
- package/.claude/skills/grilling/SKILL.md +30 -0
- package/.claude/skills/groom-backlog/SKILL.md +93 -0
- package/.claude/skills/groom-backlog/scripts/backlog-health.ts +238 -0
- package/.claude/skills/implement/SKILL.md +129 -0
- package/.claude/skills/implement/scripts/affected.ts +245 -0
- package/.claude/skills/implement/scripts/check-commands.ts +37 -0
- package/.claude/skills/implement/scripts/check-language.ts +15 -0
- package/.claude/skills/implement/scripts/check-scenarios.ts +59 -0
- package/.claude/skills/implement/scripts/next-story.ts +23 -0
- package/.claude/skills/implement/scripts/story-context.ts +135 -0
- package/.claude/skills/implement/scripts/story-status.ts +47 -0
- package/.claude/skills/implement/scripts/verify.ts +92 -0
- package/.claude/skills/improve-codebase-architecture/HTML-REPORT.md +123 -0
- package/.claude/skills/improve-codebase-architecture/SKILL.md +71 -0
- package/.claude/skills/retro/SKILL.md +53 -0
- package/.claude/skills/review-stories/SKILL.md +31 -0
- package/.claude/skills/shape/SKILL.md +193 -0
- package/.claude/skills/tdd/SKILL.md +38 -0
- package/.claude/skills/tdd/mocking.md +59 -0
- package/.claude/skills/tdd/tests.md +77 -0
- package/.claude/skills/user-stories/SKILL.md +138 -0
- package/.claude/skills/user-stories/schema/story.schema.json +39 -0
- package/.claude/skills/user-stories/scripts/render-backlog.ts +4 -0
- package/.claude/skills/user-stories/scripts/validate-stories.ts +13 -0
- package/.claude/skills/user-stories/templates/story-template.md +38 -0
- package/.claude/skills/ux-design/SKILL.md +107 -0
- package/.claude/skills/writing-for-agents/SKILL-MECHANICS.md +22 -0
- package/.claude/skills/writing-for-agents/SKILL.md +81 -0
- package/.claude/tsconfig.json +15 -0
- package/.opencode/agents/acceptance-tester.md +64 -0
- package/.opencode/agents/code-reviewer.md +69 -0
- package/.opencode/agents/domain-architect.md +59 -0
- package/.opencode/agents/lead-dev.md +67 -0
- package/.opencode/agents/product-owner.md +59 -0
- package/.opencode/agents/repo-analyst.md +86 -0
- package/.opencode/agents/requirements-engineer.md +58 -0
- package/.opencode/agents/ux-designer.md +83 -0
- package/.opencode/commands/adopt.md +7 -0
- package/.opencode/commands/backlog-sync.md +7 -0
- package/.opencode/commands/bootstrap.md +7 -0
- package/.opencode/commands/event-storming.md +7 -0
- package/.opencode/commands/feature.md +7 -0
- package/.opencode/commands/grill-me.md +7 -0
- package/.opencode/commands/grill-with-docs.md +7 -0
- package/.opencode/commands/groom-backlog.md +7 -0
- package/.opencode/commands/implement.md +7 -0
- package/.opencode/commands/improve-codebase-architecture.md +7 -0
- package/.opencode/commands/retro.md +7 -0
- package/.opencode/commands/review-stories.md +7 -0
- package/.opencode/commands/shape.md +7 -0
- package/.opencode/opencode.jsonc +15 -0
- package/.opencode/plugins/kataster/index.ts +283 -0
- package/AGENTS.md +21 -0
- package/CHANGELOG.md +82 -0
- package/LICENSE +21 -0
- package/README.md +324 -2
- package/bin/kataster.mjs +7 -0
- package/extras/skills/shadcn/SKILL.md +277 -0
- package/extras/skills/shadcn/agents/openai.yml +5 -0
- package/extras/skills/shadcn/assets/shadcn-small.png +0 -0
- package/extras/skills/shadcn/assets/shadcn.png +0 -0
- package/extras/skills/shadcn/cli.md +290 -0
- package/extras/skills/shadcn/customization.md +209 -0
- package/extras/skills/shadcn/evals/evals.json +77 -0
- package/extras/skills/shadcn/mcp.md +105 -0
- package/extras/skills/shadcn/registry.md +277 -0
- package/extras/skills/shadcn/rules/base-vs-radix.md +306 -0
- package/extras/skills/shadcn/rules/chat.md +250 -0
- package/extras/skills/shadcn/rules/composition.md +213 -0
- package/extras/skills/shadcn/rules/forms.md +192 -0
- package/extras/skills/shadcn/rules/icons.md +101 -0
- package/extras/skills/shadcn/rules/styling.md +185 -0
- package/guide/README.md +9 -0
- package/guide/brownfield.md +242 -0
- package/guide/concepts.md +109 -0
- package/guide/greenfield.md +84 -0
- package/guide/install.md +144 -0
- package/guide/release.md +62 -0
- package/package.json +56 -4
- package/src/cli.mjs +302 -0
- package/src/detect.mjs +237 -0
- package/src/install.mjs +427 -0
- package/src/repo.mjs +129 -0
- package/src/util.mjs +110 -0
- package/templates/CONTEXT.md +21 -0
- package/templates/conventions.md +63 -0
- package/templates/docs/adr/README.md +7 -0
- package/templates/docs/architecture/data-model.md +31 -0
- package/templates/docs/domain/context-map.md +21 -0
- package/templates/docs/domain/events.yaml +23 -0
- package/templates/docs/product/initiatives/README.md +41 -0
- package/templates/docs/product/ux-guidelines.md +27 -0
- package/templates/docs/product/vision.md +36 -0
- package/templates/docs/reviews/.gitkeep +0 -0
- package/templates/docs/stories/OPEN_QUESTIONS.md +8 -0
- package/templates/docs/stories/README.md +26 -0
- package/templates/docs/workflow.md +135 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: event-storming
|
|
3
|
+
description: Facilitates an interactive event storming with the user (big picture or a single process) and maintains docs/domain/events.yaml and the glossary in CONTEXT.md. Starts by grilling the user on the vision. For domain exploration and new business processes.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
argument-hint: "[process/focus, e.g. 'order fulfilment' – empty = big picture]"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Facilitating Event Storming
|
|
9
|
+
|
|
10
|
+
You are the facilitator, the user is the domain expert. You propose, they decide.
|
|
11
|
+
Focus of this session: the arguments from the invocation (empty = big picture across the whole domain).
|
|
12
|
+
|
|
13
|
+
## Preparation
|
|
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`.
|
|
16
|
+
3. Format reference: `templates/events.example.yaml` in this skill folder (unrelated example domain – copy the format only, no content).
|
|
17
|
+
|
|
18
|
+
## Facilitation Rules
|
|
19
|
+
- **Ask like the grilling skill**: numbered questions in rounds, each with your recommended answer; a round asks the whole frontier (everything answerable now). Facts you can look up are your job, decisions are the user's.
|
|
20
|
+
- **Events** are business facts in the past tense: "Order placed", not "Button clicked", and not CRUD ("Record saved").
|
|
21
|
+
- Uncertainties the user can't settle now, conflicts, "it depends" → capture immediately as a **hotspot** (`HS-n`), don't argue them away.
|
|
22
|
+
- **Language**: challenge terms against `CONTEXT.md`, sharpen fuzzy words, and add resolved terms to `CONTEXT.md` the moment they're settled (domain-model skill).
|
|
23
|
+
- No technology: no tables, endpoints, frameworks, screens.
|
|
24
|
+
- Write in the artifact language. IDs: CamelCase with prefix (`EVT-OrderPlaced`); names in plain words using the glossary terms ("Order placed").
|
|
25
|
+
- Write `docs/domain/events.yaml` after **every phase**. The hook validates it and renders `docs/domain/event-storming.md`. If it reports errors: fix them immediately. Warnings are normal in early phases.
|
|
26
|
+
- At the end of each phase: a 3–5 line summary + checkpoint ("Continue with phase X?").
|
|
27
|
+
|
|
28
|
+
## Phases
|
|
29
|
+
0. **Grill the vision** – Entry point. Grill the user on whatever the focus needs and `docs/product/vision.md` doesn't settle yet: problem, user groups, goals, non-goals, success criteria, constraints (big picture); trigger, participants, outcome and scope boundaries (single process). Continue until the frontier is empty and the user confirms a shared understanding, then update `vision.md` (remove answered `[OPEN]`s) and `CONTEXT.md`.
|
|
30
|
+
1. **Chaotic exploration** – Propose 8–15 suspected events as a starting point. The user deletes, corrects, adds. Ask specifically about exceptions, failure cases and rare events.
|
|
31
|
+
2. **Timeline** – Order events into `flows` (one flow per business process). Mark pivotal events (phase changes) with `pivotal: true`.
|
|
32
|
+
3. **Hotspots** – Systematically collect gaps and contradictions along the timeline, then grill them: resolve the ones the user can decide now (`status: resolved` + `resolution`), keep the rest open.
|
|
33
|
+
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
|
+
5. **Policies** – "Whenever <event>, then <command>". Include time-triggered ones (event with `origin: time`) and manual routines.
|
|
35
|
+
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
|
+
8. **Bounded contexts (proposal)** – Where do language or responsibility change? Propose rough boundaries.
|
|
38
|
+
|
|
39
|
+
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.
|
|
40
|
+
|
|
41
|
+
## Wrap-up
|
|
42
|
+
- Output: number of events/commands/policies/read models, open hotspots, glossary terms added or changed.
|
|
43
|
+
- Run `node .claude/skills/event-storming/scripts/validate-events.ts` and show the result.
|
|
44
|
+
- Propose the next step: `@domain-architect` for context map, aggregates, data model and ADRs.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "Event storming model (docs/domain/events.yaml)",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"additionalProperties": false,
|
|
6
|
+
"required": ["version", "domain", "events"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"version": { "const": 1 },
|
|
9
|
+
"domain": { "type": "string", "minLength": 1 },
|
|
10
|
+
"actors": { "type": "array", "items": { "$ref": "#/$defs/actor" } },
|
|
11
|
+
"external_systems": { "type": "array", "items": { "$ref": "#/$defs/external" } },
|
|
12
|
+
"bounded_contexts": { "type": "array", "items": { "$ref": "#/$defs/context" } },
|
|
13
|
+
"aggregates": { "type": "array", "items": { "$ref": "#/$defs/aggregate" } },
|
|
14
|
+
"events": { "type": "array", "items": { "$ref": "#/$defs/event" } },
|
|
15
|
+
"commands": { "type": "array", "items": { "$ref": "#/$defs/command" } },
|
|
16
|
+
"policies": { "type": "array", "items": { "$ref": "#/$defs/policy" } },
|
|
17
|
+
"read_models": { "type": "array", "items": { "$ref": "#/$defs/readModel" } },
|
|
18
|
+
"hotspots": { "type": "array", "items": { "$ref": "#/$defs/hotspot" } },
|
|
19
|
+
"flows": { "type": "array", "items": { "$ref": "#/$defs/flow" } }
|
|
20
|
+
},
|
|
21
|
+
"$defs": {
|
|
22
|
+
"text": { "type": "string", "minLength": 1 },
|
|
23
|
+
"idList": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
|
|
24
|
+
"actor": {
|
|
25
|
+
"type": "object", "additionalProperties": false, "required": ["id", "name"],
|
|
26
|
+
"properties": {
|
|
27
|
+
"id": { "type": "string", "pattern": "^ACT-[A-Za-z0-9]+$" },
|
|
28
|
+
"name": { "$ref": "#/$defs/text" },
|
|
29
|
+
"description": { "type": "string" }
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"external": {
|
|
33
|
+
"type": "object", "additionalProperties": false, "required": ["id", "name"],
|
|
34
|
+
"properties": {
|
|
35
|
+
"id": { "type": "string", "pattern": "^EXT-[A-Za-z0-9]+$" },
|
|
36
|
+
"name": { "$ref": "#/$defs/text" },
|
|
37
|
+
"description": { "type": "string" }
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"context": {
|
|
41
|
+
"type": "object", "additionalProperties": false, "required": ["id", "name", "purpose"],
|
|
42
|
+
"properties": {
|
|
43
|
+
"id": { "type": "string", "pattern": "^BC-[A-Za-z0-9]+$" },
|
|
44
|
+
"name": { "$ref": "#/$defs/text" },
|
|
45
|
+
"purpose": { "$ref": "#/$defs/text" }
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"aggregate": {
|
|
49
|
+
"type": "object", "additionalProperties": false, "required": ["id", "name"],
|
|
50
|
+
"properties": {
|
|
51
|
+
"id": { "type": "string", "pattern": "^AGG-[A-Za-z0-9]+$" },
|
|
52
|
+
"name": { "$ref": "#/$defs/text" },
|
|
53
|
+
"context": { "type": "string" },
|
|
54
|
+
"invariants": { "type": "array", "items": { "$ref": "#/$defs/text" } },
|
|
55
|
+
"description": { "type": "string" }
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"event": {
|
|
59
|
+
"type": "object", "additionalProperties": false, "required": ["id", "name"],
|
|
60
|
+
"properties": {
|
|
61
|
+
"id": { "type": "string", "pattern": "^EVT-[A-Za-z0-9]+$" },
|
|
62
|
+
"name": { "$ref": "#/$defs/text" },
|
|
63
|
+
"aggregate": { "type": "string" },
|
|
64
|
+
"context": { "type": "string" },
|
|
65
|
+
"origin": { "enum": ["command", "external", "time"] },
|
|
66
|
+
"pivotal": { "type": "boolean" },
|
|
67
|
+
"data": { "type": "array", "items": { "$ref": "#/$defs/text" } },
|
|
68
|
+
"description": { "type": "string" }
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"command": {
|
|
72
|
+
"type": "object", "additionalProperties": false, "required": ["id", "name", "produces"],
|
|
73
|
+
"properties": {
|
|
74
|
+
"id": { "type": "string", "pattern": "^CMD-[A-Za-z0-9]+$" },
|
|
75
|
+
"name": { "$ref": "#/$defs/text" },
|
|
76
|
+
"actor": { "type": "string" },
|
|
77
|
+
"aggregate": { "type": "string" },
|
|
78
|
+
"produces": { "$ref": "#/$defs/idList", "minItems": 1 },
|
|
79
|
+
"rules": { "type": "array", "items": { "$ref": "#/$defs/text" } },
|
|
80
|
+
"description": { "type": "string" }
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"policy": {
|
|
84
|
+
"type": "object", "additionalProperties": false, "required": ["id", "name", "when", "then"],
|
|
85
|
+
"properties": {
|
|
86
|
+
"id": { "type": "string", "pattern": "^POL-[A-Za-z0-9]+$" },
|
|
87
|
+
"name": { "$ref": "#/$defs/text" },
|
|
88
|
+
"when": { "$ref": "#/$defs/idList" },
|
|
89
|
+
"then": { "$ref": "#/$defs/idList" },
|
|
90
|
+
"description": { "type": "string" }
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"readModel": {
|
|
94
|
+
"type": "object", "additionalProperties": false, "required": ["id", "name", "fed_by"],
|
|
95
|
+
"properties": {
|
|
96
|
+
"id": { "type": "string", "pattern": "^RM-[A-Za-z0-9]+$" },
|
|
97
|
+
"name": { "$ref": "#/$defs/text" },
|
|
98
|
+
"fed_by": { "$ref": "#/$defs/idList" },
|
|
99
|
+
"used_by": { "$ref": "#/$defs/idList" },
|
|
100
|
+
"fields": { "type": "array", "items": { "$ref": "#/$defs/text" } },
|
|
101
|
+
"description": { "type": "string" }
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"hotspot": {
|
|
105
|
+
"type": "object", "additionalProperties": false, "required": ["id", "question"],
|
|
106
|
+
"properties": {
|
|
107
|
+
"id": { "type": "string", "pattern": "^HS-[0-9]+$" },
|
|
108
|
+
"question": { "$ref": "#/$defs/text" },
|
|
109
|
+
"refs": { "$ref": "#/$defs/idList" },
|
|
110
|
+
"status": { "enum": ["open", "resolved"] },
|
|
111
|
+
"resolution": { "type": "string" }
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"flow": {
|
|
115
|
+
"type": "object", "additionalProperties": false, "required": ["id", "name", "sequence"],
|
|
116
|
+
"properties": {
|
|
117
|
+
"id": { "type": "string", "pattern": "^FLOW-[A-Za-z0-9]+$" },
|
|
118
|
+
"name": { "$ref": "#/$defs/text" },
|
|
119
|
+
"description": { "type": "string" },
|
|
120
|
+
"sequence": { "$ref": "#/$defs/idList", "minItems": 1 }
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Renders docs/domain/event-storming.md from docs/domain/events.yaml (only if the model is valid). */
|
|
2
|
+
import * as d from "../../../lib/discovery.ts";
|
|
3
|
+
|
|
4
|
+
const report = new d.Report();
|
|
5
|
+
const model = d.validateEvents(report);
|
|
6
|
+
if (!report.ok || model === null) {
|
|
7
|
+
for (const line of report.lines()) console.log(line);
|
|
8
|
+
console.log("Not rendered – fix the errors first.");
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
console.log(`Written: ${d.rel(d.writeEventStormingMd(model))}`);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Validates docs/domain/events.yaml (schema + references). Exit 1 on errors. */
|
|
2
|
+
import * as d from "../../../lib/discovery.ts";
|
|
3
|
+
|
|
4
|
+
const report = new d.Report();
|
|
5
|
+
const model = d.validateEvents(report);
|
|
6
|
+
for (const line of report.lines()) console.log(line);
|
|
7
|
+
if (report.ok && model !== null) {
|
|
8
|
+
const counts = d.LIST_KEYS.map((k) => [k, Array.isArray(model[k]) ? model[k].length : 0] as const).filter(([, n]) => n);
|
|
9
|
+
console.log("OK – " + counts.map(([k, n]) => `${k}: ${n}`).join(", "));
|
|
10
|
+
}
|
|
11
|
+
process.exit(report.ok ? 0 : 1);
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# FORMAT EXAMPLE (unrelated domain: bike rental). Copy the structure only!
|
|
2
|
+
version: 1
|
|
3
|
+
domain: Bike Rental
|
|
4
|
+
|
|
5
|
+
actors:
|
|
6
|
+
- id: ACT-Customer
|
|
7
|
+
name: Customer
|
|
8
|
+
- id: ACT-Mechanic
|
|
9
|
+
name: Mechanic
|
|
10
|
+
|
|
11
|
+
external_systems:
|
|
12
|
+
- id: EXT-Payment
|
|
13
|
+
name: Payment provider
|
|
14
|
+
|
|
15
|
+
bounded_contexts:
|
|
16
|
+
- id: BC-Rental
|
|
17
|
+
name: Rental
|
|
18
|
+
purpose: Renting out and returning bikes
|
|
19
|
+
- id: BC-Workshop
|
|
20
|
+
name: Workshop
|
|
21
|
+
purpose: Maintaining the fleet
|
|
22
|
+
|
|
23
|
+
aggregates:
|
|
24
|
+
- id: AGG-Bike
|
|
25
|
+
name: Bike
|
|
26
|
+
context: BC-Rental
|
|
27
|
+
invariants:
|
|
28
|
+
- A bike can only be rented out once at a time
|
|
29
|
+
- A bike marked as damaged cannot be rented out
|
|
30
|
+
- id: AGG-RepairOrder
|
|
31
|
+
name: Repair order
|
|
32
|
+
context: BC-Workshop
|
|
33
|
+
|
|
34
|
+
events:
|
|
35
|
+
- id: EVT-BikeRented
|
|
36
|
+
name: Bike rented
|
|
37
|
+
aggregate: AGG-Bike
|
|
38
|
+
pivotal: true
|
|
39
|
+
data: [Bike number, Customer, Start time]
|
|
40
|
+
- id: EVT-DamageReported
|
|
41
|
+
name: Damage reported
|
|
42
|
+
aggregate: AGG-Bike
|
|
43
|
+
data: [Bike number, Description, Photo]
|
|
44
|
+
- id: EVT-RepairOrderOpened
|
|
45
|
+
name: Repair order opened
|
|
46
|
+
aggregate: AGG-RepairOrder
|
|
47
|
+
- id: EVT-InspectionDue
|
|
48
|
+
name: Inspection due
|
|
49
|
+
origin: time
|
|
50
|
+
context: BC-Workshop
|
|
51
|
+
|
|
52
|
+
commands:
|
|
53
|
+
- id: CMD-RentBike
|
|
54
|
+
name: Rent bike
|
|
55
|
+
actor: ACT-Customer
|
|
56
|
+
aggregate: AGG-Bike
|
|
57
|
+
produces: [EVT-BikeRented]
|
|
58
|
+
rules: [Customer has a valid payment method]
|
|
59
|
+
- id: CMD-ReportDamage
|
|
60
|
+
name: Report damage
|
|
61
|
+
actor: ACT-Customer
|
|
62
|
+
aggregate: AGG-Bike
|
|
63
|
+
produces: [EVT-DamageReported]
|
|
64
|
+
- id: CMD-OpenRepairOrder
|
|
65
|
+
name: Open repair order
|
|
66
|
+
aggregate: AGG-RepairOrder
|
|
67
|
+
produces: [EVT-RepairOrderOpened]
|
|
68
|
+
|
|
69
|
+
policies:
|
|
70
|
+
- id: POL-DamageCreatesRepair
|
|
71
|
+
name: Damage creates repair order
|
|
72
|
+
when: [EVT-DamageReported, EVT-InspectionDue]
|
|
73
|
+
then: [CMD-OpenRepairOrder]
|
|
74
|
+
|
|
75
|
+
read_models:
|
|
76
|
+
- id: RM-AvailableBikes
|
|
77
|
+
name: Available bikes
|
|
78
|
+
fed_by: [EVT-BikeRented, EVT-DamageReported]
|
|
79
|
+
used_by: [ACT-Customer]
|
|
80
|
+
fields: [Bike number, Location, Type]
|
|
81
|
+
|
|
82
|
+
hotspots:
|
|
83
|
+
- id: HS-1
|
|
84
|
+
question: May a bike with reported minor damage still be rented out?
|
|
85
|
+
refs: [EVT-DamageReported, AGG-Bike]
|
|
86
|
+
status: open
|
|
87
|
+
|
|
88
|
+
flows:
|
|
89
|
+
- id: FLOW-DamageToRepair
|
|
90
|
+
name: From damage to repair
|
|
91
|
+
sequence: [ACT-Customer, CMD-ReportDamage, EVT-DamageReported, POL-DamageCreatesRepair, CMD-OpenRepairOrder, EVT-RepairOrderOpened]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
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.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
argument-hint: "<idea | ST-NNN | #issue | PROJ-123 | URL>"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# New Feature
|
|
9
|
+
|
|
10
|
+
The argument is a feature idea, an existing story or a ticket. Empty → ask the user for it first.
|
|
11
|
+
Pick a short kebab-case slug for it (e.g. `order-photos`); stories get the label `feature:<slug>`.
|
|
12
|
+
|
|
13
|
+
## 0. Intake – when the argument is a reference
|
|
14
|
+
|
|
15
|
+
A reference is `ST-NNN`, `#123`, `PROJ-123`, a GitHub/Jira URL, or a Jira issue passed with `--from <issue.json>`.
|
|
16
|
+
Resolve it before asking anything:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
node .claude/skills/feature/scripts/intake.ts <reference> --json
|
|
20
|
+
# Jira: fetch the issue with jira_get_issue, write it as JSON, then
|
|
21
|
+
node .claude/skills/feature/scripts/intake.ts PROJ-123 --from <issue.json> --json
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The script is read-only. It returns the source, a matching local story (by id or `external`), signals and a `route`.
|
|
25
|
+
Follow the route:
|
|
26
|
+
|
|
27
|
+
| `route` | What to do |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `continue-story` | Read that story and treat it as the idea. Its open questions are the first grilling frontier. Do not create a parallel feature. |
|
|
30
|
+
| `review-story` | Stop; run `/review-stories <id>` (or revise the story if it is still being written). |
|
|
31
|
+
| `implement-story` | Stop; the next command is `/implement <id>`. |
|
|
32
|
+
| `new-story` | Finished behaviour is final; continue as a new feature and name the old story as the predecessor. |
|
|
33
|
+
| `bug` | Use the bug path below, not the feature pipeline. |
|
|
34
|
+
| `feature` | Continue with step 1. |
|
|
35
|
+
|
|
36
|
+
Before grilling, summarize the source in 3–5 lines and ask the user to confirm it – problem, requested behaviour,
|
|
37
|
+
acceptance hints, contradictions. A ticket is **evidence, not a specification**: grill its acceptance criteria,
|
|
38
|
+
separate solution language from the problem, and record contradictions with `CONTEXT.md`, `events.yaml`, ADRs or the
|
|
39
|
+
UX guidelines. Record the source in every derived story as `Source: <ref> (<url>)` under `## Context`. Never write
|
|
40
|
+
`external` by hand – the backlog sync owns it.
|
|
41
|
+
|
|
42
|
+
### Bug path
|
|
43
|
+
|
|
44
|
+
A bug is behaviour that contradicts what the model already documents. Check `CONTEXT.md`, `events.yaml`, accepted
|
|
45
|
+
ADRs and `docs/product/ux-guidelines.md` first.
|
|
46
|
+
|
|
47
|
+
- **Documented behaviour, code deviates** → one story, `type: story`, label `bug`, with a regression scenario that
|
|
48
|
+
reproduces the report and at least one edge case. No new events or commands; link the affected event if one
|
|
49
|
+
exists. Then `/review-stories` and `/implement` as usual.
|
|
50
|
+
- **The documented rule itself is wrong** → this is a feature: the rule changes, so run the normal pipeline and say
|
|
51
|
+
so in the wrap-up.
|
|
52
|
+
- **No model yet** (brownfield not adopted) → do not invent one from the bug; record the finding and point to
|
|
53
|
+
`/adopt`.
|
|
54
|
+
|
|
55
|
+
Do not run an event storming for a bug and do not create a feature slug unless the rule changes.
|
|
56
|
+
|
|
57
|
+
## 1. Preparation
|
|
58
|
+
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.
|
|
59
|
+
|
|
60
|
+
## 2. Grill the idea
|
|
61
|
+
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 story review later only checks – product owner, lead dev, 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:
|
|
62
|
+
- **PO**: 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?
|
|
63
|
+
- **Lead dev**: Which existing code, data and stories change? Is there a migration? What is hard to test? Where does it cut into stories – each a vertical slice of at most ~10 scenarios?
|
|
64
|
+
- Which existing processes, events and stories does it change? What's explicitly out of scope?
|
|
65
|
+
- **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 the label `ui`.
|
|
66
|
+
- New or changed terms → `CONTEXT.md` inline.
|
|
67
|
+
- An architectural trade-off → ADR (`status: proposed`) only if the architect skill's three criteria hold.
|
|
68
|
+
|
|
69
|
+
Don't move on before the user confirms.
|
|
70
|
+
|
|
71
|
+
## 3. Focused event storming
|
|
72
|
+
Read `.claude/skills/event-storming/SKILL.md` and follow it with the feature as focus: phases 1–6 (phase 0 is covered by step 2), 7–8 only if aggregates or contexts are affected. Capture the feature as its own flow (`FLOW-<FeatureName>`) and write `docs/domain/events.yaml` after every phase.
|
|
73
|
+
|
|
74
|
+
## 4. Domain model & architecture
|
|
75
|
+
- Contexts, aggregates or the data model affected → delegate to `domain-architect` with the file paths, the changed/new IDs from `events.yaml` and a clear task.
|
|
76
|
+
- An architectural trade-off came up that wasn't recorded during grilling → offer an ADR per the architect skill's three criteria (`status: proposed`, the user accepts).
|
|
77
|
+
- A UX decision changes or adds a guideline → delegate to `ux-designer`: write exactly these decisions into `docs/product/ux-guidelines.md`. The audit of existing screens belongs to `/groom-backlog`, not to the feature.
|
|
78
|
+
|
|
79
|
+
## 5. Stories
|
|
80
|
+
Delegate to `requirements-engineer`: derive stories for the feature's new or changed commands, policies and read models; name the event/command IDs, the label `feature:<slug>`, the label `ui` for every story with a frontend part, 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 story cut from step 2, and existing stories that need revising. Finished stories get `status: review`; have it report the IDs of all stories it created or revised.
|
|
81
|
+
|
|
82
|
+
## 6. Review
|
|
83
|
+
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 still approves every change and every `ready`.
|
|
84
|
+
|
|
85
|
+
## 7. Wrap-up
|
|
86
|
+
Summarize: the source and the route taken (idea, ticket, existing story or bug), glossary changes, new/changed events, ADRs proposed, 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.
|