@milehimikey/em 1.8.1 → 1.9.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 (104) hide show
  1. package/.claude/skills/event-modeling/SKILL.md +58 -404
  2. package/.claude/skills/event-modeling-conform/SKILL.md +77 -0
  3. package/.claude/skills/{event-modeling → event-modeling-conform}/reference/conform.md +39 -13
  4. package/.claude/skills/event-modeling-design/SKILL.md +139 -0
  5. package/.claude/skills/event-modeling-discover/SKILL.md +89 -0
  6. package/.claude/skills/{event-modeling → event-modeling-discover}/reference/extract.md +3 -2
  7. package/.claude/skills/event-modeling-implement/SKILL.md +40 -0
  8. package/.claude/skills/{event-modeling → event-modeling-implement}/reference/implement.md +3 -2
  9. package/.claude/skills/event-modeling-review/SKILL.md +58 -0
  10. package/.claude/skills/{event-modeling → event-modeling-shared}/reference/em-dsl.md +115 -83
  11. package/.claude/skills/{event-modeling → event-modeling-shared}/reference/methodology.md +6 -5
  12. package/.claude/skills/event-modeling-shared/reference/operating-principles.md +147 -0
  13. package/.claude/skills/{event-modeling → event-modeling-shared}/templates/model-readme.md +2 -2
  14. package/.claude/skills/{event-modeling → event-modeling-shared}/templates/slice.md +51 -8
  15. package/README.md +24 -4
  16. package/dist/catalog/build.js +9 -0
  17. package/dist/catalog/build.js.map +1 -1
  18. package/dist/catalog/docJoin.d.ts +15 -0
  19. package/dist/catalog/docJoin.js +8 -0
  20. package/dist/catalog/docJoin.js.map +1 -1
  21. package/dist/catalog/modelCollisionValidate.d.ts +22 -0
  22. package/dist/catalog/modelCollisionValidate.js +67 -0
  23. package/dist/catalog/modelCollisionValidate.js.map +1 -0
  24. package/dist/catalog/orphanedSliceDocValidate.d.ts +11 -0
  25. package/dist/catalog/orphanedSliceDocValidate.js +98 -0
  26. package/dist/catalog/orphanedSliceDocValidate.js.map +1 -0
  27. package/dist/catalog/sliceDoc.d.ts +15 -0
  28. package/dist/catalog/sliceDoc.js +18 -0
  29. package/dist/catalog/sliceDoc.js.map +1 -1
  30. package/dist/cli/changelogBuild.d.ts +12 -0
  31. package/dist/cli/changelogBuild.js +89 -0
  32. package/dist/cli/changelogBuild.js.map +1 -0
  33. package/dist/cli/ciInit.d.ts +42 -0
  34. package/dist/cli/ciInit.js +298 -0
  35. package/dist/cli/ciInit.js.map +1 -0
  36. package/dist/cli/conformSupersede.d.ts +32 -0
  37. package/dist/cli/conformSupersede.js +102 -0
  38. package/dist/cli/conformSupersede.js.map +1 -0
  39. package/dist/cli/coverage.d.ts +6 -1
  40. package/dist/cli/coverage.js +28 -3
  41. package/dist/cli/coverage.js.map +1 -1
  42. package/dist/cli/frontmatterSurgery.d.ts +28 -0
  43. package/dist/cli/frontmatterSurgery.js +66 -0
  44. package/dist/cli/frontmatterSurgery.js.map +1 -0
  45. package/dist/cli/markImplemented.js +6 -45
  46. package/dist/cli/markImplemented.js.map +1 -1
  47. package/dist/cli/ratify.d.ts +41 -0
  48. package/dist/cli/ratify.js +151 -0
  49. package/dist/cli/ratify.js.map +1 -0
  50. package/dist/cli/reratify.d.ts +33 -0
  51. package/dist/cli/reratify.js +137 -0
  52. package/dist/cli/reratify.js.map +1 -0
  53. package/dist/cli/skillCheck.d.ts +6 -0
  54. package/dist/cli/skillCheck.js +46 -0
  55. package/dist/cli/skillCheck.js.map +1 -1
  56. package/dist/cli/skillDirs.d.ts +15 -0
  57. package/dist/cli/skillDirs.js +34 -0
  58. package/dist/cli/skillDirs.js.map +1 -0
  59. package/dist/cli/skillSync.d.ts +10 -0
  60. package/dist/cli/skillSync.js +15 -0
  61. package/dist/cli/skillSync.js.map +1 -1
  62. package/dist/cli/sliceIndex.d.ts +3 -0
  63. package/dist/cli/sliceIndex.js +6 -2
  64. package/dist/cli/sliceIndex.js.map +1 -1
  65. package/dist/cli/sliceLink.d.ts +52 -0
  66. package/dist/cli/sliceLink.js +152 -0
  67. package/dist/cli/sliceLink.js.map +1 -0
  68. package/dist/cli/status.d.ts +261 -0
  69. package/dist/cli/status.js +536 -0
  70. package/dist/cli/status.js.map +1 -0
  71. package/dist/cli/usageLog.d.ts +75 -0
  72. package/dist/cli/usageLog.js +193 -0
  73. package/dist/cli/usageLog.js.map +1 -0
  74. package/dist/cli.js +501 -130
  75. package/dist/cli.js.map +1 -1
  76. package/dist/emit/freshnessJson.d.ts +6 -0
  77. package/dist/emit/freshnessJson.js +24 -0
  78. package/dist/emit/freshnessJson.js.map +1 -0
  79. package/dist/emit/json.d.ts +62 -8
  80. package/dist/emit/json.js +14 -3
  81. package/dist/emit/json.js.map +1 -1
  82. package/dist/emit/statusJson.d.ts +7 -0
  83. package/dist/emit/statusJson.js +39 -0
  84. package/dist/emit/statusJson.js.map +1 -0
  85. package/dist/emit/typespec.d.ts +26 -0
  86. package/dist/emit/typespec.js +356 -0
  87. package/dist/emit/typespec.js.map +1 -0
  88. package/dist/emit/usageReportJson.d.ts +3 -0
  89. package/dist/emit/usageReportJson.js +23 -0
  90. package/dist/emit/usageReportJson.js.map +1 -0
  91. package/dist/mcp/server.d.ts +1 -1
  92. package/dist/mcp/server.js +301 -11
  93. package/dist/mcp/server.js.map +1 -1
  94. package/dist/model/rules.d.ts +13 -0
  95. package/dist/model/rules.js +20 -0
  96. package/dist/model/rules.js.map +1 -1
  97. package/dist/templates.d.ts +1 -1
  98. package/dist/templates.js +2 -2
  99. package/dist/util/markers.d.ts +16 -4
  100. package/dist/util/markers.js +23 -10
  101. package/dist/util/markers.js.map +1 -1
  102. package/package.json +2 -1
  103. /package/.claude/skills/{event-modeling → event-modeling-shared}/templates/conformance-report.md +0 -0
  104. /package/.claude/skills/{event-modeling → event-modeling-shared}/templates/state.md +0 -0
