@milehimikey/em 1.19.7 → 1.21.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 +1 -1
- package/.claude/skills/event-modeling-conform/SKILL.md +1 -1
- package/.claude/skills/event-modeling-conform/reference/conform.md +29 -1
- package/.claude/skills/event-modeling-design/SKILL.md +33 -7
- package/.claude/skills/event-modeling-discover/SKILL.md +2 -2
- package/.claude/skills/event-modeling-discover/reference/extract.md +12 -0
- package/.claude/skills/event-modeling-engagement/SKILL.md +1 -1
- package/.claude/skills/event-modeling-implement/SKILL.md +7 -2
- package/.claude/skills/event-modeling-implement/reference/implement.md +73 -6
- package/.claude/skills/event-modeling-review/SKILL.md +19 -7
- package/.claude/skills/event-modeling-shared/reference/em-dsl.md +57 -5
- package/.claude/skills/event-modeling-shared/reference/methodology.md +51 -2
- package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +2 -1
- package/.claude/skills/event-modeling-shared/templates/model-readme.md +10 -2
- package/.claude/skills/event-modeling-shared/templates/slice.md +12 -1
- package/.claude-plugin/marketplace.json +2 -2
- package/dist/catalog/build.js +6 -5
- package/dist/catalog/build.js.map +1 -1
- package/dist/catalog/coverage.d.ts +3 -0
- package/dist/catalog/coverage.js +12 -0
- package/dist/catalog/coverage.js.map +1 -1
- package/dist/catalog/docBadge.d.ts +16 -0
- package/dist/catalog/docBadge.js +50 -0
- package/dist/catalog/docBadge.js.map +1 -0
- package/dist/catalog/docLocate.d.ts +17 -0
- package/dist/catalog/docLocate.js +97 -0
- package/dist/catalog/docLocate.js.map +1 -0
- package/dist/catalog/docModelConsistencyValidate.js +9 -2
- package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
- package/dist/catalog/frontmatterCoherenceValidate.js +16 -1
- package/dist/catalog/frontmatterCoherenceValidate.js.map +1 -1
- package/dist/catalog/invTokens.d.ts +49 -0
- package/dist/catalog/invTokens.js +94 -0
- package/dist/catalog/invTokens.js.map +1 -0
- package/dist/catalog/orphanedSliceDocValidate.js +15 -10
- package/dist/catalog/orphanedSliceDocValidate.js.map +1 -1
- package/dist/catalog/pages.js +48 -1
- package/dist/catalog/pages.js.map +1 -1
- package/dist/catalog/readSliceDoc.js +5 -4
- package/dist/catalog/readSliceDoc.js.map +1 -1
- package/dist/catalog/scenarioQualityValidate.js +2 -2
- package/dist/catalog/scenarioQualityValidate.js.map +1 -1
- package/dist/catalog/scenarios.d.ts +4 -0
- package/dist/catalog/scenarios.js +4 -1
- package/dist/catalog/scenarios.js.map +1 -1
- package/dist/catalog/sliceDoc.d.ts +54 -1
- package/dist/catalog/sliceDoc.js +99 -2
- package/dist/catalog/sliceDoc.js.map +1 -1
- package/dist/catalog/sliceDocRender.d.ts +3 -0
- package/dist/catalog/sliceDocRender.js +295 -0
- package/dist/catalog/sliceDocRender.js.map +1 -0
- package/dist/catalog/sliceSections.d.ts +18 -1
- package/dist/catalog/sliceSections.js +38 -4
- package/dist/catalog/sliceSections.js.map +1 -1
- package/dist/cli/coverage.d.ts +13 -23
- package/dist/cli/coverage.js +51 -91
- package/dist/cli/coverage.js.map +1 -1
- package/dist/cli/defer.js +3 -2
- package/dist/cli/defer.js.map +1 -1
- package/dist/cli/ledgerCheck.js +11 -8
- package/dist/cli/ledgerCheck.js.map +1 -1
- package/dist/cli/markImplemented.js +2 -2
- package/dist/cli/markImplemented.js.map +1 -1
- package/dist/cli/ratify.js +2 -2
- package/dist/cli/ratify.js.map +1 -1
- package/dist/cli/refsCheck.d.ts +52 -0
- package/dist/cli/refsCheck.js +129 -2
- package/dist/cli/refsCheck.js.map +1 -1
- package/dist/cli/render-inputs.d.ts +1 -1
- package/dist/cli/render-inputs.js +3 -2
- package/dist/cli/render-inputs.js.map +1 -1
- package/dist/cli/review.js +2 -2
- package/dist/cli/review.js.map +1 -1
- package/dist/cli/revise.js +2 -2
- package/dist/cli/revise.js.map +1 -1
- package/dist/cli/skillDirs.d.ts +22 -0
- package/dist/cli/skillDirs.js +24 -0
- package/dist/cli/skillDirs.js.map +1 -1
- package/dist/cli/sliceConform.d.ts +57 -1
- package/dist/cli/sliceConform.js +111 -10
- package/dist/cli/sliceConform.js.map +1 -1
- package/dist/cli/sliceIndex.d.ts +19 -3
- package/dist/cli/sliceIndex.js +81 -17
- package/dist/cli/sliceIndex.js.map +1 -1
- package/dist/cli/sliceNew.js +2 -0
- package/dist/cli/sliceNew.js.map +1 -1
- package/dist/cli/sliceStubAll.js +7 -2
- package/dist/cli/sliceStubAll.js.map +1 -1
- package/dist/cli/sliceSync.d.ts +12 -0
- package/dist/cli/sliceSync.js +42 -4
- package/dist/cli/sliceSync.js.map +1 -1
- package/dist/cli/status.d.ts +3 -4
- package/dist/cli/status.js +5 -4
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/storylineSplit.d.ts +18 -0
- package/dist/cli/storylineSplit.js +110 -0
- package/dist/cli/storylineSplit.js.map +1 -0
- package/dist/cli/upgrade.js +39 -14
- package/dist/cli/upgrade.js.map +1 -1
- package/dist/cli/watchStoryline.d.ts +33 -0
- package/dist/cli/watchStoryline.js +65 -0
- package/dist/cli/watchStoryline.js.map +1 -0
- package/dist/cli.js +423 -71
- package/dist/cli.js.map +1 -1
- package/dist/emit/docJson.d.ts +99 -0
- package/dist/emit/docJson.js +197 -0
- package/dist/emit/docJson.js.map +1 -0
- package/dist/emit/json.d.ts +22 -1
- package/dist/emit/json.js +12 -1
- package/dist/emit/json.js.map +1 -1
- package/dist/emit/refsJson.d.ts +5 -3
- package/dist/emit/refsJson.js +5 -2
- package/dist/emit/refsJson.js.map +1 -1
- package/dist/mcp/server.js +43 -9
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/continuation.d.ts +9 -0
- package/dist/model/continuation.js +30 -0
- package/dist/model/continuation.js.map +1 -1
- package/dist/model/edges.d.ts +1 -1
- package/dist/model/edges.js +8 -1
- package/dist/model/edges.js.map +1 -1
- package/dist/model/loadModel.d.ts +38 -0
- package/dist/model/loadModel.js +122 -0
- package/dist/model/loadModel.js.map +1 -0
- package/dist/model/model.d.ts +9 -4
- package/dist/model/model.js +4 -0
- package/dist/model/model.js.map +1 -1
- package/dist/model/rules.d.ts +31 -0
- package/dist/model/rules.js +31 -0
- package/dist/model/rules.js.map +1 -1
- package/dist/model/shapeLint.js +143 -0
- package/dist/model/shapeLint.js.map +1 -1
- package/dist/model/sliceDocIndex.js +13 -5
- package/dist/model/sliceDocIndex.js.map +1 -1
- package/dist/model/sliceDocPath.d.ts +19 -0
- package/dist/model/sliceDocPath.js +49 -0
- package/dist/model/sliceDocPath.js.map +1 -0
- package/dist/model/storylineMap.d.ts +20 -0
- package/dist/model/storylineMap.js +55 -0
- package/dist/model/storylineMap.js.map +1 -0
- package/dist/model/validate.d.ts +7 -0
- package/dist/model/validate.js +127 -0
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/ast.d.ts +27 -0
- package/dist/parser/parser.d.ts +17 -1
- package/dist/parser/parser.js +142 -3
- package/dist/parser/parser.js.map +1 -1
- package/dist/pipeline.d.ts +16 -0
- package/dist/pipeline.js +19 -2
- package/dist/pipeline.js.map +1 -1
- package/dist/render/drawEdges.d.ts +5 -1
- package/dist/render/drawEdges.js +57 -4
- package/dist/render/drawEdges.js.map +1 -1
- package/dist/render/drawNotes.d.ts +4 -1
- package/dist/render/drawNotes.js +40 -10
- package/dist/render/drawNotes.js.map +1 -1
- package/dist/render/render.d.ts +11 -0
- package/dist/render/render.js +93 -10
- package/dist/render/render.js.map +1 -1
- package/dist/render/serve.d.ts +5 -0
- package/dist/render/serve.js +18 -2
- package/dist/render/serve.js.map +1 -1
- package/dist/render/sliceDiagram.js +3 -0
- package/dist/render/sliceDiagram.js.map +1 -1
- package/dist/render/sliceOverlay.d.ts +5 -1
- package/dist/render/sliceOverlay.js +24 -2
- package/dist/render/sliceOverlay.js.map +1 -1
- package/dist/render/sliceStatus.d.ts +8 -0
- package/dist/render/sliceStatus.js +22 -15
- package/dist/render/sliceStatus.js.map +1 -1
- package/dist/render/storylineBands.d.ts +0 -3
- package/dist/render/storylineBands.js +2 -22
- package/dist/render/storylineBands.js.map +1 -1
- package/dist/render/storylineDiagram.js +17 -69
- package/dist/render/storylineDiagram.js.map +1 -1
- package/dist/render/storylineMap.d.ts +18 -0
- package/dist/render/storylineMap.js +263 -0
- package/dist/render/storylineMap.js.map +1 -0
- package/dist/render/storylinePicker.d.ts +9 -0
- package/dist/render/storylinePicker.js +17 -0
- package/dist/render/storylinePicker.js.map +1 -0
- package/dist/render/svgGeometry.d.ts +9 -0
- package/dist/render/svgGeometry.js +16 -0
- package/dist/render/svgGeometry.js.map +1 -1
- package/dist/render/viewerHtml.js +1 -1
- package/dist/render/viewerHtml.js.map +1 -1
- package/dist/templates.d.ts +1 -1
- package/dist/templates.js +10 -2
- package/dist/templates.js.map +1 -1
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/shared/reference/em-dsl.md +57 -5
- package/plugin/shared/reference/methodology.md +51 -2
- package/plugin/shared/reference/slice-doc-schema.md +2 -1
- package/plugin/shared/templates/model-readme.md +10 -2
- package/plugin/shared/templates/slice.md +12 -1
- package/plugin/skills/conform/SKILL.md +1 -1
- package/plugin/skills/conform/reference/conform.md +29 -1
- package/plugin/skills/design/SKILL.md +33 -7
- package/plugin/skills/discover/SKILL.md +2 -2
- package/plugin/skills/discover/reference/extract.md +12 -0
- package/plugin/skills/engagement/SKILL.md +1 -1
- package/plugin/skills/event-modeling/SKILL.md +1 -1
- package/plugin/skills/implement/SKILL.md +7 -2
- package/plugin/skills/implement/reference/implement.md +73 -6
- package/plugin/skills/review/SKILL.md +19 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when the user runs `/event-modeling` (with or without a phase name), or wants to resume an
|
|
6
6
|
event-modeling session without specifying which part of the process applies. Reads the model's
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-conform
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when checking a ratified event model (and its slice docs) for drift against the codebase
|
|
6
6
|
that implements it — advisory only, never a gate, never an unprompted edit — or when walking
|
|
@@ -39,7 +39,9 @@ difference is what you do with what you find: extract *builds* a model from the
|
|
|
39
39
|
(or the status the user says corresponds to shipped code) for whichever slices are in scope.
|
|
40
40
|
Checking a `draft` or `ready-to-implement` slice against code is a wasted walk — ratified or
|
|
41
41
|
not, nobody has built to it yet; tell the user and skip it rather than reporting "drift"
|
|
42
|
-
against it.
|
|
42
|
+
against it. (GH #400: the ONE exception is a deliberate pre-ship advisory run — see
|
|
43
|
+
`--preview` under step 5 below — not a reason to treat this precondition as optional for an
|
|
44
|
+
ordinary post-ship sweep.)
|
|
43
45
|
3. The codebase to check: the state file's **Existing system refs** (populated during
|
|
44
46
|
`extract`, if this model came from one) or ask the user for the repo path if not set. Record
|
|
45
47
|
it if missing. In a headless/scheduled run with no user to ask, default to the repository
|
|
@@ -335,6 +337,32 @@ been through this) instead of just trusting `implementedIn`. Legal only for `sta
|
|
|
335
337
|
with a link, and itself refuses if an unruled finding for that slice still exists at this
|
|
336
338
|
revision — the mechanical proof this step comes only after rulings, not before.
|
|
337
339
|
|
|
340
|
+
**Pre-ship advisory mode: `--preview` (GH #400).** The certify step above is legal only for a
|
|
341
|
+
**shipped** slice (`status: implemented`/`shippedVersion:` + `implementedIn:`) — precondition 2
|
|
342
|
+
reflects that this phase ordinarily walks shipped code. `--preview` is the deliberate exception:
|
|
343
|
+
the SAME doc-resolution and findings-check read, legal for a slice that hasn't shipped yet
|
|
344
|
+
(the shipped/`implementedIn:` preconditions are waived), and it **never writes anything** —
|
|
345
|
+
no `conformedVersion`/`conformedAt`/`conformedOn`, ever, regardless of outcome:
|
|
346
|
+
|
|
347
|
+
```
|
|
348
|
+
em slice conform <model-name>.em <slice-key> --at <target-repo revision> --preview
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Use this to run a conform sweep against your OWN implementing branch before it merges — catching
|
|
352
|
+
spec/code drift while you can still fix it on the same branch, rather than after shipping. The
|
|
353
|
+
walk itself (steps 1-4 above) is unchanged; only the certify step's preconditions differ. Output
|
|
354
|
+
is ephemeral by default (nothing is written, not even to `conformance/`); pass
|
|
355
|
+
`--write-findings` to persist the run's own unruled findings as a normal
|
|
356
|
+
`conformance/<date>-<slice-key>-preview-findings.json` (this is deliberate — `docs/cli.md`'s
|
|
357
|
+
`em slice conform --preview` section documents the exact shape and naming). Know before opting
|
|
358
|
+
in: the written file has no sibling report (`report` is synthetic), so `em conform-supersede`
|
|
359
|
+
refuses to rule on it — unruled entries in it gate certify/`set-conformance` at that revision
|
|
360
|
+
until you rule them in the file by hand, delete the snapshot, or author the sibling report.
|
|
361
|
+
`em state set-conformance` and the unruled-findings gates are unaffected by
|
|
362
|
+
this mode either way: a default preview run writes nothing for them to read, so it can never
|
|
363
|
+
block a later certify or `set-conformance` call. There is no `--slice-ready` integration for this
|
|
364
|
+
mode yet.
|
|
365
|
+
|
|
338
366
|
End of run: update the state file's `Last conformance:` marker with
|
|
339
367
|
|
|
340
368
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-design
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when structuring a draft event model into swimlanes and the four patterns (State Change,
|
|
6
6
|
State View, Automation, Translation), evaluating a model's structural completeness, or writing
|
|
@@ -71,7 +71,13 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
|
|
|
71
71
|
optional `after "<storyline>"` timeline clause: `em-dsl.md`) so the diagram gets a band per
|
|
72
72
|
story and `em render --storyline "Name"` can show one alone; slices keep their file order, and
|
|
73
73
|
a model can adopt storylines incrementally (`slice-outside-storyline` is only an advisory
|
|
74
|
-
warning) — but name them before you slice, not after.
|
|
74
|
+
warning) — but name them before you slice, not after. **Once the storylines are named, give
|
|
75
|
+
each its own file** (GH #421): run `em storyline split <root>.em` so the root keeps the
|
|
76
|
+
vocabulary and the storyline list with its flow (`storyline "Name" [after "Other"]`) and each
|
|
77
|
+
story's slices live in `<slug>/<slug>.em` with its docs in `<slug>/slices/` — do this before any
|
|
78
|
+
doc is wired, so nothing moves twice. **A storyline that reads another story's events declares
|
|
79
|
+
`after` it** (`storyline-reads-without-after` flags the ones you miss); two stories that run in
|
|
80
|
+
parallel read nothing from each other. Then group events into **contexts** (bounded contexts /
|
|
75
81
|
aggregates) — ask which events share a consistency boundary and who owns them. Classify each
|
|
76
82
|
slice as one of the 4 patterns. **Share the slice between every automation or translation and
|
|
77
83
|
the command it triggers** (the reaction — processor/translation — together with the command
|
|
@@ -88,16 +94,29 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
|
|
|
88
94
|
shape — reshape it with the "Reshaping an existing model" checklist. Then the **intent test**
|
|
89
95
|
per command (would a business person say this name at this step in the story? an endpoint-shaped
|
|
90
96
|
name fails), the **question test** per view (write the question it answers; no question, no
|
|
91
|
-
read model; a child view only when its query needs what the parent view lacks),
|
|
97
|
+
read model; a child view only when its query needs what the parent view lacks), the
|
|
98
|
+
**views-as-lookups check** per `from "E"` on a view (does E add, change or remove a row here? if
|
|
99
|
+
it only fills a column, put the column on the event that creates the row and drop E — see
|
|
100
|
+
`../event-modeling-shared/reference/methodology.md`, "Views as lookups"), then the
|
|
101
|
+
**trigger / housekeeping split** on what is left (*which event is the reason this row appears?*
|
|
102
|
+
that one stays in `from`; every event that only keeps a row current or removes it moves to
|
|
103
|
+
`updates from` — the view still reads it, the diagram no longer draws it; a to-do list with more
|
|
104
|
+
than one or two inbound arrows is missing this split), the **continuation check** per `view X
|
|
105
|
+
again` (it names only the events that changed the view since the previous instance, never the
|
|
106
|
+
first instance's list again), and the
|
|
92
107
|
**conditional-invariant signal** (invariants or fields that apply only "if `<field>` is set"
|
|
93
|
-
mean two intents in one command: split it).
|
|
94
|
-
`
|
|
95
|
-
|
|
108
|
+
mean two intents in one command: split it). Read each story on its own render and on the canvas
|
|
109
|
+
(`em render <root>.em --map`), not on the full timeline. The `timeline-entity-clustered`,
|
|
110
|
+
`command-second-intent`, `automation-split-by-outcome`, `view-lookup-source`,
|
|
111
|
+
`again-restates-sources` and `storyline-reads-without-after` lints are the
|
|
112
|
+
mechanical half (the lookup one only catches the cross-context cases — do the check by eye too); the
|
|
113
|
+
design exit gate is `em validate --shape`. Shape the model first, scaffold docs after: a rename,
|
|
96
114
|
split or merge from the reshape would orphan docs already wired with `--wire`. The `slice` phase is unchanged (timeline order).
|
|
97
115
|
3. **Elaborate scenarios — first pass (step 6).** Scaffold every slice's doc now, one per
|
|
98
116
|
slice, none skipped: `em slice new "<slice name>" --pattern <state-change|state-view|
|
|
99
117
|
automation|translation> --swimlane "<Persona> → <Context>" --wire <model>.em` writes
|
|
100
|
-
`slices/<slice-name>.md` at `status: draft` (the
|
|
118
|
+
`slices/<slice-name>.md` at `status: draft` (into the slice's own storyline folder when the model
|
|
119
|
+
is split — pass the ROOT model to `--wire`) (the same command, flags, and `--wire`
|
|
101
120
|
note-binding the `slice` phase's step 2 below documents in full). A slice whose only element
|
|
102
121
|
is a `view X again` instance is a **continuation** (MIL-208), not a slice to scaffold —
|
|
103
122
|
`--wire` refuses it and names the originating slice holding `X`'s first declaration; its
|
|
@@ -130,6 +149,13 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
|
|
|
130
149
|
that reads it; another model/system reads it → mark it `public`; only an automation reads
|
|
131
150
|
it → nothing, it's internal by design. No new keyword — reachability is already what `ui` and
|
|
132
151
|
`public` mean.
|
|
152
|
+
**Per `view`, also ask whether each of its sources earns its place (GH #398):** for every
|
|
153
|
+
`from "E"` on the view, does E add, change or remove a row here — or only fill a column on a
|
|
154
|
+
row some other event already created? The latter is the views-as-lookups smell (methodology
|
|
155
|
+
reference, "Views as lookups"): drop E as a source and have the event that creates the row
|
|
156
|
+
carry the field instead. `view-lookup-source` flags the cross-context instances of this
|
|
157
|
+
mechanically; a lookup from the view's own context (no `@Context` mismatch to key on) only
|
|
158
|
+
this by-eye check catches.
|
|
133
159
|
**Per translation fed from another model, declare what it consumes (MIL-235):** write
|
|
134
160
|
`translation Order Intake consumes checkout:event.order-submitted`. The ref is
|
|
135
161
|
`<modelKey>:<kind>.<slug>`, where kind is `event` or `view` and the target is marked `public`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-discover
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when starting a brand-new event model from scratch — greenfield discovery: brainstorming
|
|
6
6
|
past-tense events, storyboarding the happy path, finding the commands and read models — or when
|
|
@@ -68,7 +68,7 @@ Goal: a draft model of events, storyboard, commands, and views. Loose is OK; str
|
|
|
68
68
|
**Close the loop before leaving this step:** every event from step 3 must be read by at least one
|
|
69
69
|
read model. Walk the event list and ask, for each one, *"who looks at this, and what do they do
|
|
70
70
|
with it?"* An event with no answer is either missing its read model or shouldn't be recorded —
|
|
71
|
-
both are worth raising with the user rather than leaving dangling.
|
|
71
|
+
both are worth raising with the user rather than leaving dangling. Keep the draft in one file with inline `storyline` blocks; the design phase splits it into one file per story (`em storyline split`) once the names are settled.
|
|
72
72
|
|
|
73
73
|
End of phase: write/refresh the `.em`, render it, update `.event-modeling.md` (steps done,
|
|
74
74
|
decisions, open questions — run `em state set-phase model` rather than hand-editing `Current
|
|
@@ -96,6 +96,18 @@ it is fine to finish a round with `# TBD`s still parked.
|
|
|
96
96
|
read model* warnings: real systems do record fire-and-forget events. In an as-is model that is
|
|
97
97
|
a **finding about the system**, not a modelling mistake — never invent a reader to silence it
|
|
98
98
|
(that would be desired state). Park it in the Decisions log and carry the warning.
|
|
99
|
+
**Expect lookup-style sources too.** A lifted model will faithfully reproduce the projection's
|
|
100
|
+
lookup joins — a view wired to `from "Order Created"` only because the current query joins the
|
|
101
|
+
orders table to get `customerName`, not because this view owns any row that event changes. Wire
|
|
102
|
+
it as-is (current-state-only stance: that join is how the system behaves today); don't fix it
|
|
103
|
+
here, that would be inventing desired state. Note it as a finding in the Decisions log the same
|
|
104
|
+
way as an unread event, and leave it for `model`/`slice` to apply the views-as-lookups rule
|
|
105
|
+
(`../../event-modeling-shared/reference/methodology.md`, "Views as lookups") once the as-is
|
|
106
|
+
model is agreed. **Housekeeping handlers are `updates from`, as-is:** when the projection code
|
|
107
|
+
handles an event only to update or delete a row it already holds (a status flip, a due date
|
|
108
|
+
moved, an address changed, a row removed), write that event in `updates from "…"`, not `from` —
|
|
109
|
+
that is what the code does today, it keeps the field tracing complete, and the as-is render then
|
|
110
|
+
shows the one line that puts work on the list instead of every handler.
|
|
99
111
|
- **R5 — Boundaries & reactions.** Current automations and integrations as-is: schedulers,
|
|
100
112
|
listeners, outbound syncs, inbound webhooks. Model each as a reaction sharing its slice with
|
|
101
113
|
the `command` + `event` it triggers (`reaction → command → event`, per `em-dsl.md`) — the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-engagement
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when leading an engagement: building a named set of ratified event-modeling slices
|
|
6
6
|
(`em engagement`) into one independent PR per slice, each against main, by dispatching the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-implement
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when building a single ratified event-modeling slice (status: ready-to-implement) into
|
|
6
6
|
merged, tested code — the one phase where the agent builds rather than facilitates. Gates on
|
|
@@ -52,7 +52,12 @@ routing table (§7) is what names the skill set for each pattern.
|
|
|
52
52
|
Preconditions (tool check, model location) are the same as every other phase — see
|
|
53
53
|
`../event-modeling-shared/reference/operating-principles.md` — but this phase additionally
|
|
54
54
|
requires the target slice to already be ratified; if it isn't, stop and say so rather than
|
|
55
|
-
starting on unratified work.
|
|
55
|
+
starting on unratified work. The one documented exception is **inline ratification** (GH #399,
|
|
56
|
+
`reference/implement.md` §1a): for an internal (non-public-touching, non-engagement) slice whose
|
|
57
|
+
doc is already `reviewed`, drafting code on the same branch ahead of the human's `em slice
|
|
58
|
+
ratify` is sanctioned — provided you never flip the gate yourself and re-confirm
|
|
59
|
+
`--slice-ready` reads `true` before treating the slice as done. `event-modeling-engagement` is
|
|
60
|
+
unchanged by this: it still requires every dispatched slice ratified before its branch is cut.
|
|
56
61
|
|
|
57
62
|
End of phase: PR merged, slice doc flipped to `status: implemented` with `implementedIn`
|
|
58
63
|
filled, `em slice index <model-name>.em` run to refresh `README.md`'s Slices table. Implement
|
|
@@ -46,15 +46,82 @@ A warning whose code is in this list blocks; any other warning never does — `c
|
|
|
46
46
|
|
|
47
47
|
Because of that list, `ready` can be `false` with every `gates` entry `true` (a `both-ends-of-a-flow/*` warning on one of the slice's own elements, say). Don't work it out from `gates`: read **`blockedBy`** (schema `1.5`, GH #377), the codes that flipped `ready`, `[]` exactly when it is `true`, and report those codes with the `false` gates when you hand the slice back.
|
|
48
48
|
|
|
49
|
-
**`ready: false` means stop** — with
|
|
50
|
-
with `driftSignal: in-sync` or `uncertified` (MIL-214) also reads `ready: false`
|
|
51
|
-
`statusReady` gate fails because nothing is newly ratified), and that specific case is
|
|
52
|
-
re-implementation/repair, not a blocker — see §3's third mode before treating it as one.
|
|
49
|
+
**`ready: false` means stop** — with two named exceptions. First: a slice already `status:
|
|
50
|
+
implemented` with `driftSignal: in-sync` or `uncertified` (MIL-214) also reads `ready: false`
|
|
51
|
+
(its `statusReady` gate fails because nothing is newly ratified), and that specific case is
|
|
52
|
+
re-implementation/repair, not a blocker — see §3's third mode before treating it as one. Second:
|
|
53
|
+
under **inline ratification** (§1a) a slice doc that's only `status: reviewed` — not yet
|
|
54
|
+
`ready-to-implement` — is a sanctioned starting point for drafting code on the SAME branch, with
|
|
55
|
+
the explicit, non-negotiable condition that you treat nothing as actually ratified, and open
|
|
56
|
+
nothing for merge, until a human has run `em slice ratify` and `--slice-ready` reads `true` for
|
|
57
|
+
real; §1a names exactly which slices qualify and what that condition requires in practice. For
|
|
53
58
|
every other `false`, report which `gates`
|
|
54
59
|
entries are `false` and what `blockedBy` names (and any `diagnostics` entries concerning this
|
|
55
60
|
slice) and hand the slice back to the humans. Never make the gate pass yourself — checking an open-question box, flipping
|
|
56
|
-
`status`, or editing frontmatter are ratification decisions,
|
|
57
|
-
|
|
61
|
+
`status`, or editing frontmatter are ratification decisions, made by a human in a ratification
|
|
62
|
+
session, never by you running `em slice ratify` on their behalf. That session is usually a
|
|
63
|
+
separate doc-only PR, merged before an implementation branch is even cut — but it doesn't have
|
|
64
|
+
to be: **inline ratification** (GH #399, §1a below) lets the session be the PR review of the
|
|
65
|
+
very branch you're implementing on, for internal slices. Either shape, the rule here is the
|
|
66
|
+
same: you never flip the gate yourself, whatever branch you're on.
|
|
67
|
+
|
|
68
|
+
### 1a. The inline variant: ratifying on the implementation branch
|
|
69
|
+
|
|
70
|
+
Most of this document assumes the ordinary shape — a slice is already `ready-to-implement` when
|
|
71
|
+
you start, ratified in its own prior PR, and §1's gate reads `true` before you write a line of
|
|
72
|
+
code. **Inline ratification** is the documented alternative
|
|
73
|
+
(`docs/process.md`'s
|
|
74
|
+
["Inline ratification" section](https://github.com/milehimikey/em/blob/main/docs/process.md#inline-ratification-approval-as-the-ratification-session)):
|
|
75
|
+
draft the slice doc *and* build it on the same branch, spec commits first, and let the human's
|
|
76
|
+
review of that one PR be the ratification session — which means you are, deliberately and
|
|
77
|
+
sanctioned, building for most of that branch's life against a doc that reads `ready: false`.
|
|
78
|
+
What doesn't change: you still never flip `status` yourself, never run `em slice ratify` on the
|
|
79
|
+
human's behalf, and never write a word of the ratification record — see §1's second named
|
|
80
|
+
exception for the precise condition this depends on. What's different is sequencing and tiering:
|
|
81
|
+
|
|
82
|
+
- **Draft the doc first, then build on the same branch.** Commit the slice doc (through the
|
|
83
|
+
normal `slice` phase), get it reviewed (`em slice review --by`, flipping it to `status:
|
|
84
|
+
reviewed` — a human has to do this part too, same as always) before any implementation code,
|
|
85
|
+
even though doc and code will both live on one branch and merge in one PR. Writing code before
|
|
86
|
+
the doc exists, or before a human has looked at it, is retrofit — the exact failure mode inline
|
|
87
|
+
mode is named after avoiding — whether or not anyone ever checks for it.
|
|
88
|
+
- **You may keep building past a `reviewed`-but-not-yet-`ready-to-implement` doc, but nothing is
|
|
89
|
+
ratified until `em slice ratify` actually runs.** `--slice-ready` keeps reading `false` the
|
|
90
|
+
whole time you're building — that's expected, not a signal to stop, as long as the doc's
|
|
91
|
+
`status` is `reviewed` (not `draft`: an un-reviewed doc is never a valid base, inline or not).
|
|
92
|
+
On an inline branch the human typically runs `em slice ratify --no-ref` as part of approving
|
|
93
|
+
the PR (`--no-ref` because the branch is headed for a squash/rebase merge) — not something you
|
|
94
|
+
do for them, and not something you should expect to have happened before the PR is up for
|
|
95
|
+
review. Before you report the slice done, or treat §6's merge-time flip as legitimate,
|
|
96
|
+
re-check `--slice-ready` yourself and confirm it now reads `true` with `ratifiedBy:` set — if
|
|
97
|
+
it still doesn't, the slice isn't ratified yet and you say so instead of proceeding.
|
|
98
|
+
- **A post-signature doc edit still trips the hash check.** `ratifiedHash` doesn't know or care
|
|
99
|
+
which branch it was computed on — if something changes the doc's body after the human has
|
|
100
|
+
signed it (a gap surfaces, §4), `--slice-ready` and `em slice ratify` both refuse the stale
|
|
101
|
+
signature exactly as they would across two PRs. Route it through `em slice revise --withdraw`,
|
|
102
|
+
review, re-ratify (§4) — inline doesn't shortcut that loop, it just means the re-sign happens
|
|
103
|
+
on the branch you're already on instead of a fresh one.
|
|
104
|
+
- **Not every slice is a candidate.** A slice owning a `public` command, event or view
|
|
105
|
+
(`isPublicTouchingSlice`) keeps the separate doc PR — the contract is a promise to consumers
|
|
106
|
+
who never see your implementation diff, and `em slice ratify` already refuses a public-touching
|
|
107
|
+
slice without `--meaning-unchanged`/`--contract-change` regardless of which branch it runs on.
|
|
108
|
+
An engagement-dispatched slice is never inline either — engagements structurally need every
|
|
109
|
+
contract frozen before any implementer branch is cut, so the engagement skill never offers you
|
|
110
|
+
this shape (it is explicitly unchanged by GH #399 — this is a note for your own judgment
|
|
111
|
+
outside an engagement, not something to apply inside one).
|
|
112
|
+
- **Pre-ship advisory conform is the loop's natural checkpoint.** Before the PR merges, a human
|
|
113
|
+
(or you, if asked) can run `em slice conform <model>.em <key> --at <rev> --preview` — the
|
|
114
|
+
pre-ship, non-certifying mode (GH #400): same doc-resolution and findings-check read as a real
|
|
115
|
+
certification, legal before the slice has shipped, never writes `conformedVersion:`/
|
|
116
|
+
`conformedAt:`/`conformedOn:`. It's advisory and ephemeral by default (nothing written unless
|
|
117
|
+
`--write-findings` is passed) — a cheap "did I just drift from the doc I signed" look before
|
|
118
|
+
asking for the PR review that will also be the ratification.
|
|
119
|
+
- **The ordering advisory is informational, not yours to act on.** `em refs --check-order`
|
|
120
|
+
(GH #399) can report whether a commit on this branch touched code before the doc's
|
|
121
|
+
`ratifiedRef` — a retrofit smoke signal for the human reviewing the PR. It's advisory, never a
|
|
122
|
+
gate, and nothing in this skill asks you to run it or react to its output; if a human shows you
|
|
123
|
+
a `code-before-ratification` result, treat it the same as any other gap raised against your
|
|
124
|
+
work (§4), not as something to silence.
|
|
58
125
|
|
|
59
126
|
## 2. Read the spec
|
|
60
127
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-review
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when starting em's live browser viewer (`em watch --serve`) so a team can watch a model
|
|
6
6
|
update in real time, or facilitating a SCHEDULED stakeholder walkthrough that steps through
|
|
@@ -15,8 +15,16 @@ description: >-
|
|
|
15
15
|
Start the watcher with `--serve` in the background:
|
|
16
16
|
`em watch <model-name>.em -o <model-name>.svg --serve` (run_in_background). It re-renders on every
|
|
17
17
|
save and pushes an instant reload to the browser over Server-Sent Events. Tell the user to open the
|
|
18
|
-
URL it prints
|
|
19
|
-
|
|
18
|
+
URL it prints and share their screen — updates appear the moment you save, with no polling and no
|
|
19
|
+
idle churn between edits.
|
|
20
|
+
|
|
21
|
+
What that URL opens depends on the model. A model that declares storylines opens on the
|
|
22
|
+
**storyline canvas** (`http://localhost:5173/map`): every storyline's own diagram in a draggable
|
|
23
|
+
frame, the flow between storylines drawn between frames, reloaded live on every save with the
|
|
24
|
+
layout kept. A frame's **open ›** drills into that storyline — the viewer on its own slices and
|
|
25
|
+
nothing from outside it — and **‹ Storylines** in the header returns to the canvas. A model
|
|
26
|
+
without storylines opens on the timeline (`http://localhost:5173/?svg=<model-name>.svg`). Never
|
|
27
|
+
send a room to the full timeline of a storyline model; the storyline is the unit people read.
|
|
20
28
|
|
|
21
29
|
The viewer navigates like a map — drag to pan, scroll/pinch to zoom, **Fit** to reset — and its
|
|
22
30
|
**Review mode** steps through slices one at a time (see the `review` phase below). A save that
|
|
@@ -34,10 +42,14 @@ speculation.** Don't propose this phase proactively; it exists for facilitated r
|
|
|
34
42
|
non-engineer stakeholders in the room, not routine model editing.
|
|
35
43
|
|
|
36
44
|
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
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
(run_in_background). Open the printed URL and share the screen. With storylines, review one
|
|
46
|
+
storyline at a time: open it from the canvas (or start inside it with `--storyline "<name>"`),
|
|
47
|
+
then click **Review mode** in the header — Prev/Next walk that storyline's slices only. Between
|
|
48
|
+
storylines, **‹ Storylines** returns to the canvas, where the arrows between frames are the
|
|
49
|
+
order to take them in. Without storylines, click **Review mode** on the timeline. Use Prev/Next
|
|
50
|
+
(or the left/right arrow keys) to step through slices in declaration order — each one
|
|
51
|
+
pans/zooms into view with everything else dimmed, so the room's attention tracks one slice at
|
|
52
|
+
a time.
|
|
41
53
|
|
|
42
54
|
**When a State View slice is on screen, ask who reads it (MIL-215):** a person or client in the
|
|
43
55
|
room → the `ui` should draw it; another system → `public`; only an automation → nothing, it's
|
|
@@ -22,12 +22,15 @@ em render <file> # transpile
|
|
|
22
22
|
em render <file> -o, --out <path> # output path (extension picks the format)
|
|
23
23
|
em render <file> -T, --format <fmt> # output format (svg, png, pdf, ...)
|
|
24
24
|
em render <file> --slice <name> # render only this slice, redrawn in its own canonical pattern shape (default out: slices/<kebab-slug>.svg)
|
|
25
|
-
em render <file> --storyline <name> # render only this storyline: its slices in order,
|
|
25
|
+
em render <file> --storyline <name> # render only this storyline: its own slices in order, nothing from outside it (default out: storylines/<kebab-slug>.svg)
|
|
26
|
+
em render <file> --map # render every storyline to storylines/<kebab-slug>.svg plus a draggable canvas of them all, with the flow between storylines, at storylines/map.html (-o picks the html path)
|
|
26
27
|
em render <file> --emit-dot # print the generated DOT instead of rendering
|
|
27
28
|
em render <file> --keep-empty-lanes # keep the API lane even when empty
|
|
28
29
|
em export <file> # export a versioned JSON snapshot of the normalized model
|
|
29
30
|
em export <file> -o, --out <path> # write to a file instead of stdout
|
|
30
31
|
em export <file> --slice <key> # export only this slice's object (pattern/fields/doc) instead of the whole model (export key, MIL-128) — refuses only if THIS slice has an error; an unrelated slice's breakage elsewhere in the model doesn't block it (see docs/cli.md)
|
|
32
|
+
em export <file> --doc-json # emit the structured slice-doc export (GH #401) instead of the model snapshot: per slice the frontmatter join plus the parsed sections as data (fields, invariants, scenarios, error flows, open questions) and a model-level invariant catalog. Own schema version; whole model only (does not combine with --slice)
|
|
33
|
+
em export <file> --include-html # with --doc-json, include each slice doc's rendered HTML body (excluded by default; the authored body never appears in a plain export)
|
|
31
34
|
em api generate <file> # write the TypeSpec contract for the model's public commands, events and views to <model dir>/contracts/<model key>.tsp
|
|
32
35
|
em api generate <file> -o, --out <path> # write to this path instead of <model dir>/contracts/<model key>.tsp
|
|
33
36
|
em api generate <file> --stdout # print the contract instead of writing it
|
|
@@ -68,6 +71,7 @@ em slice stub-all <file> --implemented-in <url> # PR/commit
|
|
|
68
71
|
em slice stub-all <file> --dry-run # list what would be stubbed/wired without writing anything
|
|
69
72
|
em slice index <file> # rewrite the model's sibling README.md's GENERATED Slices table from `em export`'s slice facts (key, pattern, doc status/implementedIn) — the hand-maintained table is deprecated
|
|
70
73
|
em slice index <file> --check # verify the table is current; exit non-zero on drift without writing (CI)
|
|
74
|
+
em slice index <file> --full # every lifecycle column (reviewed/ratified/owner/tracking/implemented/conformed) instead of the reader's five
|
|
71
75
|
em slice mark-implemented <file> <slice-key> <pr-url> # flip a slice doc's frontmatter to `status: implemented` / `implementedIn: <pr-url>` — the one edit an implementing agent makes to a ratified doc at merge (MIL-103, replaces the em-sdd-bridge `em-sdd-mark-implemented` script; see reference/implement.md §6). Applies only to a `ready-to-implement` doc (MIL-277: a `draft`/`reviewed` doc refuses — ratify first). Also records the shipped version beside the link (MIL-284): `shippedVersion:`, `shippedRef:` (the doc's `ratifiedRef:`, when it has one) and `shippedOn:`, and opens the next version as a `draft` when an Open Question was deferred to it (MIL-283). Idempotent on the same URL — also after that draft opened; refuses to overwrite a different one; never touches the doc body except to re-open those deferred questions
|
|
72
76
|
em slice mark-implemented <file> <slice-key> <pr-url> --on <date> # merge date recorded as `shippedOn:`, YYYY-MM-DD (default: today, local date; MIL-284)
|
|
73
77
|
em slice mark-implemented <file> <slice-key> <pr-url> --json # print a JSON document instead of text: { path, changed, implementedIn, nextDraft: { version, reopened[] } | null } (GH #285)
|
|
@@ -98,10 +102,13 @@ em slice defer <file> <slice-key> [question] --decision <text> # what this
|
|
|
98
102
|
em slice defer <file> <slice-key> [question] --from-issue <text> # defer a captured `issue "..."` on this slice instead of a doc Open Question (case-sensitive substring of its text)
|
|
99
103
|
em slice defer <file> <slice-key> [question] --by <name> # who deferred it
|
|
100
104
|
em slice defer <file> <slice-key> [question] --on <date> # deferral date, YYYY-MM-DD (default: today, local date)
|
|
101
|
-
em slice conform <file> <slice-key> # record per-slice-per-version conformance certification: sets `conformedVersion:`/`conformedAt:`/`conformedOn:` on a slice doc (MIL-214) — the fact `driftSignal: in-sync` now depends on. Legal only for a shipped slice (`status: implemented`, or any status with a `shippedVersion:` — MIL-283) with an `implementedIn:` link; `conformedVersion:` is the shipped version. Idempotent on the same (version, --at) pair; a different --at simply overwrites (a later re-certification is normal — there's no way for em to tell 'later' from 'earlier' for an arbitrary revision string, so there's no --force to reach for). Refuses when the conformance/<date>[-<name>]-findings.json file matching --at still has an unruled finding in scope for this slice; --skip-findings-check overrides with a loud notice.
|
|
105
|
+
em slice conform <file> <slice-key> # record per-slice-per-version conformance certification: sets `conformedVersion:`/`conformedAt:`/`conformedOn:` on a slice doc (MIL-214) — the fact `driftSignal: in-sync` now depends on. Legal only for a shipped slice (`status: implemented`, or any status with a `shippedVersion:` — MIL-283) with an `implementedIn:` link; `conformedVersion:` is the shipped version. Idempotent on the same (version, --at) pair; a different --at simply overwrites (a later re-certification is normal — there's no way for em to tell 'later' from 'earlier' for an arbitrary revision string, so there's no --force to reach for). Refuses when the conformance/<date>[-<name>]-findings.json file matching --at still has an unruled finding in scope for this slice; --skip-findings-check overrides with a loud notice. GH #400: --preview runs the same doc-resolution and findings-check read for a slice that hasn't shipped yet — the shipped/implementedIn gates are waived and NOTHING is ever written to the doc; output is ephemeral (text or --json) unless --write-findings opts into persisting a normal findings file.
|
|
102
106
|
em slice conform <file> <slice-key> --at <rev> # the target-repo revision this certification sweep diffed against — or, when what was exercised is not a commit that stays reachable (a per-PR environment under squash/rebase merges, a build or image), an opaque `<kind>:<id>` such as build:1234 or deploy:eu-1-2026-10-15 (GH #261); recorded verbatim, skipped by git-reachability checks
|
|
103
107
|
em slice conform <file> <slice-key> --on <date> # certification date, YYYY-MM-DD (default: today, local date)
|
|
104
108
|
em slice conform <file> <slice-key> --skip-findings-check # certify even with unruled findings in scope — prints a loud notice on stderr
|
|
109
|
+
em slice conform <file> <slice-key> --preview # GH #400: pre-ship advisory mode — waives the shipped-status/`implementedIn:` gates, writes NOTHING to the doc (no conformedVersion/conformedAt/conformedOn, ever); ephemeral by default, --write-findings opts into persisting a normal findings file. --skip-findings-check has no effect in this mode (preview never refuses on findings)
|
|
110
|
+
em slice conform <file> <slice-key> --write-findings # with --preview: persist the preview's own unruled findings as conformance/<on>-<slice-key>-preview-findings.json
|
|
111
|
+
em slice conform <file> <slice-key> --json # with --preview: print a JSON document instead of the text report
|
|
105
112
|
em changelog <file> # render a model's git history as a business-readable ledger (see docs/cli.md)
|
|
106
113
|
em changelog <file> --from <rev> # start the walk at this revision (inclusive)
|
|
107
114
|
em changelog <file> --to <rev> # end the walk at this revision (inclusive; default HEAD)
|
|
@@ -145,6 +152,7 @@ em watch <file> -T, --format <fmt> # output for
|
|
|
145
152
|
em watch <file> --keep-empty-lanes # keep the API lane even when empty
|
|
146
153
|
em watch <file> --serve # serve a live viewer with instant push-reload (no polling)
|
|
147
154
|
em watch <file> --port <n> # port for --serve (default 5173)
|
|
155
|
+
em watch <file> --storyline <name> # GH #309 (deferred from #277): filter the live view to one storyline's subset — the same subset `em render --storyline` draws (its own slices in order, plus dimmed stub columns for what they read from outside it and the `after` end state). Whenever the model declares any storylines the viewer also offers a picker to switch to the full model or another declared storyline, live, without restarting. An unknown name errors, listing the declared storylines; requires --serve
|
|
148
156
|
em validate <file> # check a model against event-modeling rules
|
|
149
157
|
em validate <file> --list-issues # print only open `issue` diagnostics (slice, element, line, text)
|
|
150
158
|
em validate <file> --list-divergences # print only accepted-divergence annotations (slice, element, line, text) — never fails the build
|
|
@@ -164,6 +172,7 @@ em refs <file> # check that
|
|
|
164
172
|
em refs <file> --reachable-from <rev> # the branch or commit every ref must be an ancestor of (e.g. origin/main)
|
|
165
173
|
em refs <file> --waive <slice-key> # excuse this slice's non-ancestor/unresolved/undecidable results from the exit code (repeatable); still reported
|
|
166
174
|
em refs <file> --waive-file <path> # a baseline file of slice keys to waive, one per line (`#` comments allowed); missing file = no waivers
|
|
175
|
+
em refs <file> --check-order # advisory-only (GH #399): for every slice doc with a ratifiedRef, report whether a commit between the branch's fork point and ratifiedRef already touched code other than the doc itself — a retrofit signal for inline ratification (spec written to describe code that already exists). History is rewritable, so this NEVER affects the exit code or `ok`, and is never a validate gate — see docs/process.md's inline-ratification section
|
|
167
176
|
em refs <file> --json # print a JSON document instead of the text report (see docs/cli.md)
|
|
168
177
|
em ledger <file> # check slice docs' version: field agrees with their content across two git revisions (opt-in CI check, MIL-89 — never part of `em validate`, see docs/ci.md)
|
|
169
178
|
em ledger <file> --from <rev> # baseline revision
|
|
@@ -268,15 +277,25 @@ em mcp # start an M
|
|
|
268
277
|
em skill install # copy the event-modeling skill bundle into .claude/skills/ (event-modeling, event-modeling-discover/-design/-implement/-conform/-review, event-modeling-shared); across a structural bundle change (e.g. the MIL-157 split of the old single event-modeling/ directory into this six-directory bundle), `em skill sync` is the migration path — --force now performs the same reconcile (MIL-180)
|
|
269
278
|
em skill install -f, --force # overwrite an existing installation, reconciling added/updated/removed files within the bundle's own managed directories the same way `em skill sync` does — never touching an unrelated sibling skill (MIL-180)
|
|
270
279
|
em skill install --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
|
|
280
|
+
em skill install --skills-dir <dir> # where the vendored skill bundle lives, relative to the repo root (default .claude/skills; .agents/skills when that exists and .claude/skills does not — GH #412)
|
|
281
|
+
em skill install --agents-dir <dir> # where the four em sub-agent definitions live, relative to the repo root (default .claude/agents, or .agents/agents beside an .agents/skills bundle — GH #412)
|
|
271
282
|
em skill sync [path] # update the vendored .claude/skills/ event-modeling skill bundle in [path] to match the installed em package (overwrites unconditionally; local edits are never merged, MIL-93)
|
|
272
283
|
em skill sync [path] --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
|
|
284
|
+
em skill sync [path] --skills-dir <dir> # where the vendored skill bundle lives, relative to the repo root (default .claude/skills; .agents/skills when that exists and .claude/skills does not — GH #412)
|
|
285
|
+
em skill sync [path] --agents-dir <dir> # where the four em sub-agent definitions live, relative to the repo root (default .claude/agents, or .agents/agents beside an .agents/skills bundle — GH #412)
|
|
273
286
|
em skill check [path] # check [path]'s em skills for drift against the installed em package: the em Claude Code plugin's pin (settings + this machine's marketplace registry) when the repo declares it, and the vendored .claude/skills/ bundle when present; exits non-zero on any mismatch (CI-ready, MIL-93, MIL-231)
|
|
274
287
|
em skill check [path] --json # print a JSON document instead of the text report (see docs/cli.md)
|
|
275
288
|
em skill check [path] --ci # also fail (exit 1) when the declared plugin is not registered on this machine (implied by CI=true in the environment); without it that finding prints the install commands on stderr and exits 0
|
|
289
|
+
em skill check [path] --skills-dir <dir> # where the vendored skill bundle lives, relative to the repo root (default .claude/skills; .agents/skills when that exists and .claude/skills does not — GH #412)
|
|
290
|
+
em skill check [path] --agents-dir <dir> # where the four em sub-agent definitions live, relative to the repo root (default .claude/agents, or .agents/agents beside an .agents/skills bundle — GH #412)
|
|
276
291
|
em ci init <model> # install .github/workflows/em-ci.yml (PR gates: em validate, em slice index --check, em coverage --strict, em ledger, em skill check, em glossary --fail-on-conflicts, plus a push-triggered status-badge rebuild) and em-conform.yml (scheduled, advisory-only conformance cadence) — same install discipline as `em skill install`: marker-delimited, idempotent, --check for CI self-verification (MIL-166, see docs/ci.md). Give it a system.yaml (or its directory) instead of a model to cover every model in the system: one workflow, per-model jobs, a conform matrix (MIL-233)
|
|
277
292
|
em ci init <model> --tests <dir> # test directory the coverage/status steps scan for INV-* citations
|
|
278
293
|
em ci init <model> -f, --force # replace an existing workflow file that has no GENERATED markers, or a managed block generated for a different set of models
|
|
279
294
|
em ci init <model> --check # verify both files match the current preset; exit non-zero on drift without writing (CI)
|
|
295
|
+
em storyline split <file> # move each inline `storyline "X" { … }` block into its own storyline model file <slug>/<slug>.em (a `storyline "X" [source]` header, then the block's slices) and leave the one-line declaration `storyline "X" [after "Y"]` in the root (GH #421). Slice docs stay under the root's slices/. A storyline declared in several blocks is left alone (merge them first)
|
|
296
|
+
em storyline split <file> --storyline <name> # split only this storyline
|
|
297
|
+
em storyline split <file> --dry-run # print what would be written without touching anything
|
|
298
|
+
em storyline split <file> -f, --force # overwrite a storyline model file that already exists
|
|
280
299
|
em storyline suggest <file> # advisory (GH #290): propose `storyline` blocks for a model that has none — one per distinct slice `source "url"`, the remaining slices grouped by the view-instance chains (`again`) they feed — printed as a unified diff on stdout (apply with `patch -p1` or `git apply`); never writes the model
|
|
281
300
|
em upgrade <file> # bring a model repo authored under an older em (1.6 forward) up to the installed version: an ordered list of mechanical steps (skill bundle, reaction shape, state-file bullets, generated CI blocks, constitution scaffold) plus a human list of things no command can safely decide by itself (MIL-219, see docs/upgrading.md). Dry-run by default; --apply makes one git commit per applicable step, refusing on a dirty working tree
|
|
282
301
|
em upgrade <file> --apply # apply every applicable mechanical step, one git commit each, then a final `Em version:` commit
|
|
@@ -303,12 +322,14 @@ context Name # an event swimlane row (bounded context / aggr
|
|
|
303
322
|
storyline "Name" [source "url"] [after "Other"] { # optional chapter grouping slices (see Storylines)
|
|
304
323
|
slice "Name" { ... }
|
|
305
324
|
}
|
|
325
|
+
storyline "Name" [after "Other"] [in "path.em"] # a storyline MODEL: its slices live in <slug>/<slug>.em (see Storylines)
|
|
306
326
|
|
|
307
327
|
slice "Name" [source "url"] { # one vertical time step (a column); source is optional
|
|
308
328
|
ui Free Text @Persona # screen; @Persona picks its row (defaults to first/"User")
|
|
309
329
|
command Free Text # state-changing request (API band)
|
|
310
330
|
invariant INV-ORD-1 "Rule" # rule guarding the command/event just above (see Clauses)
|
|
311
331
|
view Free Text from "Event A", "Event B" # read model fed by event(s)
|
|
332
|
+
view Free Text from "Event A" updates from "Event B", "Event C" # B, C keep rows current: read, never drawn (see Clauses)
|
|
312
333
|
view Free Text again from "Event C" # later instance of an evolving read model (see Clauses)
|
|
313
334
|
event Free Text @Context # recorded fact; @Context picks its row (defaults to "Domain")
|
|
314
335
|
processor Free Text from "View" # automation; aliases: automation | saga | translation
|
|
@@ -352,6 +373,14 @@ type Name { field: Type, ... } # named structured type, reusable from any f
|
|
|
352
373
|
previous instance of V that also reads E), and EVERY site needs a reader at or after it (add `view V again from "E"`
|
|
353
374
|
after the last site, or `event-unread` warns for that site). The same name in a different context
|
|
354
375
|
is still a `duplicate-name` warning.
|
|
376
|
+
- **`updates from "Event", …`** (views only, GH #414): the subset of a view's sources that only keep a
|
|
377
|
+
row current or remove it (a due date moved, an address changed, a loan returned). They are folded
|
|
378
|
+
into the view's `from` for every check — `derived from`, completeness, the generated built-from
|
|
379
|
+
list — but never drawn as arrows: the diagram shows the line from the event that puts work on the
|
|
380
|
+
list, and lists the rest under "Kept current by". The author chooses the triggers: `view Holds To
|
|
381
|
+
Fulfill from "Hold Placed", "Tool Returned" updates from "Hold Collected", "Hold Cancelled"`.
|
|
382
|
+
Valid on an `again` instance too. A to-do view with more than one or two inbound arrows is missing
|
|
383
|
+
this split.
|
|
355
384
|
- **`again`** (views only): `view <Name> again [from "Event", …]` declares a later instance of an
|
|
356
385
|
already-declared read model — the forward-only device for a view that evolves as later events
|
|
357
386
|
land. Instances are ONE logical view: the first declaration owns the `note` binding; each
|
|
@@ -489,7 +518,19 @@ type Name { field: Type, ... } # named structured type, reusable from any f
|
|
|
489
518
|
declared `type T`, with `derived from "Child Created", "Child Deleted"`, embeds a child entity:
|
|
490
519
|
each field of `T` must trace to a named event (`fields-completeness/view-field-no-source`
|
|
491
520
|
otherwise); a field also traces one level through the declared element type of an array field
|
|
492
|
-
on the event (`optionValues: VariantOptionValue[]`), no deeper
|
|
521
|
+
on the event (`optionValues: VariantOptionValue[]`), no deeper by same name. When the event
|
|
522
|
+
renamed or flattened the field, declare the element field's source by **path** into the named
|
|
523
|
+
event, as the unquoted form of the same clause (GH #383): `attributeValueIds: string[] derived
|
|
524
|
+
from values[].attributeValueId` — a `.`-joined chain of identifiers, each `[]`-suffixed exactly
|
|
525
|
+
when it steps through an array field (the marker is enforced against the event field's actual
|
|
526
|
+
arrayness). The path must resolve on a named event — every named event is tried; non-leaf
|
|
527
|
+
segments must be `type`-valued fields — and the leaf field's type must match the element
|
|
528
|
+
field's (array markers stripped); an unresolved path or leaf-type mismatch is
|
|
529
|
+
`fields-completeness/view-field-no-source` (implicit same-name nested tracing matches names
|
|
530
|
+
only; the explicit path form earns the stronger leaf-type check). The quoted event-list form
|
|
531
|
+
and the unquoted path form are mutually exclusive on one field — both at once is a parse error.
|
|
532
|
+
A plain (non-collection) view field may carry the same path form, checked the same way against
|
|
533
|
+
the view's source events — never silently exempt like a bare `derived` field. An
|
|
493
534
|
element field the projection computes rather than copies (an audit stamp from event metadata,
|
|
494
535
|
say) is marked `derived` on the `type` field itself — bare or `derived from "<events>"`, same
|
|
495
536
|
syntax as a view field (GH #382): it is then skipped by `view-field-no-source`, and a traced
|
|
@@ -530,8 +571,15 @@ type Name { field: Type, ... } # named structured type, reusable from any f
|
|
|
530
571
|
Slices keep their file-order timeline position; a slice outside any storyline is allowed;
|
|
531
572
|
storylines don't nest and a repeated name continues that storyline (its slices join it; a continuation may not add or change
|
|
532
573
|
`source`/`after` — parse error). The full render draws a
|
|
533
|
-
labelled band above the slice headers; `em render --storyline "Name"` draws one story alone
|
|
534
|
-
|
|
574
|
+
labelled band above the slice headers; `em render --storyline "Name"` draws one story alone — its own
|
|
575
|
+
slices only, nothing from outside it — and `em render <root>.em --map` puts every story's real
|
|
576
|
+
diagram on one draggable canvas with the flow between stories (`after` thick, reads dashed and
|
|
577
|
+
labelled). **Storyline models (GH #421):** `storyline "Name" [after "Other"] [in "path.em"]` with no
|
|
578
|
+
body declares a storyline whose slices live in `<slug>/<slug>.em` — a file that starts with
|
|
579
|
+
`storyline "Name" [source "url"]` and holds slice blocks only — with its docs in `<slug>/slices/`;
|
|
580
|
+
the root is the compile unit (always give em the root), and `em storyline split <root>.em` turns
|
|
581
|
+
inline blocks into files, moving each story's docs. A storyline that reads another declares `after`
|
|
582
|
+
it (`storyline-reads-without-after`). `em export` carries `slice.storyline` and
|
|
535
583
|
`model.storylines[]`; `em query slices --storyline`; `em slice index` adds a Storyline column. Once
|
|
536
584
|
any storyline exists a slice outside every one is the advisory warning `slice-outside-storyline`.
|
|
537
585
|
`after "<other>"` reads the storyline as if its slices followed the referenced storyline's last
|
|
@@ -857,6 +905,7 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
857
905
|
<!-- GENERATED:validate-rules:start -- run `npm run docs:generate` to refresh, do not hand-edit -->
|
|
858
906
|
| Code | Severity | Title | Fix |
|
|
859
907
|
|---|---|---|---|
|
|
908
|
+
| `again-restates-sources` | warning | Continuation restates sources an earlier instance already read | Name only the events that changed the view since the previous instance on the `again` line; the view's field sources are the union across instances, so nothing is lost (docs/dsl.md#view--again). |
|
|
860
909
|
| `alternative-events-no-command` | error | Alternative events without a command | Add the command whose decision records one of the alternatives, in the same slice. |
|
|
861
910
|
| `arrow-backward` | error | Backward arrow | Restructure so the target comes later. |
|
|
862
911
|
| `arrow-unresolved-source` | error | Arrow source unresolved | Fix the arrow's source name. |
|
|
@@ -897,6 +946,7 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
897
946
|
| `fields-completeness/view-field-no-source` | warning | View field with no source | Add the field to a source event, or remove it from the view. |
|
|
898
947
|
| `frontmatter-coherence-implemented-without-link` | warning | Implemented without a link | Add `implementedIn` once the slice ships. |
|
|
899
948
|
| `frontmatter-invalid` | warning | Invalid or missing frontmatter | Add the required frontmatter keys, or add a frontmatter block. |
|
|
949
|
+
| `frontmatter-status-unrecognized` | warning | Unrecognized slice status | Set `status:` to one of draft, reviewed, ready-to-implement, implemented. |
|
|
900
950
|
| `grid-collision` | error | Band collision | Split the colliding elements into separate slices. |
|
|
901
951
|
| `invariant-without-scenario` | warning | Invariant cited by no scenario | Cite the INV id in the Given/When/Then (or title) of the scenario that exercises it, or add one. |
|
|
902
952
|
| `invariants/declared-in-both` | warning | Invariant declared in the model and in a slice doc | Keep the model's `invariant` line; in the doc, cite the ID and elaborate instead of restating it as a `**INV-…:**` rule. |
|
|
@@ -940,6 +990,7 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
940
990
|
| `storyline-after-cycle` | error | Storyline `after` cycle | Remove an `after` clause so no storyline comes after itself. |
|
|
941
991
|
| `storyline-after-out-of-order` | error | Backward timeline (storyline declared above the one it comes after) | Move the storyline block below the storyline it comes `after`, or restructure the feed. |
|
|
942
992
|
| `storyline-after-unknown` | error | `after` names an unknown storyline | Name a storyline declared in this model, or drop the `after` clause. |
|
|
993
|
+
| `storyline-reads-without-after` | warning | Storyline reads another without declaring `after` it | Add `after "<the storyline it reads>"` to the reading storyline (or to one between them); if the two stories are parallel on purpose, accept it on the shape exit gate (docs/storyline.md). |
|
|
943
994
|
| `system-manifest-invalid` | error | Seam manifest invalid | Fix the manifest: `systemSchemaVersion: "2.0"`, `models:` with a readable `source` per model, and nothing else (`seams:`/`owner:` moved into the models — run `em upgrade`). |
|
|
944
995
|
| `system-manifest-outdated` | warning | Seam manifest is schema 1.0 | Run `em upgrade <model>.em --apply` once: it moves `seams:` into `consumes` clauses and `owner:` onto each model header, and rewrites the manifest to 2.0. |
|
|
945
996
|
| `system-model-key-mismatch` | error | Manifest model key differs from the export's `model.key` | Rename the manifest's `models:` key to the computed key the message prints. |
|
|
@@ -954,6 +1005,7 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
954
1005
|
| `view-again-without-earlier` | error | `again` without an earlier declaration | Declare the view plainly the first time it appears. |
|
|
955
1006
|
| `view-from-future-event` | error | Backward timeline (view reads a future event) | Move the source to a later `view X again` instance. |
|
|
956
1007
|
| `view-from-unresolved` | error | Unknown event source | Fix the `from` reference to name an existing event. |
|
|
1008
|
+
| `view-lookup-source` | warning | View reads an event only as a lookup | Carry the field on the event that creates this view's own row instead; if this is a genuine cross-context row change, accept it on the shape exit gate (docs/validation.md#the-shape-exit-gate) rather than fixing it (docs/patterns.md#state-view). |
|
|
957
1009
|
| `view-no-source` | warning | Read model without source | Add `from "Event"`, or place the view in a slice with an event. |
|
|
958
1010
|
<!-- GENERATED:validate-rules:end -->
|
|
959
1011
|
|