@milehimikey/em 1.9.1 → 1.11.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 +5 -1
- package/.claude/skills/event-modeling-design/SKILL.md +31 -12
- package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
- package/.claude/skills/event-modeling-implement/SKILL.md +14 -3
- package/.claude/skills/event-modeling-implement/reference/implement.md +73 -6
- package/.claude/skills/event-modeling-review/SKILL.md +14 -3
- package/.claude/skills/event-modeling-shared/reference/em-dsl.md +110 -11
- package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +4 -1
- package/.claude/skills/event-modeling-shared/templates/constitution.md +111 -0
- package/.claude/skills/event-modeling-shared/templates/model-readme.md +2 -2
- package/.claude/skills/event-modeling-shared/templates/slice.md +4 -0
- package/README.md +8 -1
- package/dist/catalog/docJoin.d.ts +8 -0
- package/dist/catalog/docJoin.js +4 -0
- package/dist/catalog/docJoin.js.map +1 -1
- package/dist/catalog/sliceDoc.d.ts +8 -0
- package/dist/catalog/sliceDoc.js +2 -0
- package/dist/catalog/sliceDoc.js.map +1 -1
- package/dist/cli/ciInit.d.ts +10 -3
- package/dist/cli/ciInit.js +22 -14
- package/dist/cli/ciInit.js.map +1 -1
- package/dist/cli/ledgerCheck.d.ts +72 -0
- package/dist/cli/ledgerCheck.js +122 -1
- package/dist/cli/ledgerCheck.js.map +1 -1
- package/dist/cli/ratify.d.ts +37 -5
- package/dist/cli/ratify.js +106 -9
- package/dist/cli/ratify.js.map +1 -1
- package/dist/cli/reratify.js +14 -5
- package/dist/cli/reratify.js.map +1 -1
- package/dist/cli/review.d.ts +38 -0
- package/dist/cli/review.js +160 -0
- package/dist/cli/review.js.map +1 -0
- package/dist/cli/sliceIndex.d.ts +3 -0
- package/dist/cli/sliceIndex.js +5 -4
- package/dist/cli/sliceIndex.js.map +1 -1
- package/dist/cli/stateFile.d.ts +10 -0
- package/dist/cli/stateFile.js +14 -0
- package/dist/cli/stateFile.js.map +1 -1
- package/dist/cli/status.d.ts +44 -3
- package/dist/cli/status.js +75 -18
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/systemInputs.d.ts +34 -0
- package/dist/cli/systemInputs.js +129 -0
- package/dist/cli/systemInputs.js.map +1 -0
- package/dist/cli.js +362 -23
- package/dist/cli.js.map +1 -1
- package/dist/emit/freshnessJson.d.ts +1 -1
- package/dist/emit/freshnessJson.js +5 -1
- package/dist/emit/freshnessJson.js.map +1 -1
- package/dist/emit/json.d.ts +37 -1
- package/dist/emit/json.js +67 -1
- package/dist/emit/json.js.map +1 -1
- package/dist/emit/ledgerJson.d.ts +1 -1
- package/dist/emit/ledgerJson.js +6 -1
- package/dist/emit/ledgerJson.js.map +1 -1
- package/dist/emit/queryJson.d.ts +6 -0
- package/dist/emit/queryJson.js +33 -0
- package/dist/emit/queryJson.js.map +1 -0
- package/dist/emit/statusJson.d.ts +1 -1
- package/dist/emit/statusJson.js +5 -1
- package/dist/emit/statusJson.js.map +1 -1
- package/dist/emit/systemJson.d.ts +8 -0
- package/dist/emit/systemJson.js +38 -0
- package/dist/emit/systemJson.js.map +1 -0
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +195 -9
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/edges.d.ts +28 -1
- package/dist/model/edges.js +77 -15
- package/dist/model/edges.js.map +1 -1
- package/dist/model/model.d.ts +6 -0
- package/dist/model/model.js +2 -0
- package/dist/model/model.js.map +1 -1
- package/dist/model/qualifiedRef.d.ts +47 -0
- package/dist/model/qualifiedRef.js +100 -0
- package/dist/model/qualifiedRef.js.map +1 -0
- package/dist/model/queryIndex.d.ts +53 -0
- package/dist/model/queryIndex.js +114 -0
- package/dist/model/queryIndex.js.map +1 -0
- package/dist/model/rules.d.ts +88 -0
- package/dist/model/rules.js +101 -0
- package/dist/model/rules.js.map +1 -1
- package/dist/model/sliceDocIndex.d.ts +30 -0
- package/dist/model/sliceDocIndex.js +110 -0
- package/dist/model/sliceDocIndex.js.map +1 -0
- package/dist/model/validate.js +85 -11
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/ast.d.ts +25 -0
- package/dist/parser/parser.d.ts +2 -0
- package/dist/parser/parser.js +104 -34
- package/dist/parser/parser.js.map +1 -1
- package/dist/query/format.d.ts +8 -0
- package/dist/query/format.js +80 -0
- package/dist/query/format.js.map +1 -0
- package/dist/query/pipeline.d.ts +17 -0
- package/dist/query/pipeline.js +38 -0
- package/dist/query/pipeline.js.map +1 -0
- package/dist/query/system.d.ts +60 -0
- package/dist/query/system.js +87 -0
- package/dist/query/system.js.map +1 -0
- package/dist/query/verbs.d.ts +100 -0
- package/dist/query/verbs.js +306 -0
- package/dist/query/verbs.js.map +1 -0
- package/dist/render/drawEdges.js +15 -4
- package/dist/render/drawEdges.js.map +1 -1
- package/dist/render/drawNotes.d.ts +13 -3
- package/dist/render/drawNotes.js +96 -20
- package/dist/render/drawNotes.js.map +1 -1
- package/dist/render/render.js +6 -5
- package/dist/render/render.js.map +1 -1
- package/dist/render/sliceDiagram.js +1 -0
- package/dist/render/sliceDiagram.js.map +1 -1
- package/dist/system/manifest.d.ts +45 -0
- package/dist/system/manifest.js +178 -0
- package/dist/system/manifest.js.map +1 -0
- package/dist/system/verify.d.ts +88 -0
- package/dist/system/verify.js +263 -0
- package/dist/system/verify.js.map +1 -0
- package/dist/templates.d.ts +14 -1
- package/dist/templates.js +134 -5
- package/dist/templates.js.map +1 -1
- package/dist/util/slug.js +16 -10
- package/dist/util/slug.js.map +1 -1
- package/package.json +10 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.11.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.11.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
|
|
@@ -37,6 +37,10 @@ canonical model's names wherever the code matches them); run `em diff <model-nam
|
|
|
37
37
|
proposals the user ratifies, then re-render and validate; run `em state set-conformance
|
|
38
38
|
<revision> --report <path>` to update the state file's `Last conformance:` marker.
|
|
39
39
|
|
|
40
|
+
Ruling on a finding is a human gate, like ratifying a slice
|
|
41
|
+
(docs/process.md#the-slice-lifecycle-gates): the sweep gathers evidence and proposes, a person
|
|
42
|
+
decides, and `em state set-conformance` records the decision — never run it on your own judgment.
|
|
43
|
+
|
|
40
44
|
End of phase: state file's `Last conformance:` marker updated (via `em state set-conformance`),
|
|
41
45
|
Decisions log entry if any
|
|
42
46
|
proposals were applied. Conform doesn't chain to another phase — it's a recurring loop, run
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-design
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.11.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
|
|
@@ -36,9 +36,19 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
|
|
|
36
36
|
directly**. Add `translation` slices for external inputs (externally triggered: external →
|
|
37
37
|
translation → command → event, no slice before) and for the system reacting to its own state
|
|
38
38
|
(internally triggered: read model in the slice before → translation → command → event).
|
|
39
|
-
2. **Elaborate scenarios — first pass (step 6).**
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
2. **Elaborate scenarios — first pass (step 6).** Scaffold every slice's doc now, one per
|
|
40
|
+
slice, none skipped: `em slice new "<slice name>" --pattern <state-change|state-view|
|
|
41
|
+
automation|translation> --swimlane "<Persona> → <Context>" --wire <model>.em` writes
|
|
42
|
+
`slices/<slice-name>.md` at `status: draft` (the same command, flags, and `--wire`
|
|
43
|
+
note-binding the `slice` phase's step 2 below documents in full). Then, for each freshly
|
|
44
|
+
scaffolded doc, hold a first-pass Socratic pass and write the happy-path Given/When/Then into
|
|
45
|
+
its `## Scenarios (Given / When / Then)` section and the obvious invariants known so far into
|
|
46
|
+
its `## Invariants / Business Rules` section — **into the doc, never into the state file.**
|
|
47
|
+
Keep this pass shallow (no field tables, alternate/error flows, or NFRs yet — that's the full
|
|
48
|
+
deep-dive in the `slice` phase below); the docs are the home for everything collected from
|
|
49
|
+
here on, not yet implementation-ready specs. Because every doc already exists by the time the
|
|
50
|
+
`slice` phase begins, its own step 2 scaffolding call is then a no-op — that phase picks up
|
|
51
|
+
at its step 1's deeper pass.
|
|
42
52
|
3. **Evaluate completeness (step 7).** Walk the model: every slice is a **complete** pattern, not a
|
|
43
53
|
half-slice — **every command has something that triggers it**, every command emits an event,
|
|
44
54
|
**every event is read by a read model**, **every read model has a consumer**, every view has a
|
|
@@ -51,13 +61,19 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
|
|
|
51
61
|
this fact and what they do with it. The honest answers are "here's the read model we missed" or
|
|
52
62
|
"nobody — so why are we recording it", and both improve the model.
|
|
53
63
|
|
|
54
|
-
End of phase: render, update state (`em state set-phase slice`
|
|
55
|
-
|
|
64
|
+
End of phase: render, update state (`em state set-phase slice` — the mechanical marker the state
|
|
65
|
+
machine expects), and stop. Every slice already has a draft doc ready to receive the deep spec,
|
|
66
|
+
but slicing is deliberate work the team starts when it's ready for it, not this phase's automatic
|
|
67
|
+
next step.
|
|
56
68
|
|
|
57
69
|
## Phase: `slice` — deep slice documents
|
|
58
70
|
|
|
59
|
-
Goal: implementation-ready specs. Go slice by slice
|
|
60
|
-
|
|
71
|
+
Goal: implementation-ready specs. Go slice by slice **in timeline order, starting with the first
|
|
72
|
+
slice on the storyboard** — never ask the user which slice to spec first, and never propose
|
|
73
|
+
starting with whichever slice looks highest-risk or most uncertain instead. Ratification
|
|
74
|
+
proceeds in the same order: later slices' scenarios and invariants depend on earlier slices'
|
|
75
|
+
events already being settled, so working out of order means re-litigating an earlier slice's
|
|
76
|
+
contract mid-spec. Check `README.md`'s Slices table for what's already done (run `em slice index
|
|
61
77
|
<model-name>.em` first if it looks stale).
|
|
62
78
|
|
|
63
79
|
This is also where **branch / unhappy-path events** are discovered and added to the model — as a
|
|
@@ -130,10 +146,13 @@ For each slice:
|
|
|
130
146
|
`implementedIn` once shipped). Never hand-edit the table; it's a generated block.
|
|
131
147
|
6. Re-render and `em validate`.
|
|
132
148
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
`
|
|
136
|
-
|
|
149
|
+
A finished draft doesn't become implementable here: it goes through the review gate and then the
|
|
150
|
+
ratification gate, both human, both outside this phase — see
|
|
151
|
+
`docs/process.md#the-slice-lifecycle-gates` for who runs which and in what order.
|
|
152
|
+
|
|
153
|
+
Before the project's first slice is implemented it also needs a ratified implementation
|
|
154
|
+
constitution (stack, code style, testing norms, NFR baselines, review norms) — the
|
|
155
|
+
`event-modeling-implement` skill elicits it, see its `reference/implement.md` §7.
|
|
137
156
|
|
|
138
157
|
End of phase: every slice that should exist has a doc, `README.md`'s Slices table is current,
|
|
139
158
|
and the model validates clean. Suggest `event-modeling-implement` for each ratified slice.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-discover
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.11.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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-implement
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.11.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
|
|
@@ -15,19 +15,30 @@ the agent builds rather than facilitates.
|
|
|
15
15
|
|
|
16
16
|
**Read `reference/implement.md` before doing any implement work and follow it as the
|
|
17
17
|
contract.** In short: gate on `em validate <model>.em --slice-ready <key>` (stop and hand
|
|
18
|
-
back if it fails — never edit the doc to make the gate pass);
|
|
18
|
+
back if it fails — never edit the doc to make the gate pass); read the project's implementation
|
|
19
|
+
constitution before writing code and stay inside its rules; treat the slice doc as the
|
|
19
20
|
spec (read-only, except the merge-time `status`/`implementedIn` flip); surface every gap to
|
|
20
21
|
the user instead of deciding it silently; cover every `INV-<MNEMONIC>-n` and every scenario with
|
|
21
22
|
tests; in spec-kit projects, allocate via em-sdd-bridge (redirect mode) and never run
|
|
22
23
|
`/speckit.specify`.
|
|
23
24
|
|
|
25
|
+
**Gate: no constitution, no first slice.** The constitution is the project's ratified house rules
|
|
26
|
+
— stack and architectural shape (including which implementation skill each slice pattern routes
|
|
27
|
+
to), code style, testing norms, NFR baselines, review/merge norms. It lives at
|
|
28
|
+
`.specify/memory/constitution.md` in a spec-kit project, otherwise `constitution.md` beside the
|
|
29
|
+
model; `em status` reports which, and whether it's there. If it's missing — or its `ratifiedBy:`
|
|
30
|
+
is empty, meaning nobody has signed it off — run `reference/implement.md` §7 ("Before the first
|
|
31
|
+
slice: the constitution") first: ask its questions conversationally, write the answers in, and
|
|
32
|
+
have a human ratify them. Don't decide the project's stack or style yourself to get moving.
|
|
33
|
+
|
|
24
34
|
That contract applies to any implementing agent, whether or not the session started from
|
|
25
35
|
`/event-modeling` — `em contract` prints it to stdout with no `.claude/` awareness required, for
|
|
26
36
|
an agent that can run a shell but isn't Claude Code.
|
|
27
37
|
|
|
28
38
|
If the project ships pattern-specific implementation skills (for example an Axon/DCB skill set
|
|
29
39
|
keyed on a slice doc's `pattern:` frontmatter), route by the slice's pattern and follow those —
|
|
30
|
-
`reference/implement.md` §2 explains where that hand-off happens
|
|
40
|
+
`reference/implement.md` §2 explains where that hand-off happens, and the constitution's
|
|
41
|
+
routing table (§7) is what names the skill set for each pattern.
|
|
31
42
|
|
|
32
43
|
Preconditions (tool check, model location) are the same as every other phase — see
|
|
33
44
|
`../event-modeling-shared/reference/operating-principles.md` — but this phase additionally
|
|
@@ -41,7 +41,22 @@ implementation branch.
|
|
|
41
41
|
|
|
42
42
|
## 2. Read the spec
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
**First, read the project's constitution** — the house rules for *how* implementation happens
|
|
45
|
+
here (stack and architectural shape, which implementation skill each slice pattern routes to,
|
|
46
|
+
code style, testing norms, NFR baselines, review and merge norms). It lives in one of exactly two
|
|
47
|
+
places, never both:
|
|
48
|
+
|
|
49
|
+
- **spec-kit project** (a `.specify/` directory exists at or above the model):
|
|
50
|
+
`.specify/memory/constitution.md` — spec-kit's own slot, which em defers to.
|
|
51
|
+
- **anything else**: `constitution.md` beside the model, where `em scaffold` writes it.
|
|
52
|
+
|
|
53
|
+
`em status <model>.em --json` reports which one applies and whether it's there
|
|
54
|
+
(`conformance[].constitution`) — existence only; nothing in `em` reads or judges its content.
|
|
55
|
+
**Its rules bound every technical choice you make on this slice** (see §4). If it's missing, or
|
|
56
|
+
its `ratifiedBy:` is empty (spec-kit's file: the `**Ratified**:` footer still a placeholder),
|
|
57
|
+
it isn't ratified — go to §7 before writing code.
|
|
58
|
+
|
|
59
|
+
Then read `slices/<slice-key>.md` end to end — every section is load-bearing:
|
|
45
60
|
|
|
46
61
|
| Section | What it is to the implementer |
|
|
47
62
|
|---|---|
|
|
@@ -92,7 +107,10 @@ undocumented ordering, a contradiction with adjacent code. The discipline:
|
|
|
92
107
|
a business person could have an opinion on. Silent divergence is the failure mode the whole
|
|
93
108
|
conformance loop exists to catch — don't manufacture it.
|
|
94
109
|
- Purely technical choices with no behavioral surface (private naming, idiomatic structure,
|
|
95
|
-
which assertion library) are yours
|
|
110
|
+
which assertion library) are yours — **within the constitution's rules** (§2); anything
|
|
111
|
+
observable in behavior, data, or contract is not. If no constitution exists (or its
|
|
112
|
+
`ratifiedBy` is empty), surface that to the human and do not proceed on unilateral style or
|
|
113
|
+
stack decisions for a first slice: run the constitution step (§7) first.
|
|
96
114
|
|
|
97
115
|
## 5. Definition of done
|
|
98
116
|
|
|
@@ -104,7 +122,7 @@ undocumented ordering, a contradiction with adjacent code. The discipline:
|
|
|
104
122
|
- Alternate/error flows (idempotency included) are covered by tests.
|
|
105
123
|
- The build and full test suite are green; the model still validates (`em validate` in CI —
|
|
106
124
|
you didn't touch the `.em`, so this only fails if something else broke).
|
|
107
|
-
- Nothing between the slice doc and the code was committed as a source of truth (see §
|
|
125
|
+
- Nothing between the slice doc and the code was committed as a source of truth (see §8 —
|
|
108
126
|
work containers are ephemeral; generated or symlinked specs are renderings).
|
|
109
127
|
|
|
110
128
|
## 6. At merge: the lifecycle flip
|
|
@@ -131,7 +149,55 @@ Then, if the project keeps a model README (from `../../event-modeling-shared/tem
|
|
|
131
149
|
link — never hand-edit that table. The `implementedIn` link is what the `conform` phase later
|
|
132
150
|
uses to anchor drift-checking — leaving it empty blinds the loop.
|
|
133
151
|
|
|
134
|
-
## 7.
|
|
152
|
+
## 7. Before the first slice: the constitution
|
|
153
|
+
|
|
154
|
+
The first time this project's slices reach implementation — or any time §2 finds no constitution,
|
|
155
|
+
or one whose `ratifiedBy` is still empty — **stop and run this short conversation before writing
|
|
156
|
+
code.** It happens once per project, not once per slice.
|
|
157
|
+
|
|
158
|
+
Start from the template the skill bundle ships,
|
|
159
|
+
`../../event-modeling-shared/templates/constitution.md`. Each of its five sections opens with the
|
|
160
|
+
question to ask; ask them **conversationally, one section at a time**, and write the answers into
|
|
161
|
+
the document as you go — never fill a section by guessing, by reading the codebase and inferring
|
|
162
|
+
"what they probably do", or by pasting the template's own examples. Unanswerable questions get
|
|
163
|
+
parked in the document as open items, exactly like a slice doc's Open Questions:
|
|
164
|
+
|
|
165
|
+
1. **Stack and architectural shape** — languages/runtimes, frameworks, the architectural pattern,
|
|
166
|
+
where a slice's code lives, and the routing table: which implementation skill or approach each
|
|
167
|
+
of the four slice patterns uses (for example, State Change slices → the `axon-*` skill set).
|
|
168
|
+
That table is what you obey in §2 when you read a slice's `pattern:`.
|
|
169
|
+
2. **Code style** — formatter/linter, naming, module layout, and what "idiomatic" means here.
|
|
170
|
+
3. **Testing norms** — which test levels each pattern requires, where invariant and scenario
|
|
171
|
+
tests live, and the test-naming convention that lets `em coverage` trace `INV-<MNEMONIC>-n`
|
|
172
|
+
citations.
|
|
173
|
+
4. **NFR baselines** — authz model, PII handling, performance defaults, observability: the
|
|
174
|
+
standing defaults every slice inherits where its own `## Non-Functional Requirements` section
|
|
175
|
+
is silent.
|
|
176
|
+
5. **Review and merge norms** — who reviews, what blocks a merge, and who runs
|
|
177
|
+
`em slice mark-implemented` at merge (§6).
|
|
178
|
+
|
|
179
|
+
**A human ratifies it.** The answers are the project's, not yours — you drafted the wording, they
|
|
180
|
+
sign it off. In the em-native file that's the `ratifiedBy:`/`ratifiedOn:` frontmatter (a named
|
|
181
|
+
person and an ISO date, hand-filled — no `em` command writes this file, and an empty `ratifiedBy:`
|
|
182
|
+
means *draft*). In a spec-kit project it's that file's own `**Ratified**:` footer line — never add
|
|
183
|
+
frontmatter to spec-kit's document. Until it's ratified, treat it as a proposal: you may not
|
|
184
|
+
build a first slice on it.
|
|
185
|
+
|
|
186
|
+
**In a spec-kit project, merge — never duplicate.** The constitution IS
|
|
187
|
+
`.specify/memory/constitution.md`; em writes no second file and neither do you. Append em's five
|
|
188
|
+
sections to it under their own `##` headings, **leaving every existing section byte-untouched** —
|
|
189
|
+
including spec-kit's own `## Core Principles` and `## Governance`, and any principle a team
|
|
190
|
+
already wrote. If a heading of the same name is already there, add to it rather than replacing it,
|
|
191
|
+
and show the human the diff before writing. Two cautions: spec-kit's `/speckit.constitution`
|
|
192
|
+
command rewrites that whole file from its template, so run it (if at all) **before** this
|
|
193
|
+
conversation, never after — and never use it to author em's sections. If the file is still the
|
|
194
|
+
blank stock template (`[PROJECT_NAME]`, `[PRINCIPLE_1_NAME]`, … placeholders), say so: filling
|
|
195
|
+
spec-kit's own placeholders is the team's call, and em's sections go in alongside them either way.
|
|
196
|
+
|
|
197
|
+
`em status` will then report `constitution: present` for the model. That's the whole mechanical
|
|
198
|
+
check — em stores and locates this document, and never validates a word of it.
|
|
199
|
+
|
|
200
|
+
## 8. Spec-kit projects: the SDD adapter
|
|
135
201
|
|
|
136
202
|
If the repository uses spec-kit (a `.specify/` directory exists), do not hand-author spec-kit
|
|
137
203
|
artifacts — allocate through **em-sdd-bridge**, redirect mode preferred:
|
|
@@ -163,7 +229,7 @@ plan/tasks as FEATURE_SPEC. The rules that keep redirect mode safe:
|
|
|
163
229
|
No spec-kit (or any SDD tool)? Implement straight from the slice doc — it already contains
|
|
164
230
|
everything a spec holds. Don't introduce an intermediate spec document of your own.
|
|
165
231
|
|
|
166
|
-
##
|
|
232
|
+
## 9. Never do
|
|
167
233
|
|
|
168
234
|
| Rule | Because |
|
|
169
235
|
|---|---|
|
|
@@ -172,10 +238,11 @@ everything a spec holds. Don't introduce an intermediate spec document of your o
|
|
|
172
238
|
| Never edit the `.em` model | Model edits are ratified decisions — propose, don't write |
|
|
173
239
|
| Never bump `version:` | Versions move only with ratified deltas; see `em ledger` |
|
|
174
240
|
| Never silently decide unspecified behavior | Silent divergence is the disease the conformance loop exists to catch |
|
|
241
|
+
| Never invent the house rules a first slice needs (stack, style, testing, NFR defaults) | They're the project's decision, ratified in the constitution — §7, not your judgment call |
|
|
175
242
|
| Never regenerate merged code from the model | Generated-then-owned: post-merge code belongs to its owners |
|
|
176
243
|
| Never commit an authored intermediate spec | The slice is the spec; anything between it and the code is a rendering |
|
|
177
244
|
|
|
178
|
-
##
|
|
245
|
+
## 10. Afterward: the loop closes
|
|
179
246
|
|
|
180
247
|
Implementation isn't the end of the slice's story. On a cadence — or whenever someone asks —
|
|
181
248
|
the `conform` phase checks implemented slices against the code, using the `implementedIn` link
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-review
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.11.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
|
|
@@ -49,8 +49,19 @@ walk each one with the user, same as any open issue. Update the state file's Par
|
|
|
49
49
|
section with who attended, and run `em state set-review <date>` to set the `Last stakeholder
|
|
50
50
|
review:` marker (mirrors `Last conformance:`).
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
**Per-slice outcome.** A slice whose open questions are all resolved in the room →
|
|
53
|
+
`em slice review <model>.em <key> --by <name>` (flips its doc to `status: reviewed` and records
|
|
54
|
+
`reviewedBy:`/`reviewedOn:`). Anything still open stays `draft` — the walkthrough doesn't decide
|
|
55
|
+
it, the next session or the open-questions list does.
|
|
56
|
+
|
|
57
|
+
**The facilitator never ratifies, never offers to ratify, and never suggests ratification in a
|
|
58
|
+
review session. Ratification is a separate human gate after review**
|
|
59
|
+
(docs/process.md#the-slice-lifecycle-gates). It is typically multi-person, routed through
|
|
60
|
+
CODEOWNERS on `slices/**`, and it is not this session's to run — `em slice ratify` will itself
|
|
61
|
+
refuse a doc that hasn't been through `em slice review`.
|
|
62
|
+
|
|
63
|
+
End of phase: state file's `Last stakeholder review:` marker updated, every walked slice whose
|
|
64
|
+
questions all closed moved to `status: reviewed`, every issue captured live triaged (resolved on the spot, moved to Open questions / parking lot, or left open on
|
|
54
65
|
purpose). Review doesn't chain to another phase — it's a recurring, scheduled activity like
|
|
55
66
|
`conform`, not a step in the discover → model → slice sequence.
|
|
56
67
|
|
|
@@ -15,7 +15,7 @@ Keep `.em` files focused on **structure**; put deep design in markdown linked vi
|
|
|
15
15
|
em --version # print the installed em version
|
|
16
16
|
em init [file] # scaffold a starter .em model
|
|
17
17
|
em init [file] -f, --force # overwrite if the file exists
|
|
18
|
-
em scaffold <name> # scaffold a full project: <slug>/<slug>.em, README.md, .event-modeling.md (see docs/cli.md — for just a starter .em, use `em init`; for a multi-model project, pass --under to nest it under a shared parent directory)
|
|
18
|
+
em scaffold <name> # scaffold a full project: <slug>/<slug>.em, README.md, .event-modeling.md, and constitution.md (the implementation constitution — skipped, with a note, in a spec-kit project, where `.specify/memory/constitution.md` IS that document) (see docs/cli.md — for just a starter .em, use `em init`; for a multi-model project, pass --under to nest it under a shared parent directory)
|
|
19
19
|
em scaffold <name> -f, --force # overwrite the directory's contents if it already exists
|
|
20
20
|
em scaffold <name> --under <dir> # parent directory to scaffold into — writes <dir>/<slug>/ instead of ./<slug>/, the supported multi-model layout (docs/cli.md, "Multi-model projects"): one directory per model, so each model's slices/ never collides with a sibling model's
|
|
21
21
|
em render <file> # transpile a model and render it (or emit DOT)
|
|
@@ -52,10 +52,14 @@ em slice new <name> --wire <model-file> # also insert the
|
|
|
52
52
|
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
|
|
53
53
|
em slice index <file> --check # verify the table is current; exit non-zero on drift without writing (CI)
|
|
54
54
|
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). Idempotent on the same URL; refuses to overwrite a different one; never touches `version:` or the doc body
|
|
55
|
-
em slice
|
|
55
|
+
em slice review <file> <slice-key> # flip a slice doc's frontmatter to `status: reviewed` and record `reviewedBy:`/`reviewedOn:` — the FIRST of the two human gates (MIL-201, docs/process.md#the-slice-lifecycle-gates): the room walked this slice and every open question it raised is resolved. Ratification is a separate, later gate (`em slice ratify`). Legal from `status: draft`; idempotent on the same --by/--on pair; refuses to overwrite a different one already recorded; refuses a doc already `ready-to-implement`/`implemented`; never touches `version:` or the doc body
|
|
56
|
+
em slice review <file> <slice-key> --by <name> # the reviewer's (or facilitator's) name
|
|
57
|
+
em slice review <file> <slice-key> --on <date> # review date, YYYY-MM-DD (default: today)
|
|
58
|
+
em slice ratify <file> <slice-key> # flip a slice doc's frontmatter to `status: ready-to-implement` and record `ratifiedBy:`/`ratifiedOn:` — the handoff sign-off (MIL-165, docs/process.md#the-slice-lifecycle-gates) that makes who ratified, and when, a first-class recorded fact. Refuses a doc that never passed the review gate (`em slice review`) unless --skip-review is passed. Idempotent on the same --by/--on pair; refuses to overwrite a different one already recorded; never touches `version:` or the doc body
|
|
56
59
|
em slice ratify <file> <slice-key> --by <name> # the ratifier's name
|
|
57
60
|
em slice ratify <file> <slice-key> --on <date> # ratification date, YYYY-MM-DD (default: today)
|
|
58
|
-
em slice
|
|
61
|
+
em slice ratify <file> <slice-key> --skip-review # ratify without a recorded review — prints a loud notice on stderr
|
|
62
|
+
em slice reratify <file> <slice-key> # bump `version:` and flip a shipped slice doc's frontmatter back to `status: ready-to-implement` — the re-ratification mechanical edit (MIL-161, mirrors `em slice mark-implemented`). Only applies to a doc at `status: implemented`; clears any stale `ratifiedBy:`/`ratifiedOn:`/`reviewedBy:`/`reviewedOn:` (they describe the PRIOR version's review and sign-off) so a follow-up `em slice ratify --by` applies cleanly — and needs no fresh review; never touches `implementedIn:` or the doc body
|
|
59
63
|
em changelog <file> # render a model's git history as a business-readable ledger (see docs/cli.md)
|
|
60
64
|
em changelog <file> --from <rev> # start the walk at this revision (inclusive)
|
|
61
65
|
em changelog <file> --to <rev> # end the walk at this revision (inclusive; default HEAD)
|
|
@@ -96,6 +100,7 @@ em migrate <file> --write # apply the rewrit
|
|
|
96
100
|
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)
|
|
97
101
|
em ledger <file> --from <rev> # baseline revision
|
|
98
102
|
em ledger <file> --to <rev> # compare revision (default: current working tree)
|
|
103
|
+
em ledger <file> --waive <slice-key> # excuse a doc-content-without-version-bump finding for this slice key (repeatable; MIL-185, see docs/cli.md) — never waives a version regression or bump-without-content-change
|
|
99
104
|
em ledger <file> --json # print a JSON document instead of the text report (see docs/cli.md)
|
|
100
105
|
em coverage <file> # check that every INV-* invariant ID cited in a ready-to-implement/implemented slice doc is cited by a test under --tests <dir> (MIL-130) — mechanizes reference/implement.md's definition-of-done citation check; advisory by default, --strict for CI
|
|
101
106
|
em coverage <file> --tests <dir> # directory to scan recursively for test files citing invariant IDs
|
|
@@ -111,10 +116,45 @@ em status <files> -o, --out <path> # write output to
|
|
|
111
116
|
em freshness <file> # standalone freshness signal for one model's conformance record (MIL-164): "last conformed <rev> — N commits and M slice-PRs behind HEAD", computed from the same conform-scope machinery `em status`'s conformance clause uses — for when you want just this fact, no full state-of-the-system rollup (see docs/cli.md)
|
|
112
117
|
em freshness <file> --repo <path> # git repo to compute behind-HEAD in (default: the model's own directory)
|
|
113
118
|
em freshness <file> --json # print a JSON document instead of the text line
|
|
119
|
+
em query consumers <files> # views/reactions consuming an event, plus their slices
|
|
120
|
+
em query consumers <files> --event <ref-or-name> # the event's export ref or display name
|
|
121
|
+
em query consumers <files> --json # print a JSON document instead of the text report
|
|
122
|
+
em query producers <files> # commands producing an event, plus their slices and ui triggers
|
|
123
|
+
em query producers <files> --event <ref-or-name> # the event's export ref or display name
|
|
124
|
+
em query producers <files> --json # print a JSON document instead of the text report
|
|
125
|
+
em query downstream <files> # transitive closure along legal edges from an element — impact analysis
|
|
126
|
+
em query downstream <files> --of <ref-or-name> # the starting element's export ref or display name
|
|
127
|
+
em query downstream <files> --depth <n> # limit traversal to n hops (default: unlimited)
|
|
128
|
+
em query downstream <files> --json # print a JSON document instead of the text report
|
|
129
|
+
em query upstream <files> # transitive closure against legal-edge direction from an element
|
|
130
|
+
em query upstream <files> --of <ref-or-name> # the starting element's export ref or display name
|
|
131
|
+
em query upstream <files> --depth <n> # limit traversal to n hops (default: unlimited)
|
|
132
|
+
em query upstream <files> --json # print a JSON document instead of the text report
|
|
133
|
+
em query slices <files> # filtered slice list — pattern/status/context/persona/tag filters AND-combine
|
|
134
|
+
em query slices <files> --pattern <p> # state-change | state-view | automation | translation | unclassified
|
|
135
|
+
em query slices <files> --status <s> # the slice's joined doc status (draft, reviewed, ready-to-implement, implemented, ...)
|
|
136
|
+
em query slices <files> --context <c> # match a slice with an event in this @Context
|
|
137
|
+
em query slices <files> --persona <p> # match a slice with a ui in this @Persona
|
|
138
|
+
em query slices <files> --tag <t> # match a slice with an event carrying this tag key
|
|
139
|
+
em query slices <files> --json # print a JSON document instead of the text report
|
|
140
|
+
em query invariant <files> # declaring slice + doc facts for one INV-* id, and (with --tests) its test citations
|
|
141
|
+
em query invariant <files> --id <inv-id> # the INV-* id to look up
|
|
142
|
+
em query invariant <files> --tests <dir> # directory to scan for test files citing this id
|
|
143
|
+
em query invariant <files> --json # print a JSON document instead of the text report
|
|
144
|
+
em query field <files> # one field's facts on an element — type, tag/assigned markers, renamed-from chain
|
|
145
|
+
em query field <files> --of <element-ref> # the element's export ref or display name
|
|
146
|
+
em query field <files> --name <field> # the field's name
|
|
147
|
+
em query field <files> --json # print a JSON document instead of the text report
|
|
148
|
+
em query path <files> # shortest path between two elements through the six legal connection types
|
|
149
|
+
em query path <files> --from <ref-or-name> # the starting element's export ref or display name
|
|
150
|
+
em query path <files> --to <ref-or-name> # the ending element's export ref or display name
|
|
151
|
+
em query path <files> --json # print a JSON document instead of the text report
|
|
152
|
+
em system <manifest> # verify a seam manifest (system.yaml) against its models' exports — every `public` event/view bound to a reaction in another model, the cross-model half of "both ends of a flow" (MIL-194, see docs/cli.md)
|
|
153
|
+
em system <manifest> --json # print a JSON document instead of the text report (see docs/cli.md)
|
|
114
154
|
em contract # print the packaged implementation contract (reference/implement.md) to stdout — the agent-neutral discovery path for any agent that can run a shell, not just Claude Code (MIL-129); see docs/cli.md
|
|
115
|
-
em mcp # start an MCP (Model Context Protocol) server over stdio
|
|
116
|
-
em skill install # copy the event-modeling skill bundle into .claude/skills/ (event-modeling, event-modeling-discover/-design/-implement/-conform/-review, event-modeling-shared)
|
|
117
|
-
em skill install -f, --force # overwrite an existing installation
|
|
155
|
+
em mcp # start an MCP (Model Context Protocol) server over stdio (MIL-21) — a structured, agent-facing alternative to shelling out to `em`; see docs/mcp.md for the full, current tool table (the list changes as commands gain MCP parity, so it's not repeated here — MIL-187). Equivalent to running the `em-mcp` bin directly
|
|
156
|
+
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)
|
|
157
|
+
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)
|
|
118
158
|
em skill install --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
|
|
119
159
|
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)
|
|
120
160
|
em skill sync [path] --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
|
|
@@ -160,7 +200,7 @@ type Name { field: Type, ... } # named structured type, reusable from any f
|
|
|
160
200
|
| `ui` | persona | screen / interface | `@Persona` | `note`, `issue`, `divergence`, `{ fields }` |
|
|
161
201
|
| `command` | API | state-changing request | — | `note`, `issue`, `divergence`, `renamed from`, `{ fields }` |
|
|
162
202
|
| `view` | API | read model / projection | — | `from "Event"…`, `note`, `issue`, `divergence`, `public`, `{ fields }` |
|
|
163
|
-
| `event` | context | recorded fact (past tense) | `@Context` | `note`, `issue`, `divergence`, `public`, `tag`, `renamed from`, field-level `assigned`, `{ fields }` |
|
|
203
|
+
| `event` | context | recorded fact (past tense) | `@Context` | `note`, `issue`, `divergence`, `public`, `tag`, `renamed from`, `loops-to`, field-level `assigned`, `{ fields }` |
|
|
164
204
|
| `processor` / `automation` / `saga` / `translation` | automation | system reaction / adapter | — | `from "…"`, `note`, `issue`, `divergence`, `{ fields }` |
|
|
165
205
|
|
|
166
206
|
### Clauses
|
|
@@ -185,6 +225,22 @@ type Name { field: Type, ... } # named structured type, reusable from any f
|
|
|
185
225
|
instance are what show the view changing. `again` with no earlier declaration is a validation error.
|
|
186
226
|
Use `again` (not a plain repeated `view` name) whenever the view is referenced by a
|
|
187
227
|
`from`/`arrow` — plain repeats are only warning-free while unreferenced.
|
|
228
|
+
- **`loops-to "View"`** (events only): marks an event as re-feeding an earlier read model — a
|
|
229
|
+
poll/retry loop where a later fact must re-trigger an automation that already ran (a lapsed
|
|
230
|
+
reservation re-notifying the next person waiting in line, and similar re-triggers). Written
|
|
231
|
+
after the event's name/`@Context`, either on the header line or trailing an
|
|
232
|
+
inline `{ fields }` block; repeatable (`loops-to "A" loops-to "B"`, or comma-joined). The
|
|
233
|
+
target must resolve to a `view` instance STRICTLY EARLIER on the timeline — the opposite of
|
|
234
|
+
`from`'s "nearest at-or-before" rule; pointing at the same slice or later is a validation
|
|
235
|
+
error naming `from` on a later `view … again` instance as the forward-flowing alternative,
|
|
236
|
+
and naming a view that doesn't exist is a separate unresolved-target error. A resolved
|
|
237
|
+
`loops-to` counts as the event being read for both-ends-of-a-flow completeness. **No arrow is
|
|
238
|
+
ever drawn** for it — drawing one backward would violate the timeline laws — instead the
|
|
239
|
+
event gets an indigo ↩ corner marker (bottom-left) and the legend gains a "Loops" section:
|
|
240
|
+
`↩ 1 <Event> re-feeds "<View>"` (the number identifies the event, not the target). `em
|
|
241
|
+
export` carries it as `loopsTo: { name, ref }[] | null` (`from`'s shape); `model.edges` gains
|
|
242
|
+
`{ from: <event ref>, to: <view ref>, source: "loops-to" }`; `em query`'s adjacency labels the
|
|
243
|
+
connection `"loops-to"` too, so `downstream`/`upstream` follow it (cycle-safely).
|
|
188
244
|
- **`note "path.md"`** on ANY element links a markdown doc. Relative to the `.em` file. Renders as
|
|
189
245
|
a clickable marker in SVG and a legend entry in PNG/PDF. **This is how slice docs attach.**
|
|
190
246
|
- **`issue "text"`** on ANY element flags an open question inline — the diagram-visible red
|
|
@@ -245,6 +301,25 @@ type Name { field: Type, ... } # named structured type, reusable from any f
|
|
|
245
301
|
`=== true` convention as `tag`. **Reach for this before echoing a server-set field onto the
|
|
246
302
|
command just to silence a fields-completeness warning** — that misrepresents what the client
|
|
247
303
|
actually sends.
|
|
304
|
+
- **`derived`** (view fields only, MIL-200): marks a field as computed from which events have
|
|
305
|
+
landed, rather than copied from a single source event's payload (a status stepping through
|
|
306
|
+
states as events arrive, a computed ordinal, an availability flag two events can flip).
|
|
307
|
+
Trails a field's type, or the bare name of a typeless field — bare `derived` (no traced
|
|
308
|
+
source) or traced `derived from "Event A", "Event B"` (the two-word form parsed before the
|
|
309
|
+
bare check, same discipline as `renamed from` vs. plain `from`). A field whose ENTIRE text is
|
|
310
|
+
just `derived` is a field named `derived`, not a clause. `derived`/`derived from` on a
|
|
311
|
+
command/event/`ui`/`type` field is a parse error. Excludes the field from
|
|
312
|
+
`fields-completeness/view-field-no-source` entirely (and thus from `--slice-ready`). The
|
|
313
|
+
traced form still checks something: every named event must resolve among the view's ACTUAL
|
|
314
|
+
sources (its own `from` list, or the same-slice events for a `from`-less view) — an
|
|
315
|
+
unresolved name is a validation error, `derived-from-unresolved`. `em export` carries it as
|
|
316
|
+
`derived: boolean` on the field (always present, same `=== true` convention as `tag`/
|
|
317
|
+
`assigned`) and `derivedFrom: string[] | null` (the traced event name(s), `null` on a bare
|
|
318
|
+
`derived` field). **Reach for this instead of dropping a computed field out of the `.em` and
|
|
319
|
+
into doc-only prose** — the marker keeps `em export`/the model aware the field exists (the
|
|
320
|
+
`doc-model-field-mismatch` doc↔model check does not compare view field tables at all today —
|
|
321
|
+
see the slice template's field-table guidance — so this is an export-side win specifically,
|
|
322
|
+
not yet a doc-drift check).
|
|
248
323
|
- **Fields:** `command Place Order { orderId: UUID, items: LineItem[], customerId }` — inline or
|
|
249
324
|
one-per-line. Types are free text (no semantic checking) UNLESS the type string names a
|
|
250
325
|
declared `type` (see Named types below), in which case it resolves to a structured
|
|
@@ -486,6 +561,14 @@ it to the slice that displays the read model, or drop it.
|
|
|
486
561
|
a ref naming a version higher than the target's own `version:`. A `split-from`/`merged-from`
|
|
487
562
|
naming a key absent from the tree is deliberately silent — that's the normal state after a
|
|
488
563
|
real split/merge (see the four `lineage-*` codes in the table below).
|
|
564
|
+
10. **`loops-to` not earlier, or unresolved** — an event's `loops-to "View"` naming a view at the
|
|
565
|
+
same slice or later (`loops-to-forward`; that's what `from` on a later `view … again`
|
|
566
|
+
instance is for), or naming a view that doesn't exist at all, or a name that resolves to a
|
|
567
|
+
non-view (`loops-to-unresolved`).
|
|
568
|
+
11. **`derived from` names an unresolved event** — a view field's traced `derived from "Event
|
|
569
|
+
A", "Event B"` clause naming an event that isn't among the view's actual sources (its own
|
|
570
|
+
`from` list, or the same-slice events for a `from`-less view) — `derived-from-unresolved`.
|
|
571
|
+
Name one of the view's real sources, or drop the traced event.
|
|
489
572
|
|
|
490
573
|
**Warnings (should fix):**
|
|
491
574
|
1. **Reaction with no command** — a `processor`/`automation`/`saga`/`translation` that triggers
|
|
@@ -502,9 +585,11 @@ it to the slice that displays the read model, or drop it.
|
|
|
502
585
|
5. **Event nobody reads** — the mirror of (4): recording an event no read model projects is a
|
|
503
586
|
write with no reader. Follow every write slice with the read slice that consumes its event.
|
|
504
587
|
Counts as read when a `view` names it in `from` (any `again` instance will do), when a view
|
|
505
|
-
with no `from` of its own sits in its slice,
|
|
506
|
-
|
|
507
|
-
`
|
|
588
|
+
with no `from` of its own sits in its slice, via an explicit `event -> view` arrow, or via a
|
|
589
|
+
resolved `loops-to "View"` clause (a loop-back is a real consumer too — an UNRESOLVED or
|
|
590
|
+
forward `loops-to` does not count, so the event still warns as unread alongside its own
|
|
591
|
+
`loops-to-forward`/`loops-to-unresolved` error). (Events marked `public` are exempt — their
|
|
592
|
+
reader is outside the model; same for a `public` view and the no-consumer warning.)
|
|
508
593
|
6. **Read model without source** — add `from "Event"` or place the view in a slice with an event.
|
|
509
594
|
7. **Duplicate name** — the same name defined N times; references resolve to the first. Rename.
|
|
510
595
|
(A duplicate `type` name always warns, unlike a duplicate element name — there's no
|
|
@@ -514,7 +599,8 @@ it to the slice that displays the read model, or drop it.
|
|
|
514
599
|
fail while any remain open.
|
|
515
600
|
9. **View field with no source** — a `view` field whose name matches no field on any instance
|
|
516
601
|
of its source events. Only checked once BOTH the view and at least one source event declare
|
|
517
|
-
`{ fields }
|
|
602
|
+
`{ fields }` — unless the field is marked `derived` (optionally `derived from "Event A",
|
|
603
|
+
"Event B"`, whose names must be among the view's sources), which exempts it entirely.
|
|
518
604
|
10. **Event field not from a command** — an `event` field whose name matches no field on any
|
|
519
605
|
command in the same slice. Only checked once BOTH the event and at least one same-slice
|
|
520
606
|
command declare `{ fields }`. This is the payoff of the fields feature for slicing rigor:
|
|
@@ -561,11 +647,14 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
561
647
|
| `both-ends-of-a-flow/view-unconsumed` | warning | Read model with no consumer | Add a `ui` or reaction that consumes it, or drop this instance. |
|
|
562
648
|
| `connection-legality/illegal-pair` | error | Illegal connection | Only ui→command→event→view→ui and view→reaction→command are legal — the message names the missing step. |
|
|
563
649
|
| `cross-model-slice-doc-collision` | warning | Colliding slice doc path across models | Give each model its own directory (see docs/cli.md, "Multi-model projects"). |
|
|
650
|
+
| `dangling-public-event` | warning | Public event/view no seam consumes | Declare the seam that reads it, or drop `public` if nothing outside the model does. |
|
|
651
|
+
| `derived-from-unresolved` | error | `derived from` names an unknown event | Name one of the view's actual sources, or drop the traced event from `derived from`. |
|
|
564
652
|
| `doc-model-element-not-in-doc` | warning | Model element the doc doesn't mention | Add the matching marker to the doc, or remove the element from the model. |
|
|
565
653
|
| `doc-model-element-not-in-model` | warning | Doc names an element the model doesn't have | Add the element to the model, or fix/remove it in the doc. |
|
|
566
654
|
| `doc-model-field-mismatch` | warning | Doc/model field mismatch | Reconcile the field table with the model's fields — names and types. |
|
|
567
655
|
| `doc-model-pattern-mismatch` | warning | Doc/model pattern mismatch | Fix the doc's `pattern:` frontmatter to match the model, or restructure the slice to match the doc. |
|
|
568
656
|
| `duplicate-element-ref` | warning | Duplicate element ref | Rename the element so its export ref is unique. |
|
|
657
|
+
| `duplicate-model-key` | warning | Duplicate model key | Give each model a unique `model "Name"` so its key (and every cross-model ref) is stable. |
|
|
569
658
|
| `duplicate-name` | warning | Duplicate name | Rename one of the duplicates. |
|
|
570
659
|
| `duplicate-slice-name` | warning | Duplicate slice name | Rename the slice so its export key is unique. |
|
|
571
660
|
| `duplicate-type-name` | warning | Duplicate type name | Rename one of the duplicate `type` declarations. |
|
|
@@ -579,6 +668,8 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
579
668
|
| `lineage-ref-cycle` | error | Lineage cycle | Break the cycle — a slice can't be its own ancestor. |
|
|
580
669
|
| `lineage-ref-malformed` | error | Malformed lineage ref | Fix the value to `<slice-key>@v<N>`, or remove it. |
|
|
581
670
|
| `lineage-version-impossible` | error | Impossible lineage version | Fix the referenced version, or ratify the target slice first. |
|
|
671
|
+
| `loops-to-forward` | error | `loops-to` target not earlier on the timeline | Point `loops-to` at an earlier view, or use `from` on a later `view … again` instance instead. |
|
|
672
|
+
| `loops-to-unresolved` | error | `loops-to` target unresolved | Name a view that exists, or declare it before this event. |
|
|
582
673
|
| `note-binding-dangling` | warning | Dangling cross-slice note | Create the doc at that path, or fix/remove the note. |
|
|
583
674
|
| `note-binding-extra` | warning | Extra doc-binding note, ignored | Remove the note, or point it at the slice's actual bound doc. |
|
|
584
675
|
| `note-binding-unratified` | warning | Unratified cross-slice note | Add `covers: <this-slice-key>` to that doc's frontmatter, or correct the note's path. |
|
|
@@ -587,11 +678,19 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
587
678
|
| `orphaned-slice-doc` | warning | Orphaned slice doc | Rename it to a current slice's key, add `covers:` (plus a `note` binding) to attach it to a live slice, or delete it. |
|
|
588
679
|
| `reaction-from-future-view` | error | Backward timeline (reaction reads a future view) | Declare the view in or before the reaction's slice. |
|
|
589
680
|
| `reaction-from-unresolved` | error | Unknown read-model source | Project the event into a view first, or fix the `from` reference. |
|
|
681
|
+
| `seam-consumer-not-reaction` | error | Seam consumer is not a reaction | Point `to` at a translation/automation element (or a slice containing exactly one). |
|
|
682
|
+
| `seam-duplicate` | warning | Duplicate seam | Remove the repeated `from`/`to` pair. |
|
|
683
|
+
| `seam-endpoint-unresolved` | error | Seam endpoint does not resolve | Fix the ref to an element the named model actually exports (`em export` lists every ref), or re-declare the seam after a rename. |
|
|
684
|
+
| `seam-source-not-public` | error | Seam source is not `public` | Mark the event/view `public` in its model, or point the seam at the element that is. |
|
|
685
|
+
| `system-manifest-invalid` | error | Seam manifest invalid | Fix the manifest: required keys, `systemSchemaVersion: "1.0"`, a readable `source` per model, and only declared model keys in seam refs. |
|
|
686
|
+
| `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. |
|
|
590
687
|
| `tag-composite-unknown-field` | error | Composite tag names an unknown field | Fix the field name, or add it to the event's fields. |
|
|
591
688
|
| `tag-duplicate-key` | error | Duplicate tag key | Rename one of the tags so every key on the event is unique. |
|
|
592
689
|
| `translation-name-collision` | warning | Translation name reused for different producers | Use a distinct name per producer to avoid confusion. |
|
|
593
690
|
| `type-cycle` | error | Cyclic type reference | Break the cycle, or route the self/mutual reference through an array. |
|
|
594
691
|
| `ui-shares-slice-with-automation` | warning | `ui` shares slice with a reaction | Move the `ui` to the slice that displays the read model, or drop it. |
|
|
692
|
+
| `unbound-translation` | warning | Externally-fed reaction no seam feeds | Declare the seam whose `to` is this reaction, or give it an in-model `from`. |
|
|
693
|
+
| `undeclared-seam-candidate` | warning | Looks connected across models, no seam declared | Declare the seam, or rename one side so the name match stops looking like a link. |
|
|
595
694
|
| `view-again-without-earlier` | error | `again` without an earlier declaration | Declare the view plainly the first time it appears. |
|
|
596
695
|
| `view-from-future-event` | error | Backward timeline (view reads a future event) | Move the source to a later `view X again` instance. |
|
|
597
696
|
| `view-from-unresolved` | error | Unknown event source | Fix the `from` reference to name an existing event. |
|
|
@@ -56,13 +56,15 @@ to decide `frontmatter-invalid` without re-deriving frontmatter-shape rules of i
|
|
|
56
56
|
| `schemaVersion` | integer | `1` (current dialect version) | its *value* is not read back by any `em` command today (reserved) — but its *presence* is required by `hasUsableFrontmatter()`: a doc omitting it is `frontmatter-invalid` (see below) |
|
|
57
57
|
| `pattern` | string | `state-change` \| `state-view` \| `automation` \| `translation` | authored/informational only — `em catalog` and `em export` both derive pattern from the `.em` AST instead (`em export`'s `slice.pattern`, schema `1.4`) |
|
|
58
58
|
| `swimlane` | string | free text, `<Persona> → <Context>` | display-only |
|
|
59
|
-
| `status` | string, case-insensitive | `draft` \| `reviewed` \| `ready-to-implement` \| `implemented` | `em catalog`, `em render`/`em watch` header coloring; joined into `em export`'s `slice.doc.status` (schema `1.4`); paired with `implementedIn` to compute `slice.doc.driftSignal` (schema `1.5`, MIL-85) and `em validate`'s frontmatter-coherence check (MIL-85 — see [validation.md#frontmatter-coherence](https://github.com/milehimikey/em/blob/main/docs/validation.md#frontmatter-coherence)) |
|
|
59
|
+
| `status` | string, case-insensitive | `draft` \| `reviewed` \| `ready-to-implement` \| `implemented` | written by `em slice review` (→ `reviewed`, MIL-201), `em slice ratify`/`em slice reratify` (→ `ready-to-implement`) and `em slice mark-implemented` (→ `implemented`); read by `em catalog`, `em render`/`em watch` header coloring; joined into `em export`'s `slice.doc.status` (schema `1.4`); paired with `implementedIn` to compute `slice.doc.driftSignal` (schema `1.5`, MIL-85) and `em validate`'s frontmatter-coherence check (MIL-85 — see [validation.md#frontmatter-coherence](https://github.com/milehimikey/em/blob/main/docs/validation.md#frontmatter-coherence)) |
|
|
60
60
|
| `version` | integer | positive integer, starts at `1` | joined into `em export`'s `slice.doc.version` (schema `1.4`, MIL-91) |
|
|
61
61
|
| `implementedIn` | string | free text (PR/commit link) | joined into `em export`'s `slice.doc.implementedIn` (schema `1.4`, MIL-91); paired with `status` to compute `slice.doc.driftSignal` (schema `1.5`, MIL-85) and `em validate`'s frontmatter-coherence check (MIL-85 — see [validation.md#frontmatter-coherence](https://github.com/milehimikey/em/blob/main/docs/validation.md#frontmatter-coherence)) |
|
|
62
62
|
| `split-from` | single ref | `<slice-key>@v<N>` | joined into `em export`'s `slice.doc.splitFrom` (schema `1.4`, MIL-91) and `em diff`'s `slice-added` entries (schema `1.6`, MIL-84); current-tree referential checks by `em validate` (MIL-84 — see [validation.md#lineage](https://github.com/milehimikey/em/blob/main/docs/validation.md#lineage)) |
|
|
63
63
|
| `merged-from` | list of refs | comma-separated `<slice-key>@v<N>, ...` | joined into `em export`'s `slice.doc.mergedFrom` (schema `1.4`, MIL-91) and `em diff`'s `slice-added` entries (schema `1.6`, MIL-84); current-tree referential checks by `em validate` (MIL-84 — see [validation.md#lineage](https://github.com/milehimikey/em/blob/main/docs/validation.md#lineage)) |
|
|
64
64
|
| `superseded-by` | list of refs | comma-separated `<slice-key>@v<N>, ...` | joined into `em export`'s `slice.doc.supersededBy` (schema `1.4`, MIL-91) and `em diff`'s `slice-removed` entries (schema `1.6`, MIL-84); current-tree referential checks by `em validate` (MIL-84 — see [validation.md#lineage](https://github.com/milehimikey/em/blob/main/docs/validation.md#lineage)) |
|
|
65
65
|
| `covers` | list of slice keys | comma-separated `<slice-key>, ...` (plain keys — **not** the `<slice-key>@v<N>` ref grammar above) | ratifies a cross-slice binding (MIL-121 — see [Cross-slice coverage](#cross-slice-coverage-covers) below): read by `em export`'s doc join, `em validate --slice-ready`, and (best-effort) `em render`/`em watch`'s Slice Status legend |
|
|
66
|
+
| `reviewedBy` | string | free text (typically the facilitator's or reviewer's name) | written only by `em slice review` (MIL-201 — see [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-slice-review-file-slice-key---by-name)); joined into `em export`'s `slice.doc.reviewedBy` (schema `1.11`) and `em slice index`'s Reviewed by column |
|
|
67
|
+
| `reviewedOn` | string | `YYYY-MM-DD` | written only by `em slice review` (MIL-201); joined into `em export`'s `slice.doc.reviewedOn` (schema `1.11`) |
|
|
66
68
|
| `ratifiedBy` | string | free text (typically a person's name) | written only by `em slice ratify` (MIL-165 — see [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-slice-ratify-file-slice-key---by-name)); joined into `em export`'s `slice.doc.ratifiedBy` (schema `1.8`) and `em slice index`'s Ratified by column |
|
|
67
69
|
| `ratifiedOn` | string | `YYYY-MM-DD` | written only by `em slice ratify` (MIL-165); joined into `em export`'s `slice.doc.ratifiedOn` (schema `1.8`) |
|
|
68
70
|
| `owner` | string | free text (typically a person or team name) | hand-filled — no `em` command writes it; joined into `em export`'s `slice.doc.owner` (schema `1.9`, MIL-171), `em slice index`'s Owner column, and `em status`'s per-slice `owners[]` |
|
|
@@ -84,6 +86,7 @@ convention, not parser-enforced.
|
|
|
84
86
|
| `implementedIn` | optional | optional | optional | required once the slice has *ever* reached `implemented` — may still name a **prior** version's PR during re-ratification, see below |
|
|
85
87
|
| `split-from`, `merged-from`, `superseded-by` | optional in every state — present only on docs created by a split/merge, or on a doc that has been retired |
|
|
86
88
|
| `covers` | optional in every state — present only on a doc that deliberately also serves another slice (MIL-121, see below); most docs never carry it |
|
|
89
|
+
| `reviewedBy`, `reviewedOn` | optional in every state — present once `em slice review` (MIL-201) has run at least once; a doc that never went through the review gate, or was hand-flipped to `reviewed`, simply omits both. `em slice ratify` never clears them; `em slice reratify` does (they describe the version that shipped) |
|
|
87
90
|
| `ratifiedBy`, `ratifiedOn` | optional in every state — present once `em slice ratify` (MIL-165) has run at least once; a doc predating this feature, or ratified by hand, simply omits both |
|
|
88
91
|
| `owner`, `tracking` | optional in every state — hand-filled whenever a team wants a who-holds-this / external-tracker link; most docs never carry either (MIL-171) |
|
|
89
92
|
|