@@ -1,416 +1,70 @@
1
1
  ---
2
2
  name: event-modeling
3
- em-version: 1.8.1
3
+ em-version: 1.9.0
4
4
  description: >-
5
- Use when the user wants to event-model a business process or system: building, editing,
6
- updating, or maintaining a model — extending or detailing an existing one into slices,
7
- extracting a current-state model from an existing codebase, implementing a ratified slice, or
8
- checking a model for drift against the code. Drives the `em` CLI through resumable phases —
9
- discover, extract, model, slice, implement, conform, watch, review, validate — or resumes
10
- automatically with no argument.
5
+ Use when the user runs `/event-modeling` (with or without a phase name), or wants to resume an
6
+ event-modeling session without specifying which part of the process applies. Reads the model's
7
+ `.event-modeling.md` state (or the given phase name) and routes to the right focused skill —
8
+ event-modeling-discover, event-modeling-design, event-modeling-implement, event-modeling-conform,
9
+ or event-modeling-review. If you already know which of those applies — starting a new model,
10
+ extracting from existing code, slicing/writing specs, implementing a ratified slice, checking
11
+ drift, or running a live/stakeholder view — invoke that skill directly instead of this one.
11
12
  ---
12
13
 
13
- # Event Modeling with `em`
14
+ # Event Modeling with `em` — resume / route
14
15
 
15
- You are facilitating an Event Modeling session. Your job is to **extract an accurate model from
16
- the user through Socratic questioning** — never to invent the domain. You drive the `em` CLI to
17
- render the model live, and you produce implementation-ready slice docs.
16
+ `em` drives Event Modeling through nine phases — `discover, extract, model, slice, implement,
17
+ conform, watch, review, validate` — split across five focused skills, one per stage of the
18
+ process. This router skill is the single entry point for `/event-modeling`: it figures out which
19
+ phase applies and hands off, so you never need to remember which of the five skills a given
20
+ phase lives in.
18
21
 
