@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.
- package/.claude/skills/event-modeling/SKILL.md +58 -404
- package/.claude/skills/event-modeling-conform/SKILL.md +77 -0
- package/.claude/skills/{event-modeling → event-modeling-conform}/reference/conform.md +39 -13
- package/.claude/skills/event-modeling-design/SKILL.md +139 -0
- package/.claude/skills/event-modeling-discover/SKILL.md +89 -0
- package/.claude/skills/{event-modeling → event-modeling-discover}/reference/extract.md +3 -2
- package/.claude/skills/event-modeling-implement/SKILL.md +40 -0
- package/.claude/skills/{event-modeling → event-modeling-implement}/reference/implement.md +3 -2
- package/.claude/skills/event-modeling-review/SKILL.md +58 -0
- package/.claude/skills/{event-modeling → event-modeling-shared}/reference/em-dsl.md +115 -83
- package/.claude/skills/{event-modeling → event-modeling-shared}/reference/methodology.md +6 -5
- package/.claude/skills/event-modeling-shared/reference/operating-principles.md +147 -0
- package/.claude/skills/{event-modeling → event-modeling-shared}/templates/model-readme.md +2 -2
- package/.claude/skills/{event-modeling → event-modeling-shared}/templates/slice.md +51 -8
- package/README.md +24 -4
- package/dist/catalog/build.js +9 -0
- package/dist/catalog/build.js.map +1 -1
- package/dist/catalog/docJoin.d.ts +15 -0
- package/dist/catalog/docJoin.js +8 -0
- package/dist/catalog/docJoin.js.map +1 -1
- package/dist/catalog/modelCollisionValidate.d.ts +22 -0
- package/dist/catalog/modelCollisionValidate.js +67 -0
- package/dist/catalog/modelCollisionValidate.js.map +1 -0
- package/dist/catalog/orphanedSliceDocValidate.d.ts +11 -0
- package/dist/catalog/orphanedSliceDocValidate.js +98 -0
- package/dist/catalog/orphanedSliceDocValidate.js.map +1 -0
- package/dist/catalog/sliceDoc.d.ts +15 -0
- package/dist/catalog/sliceDoc.js +18 -0
- package/dist/catalog/sliceDoc.js.map +1 -1
- package/dist/cli/changelogBuild.d.ts +12 -0
- package/dist/cli/changelogBuild.js +89 -0
- package/dist/cli/changelogBuild.js.map +1 -0
- package/dist/cli/ciInit.d.ts +42 -0
- package/dist/cli/ciInit.js +298 -0
- package/dist/cli/ciInit.js.map +1 -0
- package/dist/cli/conformSupersede.d.ts +32 -0
- package/dist/cli/conformSupersede.js +102 -0
- package/dist/cli/conformSupersede.js.map +1 -0
- package/dist/cli/coverage.d.ts +6 -1
- package/dist/cli/coverage.js +28 -3
- package/dist/cli/coverage.js.map +1 -1
- package/dist/cli/frontmatterSurgery.d.ts +28 -0
- package/dist/cli/frontmatterSurgery.js +66 -0
- package/dist/cli/frontmatterSurgery.js.map +1 -0
- package/dist/cli/markImplemented.js +6 -45
- package/dist/cli/markImplemented.js.map +1 -1
- package/dist/cli/ratify.d.ts +41 -0
- package/dist/cli/ratify.js +151 -0
- package/dist/cli/ratify.js.map +1 -0
- package/dist/cli/reratify.d.ts +33 -0
- package/dist/cli/reratify.js +137 -0
- package/dist/cli/reratify.js.map +1 -0
- package/dist/cli/skillCheck.d.ts +6 -0
- package/dist/cli/skillCheck.js +46 -0
- package/dist/cli/skillCheck.js.map +1 -1
- package/dist/cli/skillDirs.d.ts +15 -0
- package/dist/cli/skillDirs.js +34 -0
- package/dist/cli/skillDirs.js.map +1 -0
- package/dist/cli/skillSync.d.ts +10 -0
- package/dist/cli/skillSync.js +15 -0
- package/dist/cli/skillSync.js.map +1 -1
- package/dist/cli/sliceIndex.d.ts +3 -0
- package/dist/cli/sliceIndex.js +6 -2
- package/dist/cli/sliceIndex.js.map +1 -1
- package/dist/cli/sliceLink.d.ts +52 -0
- package/dist/cli/sliceLink.js +152 -0
- package/dist/cli/sliceLink.js.map +1 -0
- package/dist/cli/status.d.ts +261 -0
- package/dist/cli/status.js +536 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/usageLog.d.ts +75 -0
- package/dist/cli/usageLog.js +193 -0
- package/dist/cli/usageLog.js.map +1 -0
- package/dist/cli.js +501 -130
- package/dist/cli.js.map +1 -1
- package/dist/emit/freshnessJson.d.ts +6 -0
- package/dist/emit/freshnessJson.js +24 -0
- package/dist/emit/freshnessJson.js.map +1 -0
- package/dist/emit/json.d.ts +62 -8
- package/dist/emit/json.js +14 -3
- package/dist/emit/json.js.map +1 -1
- package/dist/emit/statusJson.d.ts +7 -0
- package/dist/emit/statusJson.js +39 -0
- package/dist/emit/statusJson.js.map +1 -0
- package/dist/emit/typespec.d.ts +26 -0
- package/dist/emit/typespec.js +356 -0
- package/dist/emit/typespec.js.map +1 -0
- package/dist/emit/usageReportJson.d.ts +3 -0
- package/dist/emit/usageReportJson.js +23 -0
- package/dist/emit/usageReportJson.js.map +1 -0
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +301 -11
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/rules.d.ts +13 -0
- package/dist/model/rules.js +20 -0
- package/dist/model/rules.js.map +1 -1
- package/dist/templates.d.ts +1 -1
- package/dist/templates.js +2 -2
- package/dist/util/markers.d.ts +16 -4
- package/dist/util/markers.js +23 -10
- package/dist/util/markers.js.map +1 -1
- package/package.json +2 -1
- /package/.claude/skills/{event-modeling → event-modeling-shared}/templates/conformance-report.md +0 -0
- /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.
|
|
3
|
+
em-version: 1.9.0
|
|
4
4
|
description: >-
|
|
5
|
-
Use when the user
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
`
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
##
|
|
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.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
|
435
|
-
|
|
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`.
|