@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
@@ -3,7 +3,8 @@
3
3
  Read this **before doing any conform work**. It governs the `conform` phase: checking a
4
4
  **ratified** model (and its slice docs) against the codebase that is supposed to implement it,
5
5
  and reporting where they've drifted apart. Conform reuses `extract`'s sourcing/mode rules
6
- (`reference/extract.md`) for reading the target codebase rather than duplicating them — the
6
+ (the `event-modeling-discover` skill's `reference/extract.md`) for reading the target codebase
7
+ rather than duplicating them — the
7
8
  difference is what you do with what you find: extract *builds* a model from the code; conform
8
9
  *compares* code evidence against a model that already exists.
9
10
 
@@ -33,7 +34,7 @@ difference is what you do with what you find: extract *builds* a model from the
33
34
  ## Preconditions
34
35
 
35
36
  1. A canonical `.em` model with a state file (`.event-modeling.md`), reachable the same way the
36
- SKILL.md preconditions locate it.
37
+ shared preconditions locate it — see `../../event-modeling-shared/reference/operating-principles.md`.
37
38
  2. The slices you're about to check should be **implemented** — docs at `status: implemented`
38
39
  (or the status the user says corresponds to shipped code) for whichever slices are in scope.
39
40
  Checking a `draft` or `ready-to-implement` slice against code is a wasted walk — ratified or
@@ -57,11 +58,19 @@ named invariants, Given/When/Then scenarios). Conform checks all three surfaces
57
58
  |---|---|---|---|
58
59
  | **Structural** — `.em` ↔ code | slices/elements/fields/flow | `em` (deterministic) | `em diff --json` on canonical vs. an as-is scratch model |
59
60
  | **Spec** — slice doc ↔ code | field rules not enforced, named invariants (`INV-*`) without enforcement/test sites, GWT scenarios without test sites | you (judgment) | per-slice evidence walk: each checkable claim in the doc mapped to a code/test site by name (`INV-CHK-4` → its enforcement site + its test) |