19
- Read `reference/methodology.md` (the 7 steps + 4 patterns) and `reference/em-dsl.md` (DSL syntax and
20
- validation rules) before doing real work — they are the source of truth. Templates live in
21
- `templates/`. References to `docs/*.md` throughout this skill mean the
22
- [em repository's docs](https://github.com/milehimikey/em/tree/main/docs) — they are not
23
- vendored alongside this skill.
24
-
25
- ## Operating principles (every phase)
26
-
27
- - **Socratic, one question at a time.** Ask focused questions; use `AskUserQuestion` for tight
28
- multiple-choice decisions. Never assume a domain fact — extract it. Prefer "who/why/what-if/
29
- what-must-always-be-true/how-do-you-know" over yes-no.
30
- - **Don't guess — park it.** Unresolved items go into the Open Questions list in
31
- `.event-modeling.md`, not into invented model content. Note the source, blocker, and revisit
32
- date when known — cheap now, useful when you come back to it.
33
- - **Happy path first; branches belong to slicing.** Steps 1-7 build the **happy-path spine**.
34
- Alternate, unhappy, and exception-path events (rejections, removals, cancellations,
35
- expirations, declines) are **not** enumerated as a separate discover/model task — they
36
- surface during the `slice` phase as each slice's alternate/error flows and rule-boundary
37
- scenarios, and any new branch events get added to the `.em` then. Never list "draft the
38
- branch events" as a discover/model to-do or ask the user to do it before slicing.
39
- - **Reflect and re-render.** After each meaningful increment, update the `.em` file, re-render,
40
- and show the user what changed. Encourage running the live view (`watch`) so a team can follow.
41
- - **Keep the `.em` structural; put depth in `note` docs.** The diagram holds flow; invariants,
42
- fields, and scenarios live in `slices/*.md` linked via `note "slices/<name>.md"`.
43
- - **Headless/API models still use `ui`.** If the system is headless (clients call an API, not
44
- screens), declare a persona per external caller/role (e.g. `IntegratorAPI`) and treat its `ui`
45
- boxes as API calls, not screens: writes are `ui → command → event` and reads are
46
- `read model → ui`, exactly like any other State Change/State View slice — no separate trigger
47
- slice. `translation` stays reserved for genuine reactions and real external-system boundaries,
48
- not a synchronous request/response call. Internal-only commands/views with no public route carry
49
- no `ui` at all — they follow the ordinary Automation pattern instead. **Repeat read models**
50
- across slices so the timeline flows left-to-right — put each repeat **right after the event that feeds it**, sourcing
51
- only that one adjacent event, so every arrow is short (a read model far from its source events
52
- draws a long arrow whose head lands columns away, making the *write* slice read as dangling —
53
- keep a sub-flow that detours into another context together, not parked at the end of the model).
54
- Declare every instance after the first with
55
- **`view X again from "..."`** — `again` instances are exempt from the duplicate-name warning even
56
- when referenced, and each reference resolves to the right instance. A reaction's command is
57
- wired by same-slice presence, exactly like `ui → command` — no positional/adjacency rule to get
58
- right (see `em-dsl.md`).
59
- See `reference/methodology.md` (State View) and `reference/em-dsl.md`.
60
- - **Never connect two instances of one read model.** The repeat is a timeline device, not a flow:
61
- continuity is implied by the shared name, and the events arriving at each instance are what show
62
- it changing. An arrow between instances says the read model feeds itself, and is an error.
63
- - **Every slice is a COMPLETE pattern, never a half-slice.** A State Change is
64
- `ui → command → event`; a State View is `event → read model → ui` (or `→ reaction`). So: a
65
- command needs something that **triggers** it (the `ui` it's issued from, or the reaction that
66
- triggers it, also in this slice), its event needs a **reader**, and that read model needs a
67
- **consumer** of its own. A command nothing points at is a write nobody can start; a reaction
68
- that triggers no command is a decision the system never acts on; an event nothing projects is
69
- a write nobody can see; a read model nothing displays is information dropped on the floor.
70
- Write the whole chain together rather than sweeping up dangling ends later. Reactions don't
71
- count as readers of *events* — they read views. **Every instance** of a repeated read model
72
- needs its own consumer: if you repeat a view next to an event just to keep the arrow short,
73
- bring its screen along, or don't add the instance.
74
- - **Only six connections are legal:** `ui → command`, `command → event`, `event → read model`,
75
- `read model → ui`, `read model → reaction`, `reaction → command`. Reaching for anything else —
76
- above all `command → read model` (the CQRS violation) or `read model → command` — means the model
77
- is missing an **element**, not an arrow.
78
- - **Validate continuously.** Run `em validate` and fix errors/warnings as you go (see DSL ref).
79
- - **Save state at the end of every session** so work resumes cleanly. Also append one line to
80
- the Usage log: the phase(s) touched and the diagnostic *categories* that fired — run `em
81
- validate <model>.em --json` and dedupe each diagnostic's `usageCategory` field directly
82
- (never the full message or domain content). This is the team's only usage signal today
83
- (`docs/usage-data.md`) — keep it cheap and habitual, not a task to skip.
22
+ | These phases... | ...live in this skill |
23
+ |---|---|
24
+ | `discover`, `extract` | `event-modeling-discover` — starting a new model, or extracting a current-state model from an existing codebase |
25
+ | `model`, `slice` | `event-modeling-design` — structuring the model into swimlanes/patterns, writing deep slice specs |
26
+ | `implement` | `event-modeling-implement` — building one ratified slice into merged, tested code |
27
+ | `conform`, `validate` | `event-modeling-conform` — drift-checking a model against its codebase, walking validation diagnostics |
28
+ | `watch`, `review` | `event-modeling-review` — the live browser viewer, facilitated stakeholder walkthroughs |
84
29
 
85
- ## Preconditions (run first)
30
+ ## Routing logic
86
31
 
87
32
  1. Check the tool: `em --version`. If missing, tell the user to run `npm i -g @milehimikey/em`
88
33
  and stop until installed.
89
- 2. Locate the model. Look for an existing `<dir>/.event-modeling.md` and `*.em` in the working
90
- directory (or a `models/` subfolder). If found, run `em state read <dir>` to read the state
91
- file's mechanical fields (model path, phase, step, last updated, last conformance, last
92
- review) as JSON — don't parse the bullets by hand. If not, and the phase needs one, ask the
93
- user for the model name and where to create it.
94
- 3. Parse the argument (`$ARGUMENTS`) to pick the phase below. With **no argument**, use
95
- `em state read <dir>`'s `phase`/`step` to resume the recorded phase/step; if no model exists,
96
- propose starting `discover` (greenfield) or `extract` (modeling an existing system).
97
- 4. Populate the state file's Participants section at session start. For a live workshop, ask for
98
- a single human proxy to relay questions to the room, and attribute every answer/decision in
99
- the Decisions log to a named participant.
100
-
101
- ## Project layout this skill creates
102
-
103
- ```
104
- <model-name>/
105
- <model-name>.em # the model (slice docs linked via note "...")
106
- <model-name>.svg # render target for em watch
107
- README.md # overview + slice index (from templates/model-readme.md)
108
- .event-modeling.md # resumable state (from templates/state.md)
109
- slices/<slice-name>.md # one rich slice doc per slice (from templates/slice.md)
110
- conformance/<date>-report.md
111
- # conform-phase reports (from templates/conformance-report.md)
112
- <model-name>-asis.em # conform-phase scratch model, regenerated per run — git-ignore this
113
- ```
114
-
115
- When creating a new model, run `em scaffold <model-name>` — it creates `<model-name>/` and
116
- writes all three starter files in one step (`<model-name>.em`, `README.md`,
117
- `.event-modeling.md`), filling the Model Name/model-name placeholders and the state file's
118
- mechanical fields (model path, `Current phase: discover`, `Current step: 1`, dates) for you, so
119
- there's nothing left to hand-copy or fill in. Refuses if `<model-name>/` already exists; pass
120
- `--force` to overwrite. You'll
121
- usually replace the scaffolded `.em`'s content as the discovery conversation builds up the real
122
- model — it starts out as the same starter model `em init` writes, titled from `<model-name>`.
123
- `slices/*.md` and `conformance/` aren't part of `em scaffold`; they come from the `slice` and
124
- `conform` phases below. The `conformance/` directory
125
- and `<model-name>-asis.em` only appear once the `conform` phase runs; `em conform-scope
126
- --seed-asis` creates `<model-name>-asis.em` and gitignores `*-asis.em` for you (see
127
- `reference/conform.md`) — it's scratch, never committed.
128
-
129
- ---
130
-
131
- ## Phase: `discover` — steps 1-4
132
-
133
- Goal: a draft model of events, storyboard, commands, and views. Loose is OK; structure comes next.
134
- **Existing system?** Use `extract` instead (next section) — discover is for greenfield modeling.
135
- **New feature inside an existing codebase?** Stay in `discover`, but before locking in
136
- command/event names, Grep/Read adjacent real sources (OpenAPI specs, DB migrations, existing
137
- DTOs/event classes in sibling contexts) rather than guessing conventions — same check `slice`
138
- phase applies to field tables, below.
139
-
140
- 1. **Brainstorm events (step 1).** Ask the user to name everything that happens, as past-tense
141
- facts. Probe for missed state changes. For each candidate, apply the **"is it an event?"
142
- test** (`reference/methodology.md` step 1 — the "would this wake the CEO at 3am" heuristic):
143
- reject derived values (belong in a read model) and telemetry/activity (not business state).
144
- Don't silently drop rejections — park them in the state file's Decisions log with why, so
145
- they aren't re-proposed later. Capture the survivors as a flat list.
146
- 2. **Plot / storyboard (step 2).** Order the events into the narrative. Identify **personas**
147
- (actors) and the **UI** screens at each step. Add `persona` declarations and `ui` elements.
148
- In a **headless/API** model there are no human personas or screens — identify the external
149
- **callers** at each step instead; declare one persona per caller/role, and its `ui` boxes are
150
- the API calls (see `reference/methodology.md`).
151
- 3. **Inputs (step 3).** For each event, find the **command** that causes it (imperative name).
152
- Form `command → event` slices (State Change pattern). Every command needs a **trigger** in the
153
- same breath: the screen the user issues it from (a `ui` in the slice), or — for the Automation
154
- and Translation patterns — the reaction that triggers it, also in this slice. A command
155
- nothing points at is a write nobody can start. *"Who does this, and where are they when they
156
- do it?"*
157
- 4. **Outputs (step 4).** Identify the **read models / views** consumers need and wire them with
158
- `from "Event"` (State View pattern), each with the screen (or reaction) that consumes it — a
159
- read model nothing displays is information dropped on the floor. In a **headless/API** model
160
- the consumer is the caller persona's `ui` (the API query) — same as any screen. Read models are
161
- **repeated** in each slice where they're read (use `view X again` after the first, each instance
162
- with its own consumer) so the timeline flows (see `reference/methodology.md`).
163
- **Close the loop before leaving this step:** every event from step 3 must be read by at least one
164
- read model. Walk the event list and ask, for each one, *"who looks at this, and what do they do
165
- with it?"* An event with no answer is either missing its read model or shouldn't be recorded —
166
- both are worth raising with the user rather than leaving dangling.
167
-
168
- End of phase: write/refresh the `.em`, render it, update `.event-modeling.md` (steps done,
169
- decisions, open questions — run `em state set-phase model` rather than hand-editing `Current
170
- phase:`), and run `em slice index <model-name>.em` to seed `README.md`'s Slices table (every
171
- slice already reads "no doc yet" — no slice docs exist until the `slice` phase writes them).
172
- Tell the user they can stop here and resume with `/event-modeling model`.
173
-
174
- ## Phase: `extract` — current-state model of an existing system
175
-
176
- Goal: a faithful **current-state** model extracted from an existing system — the as-is sibling
177
- of `discover` (it replaces discover; the model then proceeds to `model` as usual).
178
-
179
- **Read `reference/extract.md` before doing any extract work** — it carries a stance override
180
- that inverts methodology step 1 (capture how the system behaves *today*; never model desired
181
- state).
182
-
183
- - Two source modes, detected from the system itself and confirmed with the user:
184
- **event-driven** (an event vocabulary already exists — schemas, topics, handlers) and
185
- **procedural/monolith** (no event vocabulary — synthesize candidate events from behavior
186
- and docs).
187
- - Converge via a ~7-round confirm-and-clarify loop (one concern per round; render from round 2,
188
- validate from round 4 — see the playbook).
189
- - **Current-state-only:** park unknowns as `# TBD` comments in the `.em`, mirrored in the state
190
- file's Open Questions — never guess intended design.
191
-
192
- End of phase: validated as-is model; state file updated (source mode, rounds, decisions; `em
193
- state set-phase model` for `Current phase:`); run `em slice index <model-name>.em` to seed
194
- `README.md`'s Slices table; then chain to `/event-modeling model` (steps 5-7).
195
-
196
- ## Phase: `model` — steps 5-7
197
-
198
- Goal: a structurally complete, **validated** model with correct patterns and swimlanes.
199
-
200
- 1. **Swimlanes & patterns (step 5).** Group events into **contexts** (bounded contexts /
201
- aggregates) — ask which events share a consistency boundary and who owns them. Classify each
202
- slice as one of the 4 patterns. **Share the slice between every automation or translation and
203
- the command it triggers** (the reaction — processor/translation — together with the command
204
- and event it produces; the read model it watches, if any, stays in the slice before). A
205
- translation or automation is a reaction: it **triggers a command and never records an event
206
- directly**. Add `translation` slices for external inputs (externally triggered: external →
207
- translation → command → event, no slice before) and for the system reacting to its own state
208
- (internally triggered: read model in the slice before → translation → command → event).
209
- 2. **Elaborate scenarios — first pass (step 6).** For each slice, capture the happy-path
210
- Given/When/Then and the obvious invariants as short notes. (The full spec is the `slice` phase.)
211
- 3. **Evaluate completeness (step 7).** Walk the model: every slice is a **complete** pattern, not a
212
- half-slice — **every command has something that triggers it**, every command emits an event,
213
- **every event is read by a read model**, **every read model has a consumer**, every view has a
214
- source, every UI is reachable, every connection is
215
- one of the six legal pairs, and every automation **and** translation triggers a command (none
216
- wired straight to an event, none with no command at all). Run `em validate` and resolve all
217
- errors and warnings — it catches a reaction wired straight to an event too now (see
218
- `reference/em-dsl.md`), so a clean run covers this case.
219
- For an unread event, don't just bolt on a view to silence the warning: ask the user who looks at
220
- this fact and what they do with it. The honest answers are "here's the read model we missed" or
221
- "nobody — so why are we recording it", and both improve the model.
222
-
223
- End of phase: render, update state (`em state set-phase slice`), suggest `/event-modeling slice`
224
- to write implementation specs.
225
-
226
- ## Phase: `slice` — deep slice documents
227
-
228
- Goal: implementation-ready specs. Go slice by slice (let the user pick order, or follow the
229
- timeline). Check `README.md`'s Slices table for what's already done (run `em slice index
230
- <model-name>.em` first if it looks stale).
231
-
232
- This is also where **branch / unhappy-path events** are discovered and added to the model — as a
233
- slice's alternate/error flows surface (a rejection, removal, cancellation, decline, expiry), add
234
- the corresponding event/slice to the `.em` and re-render. The happy-path spine from earlier
235
- phases is the starting point, not the finished event set. **Every new event needs its reader too**
236
- — a rejection or cancellation that nothing projects will warn, and usually the missing piece is
237
- real (someone has to see that the request was declined).
238
-
239
- For each slice:
240
- 0. **Check for re-ratification first.** If `slices/<slice-name>.md` already exists with
241
- `status: implemented`, this is a re-ratification, not fresh authoring: hold a Socratic
242
- deep-dive on what changed (same rigor as step 1, scoped to the delta), update whichever
243
- sections actually changed, then express the change as the `## Delta` section — fixed heading,
244
- `### Added`/`Modified`/`Removed`/`Renamed` Requirement blocks each carrying its own scenarios
245
- (see `templates/slice.md` and `docs/slice-doc-schema.md#delta-section-grammar-and-lifecycle`)
246
- — **overwriting** whatever the section held before, never appending to it. Then continue at
247
- step 2 to bump `version` and flip `status` back to `ready-to-implement`, leaving
248
- `implementedIn` naming the prior version's PR (intended drift signal, not a bug — see the
249
- schema doc). Otherwise, this is first-time authoring: continue at step 1.
250
- 1. Hold a Socratic deep-dive to fill every section of `templates/slice.md`: intent, trigger/actor,
251
- command + field table (types & rules), event(s) + payload (mark immutable facts), invariants
252
- (give each a stable ID), Given/When/Then scenarios (happy path + rule boundaries + edge cases),
253
- alternate/error flows (retries, idempotency, compensations), non-functional requirements
254
- (security/authz, PII/compliance, performance/SLA), read models affected, open questions. Park
255
- anything unresolved rather than guessing. If the slice lives in an existing codebase, Grep/Read
256
- adjacent real sources (OpenAPI specs, DB migrations, existing DTOs/event classes in sibling
257
- contexts) before finalizing field names/types or invariants — don't guess a shape that's
258
- already defined elsewhere.
259
- 2. **First-time authoring:** scaffold the doc mechanically rather than hand-writing the
260
- frontmatter — `em slice new "<slice name>" --pattern <state-change|state-view|automation|
261
- translation> --swimlane "<Persona> → <Context>"` writes `slices/<slice-name>.md`
262
- (kebab-cased to match, via the same slugging `em` uses everywhere else) with the canonical
263
- `schemaVersion`/`pattern`/`swimlane`/`status: draft`/`version: 1` frontmatter — exactly the
264
- five keys `em export` and the readiness gate require, no more — and the `# Slice:` heading +
265
- diagram-image stub already in place. Both `--pattern` and `--swimlane` are required; an
266
- invalid `--pattern` is refused with the valid choices listed. Never hand-type this block, and
267
- never fall back to a placeholder pattern/swimlane to dodge the flags. Then fill in every
268
- judgment section below the stub from step 1 (Intent, Command, Event(s), Invariants,
269
- Scenarios, ...) — the doc's prose is still entirely hand-authored, only the frontmatter/
270
- heading scaffold is mechanized. Record the originating need (ticket/conversation link) in the
271
- Intent section when one exists. When this doc exists because of a split, merge, or rename,
272
- add the matching lineage key(s) by hand (`split-from`/`merged-from`/`superseded-by`,
273
- `<slice-key>@v<N>` grammar — see `docs/slice-doc-schema.md` for the full schema).
274
- **Re-ratification (step 0):** the doc already exists, so `em slice new` doesn't apply here
275
- (it refuses to overwrite an existing file without `--force`, and forcing would blow away the
276
- doc's authored body) — bump `version` and flip `status` back to `ready-to-implement` by hand
277
- in the existing frontmatter instead.
278
- 3. Render the slice's own diagram: `em render <model>.em --slice "<slice name>" -o
279
- slices/<slice-name>.svg` (kebab-case, matching the doc's filename and the `![Diagram]` stub
280
- `em slice new` already wrote) — redraws just this slice in its own canonical pattern shape.
281
- 4. Wire it into the `.em`: `em slice new` (step 2) printed the exact `note
282
- "slices/<slice-name>.md"` line to add to the slice's primary element (the command for State
283
- Change, the view for State View, the processor for Automation, the translation for
284
- Translation) — `em slice new` only writes the new doc file, never edits the `.em` source
285
- itself, so add that line by hand.
286
- 5. Run `em slice index <model-name>.em` to regenerate `README.md`'s Slices table — the one
287
- canonical slice index — from the model and the doc frontmatter you just wrote (status,
288
- `implementedIn` once shipped). Never hand-edit the table; it's a generated block.
289
- 6. Re-render and `em validate`.
290
-
291
- When a slice is **ratified** — a human flips its `status` to `ready-to-implement` with every
292
- open question resolved — it's ready to hand to an implementer. Confirm with
293
- `em validate <model>.em --slice-ready <key>`, and point whoever (or whatever) implements it
294
- at `reference/implement.md`.
295
-
296
- ## Phase: `implement` — build one ratified slice
297
-
298
- Goal: turn a single `ready-to-implement` slice into merged, verified code — the one phase
299
- where the agent builds rather than facilitates.
300
-
301
- **Read `reference/implement.md` before doing any implement work and follow it as the
302
- contract.** In short: gate on `em validate <model>.em --slice-ready <key>` (stop and hand
303
- back if it fails — never edit the doc to make the gate pass); treat the slice doc as the
304
- spec (read-only, except the merge-time `status`/`implementedIn` flip); surface every gap to
305
- the user instead of deciding it silently; cover every INV-<MNEMONIC>-n and every scenario with tests;
306
- in spec-kit projects, allocate via em-sdd-bridge (redirect mode) and never run
307
- `/speckit.specify`.
308
-
309
- End of phase: PR merged, slice doc flipped to `status: implemented` with `implementedIn`
310
- filled, `em slice index <model-name>.em` run to refresh `README.md`'s Slices table. Implement
311
- doesn't chain to another phase — run it once per ratified slice; `conform` later checks the
312
- result against the model.
313
-
314
- ## Phase: `conform` — drift check against the codebase
315
-
316
- Goal: check a **ratified** model (and its slice docs) against the codebase that implements it,
317
- and report where they've drifted — advisory only, never a gate, never an unprompted edit.
318
-
319
- **Read `reference/conform.md` before doing any conform work** — it carries the full flow
320
- (scope, evidence-first verification, `em diff --json`, classification, report) and the
321
- stance guardrails (evidence-first, uncertainty is never drift, propose-don't-edit). It reuses
322
- `extract`'s sourcing/mode rules for reading the target codebase rather than duplicating them.
323
-
324
- In short: run `em conform-scope <model-name>.em --repo <target-repo-path> --seed-asis` to
325
- compute the in-scope slice set (diff-scoped by default, via `Last conformance:` + the target
326
- repo's changed paths mapped through each slice doc's `implementedIn:`) and seed the scratch
327
- model in one step; for each in-scope slice, gather code evidence *before* comparing to the model
328
- or doc; write the as-is picture into that scratch model (`<model-name>-asis.em`, reusing the
329
- canonical model's names wherever the code matches them); run `em diff <model-name>.em
330
- <model-name>-asis.em --json` and let `em` decide the structural deltas; classify every finding
331
- (real drift / model gap / internal inconsistency / uncertainty) with cited evidence; write
332
- `conformance/<date>-report.md` with proposed `issue "conformance: …"` red notes; apply only the
333
- proposals the user ratifies, then re-render and validate; run `em state set-conformance
334
- <revision> --report <path>` to update the state file's `Last conformance:` marker.
335
-
336
- End of phase: state file's `Last conformance:` marker updated (via `em state set-conformance`),
337
- Decisions log entry if any
338
- proposals were applied. Conform doesn't chain to another phase — it's a recurring loop, run
339
- again whenever the codebase has moved.
340
-
341
- ## Phase: `watch` — live team view
342
-
343
- Start the watcher with `--serve` in the background:
344
- `em watch <model-name>.em -o <model-name>.svg --serve` (run_in_background). It re-renders on every
345
- save and pushes an instant reload to the browser over Server-Sent Events. Tell the user to open the
346
- URL it prints (e.g. `http://localhost:5173/?svg=<model-name>.svg`) and share their screen — updates
347
- appear the moment you save, with no polling and no idle churn between edits.
348
-
349
- The viewer navigates like a map — drag to pan, scroll/pinch to zoom, **Fit** to reset — and its
350
- **Review mode** steps through slices one at a time (see the `review` phase). A save that fails to
351
- render never blanks the shared screen: the last good diagram stays up, an error banner explains
352
- what went wrong, and the viewer recovers on its own at the next successful render.
353
-
354
- ## Phase: `review` — stakeholder walkthrough
355
-
356
- Goal: step a real stakeholder review session through the model slice by slice, one slice
357
- spotlighted at a time, with any open questions the room raises captured live as `issue "..."`
358
- red notes.
359
-
360
- **Trigger: a real stakeholder review session is on the calendar — a scheduled use, not
361
- speculation.** Don't propose this phase proactively; it exists for facilitated reviews with
362
- non-engineer stakeholders in the room, not routine model editing.
363
-
364
- Start the same live server as `watch`: `em watch <model-name>.em -o <model-name>.svg --serve`
365
- (run_in_background). Open the printed URL, click **Review mode** in the header, and share the
366
- screen. Use Prev/Next (or the left/right arrow keys) to step through slices in declaration
367
- order — each one pans/zooms into view with everything else dimmed, so the room's attention
368
- tracks one slice at a time.
369
-
370
- **Live capture:** when a stakeholder raises something unresolved, add `issue "..."` to the
371
- relevant element in the `.em` file and save — exactly the same mechanism as any other issue
372
- (see `validate` below). The browser updates over the existing SSE push within moments, without
373
- losing the current slice or resetting review mode.
374
-
375
- Wrap-up: run `em validate --list-issues` to sweep everything captured during the session and
376
- walk each one with the user, same as any open issue. Update the state file's Participants
377
- section with who attended, and run `em state set-review <date>` to set the `Last stakeholder
378
- review:` marker (mirrors `Last conformance:`).
379
-
380
- End of phase: state file's `Last stakeholder review:` marker updated, every issue captured
381
- live triaged (resolved on the spot, moved to Open questions / parking lot, or left open on
382
- purpose). Review doesn't chain to another phase — it's a recurring, scheduled activity like
383
- `conform`, not a step in the discover → model → slice sequence.
384
-
385
- ## Phase: `validate`
386
-
387
- Run `em validate <model-name>.em` and walk through each diagnostic with the user, explaining the
388
- rule (see `reference/em-dsl.md`) and proposing the fix. Apply fixes on agreement. Common ones:
389
-
390
- | Diagnostic | Fix |
391
- |---|---|
392
- | reaction triggers no command | Add the command it issues, in this same slice, or an explicit `arrow` to one elsewhere |
393
- | **command has nothing that triggers it** | Add the `ui` it's issued from — or, if the system issues it, the reaction that triggers it, also in this slice. Ask *"who does this, and where are they when they do it?"* |
394
- | **read model has no consumer** | Add the screen that displays it, or the reaction that watches it. If it's a repeat added only to shorten an arrow and nothing looks at it there, drop the instance |
395
- | read model has no source | Add the missing `from "Event"` |
396
- | command produces no event | Give the command its event, or drop the command |
397
- | **event is not read by any read model** | Add the read slice that projects it — but ask *who looks at this and what do they do with it* first. "Nobody" is a real answer, and then the question is why it's recorded at all |
398
- | **illegal `arrow` kind pair** | Don't reroute it — the model is missing an element. `command → view` needs the event between them; `view → command` needs a reaction. Between two instances of one read model, just delete the arrow: the repeat needs no connection |
399
- | `view X again` with no earlier declaration | Declare the view plainly the first time it appears |
400
- | event feeding an earlier view instance | Add a `view X again` where the event lands and move the source there |
401
-
402
- For anything genuinely unresolved rather than a rule violation, prefer `issue "text"` on the
403
- relevant element over a `# TBD` comment — it shows up as a red marker on the rendered diagram and
404
- `em validate` tracks it as an open-issue warning, so it isn't lost once rendered. `em validate
405
- --list-issues` gives a quick sweep of everything still open.
406
-
407
- `em validate` now catches a reaction wired straight to an event too — any reaction with no
408
- `command` in its own slice, and no explicit arrow to one, warns "triggers no command". A
409
- `translation`/`processor`/`automation` should always trigger a `command` in its own slice
410
- (`reaction → command → event`); if one instead records an event directly, route it through a
411
- command instead.
412
-
413
- ---
34
+ 2. Parse `$ARGUMENTS` for a phase name.
35
+ - **A recognized phase name** (`discover`, `extract`, `model`, `slice`, `implement`,
36
+ `conform`, `validate`, `watch`, `review`): look it up in the table above and invoke that
37
+ skill directly (via the `Skill` tool), passing the phase name along so it knows exactly
38
+ where to start. Don't re-derive state first — the target skill's own preconditions handle
39
+ that.
40
+ - **No argument:** locate the model (an `.event-modeling.md`/`*.em` pair in the working
41
+ directory, or one level down under `models/<slug>/` for a multi-model project — see
42
+ `../event-modeling-shared/reference/operating-principles.md`). If found, run
43
+ `em state read <dir>` and read its `phase` field as JSON — don't parse the state file's
44
+ bullets by hand. Map that phase through the table above and invoke the matching skill,
45
+ telling it to resume at the recorded `step` too. If no model exists yet, ask the user
46
+ whether this is a new model (`event-modeling-discover`, `discover`) or an existing system to
47
+ extract from (`event-modeling-discover`, `extract`), then invoke that skill.
48
+ - **An unrecognized argument:** treat it as free-text intent and pick the best-matching skill
49
+ from the table's description, same as you would if the user had asked in plain language.
50
+ 3. Once you've handed off, this skill's job is done for the session — the target skill owns the
51
+ conversation from there, including re-invoking `event-modeling` (this skill) itself at the end
52
+ if the user wants to stop and resume later.
53
+
54
+ ## Shared reference material
55
+
56
+ Every phase skill (and this one) points back to the same shared resources rather than
57
+ duplicating them — read them once, they apply everywhere:
58
+
59
+ - `../event-modeling-shared/reference/operating-principles.md` — the Socratic/validation discipline
60
+ every phase follows, the preconditions above in full, and the project layout these skills
61
+ create (including multi-model projects).
62
+ - `../event-modeling-shared/reference/methodology.md` — the 7 steps and 4 patterns (Event Modeling
63
+ methodology).
64
+ - `../event-modeling-shared/reference/em-dsl.md` — `em`'s DSL grammar, CLI reference, and the full
65
+ `em validate` rule catalog.
66
+ - `../event-modeling-shared/templates/*.md` — the slice/state/model-readme/conformance-report
67
+ templates every phase scaffolds from.
414
68
 
415
69
  ## em command reference (quick)
416
70
 
@@ -431,5 +85,5 @@ em watch <name>.em -o <name>.svg --serve # + the live browser viewer: instant
431
85
 
432
86
  Always finish a working session by: re-rendering, running `em validate`, and updating
433
87
  `.event-modeling.md` — `em state set-phase <phase> [--step <n>]` for the current phase/step,
434
- decisions and open questions by hand, and a Usage log entry (phases touched + validate
435
- diagnostic categories hit).
88
+ decisions and open questions by hand, and `em state log-usage <model>.em --phases <phases>` for
89
+ the Usage log entry.
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: event-modeling-conform
3
+ em-version: 1.9.0
4
+ description: >-
5
+ Use when checking a ratified event model (and its slice docs) for drift against the codebase
6
+ that implements it — advisory only, never a gate, never an unprompted edit — or when walking
7
+ `em validate` diagnostics on a model to explain and fix rule violations. Drives `em`'s conform
8
+ and validate phases.
9
+ ---
10
+
11
+ # Event Modeling — conform & validate
12
+
13
+ ## Phase: `conform` — drift check against the codebase
14
+
15
+ Goal: check a **ratified** model (and its slice docs) against the codebase that implements it,
16
+ and report where they've drifted — advisory only, never a gate, never an unprompted edit.
17
+
18
+ Preconditions (tool check, model location) are the same as every other phase — see
19
+ `../event-modeling-shared/reference/operating-principles.md`.
20
+
21
+ **Read `reference/conform.md` before doing any conform work** — it carries the full flow
22
+ (scope, evidence-first verification, `em diff --json`, classification, report) and the
23
+ stance guardrails (evidence-first, uncertainty is never drift, propose-don't-edit). It reuses
24
+ the `event-modeling-discover` skill's `extract` sourcing/mode rules
25
+ (`../event-modeling-discover/reference/extract.md`) for reading the target codebase rather than
26
+ duplicating them.
27
+
28
+ In short: run `em conform-scope <model-name>.em --repo <target-repo-path> --seed-asis` to
29
+ compute the in-scope slice set (diff-scoped by default, via `Last conformance:` + the target
30
+ repo's changed paths mapped through each slice doc's `implementedIn:`) and seed the scratch
31
+ model in one step; for each in-scope slice, gather code evidence *before* comparing to the model
32
+ or doc; write the as-is picture into that scratch model (`<model-name>-asis.em`, reusing the
33
+ canonical model's names wherever the code matches them); run `em diff <model-name>.em
34
+ <model-name>-asis.em --json` and let `em` decide the structural deltas; classify every finding
35
+ (real drift / model gap / internal inconsistency / uncertainty) with cited evidence; write
36
+ `conformance/<date>-report.md` with proposed `issue "conformance: …"` red notes; apply only the
37
+ proposals the user ratifies, then re-render and validate; run `em state set-conformance
38
+ <revision> --report <path>` to update the state file's `Last conformance:` marker.
39
+
40
+ End of phase: state file's `Last conformance:` marker updated (via `em state set-conformance`),
41
+ Decisions log entry if any
42
+ proposals were applied. Conform doesn't chain to another phase — it's a recurring loop, run
43
+ again whenever the codebase has moved.
44
+
45
+ ## Phase: `validate`
46
+
47
+ Run `em validate <model-name>.em` and walk through each diagnostic with the user, explaining the
48
+ rule (see `../event-modeling-shared/reference/em-dsl.md`) and proposing the fix. Apply fixes on
49
+ agreement. Common ones:
50
+
51
+ | Diagnostic | Fix |
52
+ |---|---|
53
+ | reaction triggers no command | Add the command it issues, in this same slice, or an explicit `arrow` to one elsewhere |
54
+ | **command has nothing that triggers it** | Add the `ui` it's issued from — or, if the system issues it, the reaction that triggers it, also in this slice. Ask *"who does this, and where are they when they do it?"* |
55
+ | **read model has no consumer** | Add the screen that displays it, or the reaction that watches it. If it's a repeat added only to shorten an arrow and nothing looks at it there, drop the instance |
56
+ | read model has no source | Add the missing `from "Event"` |
57
+ | command produces no event | Give the command its event, or drop the command |
58
+ | **event is not read by any read model** | Add the read slice that projects it — but ask *who looks at this and what do they do with it* first. "Nobody" is a real answer, and then the question is why it's recorded at all |
59
+ | **illegal `arrow` kind pair** | Don't reroute it — the model is missing an element. `command → view` needs the event between them; `view → command` needs a reaction. Between two instances of one read model, just delete the arrow: the repeat needs no connection |
60
+ | `view X again` with no earlier declaration | Declare the view plainly the first time it appears |
61
+ | event feeding an earlier view instance | Add a `view X again` where the event lands and move the source there |
62
+
63
+ For anything genuinely unresolved rather than a rule violation, prefer `issue "text"` on the
64
+ relevant element over a `# TBD` comment — it shows up as a red marker on the rendered diagram and
65
+ `em validate` tracks it as an open-issue warning, so it isn't lost once rendered. `em validate
66
+ --list-issues` gives a quick sweep of everything still open.
67
+
68
+ `em validate` now catches a reaction wired straight to an event too — any reaction with no
69
+ `command` in its own slice, and no explicit arrow to one, warns "triggers no command". A
70
+ `translation`/`processor`/`automation` should always trigger a `command` in its own slice
71
+ (`reaction → command → event`); if one instead records an event directly, route it through a
72
+ command instead.
73
+
74
+ Validate isn't pinned to this phase alone — every other phase runs it continuously as part of
75
+ the shared operating principles (`../event-modeling-shared/reference/operating-principles.md`).
76
+ This phase is for a dedicated, focused walkthrough of whatever diagnostics remain, and for the
77
+ full rule catalog in `../event-modeling-shared/reference/em-dsl.md`.