60
- | **Internal** — slice doc ↔ `.em` | the doc's frontmatter (`pattern:`, `status:`) or its Command/Event/Read Model sections and field tables disagreeing with the model's own elements/fields | you (judgment, v1) | cross-check the doc's structured sections against the slice's model elements |
61
-
62
- The internal surface is deterministically checkable in principle (structured doc sections +
63
- `{ fields }` blocks) — promoting it to an `em validate` rule is a natural follow-up; file it as
64
- its own issue rather than growing this phase's scope. For now it's agent judgment, same as spec.
61
+ | **Internal** — slice doc ↔ `.em` | the doc's frontmatter `pattern:` or its Command/Event/Read Model sections and field tables disagreeing with the model's own elements/fields | `em` (deterministic) | `em validate`'s `doc-model-*` diagnostics, unconditionally in the default list |
62
+
63
+ The internal surface is deterministically checked by `em validate` itself (MIL-124) — four
64
+ diagnostics, always on, no flag needed: `doc-model-pattern-mismatch` (frontmatter `pattern:` vs.
65
+ the model's own classification), `doc-model-element-not-in-model` / `doc-model-element-not-in-doc`
66
+ (the doc's Command/Event/Read Model markers vs. the slice's actual elements, each direction), and
67
+ `doc-model-field-mismatch` (a matched Command/Event's field table vs. the model's `{ fields }`
68
+ block). Run `em validate <model-name>.em --json` and read each entry's `code`/`refs`/`message`
69
+ (`docs/validation.md#doc-model-consistency` documents exactly what each one checks and
70
+ when it stays silent — every rule is declare-gated, so a thin/draft doc doesn't nag); consume it
71
+ the same way step 3 below consumes `em diff --json` — parse the structured findings, don't
72
+ re-derive them by eye. Fold any that fire for an in-scope slice into that slice's internal-surface
73
+ findings for step 4's classification, citing the diagnostic directly as the evidence.
65
74
 
66
75
  **Internal inconsistency is its own class, not drift.** When a doc and the `.em` disagree with
67
76
  each other, neither one is "the code" — you don't know which is stale. Report it as internal
@@ -171,11 +180,13 @@ For each slice in scope:
171
180
  granularity than the `.em` declares — e.g. event fields documented only in a slice doc's
172
181
  table — are checked on the **spec surface** against the doc, not smuggled into the
173
182
  structural diff.
174
- 4. Cross-check the doc's header metadata and Command/Event/Read Model sections against the
175
- slice's actual `.em` elements and fields for the internal surface — this doesn't need code
176
- evidence, just doc-vs-`.em` reading. Narrative sections (Intent, Open Questions, notes)
177
- count too when the contradiction is unambiguous — a stale sentence that flatly contradicts
178
- the `.em` is an internal inconsistency; a vague or interpretable one is not a finding.
183
+ 4. Read the in-scope slice's `doc-model-*` findings straight off the `em validate --json` run
184
+ from precondition 4 (or re-run it here) — no code evidence needed, `em` already did the
185
+ doc-vs-`.em` comparison for frontmatter `pattern:` and the Command/Event/Read Model rosters
186
+ and field tables. The only judgment left on this surface is narrative sections `em validate`
187
+ can't parse (Intent, Open Questions, notes): count a contradiction here too when it's
188
+ unambiguous — a stale sentence that flatly contradicts the `.em` is an internal
189
+ inconsistency; a vague or interpretable one is not a finding.
179
190
 
180
191
  Do this for every in-scope slice before moving on to diffing. The evidence you record here is
181
192
  what every finding in the report will cite — file paths, not vibes.
@@ -229,7 +240,7 @@ structural findings) — a finding with no citation isn't ready to report.
229
240
  ### 5. Report + proposals
230
241
 
231
242
  Write `conformance/<YYYY-MM-DD>-report.md` in the model directory, from
232
- `templates/conformance-report.md`. For a real-drift or model-gap finding, propose a
243
+ `../../event-modeling-shared/templates/conformance-report.md`. For a real-drift or model-gap finding, propose a
233
244
  ready-to-apply red note — `issue "conformance: <text>"` on the right element, written out in
234
245
  the report exactly as it should be pasted into the `.em` — when a model-side marker is the
235
246
  right fix; when the fix is purely doc wording (or the finding is an internal inconsistency
@@ -253,6 +264,21 @@ the marker (nobody ratified the outcome), so the next run re-walks the same span
253
264
  `docs/ci.md`. If any proposals were ratified and applied, log a Decisions entry noting what
254
265
  changed and why.
255
266
 
267
+ **Superseding the report you just walked (MIL-164).** Once the user has ruled on this run's
268
+ findings, also run:
269
+
270
+ ```
271
+ em conform-supersede <model-name>.em conformance/YYYY-MM-DD-report.md --as-of <target-repo revision> --findings <spec>
272
+ ```
273
+
274
+ — stamping the report with a "superseded as of `<rev>`" banner so a later reader who finds it
275
+ (a search hit, a bookmark, a link from an old PR description) sees immediately that its
276
+ file:line citations describe an ancestor of the current model, not its current state. This is
277
+ what keeps a superseded report an honest piece of history rather than a silently-misleading
278
+ current view. `<spec>` names the finding number(s) this run's ruling covers (e.g. `"1-3"`); if
279
+ only some findings were ruled on this session, run it again later with the remaining numbers —
280
+ each call adds its own stamp rather than overwriting the last.
281
+
256
282
  ## Conventions
257
283
 
258
284
  - **Scratch model:** `<model-name>-asis.em`, written **next to** the canonical model (same
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: event-modeling-design
3
+ em-version: 1.9.0
4
+ description: >-
5
+ Use when structuring a draft event model into swimlanes and the four patterns (State Change,
6
+ State View, Automation, Translation), evaluating a model's structural completeness, or writing
7
+ implementation-ready deep slice documents (field tables, invariants, Given/When/Then scenarios,
8
+ error flows) for a model that already has its happy-path spine. Drives `em`'s model and slice
9
+ phases — the core modeling work between discovery and implementation.
10
+ ---
11
+
12
+ # Event Modeling — model & slice
13
+
14
+ You are facilitating the core modeling work: turning a draft happy-path spine into a
15
+ structurally complete, validated model, and then a deep implementation-ready spec per slice.
16
+ Your job is to **extract an accurate model from the user through Socratic questioning** — never
17
+ to invent the domain. You drive the `em` CLI to render the model live, and you produce
18
+ implementation-ready slice docs.
19
+
20
+ Read `../event-modeling-shared/reference/operating-principles.md` (preconditions, project
21
+ layout, the Socratic/validation discipline every phase follows) and
22
+ `../event-modeling-shared/reference/methodology.md` (the 7 steps + 4 patterns) before doing real
23
+ work — they are the source of truth. Run the preconditions there first: this phase expects a
24
+ draft model already exists (from `event-modeling-discover`'s `discover` or `extract` phase).
25
+
26
+ ## Phase: `model` — steps 5-7
27
+
28
+ Goal: a structurally complete, **validated** model with correct patterns and swimlanes.
29
+
30
+ 1. **Swimlanes & patterns (step 5).** Group events into **contexts** (bounded contexts /
31
+ aggregates) — ask which events share a consistency boundary and who owns them. Classify each
32
+ slice as one of the 4 patterns. **Share the slice between every automation or translation and
33
+ the command it triggers** (the reaction — processor/translation — together with the command
34
+ and event it produces; the read model it watches, if any, stays in the slice before). A
35
+ translation or automation is a reaction: it **triggers a command and never records an event
36
+ directly**. Add `translation` slices for external inputs (externally triggered: external →
37
+ translation → command → event, no slice before) and for the system reacting to its own state
38
+ (internally triggered: read model in the slice before → translation → command → event).
39
+ 2. **Elaborate scenarios — first pass (step 6).** For each slice, capture the happy-path
40
+ Given/When/Then and the obvious invariants as short notes. (The full spec is the `slice` phase
41
+ below.)
42
+ 3. **Evaluate completeness (step 7).** Walk the model: every slice is a **complete** pattern, not a
43
+ half-slice — **every command has something that triggers it**, every command emits an event,
44
+ **every event is read by a read model**, **every read model has a consumer**, every view has a
45
+ source, every UI is reachable, every connection is
46
+ one of the six legal pairs, and every automation **and** translation triggers a command (none
47
+ wired straight to an event, none with no command at all). Run `em validate` and resolve all
48
+ errors and warnings — it catches a reaction wired straight to an event too now (see
49
+ `../event-modeling-shared/reference/em-dsl.md`), so a clean run covers this case.
50
+ For an unread event, don't just bolt on a view to silence the warning: ask the user who looks at
51
+ this fact and what they do with it. The honest answers are "here's the read model we missed" or
52
+ "nobody — so why are we recording it", and both improve the model.
53
+
54
+ End of phase: render, update state (`em state set-phase slice`), continue with the `slice` phase
55
+ below to write implementation specs.
56
+
57
+ ## Phase: `slice` — deep slice documents
58
+
59
+ Goal: implementation-ready specs. Go slice by slice (let the user pick order, or follow the
60
+ timeline). Check `README.md`'s Slices table for what's already done (run `em slice index
61
+ <model-name>.em` first if it looks stale).
62
+
63
+ This is also where **branch / unhappy-path events** are discovered and added to the model — as a
64
+ slice's alternate/error flows surface (a rejection, removal, cancellation, decline, expiry), add
65
+ the corresponding event/slice to the `.em` and re-render. The happy-path spine from earlier
66
+ phases is the starting point, not the finished event set. **Every new event needs its reader too**
67
+ — a rejection or cancellation that nothing projects will warn, and usually the missing piece is
68
+ real (someone has to see that the request was declined).
69
+
70
+ For each slice:
71
+ 0. **Check for re-ratification first.** If `slices/<slice-name>.md` already exists with
72
+ `status: implemented`, this is a re-ratification, not fresh authoring: hold a Socratic
73
+ deep-dive on what changed (same rigor as step 1, scoped to the delta), update whichever
74
+ sections actually changed, then express the change as the `## Delta` section — fixed heading,
75
+ `### Added`/`Modified`/`Removed`/`Renamed` Requirement blocks each carrying its own scenarios
76
+ (see `../event-modeling-shared/templates/slice.md` and
77
+ `docs/slice-doc-schema.md#delta-section-grammar-and-lifecycle`)
78
+ — **overwriting** whatever the section held before, never appending to it. Then continue at
79
+ step 2 to bump `version` and flip `status` back to `ready-to-implement`, leaving
80
+ `implementedIn` naming the prior version's PR (intended drift signal, not a bug — see the
81
+ schema doc). Otherwise, this is first-time authoring: continue at step 1.
82
+ 1. Hold a Socratic deep-dive to fill every section of `../event-modeling-shared/templates/slice.md`:
83
+ intent, trigger/actor,
84
+ command + field table (types & rules), event(s) + payload (mark immutable facts), invariants
85
+ (give each a stable ID), Given/When/Then scenarios (happy path + rule boundaries + edge cases),
86
+ alternate/error flows (retries, idempotency, compensations), non-functional requirements
87
+ (security/authz, PII/compliance, performance/SLA), read models affected, open questions. Park
88
+ anything unresolved rather than guessing. If the slice lives in an existing codebase, Grep/Read
89
+ adjacent real sources (OpenAPI specs, DB migrations, existing DTOs/event classes in sibling
90
+ contexts) before finalizing field names/types or invariants — don't guess a shape that's
91
+ already defined elsewhere.
92
+ 2. **First-time authoring:** scaffold the doc mechanically rather than hand-writing the
93
+ frontmatter — `em slice new "<slice name>" --pattern <state-change|state-view|automation|
94
+ translation> --swimlane "<Persona> → <Context>" --wire <model>.em` writes `slices/<slice-name>.md`
95
+ (kebab-cased to match, via the same slugging `em` uses everywhere else) with the canonical
96
+ `schemaVersion`/`pattern`/`swimlane`/`status: draft`/`version: 1` frontmatter — exactly the
97
+ five keys `em export` and the readiness gate require, no more — and the `# Slice:` heading +
98
+ diagram-image stub already in place. `--wire` also inserts the `note
99
+ "slices/<slice-name>.md"` line straight into the `.em`, onto the slice's primary element (the
100
+ command for State Change, the view for State View, the processor for Automation, the
101
+ translation for Translation), matched by export key — see step 4 for when it refuses instead.
102
+ Both `--pattern` and `--swimlane` are required; an invalid `--pattern` is refused with the
103
+ valid choices listed. Never hand-type this block, and never fall back to a placeholder
104
+ pattern/swimlane to dodge the flags. Then fill in every judgment section below the stub from
105
+ step 1 (Intent, Command, Event(s), Invariants, Scenarios, ...) — the doc's prose is still
106
+ entirely hand-authored, only the frontmatter/heading scaffold and the `.em` wiring are
107
+ mechanized. Record the originating need (ticket/conversation link) in the Intent section when
108
+ one exists. When this doc exists because of a split, merge, or rename, add the matching
109
+ lineage key(s) by hand (`split-from`/`merged-from`/`superseded-by`, `<slice-key>@v<N>` grammar
110
+ — see `docs/slice-doc-schema.md` for the full schema; `em validate` catches a malformed one
111
+ after the fact, see the `lineage-*` rules below).
112
+ **Re-ratification (step 0):** the doc already exists, so `em slice new` doesn't apply here
113
+ (it refuses to overwrite an existing file without `--force`, and forcing would blow away the
114
+ doc's authored body) — run `em slice reratify <model>.em <slice-key>` instead: it bumps
115
+ `version` and flips `status` back to `ready-to-implement` in the existing frontmatter,
116
+ clearing any stale `ratifiedBy:`/`ratifiedOn:` from the prior version so a follow-up
117
+ `em slice ratify --by <name>` (if the team records that) applies cleanly.
118
+ 3. Render the slice's own diagram: `em render <model>.em --slice "<slice name>" -o
119
+ slices/<slice-name>.svg` (kebab-case, matching the doc's filename and the `![Diagram]` stub
120
+ `em slice new` already wrote) — redraws just this slice in its own canonical pattern shape.
121
+ 4. Confirm it's wired into the `.em`: `em slice new --wire` (step 2) already inserted the `note
122
+ "slices/<slice-name>.md"` line onto the slice's primary element's own declaration line — it
123
+ only ever edits that one line, and only when doing so is unambiguous, so it refuses (writing
124
+ NEITHER the doc nor the `.em` edit) rather than guess when the slice has zero or more than one
125
+ candidate element of the primary kind, or when that line already carries a `note` clause. On a
126
+ refusal, re-run step 2 without `--wire` — it prints the exact line to add, paste it onto the
127
+ slice's primary element by hand.
128
+ 5. Run `em slice index <model-name>.em` to regenerate `README.md`'s Slices table — the one
129
+ canonical slice index — from the model and the doc frontmatter you just wrote (status,
130
+ `implementedIn` once shipped). Never hand-edit the table; it's a generated block.
131
+ 6. Re-render and `em validate`.
132
+
133
+ When a slice is **ratified** — a human flips its `status` to `ready-to-implement` with every
134
+ open question resolved — it's ready to hand to an implementer. Confirm with
135
+ `em validate <model>.em --slice-ready <key>`, and point whoever (or whatever) implements it
136
+ at the `event-modeling-implement` skill.
137
+
138
+ End of phase: every slice that should exist has a doc, `README.md`'s Slices table is current,
139
+ and the model validates clean. Suggest `event-modeling-implement` for each ratified slice.
@@ -0,0 +1,89 @@
1
+ ---
2
+ name: event-modeling-discover
3
+ em-version: 1.9.0
4
+ description: >-
5
+ Use when starting a brand-new event model from scratch — greenfield discovery: brainstorming
6
+ past-tense events, storyboarding the happy path, finding the commands and read models — or when
7
+ extracting a current-state model from an EXISTING codebase or system (event-driven or
8
+ procedural). Drives `em`'s discover and extract phases; produces a draft or as-is `.em` model
9
+ ready for the model/slice phases (`event-modeling-design`).
10
+ ---
11
+
12
+ # Event Modeling — discover & extract
13
+
14
+ You are facilitating the start of an Event Modeling session. Your job is to **extract an
15
+ accurate model from the user through Socratic questioning** — never to invent the domain. You
16
+ drive the `em` CLI to render the model live.
17
+
18
+ Read `../event-modeling-shared/reference/operating-principles.md` (preconditions, project
19
+ layout, the Socratic/validation discipline every phase follows) and
20
+ `../event-modeling-shared/reference/methodology.md` (the 7 steps + 4 patterns) before doing real
21
+ work — they are the source of truth. Run the preconditions there first.
22
+
23
+ **Existing system?** Use the `extract` phase below. **New feature inside an existing codebase,
24
+ not a whole-system extraction?** Stay in `discover`, but before locking in command/event names,
25
+ Grep/Read adjacent real sources (OpenAPI specs, DB migrations, existing DTOs/event classes in
26
+ sibling contexts) rather than guessing conventions — same check the `slice` phase applies to
27
+ field tables (`event-modeling-design`).
28
+
29
+ ## Phase: `discover` — steps 1-4
30
+
31
+ Goal: a draft model of events, storyboard, commands, and views. Loose is OK; structure comes next.
32
+
33
+ 1. **Brainstorm events (step 1).** Ask the user to name everything that happens, as past-tense
34
+ facts. Probe for missed state changes. For each candidate, apply the **"is it an event?"
35
+ test** (`methodology.md` step 1 — the "would this wake the CEO at 3am" heuristic):
36
+ reject derived values (belong in a read model) and telemetry/activity (not business state).
37
+ Don't silently drop rejections — park them in the state file's Decisions log with why, so
38
+ they aren't re-proposed later. Capture the survivors as a flat list.
39
+ 2. **Plot / storyboard (step 2).** Order the events into the narrative. Identify **personas**
40
+ (actors) and the **UI** screens at each step. Add `persona` declarations and `ui` elements.
41
+ In a **headless/API** model there are no human personas or screens — identify the external
42
+ **callers** at each step instead; declare one persona per caller/role, and its `ui` boxes are
43
+ the API calls (see `methodology.md`).
44
+ 3. **Inputs (step 3).** For each event, find the **command** that causes it (imperative name).
45
+ Form `command → event` slices (State Change pattern). Every command needs a **trigger** in the
46
+ same breath: the screen the user issues it from (a `ui` in the slice), or — for the Automation
47
+ and Translation patterns — the reaction that triggers it, also in this slice. A command
48
+ nothing points at is a write nobody can start. *"Who does this, and where are they when they
49
+ do it?"*
50
+ 4. **Outputs (step 4).** Identify the **read models / views** consumers need and wire them with
51
+ `from "Event"` (State View pattern), each with the screen (or reaction) that consumes it — a
52
+ read model nothing displays is information dropped on the floor. In a **headless/API** model
53
+ the consumer is the caller persona's `ui` (the API query) — same as any screen. Read models are
54
+ **repeated** in each slice where they're read (use `view X again` after the first, each instance
55
+ with its own consumer) so the timeline flows (see `methodology.md`).
56
+ **Close the loop before leaving this step:** every event from step 3 must be read by at least one
57
+ read model. Walk the event list and ask, for each one, *"who looks at this, and what do they do
58
+ with it?"* An event with no answer is either missing its read model or shouldn't be recorded —
59
+ both are worth raising with the user rather than leaving dangling.
60
+
61
+ End of phase: write/refresh the `.em`, render it, update `.event-modeling.md` (steps done,
62
+ decisions, open questions — run `em state set-phase model` rather than hand-editing `Current
63
+ phase:`), and run `em slice index <model-name>.em` to seed `README.md`'s Slices table (every
64
+ slice already reads "no doc yet" — no slice docs exist until the `slice` phase writes them).
65
+ Tell the user they can stop here and resume with `/event-modeling` (or invoke
66
+ `event-modeling-design` directly).
67
+
68
+ ## Phase: `extract` — current-state model of an existing system
69
+
70
+ Goal: a faithful **current-state** model extracted from an existing system — the as-is sibling
71
+ of `discover` (it replaces discover; the model then proceeds to `model` as usual, in
72
+ `event-modeling-design`).
73
+
74
+ **Read `reference/extract.md` before doing any extract work** — it carries a stance override
75
+ that inverts methodology step 1 (capture how the system behaves *today*; never model desired
76
+ state).
77
+
78
+ - Two source modes, detected from the system itself and confirmed with the user:
79
+ **event-driven** (an event vocabulary already exists — schemas, topics, handlers) and
80
+ **procedural/monolith** (no event vocabulary — synthesize candidate events from behavior
81
+ and docs).
82
+ - Converge via a ~7-round confirm-and-clarify loop (one concern per round; render from round 2,
83
+ validate from round 4 — see the playbook).
84
+ - **Current-state-only:** park unknowns as `# TBD` comments in the `.em`, mirrored in the state
85
+ file's Open Questions — never guess intended design.
86
+
87
+ End of phase: validated as-is model; state file updated (source mode, rounds, decisions; `em
88
+ state set-phase model` for `Current phase:`); run `em slice index <model-name>.em` to seed
89
+ `README.md`'s Slices table; then hand off to `event-modeling-design` (steps 5-7).
@@ -23,8 +23,9 @@ reaction-shares-a-slice-with-its-command shape — still applies.
23
23
 
24
24
  ## Setup
25
25
 
26
- 1. Run the SKILL.md preconditions (tool check, model location). If no model exists yet, run
27
- `em scaffold <model-name>` (see SKILL.md's "Project layout this skill creates").
26
+ 1. Run the shared preconditions (tool check, model location) — see
27
+ `../../event-modeling-shared/reference/operating-principles.md`. If no model exists yet, run
28
+ `em scaffold <model-name>` (see that doc's "Project layout this skill creates").
28
29
  2. **Agree the scope line first**: which system, which part, what's out of bounds. Write it to
29
30
  the state file's Session inputs.
30
31
  3. Record in the state file: `Source mode` (after detection, below) and
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: event-modeling-implement
3
+ em-version: 1.9.0
4
+ description: >-
5
+ Use when building a single ratified event-modeling slice (status: ready-to-implement) into
6
+ merged, tested code — the one phase where the agent builds rather than facilitates. Gates on
7
+ readiness, treats the slice doc as the read-only spec, surfaces gaps instead of deciding them
8
+ silently, and requires tests traceable to the doc's invariants and scenarios.
9
+ ---
10
+
11
+ # Event Modeling — implement
12
+
13
+ Goal: turn a single `ready-to-implement` slice into merged, verified code — the one phase where
14
+ the agent builds rather than facilitates.
15
+
16
+ **Read `reference/implement.md` before doing any implement work and follow it as the
17
+ contract.** In short: gate on `em validate <model>.em --slice-ready <key>` (stop and hand
18
+ back if it fails — never edit the doc to make the gate pass); treat the slice doc as the
19
+ spec (read-only, except the merge-time `status`/`implementedIn` flip); surface every gap to
20
+ the user instead of deciding it silently; cover every `INV-<MNEMONIC>-n` and every scenario with
21
+ tests; in spec-kit projects, allocate via em-sdd-bridge (redirect mode) and never run
22
+ `/speckit.specify`.
23
+
24
+ That contract applies to any implementing agent, whether or not the session started from
25
+ `/event-modeling` — `em contract` prints it to stdout with no `.claude/` awareness required, for
26
+ an agent that can run a shell but isn't Claude Code.
27
+
28
+ If the project ships pattern-specific implementation skills (for example an Axon/DCB skill set
29
+ keyed on a slice doc's `pattern:` frontmatter), route by the slice's pattern and follow those —
30
+ `reference/implement.md` §2 explains where that hand-off happens.
31
+
32
+ Preconditions (tool check, model location) are the same as every other phase — see
33
+ `../event-modeling-shared/reference/operating-principles.md` — but this phase additionally
34
+ requires the target slice to already be ratified; if it isn't, stop and say so rather than
35
+ starting on unratified work.
36
+
37
+ End of phase: PR merged, slice doc flipped to `status: implemented` with `implementedIn`
38
+ filled, `em slice index <model-name>.em` run to refresh `README.md`'s Slices table. Implement
39
+ doesn't chain to another phase — run it once per ratified slice; `event-modeling-conform`'s
40
+ `conform` phase later checks the result against the model.
@@ -126,7 +126,7 @@ resolves the doc via the same note-binding join `--slice-ready` uses, is idempot
126
126
  with the same URL, and refuses (never silently overwrites) if the doc is already `implemented`
127
127
  with a different URL. Prefer it over hand-editing the doc's frontmatter.
128
128
 
129
- Then, if the project keeps a model README (from `templates/model-readme.md`), run
129
+ Then, if the project keeps a model README (from `../../event-modeling-shared/templates/model-readme.md`), run
130
130
  `em slice index <model-name>.em` so its generated Slices table reflects the new status and
131
131
  link — never hand-edit that table. The `implementedIn` link is what the `conform` phase later
132
132
  uses to anchor drift-checking — leaving it empty blinds the loop.
@@ -179,6 +179,7 @@ everything a spec holds. Don't introduce an intermediate spec document of your o
179
179
 
180
180
  Implementation isn't the end of the slice's story. On a cadence — or whenever someone asks —
181
181
  the `conform` phase checks implemented slices against the code, using the `implementedIn` link
182
- you recorded, and reports drift for humans to rule on (see `reference/conform.md`). Your two
182
+ you recorded, and reports drift for humans to rule on (see the `event-modeling-conform` skill's
183
+ `reference/conform.md`). Your two
183
184
  duties to that future loop are already behind you if you followed this doc: an accurate
184
185
  lifecycle flip, and zero silent decisions.
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: event-modeling-review
3
+ em-version: 1.9.0
4
+ description: >-
5
+ Use when starting em's live browser viewer (`em watch --serve`) so a team can watch a model
6
+ update in real time, or facilitating a SCHEDULED stakeholder walkthrough that steps through
7
+ slices one at a time in Review mode, capturing anything the room raises live as `issue "..."`
8
+ red notes. Drives `em`'s watch and review phases.
9
+ ---
10
+
11
+ # Event Modeling — watch & review
12
+
13
+ ## Phase: `watch` — live team view
14
+
15
+ Start the watcher with `--serve` in the background:
16
+ `em watch <model-name>.em -o <model-name>.svg --serve` (run_in_background). It re-renders on every
17
+ save and pushes an instant reload to the browser over Server-Sent Events. Tell the user to open the
18
+ URL it prints (e.g. `http://localhost:5173/?svg=<model-name>.svg`) and share their screen — updates
19
+ appear the moment you save, with no polling and no idle churn between edits.
20
+
21
+ The viewer navigates like a map — drag to pan, scroll/pinch to zoom, **Fit** to reset — and its
22
+ **Review mode** steps through slices one at a time (see the `review` phase below). A save that
23
+ fails to render never blanks the shared screen: the last good diagram stays up, an error banner
24
+ explains what went wrong, and the viewer recovers on its own at the next successful render.
25
+
26
+ ## Phase: `review` — stakeholder walkthrough
27
+
28
+ Goal: step a real stakeholder review session through the model slice by slice, one slice
29
+ spotlighted at a time, with any open questions the room raises captured live as `issue "..."`
30
+ red notes.
31
+
32
+ **Trigger: a real stakeholder review session is on the calendar — a scheduled use, not
33
+ speculation.** Don't propose this phase proactively; it exists for facilitated reviews with
34
+ non-engineer stakeholders in the room, not routine model editing.
35
+
36
+ Start the same live server as `watch`: `em watch <model-name>.em -o <model-name>.svg --serve`
37
+ (run_in_background). Open the printed URL, click **Review mode** in the header, and share the
38
+ screen. Use Prev/Next (or the left/right arrow keys) to step through slices in declaration
39
+ order — each one pans/zooms into view with everything else dimmed, so the room's attention
40
+ tracks one slice at a time.
41
+
42
+ **Live capture:** when a stakeholder raises something unresolved, add `issue "..."` to the
43
+ relevant element in the `.em` file and save — exactly the same mechanism `event-modeling-conform`
44
+ uses for any other issue. The browser updates over the existing SSE push within moments, without
45
+ losing the current slice or resetting review mode.
46
+
47
+ Wrap-up: run `em validate --list-issues` to sweep everything captured during the session and
48
+ walk each one with the user, same as any open issue. Update the state file's Participants
49
+ section with who attended, and run `em state set-review <date>` to set the `Last stakeholder
50
+ review:` marker (mirrors `Last conformance:`).
51
+
52
+ End of phase: state file's `Last stakeholder review:` marker updated, every issue captured
53
+ live triaged (resolved on the spot, moved to Open questions / parking lot, or left open on
54
+ purpose). Review doesn't chain to another phase — it's a recurring, scheduled activity like
55
+ `conform`, not a step in the discover → model → slice sequence.
56
+
57
+ Preconditions (tool check, model location) are the same as every other phase — see
58
+ `../event-modeling-shared/reference/operating-principles.md`.