@milehimikey/em 1.10.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/.claude/skills/event-modeling/SKILL.md +1 -1
  2. package/.claude/skills/event-modeling-conform/SKILL.md +5 -1
  3. package/.claude/skills/event-modeling-design/SKILL.md +41 -14
  4. package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
  5. package/.claude/skills/event-modeling-implement/SKILL.md +24 -7
  6. package/.claude/skills/event-modeling-implement/reference/implement.md +227 -19
  7. package/.claude/skills/event-modeling-review/SKILL.md +14 -3
  8. package/.claude/skills/event-modeling-shared/reference/em-dsl.md +80 -15
  9. package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +43 -1
  10. package/.claude/skills/event-modeling-shared/templates/constitution.md +118 -0
  11. package/.claude/skills/event-modeling-shared/templates/model-readme.md +2 -2
  12. package/.claude/skills/event-modeling-shared/templates/slice.md +4 -0
  13. package/dist/catalog/build.js +42 -1
  14. package/dist/catalog/build.js.map +1 -1
  15. package/dist/catalog/coverage.d.ts +15 -0
  16. package/dist/catalog/coverage.js +34 -0
  17. package/dist/catalog/coverage.js.map +1 -0
  18. package/dist/catalog/docJoin.d.ts +19 -2
  19. package/dist/catalog/docJoin.js +30 -4
  20. package/dist/catalog/docJoin.js.map +1 -1
  21. package/dist/catalog/docModelConsistencyValidate.js +1 -1
  22. package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
  23. package/dist/catalog/noteBindingValidate.js +18 -0
  24. package/dist/catalog/noteBindingValidate.js.map +1 -1
  25. package/dist/catalog/orphanedSliceDocValidate.d.ts +8 -1
  26. package/dist/catalog/orphanedSliceDocValidate.js +33 -6
  27. package/dist/catalog/orphanedSliceDocValidate.js.map +1 -1
  28. package/dist/catalog/pages.d.ts +16 -1
  29. package/dist/catalog/pages.js +16 -4
  30. package/dist/catalog/pages.js.map +1 -1
  31. package/dist/catalog/sliceDoc.d.ts +8 -0
  32. package/dist/catalog/sliceDoc.js +2 -0
  33. package/dist/catalog/sliceDoc.js.map +1 -1
  34. package/dist/catalog/sliceReadyValidate.d.ts +12 -1
  35. package/dist/catalog/sliceReadyValidate.js +4 -4
  36. package/dist/catalog/sliceReadyValidate.js.map +1 -1
  37. package/dist/cli/agentsMd.js +9 -3
  38. package/dist/cli/agentsMd.js.map +1 -1
  39. package/dist/cli/ciInit.js +3 -0
  40. package/dist/cli/ciInit.js.map +1 -1
  41. package/dist/cli/conformScope.js +10 -3
  42. package/dist/cli/conformScope.js.map +1 -1
  43. package/dist/cli/coverage.d.ts +34 -9
  44. package/dist/cli/coverage.js +61 -24
  45. package/dist/cli/coverage.js.map +1 -1
  46. package/dist/cli/ledgerCheck.d.ts +72 -0
  47. package/dist/cli/ledgerCheck.js +122 -1
  48. package/dist/cli/ledgerCheck.js.map +1 -1
  49. package/dist/cli/markImplemented.js +12 -1
  50. package/dist/cli/markImplemented.js.map +1 -1
  51. package/dist/cli/ratify.d.ts +37 -5
  52. package/dist/cli/ratify.js +123 -10
  53. package/dist/cli/ratify.js.map +1 -1
  54. package/dist/cli/reratify.js +26 -6
  55. package/dist/cli/reratify.js.map +1 -1
  56. package/dist/cli/review.d.ts +38 -0
  57. package/dist/cli/review.js +171 -0
  58. package/dist/cli/review.js.map +1 -0
  59. package/dist/cli/sliceIndex.d.ts +3 -0
  60. package/dist/cli/sliceIndex.js +14 -8
  61. package/dist/cli/sliceIndex.js.map +1 -1
  62. package/dist/cli/sliceLink.js +16 -0
  63. package/dist/cli/sliceLink.js.map +1 -1
  64. package/dist/cli/stateFile.d.ts +10 -0
  65. package/dist/cli/stateFile.js +14 -0
  66. package/dist/cli/stateFile.js.map +1 -1
  67. package/dist/cli/status.d.ts +55 -3
  68. package/dist/cli/status.js +92 -19
  69. package/dist/cli/status.js.map +1 -1
  70. package/dist/cli.js +203 -47
  71. package/dist/cli.js.map +1 -1
  72. package/dist/emit/coverageJson.d.ts +2 -2
  73. package/dist/emit/coverageJson.js +6 -2
  74. package/dist/emit/coverageJson.js.map +1 -1
  75. package/dist/emit/freshnessJson.d.ts +1 -1
  76. package/dist/emit/freshnessJson.js +5 -1
  77. package/dist/emit/freshnessJson.js.map +1 -1
  78. package/dist/emit/json.d.ts +45 -1
  79. package/dist/emit/json.js +82 -3
  80. package/dist/emit/json.js.map +1 -1
  81. package/dist/emit/ledgerJson.d.ts +1 -1
  82. package/dist/emit/ledgerJson.js +6 -1
  83. package/dist/emit/ledgerJson.js.map +1 -1
  84. package/dist/emit/queryJson.d.ts +1 -1
  85. package/dist/emit/queryJson.js +5 -1
  86. package/dist/emit/queryJson.js.map +1 -1
  87. package/dist/emit/statusJson.d.ts +1 -1
  88. package/dist/emit/statusJson.js +10 -1
  89. package/dist/emit/statusJson.js.map +1 -1
  90. package/dist/emit/validateJson.d.ts +4 -3
  91. package/dist/emit/validateJson.js +10 -3
  92. package/dist/emit/validateJson.js.map +1 -1
  93. package/dist/mcp/server.js +47 -22
  94. package/dist/mcp/server.js.map +1 -1
  95. package/dist/model/continuation.d.ts +23 -0
  96. package/dist/model/continuation.js +49 -0
  97. package/dist/model/continuation.js.map +1 -0
  98. package/dist/model/edges.d.ts +18 -3
  99. package/dist/model/edges.js +34 -0
  100. package/dist/model/edges.js.map +1 -1
  101. package/dist/model/model.d.ts +4 -0
  102. package/dist/model/model.js +1 -0
  103. package/dist/model/model.js.map +1 -1
  104. package/dist/model/queryIndex.d.ts +5 -2
  105. package/dist/model/queryIndex.js +5 -2
  106. package/dist/model/queryIndex.js.map +1 -1
  107. package/dist/model/rules.d.ts +25 -0
  108. package/dist/model/rules.js +25 -0
  109. package/dist/model/rules.js.map +1 -1
  110. package/dist/model/sliceDocIndex.d.ts +12 -5
  111. package/dist/model/sliceDocIndex.js +18 -7
  112. package/dist/model/sliceDocIndex.js.map +1 -1
  113. package/dist/model/validate.js +82 -1
  114. package/dist/model/validate.js.map +1 -1
  115. package/dist/parser/ast.d.ts +21 -0
  116. package/dist/parser/parser.js +96 -32
  117. package/dist/parser/parser.js.map +1 -1
  118. package/dist/render/drawEdges.js +7 -0
  119. package/dist/render/drawEdges.js.map +1 -1
  120. package/dist/render/drawNotes.d.ts +13 -3
  121. package/dist/render/drawNotes.js +96 -20
  122. package/dist/render/drawNotes.js.map +1 -1
  123. package/dist/render/render.js +6 -5
  124. package/dist/render/render.js.map +1 -1
  125. package/dist/render/sliceStatus.d.ts +3 -3
  126. package/dist/render/sliceStatus.js +27 -29
  127. package/dist/render/sliceStatus.js.map +1 -1
  128. package/dist/templates.d.ts +14 -1
  129. package/dist/templates.js +141 -5
  130. package/dist/templates.js.map +1 -1
  131. package/dist/util/localDate.d.ts +2 -0
  132. package/dist/util/localDate.js +17 -0
  133. package/dist/util/localDate.js.map +1 -0
  134. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: event-modeling
3
- em-version: 1.10.0
3
+ em-version: 1.12.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.10.0
3
+ em-version: 1.12.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.10.0
3
+ em-version: 1.12.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,22 @@ 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).** For each slice, capture the happy-path
40
- Given/When/Then and the obvious invariants as short notes. (The full spec is the `slice` phase
41
- below.)
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). A slice whose only element
44
+ is a `view X again` instance is a **continuation** (MIL-208), not a slice to scaffold —
45
+ `--wire` refuses it and names the originating slice holding `X`'s first declaration; its
46
+ scenarios go into that doc instead. Then, for each freshly scaffolded doc, hold a first-pass
47
+ Socratic pass and write the happy-path Given/When/Then into
48
+ its `## Scenarios (Given / When / Then)` section and the obvious invariants known so far into
49
+ its `## Invariants / Business Rules` section — **into the doc, never into the state file.**
50
+ Keep this pass shallow (no field tables, alternate/error flows, or NFRs yet — that's the full
51
+ deep-dive in the `slice` phase below); the docs are the home for everything collected from
52
+ here on, not yet implementation-ready specs. Because every doc already exists by the time the
53
+ `slice` phase begins, its own step 2 scaffolding call is then a no-op — that phase picks up
54
+ at its step 1's deeper pass.
42
55
  3. **Evaluate completeness (step 7).** Walk the model: every slice is a **complete** pattern, not a
43
56
  half-slice — **every command has something that triggers it**, every command emits an event,
44
57
  **every event is read by a read model**, **every read model has a consumer**, every view has a
@@ -51,13 +64,19 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
51
64
  this fact and what they do with it. The honest answers are "here's the read model we missed" or
52
65
  "nobody — so why are we recording it", and both improve the model.
53
66
 
54
- End of phase: render, update state (`em state set-phase slice`), continue with the `slice` phase
55
- below to write implementation specs.
67
+ End of phase: render, update state (`em state set-phase slice` — the mechanical marker the state
68
+ machine expects), and stop. Every slice already has a draft doc ready to receive the deep spec,
69
+ but slicing is deliberate work the team starts when it's ready for it, not this phase's automatic
70
+ next step.
56
71
 
57
72
  ## Phase: `slice` — deep slice documents
58
73
 
59
- Goal: implementation-ready specs. Go slice by slice (let the user pick order, or follow the
60
- timeline). Check `README.md`'s Slices table for what's already done (run `em slice index
74
+ Goal: implementation-ready specs. Go slice by slice **in timeline order, starting with the first
75
+ slice on the storyboard** — never ask the user which slice to spec first, and never propose
76
+ starting with whichever slice looks highest-risk or most uncertain instead. Ratification
77
+ proceeds in the same order: later slices' scenarios and invariants depend on earlier slices'
78
+ events already being settled, so working out of order means re-litigating an earlier slice's
79
+ contract mid-spec. Check `README.md`'s Slices table for what's already done (run `em slice index
61
80
  <model-name>.em` first if it looks stale).
62
81
 
63
82
  This is also where **branch / unhappy-path events** are discovered and added to the model — as a
@@ -99,6 +118,9 @@ For each slice:
99
118
  "slices/<slice-name>.md"` line straight into the `.em`, onto the slice's primary element (the
100
119
  command for State Change, the view for State View, the processor for Automation, the
101
120
  translation for Translation), matched by export key — see step 4 for when it refuses instead.
121
+ A slice whose sole candidate view is a later `view X again` instance is a **continuation**
122
+ (MIL-208): `--wire` refuses it and names the originating slice holding `X`'s first
123
+ declaration — write this slice's scenarios into that doc instead of scaffolding a new one.
102
124
  Both `--pattern` and `--swimlane` are required; an invalid `--pattern` is refused with the
103
125
  valid choices listed. Never hand-type this block, and never fall back to a placeholder
104
126
  pattern/swimlane to dodge the flags. Then fill in every judgment section below the stub from
@@ -130,10 +152,15 @@ For each slice:
130
152
  `implementedIn` once shipped). Never hand-edit the table; it's a generated block.
131
153
  6. Re-render and `em validate`.
132
154
 
133
- When a slice is **ratified** — a human flips its `status` to `ready-to-implement` with every
134
- open question resolved — it's ready to hand to an implementer. Confirm with
135
- `em validate <model>.em --slice-ready <key>`, and point whoever (or whatever) implements it
136
- at the `event-modeling-implement` skill.
155
+ A finished draft doesn't become implementable here: it goes through the review gate and then the
156
+ ratification gate, both human, both outside this phase — see
157
+ `docs/process.md#the-slice-lifecycle-gates` for who runs which and in what order.
137
158
 
138
- End of phase: every slice that should exist has a doc, `README.md`'s Slices table is current,
139
- and the model validates clean. Suggest `event-modeling-implement` for each ratified slice.
159
+ Before the project's first slice is implemented it also needs a ratified implementation
160
+ constitution (stack, code style, testing norms, NFR baselines, review norms) — the
161
+ `event-modeling-implement` skill elicits it, see its `reference/implement.md` §7.
162
+
163
+ End of phase: every slice that should exist has a doc — except a continuation slice (MIL-208, a
164
+ later `view X again` instance), which has none by design and is documented by the originating
165
+ slice instead — `README.md`'s Slices table is current, and the model validates clean. Suggest
166
+ `event-modeling-implement` for each ratified slice.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: event-modeling-discover
3
- em-version: 1.10.0
3
+ em-version: 1.12.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.10.0
3
+ em-version: 1.12.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,11 +15,27 @@ 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); treat the slice doc as the
19
- spec (read-only, except the merge-time `status`/`implementedIn` flip); surface every gap to
20
- the user instead of deciding it silently; cover every `INV-<MNEMONIC>-n` and every scenario with
21
- tests; in spec-kit projects, allocate via em-sdd-bridge (redirect mode) and never run
22
- `/speckit.specify`.
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; before a project's first slice PR,
20
+ land a one-time foundation PR holding every model event (plus the shared interface shell) so
21
+ slices only ever import contracts, never invent or reach into a sibling's; build in dependency
22
+ order from `em query upstream`, not timeline order; treat the slice doc as
23
+ the spec (read-only, except the merge-time `status`/`implementedIn` flip); implement exactly one
24
+ slice doc per PR — a `covers:` doc's two keys ship together in that one PR, an `again` view
25
+ instance gets its own; ship the endpoint a
26
+ `ui`-triggered command or `ui`-consumed view obligates, and surface — never invent — one the
27
+ model doesn't show; surface every gap to the user instead of deciding it silently; cover every
28
+ `INV-<MNEMONIC>-n` and every scenario with tests; in spec-kit projects, allocate via
29
+ em-sdd-bridge (redirect mode) and never run `/speckit.specify`.
30
+
31
+ **Gate: no constitution, no first slice.** The constitution is the project's ratified house rules
32
+ — stack and architectural shape (including which implementation skill each slice pattern routes
33
+ to), code style, testing norms, NFR baselines, review/merge norms. It lives at
34
+ `.specify/memory/constitution.md` in a spec-kit project, otherwise `constitution.md` beside the
35
+ model; `em status` reports which, and whether it's there. If it's missing — or its `ratifiedBy:`
36
+ is empty, meaning nobody has signed it off — run `reference/implement.md` §7 ("Before the first
37
+ slice: the constitution") first: ask its questions conversationally, write the answers in, and
38
+ have a human ratify them. Don't decide the project's stack or style yourself to get moving.
23
39
 
24
40
  That contract applies to any implementing agent, whether or not the session started from
25
41
  `/event-modeling` — `em contract` prints it to stdout with no `.claude/` awareness required, for
@@ -27,7 +43,8 @@ an agent that can run a shell but isn't Claude Code.
27
43
 
28
44
  If the project ships pattern-specific implementation skills (for example an Axon/DCB skill set
29
45
  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.
46
+ `reference/implement.md` §2 explains where that hand-off happens, and the constitution's
47
+ routing table (§7) is what names the skill set for each pattern.
31
48
 
32
49
  Preconditions (tool check, model location) are the same as every other phase — see
33
50
  `../event-modeling-shared/reference/operating-principles.md` — but this phase additionally
@@ -26,22 +26,41 @@ em validate <model>.em --slice-ready <slice-key> --json
26
26
  ```
27
27
 
28
28
  `<slice-key>` is the slice's export key — the kebab-case slug of its name (`"Place Order"` →
29
- `place-order`). Read the JSON document's `ready` field — don't infer it from the exit code or
30
- any printed text. `ready: true` means: the slice has a doc bound via `note "slices/<key>.md"`,
31
- its frontmatter is usable, `status: ready-to-implement`, every `## Open Questions` checkbox is
32
- checked, and no status/version/link incoherence is flagged — `gates` names each of those 4
33
- conditions individually (`docBound`/`frontmatterUsable`/`statusReady`/
34
- `noUncheckedOpenQuestions`) if you need to say which one is blocking.
35
-
36
- **`ready: false` means stop.** Report which `gates` entries are `false` (and any `diagnostics`
37
- entries concerning this slice) and hand the slice back to the humans. Never make the gate pass
38
- yourself — checking an open-question box, flipping `status`, or editing frontmatter are
39
- ratification decisions, and ratification happens in a facilitated session, not in an
40
- implementation branch.
29
+ `place-order`). Don't guess it or hand-slug the name yourself: list every slice's key with
30
+ `em export <model>.em | jq -r '.model.slices[].key'`. Read the JSON document's `ready` field —
31
+ don't infer it from the exit code or any printed text. `ready: true` means: the slice has a doc
32
+ bound via `note "slices/<key>.md"`, its frontmatter is usable, `status: ready-to-implement`,
33
+ every `## Open Questions` checkbox is checked, and no status/version/link incoherence is flagged
34
+ — `gates` names each of those 4 conditions individually (`docBound`/`frontmatterUsable`/
35
+ `statusReady`/`noUncheckedOpenQuestions`) if you need to say which one is blocking.
36
+
37
+ **`ready: false` means stop** — with one named exception: a slice already `status: implemented`
38
+ with `driftSignal: in-sync` also reads `ready: false` (its `statusReady` gate fails because
39
+ nothing is newly ratified), and that specific case is re-implementation/repair, not a blocker —
40
+ see §3's third mode before treating it as one. For every other `false`, report which `gates`
41
+ entries are `false` (and any `diagnostics` entries concerning this slice) and hand the slice
42
+ back to the humans. Never make the gate pass yourself — checking an open-question box, flipping
43
+ `status`, or editing frontmatter are ratification decisions, and ratification happens in a
44
+ facilitated session, not in an implementation branch.
41
45
 
42
46
  ## 2. Read the spec
43
47
 
44
- Read `slices/<slice-key>.md` end to end — every section is load-bearing:
48
+ **First, read the project's constitution** — the house rules for *how* implementation happens
49
+ here (stack and architectural shape, which implementation skill each slice pattern routes to,
50
+ code style, testing norms, NFR baselines, review and merge norms). It lives in one of exactly two
51
+ places, never both:
52
+
53
+ - **spec-kit project** (a `.specify/` directory exists at or above the model):
54
+ `.specify/memory/constitution.md` — spec-kit's own slot, which em defers to.
55
+ - **anything else**: `constitution.md` beside the model, where `em scaffold` writes it.
56
+
57
+ `em status <model>.em --json` reports which one applies and whether it's there
58
+ (`conformance[].constitution`) — existence only; nothing in `em` reads or judges its content.
59
+ **Its rules bound every technical choice you make on this slice** (see §4). If it's missing, or
60
+ its `ratifiedBy:` is empty (spec-kit's file: the `**Ratified**:` footer still a placeholder),
61
+ it isn't ratified — go to §7 before writing code.
62
+
63
+ Then read `slices/<slice-key>.md` end to end — every section is load-bearing:
45
64
 
46
65
  | Section | What it is to the implementer |
47
66
  |---|---|
@@ -53,18 +72,42 @@ Read `slices/<slice-key>.md` end to end — every section is load-bearing:
53
72
  | `## Non-Functional Requirements` | Authz, PII, performance — implement or consciously surface, never skip |
54
73
  | `## Dependencies & Read Models Affected` | The blast radius — what else to check before and after |
55
74
 
75
+ **Interface obligations follow from the model, not from the doc's prose.** The DSL already
76
+ encodes what's reachable — see `em-dsl.md`'s "Headless / API systems & repeated read models"
77
+ section — and the routing from it is mechanical, not a technical choice you make while coding:
78
+
79
+ - A **command with a `ui` trigger** ships the endpoint that dispatches it as part of this slice
80
+ — shape, verb, status codes, and error mapping follow the constitution's interface conventions
81
+ (§7). Because: the model already said this command is reachable from outside; leaving it
82
+ reachable only through an internal gateway silently narrows what the model ratified.
83
+ - A **view with a `ui` consumer** ships the query endpoint as part of this slice, same
84
+ conventions.
85
+ - **No `ui`** on the trigger or the consumer (a command dispatched by a processor or a
86
+ translation, a view read only by a reaction) means internal-only: no endpoint. If one seems
87
+ needed anyway, that's a gap to surface (§4), not a technical choice to make mid-implementation
88
+ — adding a route the model doesn't show is exactly the kind of silent divergence §4 exists to
89
+ catch.
90
+ - **`public` events and views** are the model's published integration surface: their shape is a
91
+ contract, not an implementation detail. `em validate --list-public` lists them; `em typespec`
92
+ is the POC generator for a downstream schema. Changing a public element's shape is a ratified
93
+ delta, never an implementation-time choice.
94
+
56
95
  For timeline context, read the slice's surroundings in the `.em` (what triggers it, what
57
96
  consumes its output) — the slice's own diagram (`slices/<slice-key>.svg`) shows its canonical
58
97
  pattern shape. For machine-readable facts, use `em export <model>.em --slice <slice-key>`
59
98
  rather than parsing the DSL or the doc's frontmatter yourself: it returns just this slice's
60
99
  object — `pattern`, element refs, fields, and the joined doc metadata (`slice.doc.status`,
61
100
  `version`, `driftSignal`) — without piping the whole model's export to find one `slice.doc`.
101
+ When the view repeats later via `again` (MIL-208), that same call on the *originating* slice
102
+ also returns `alsoReads: [{ event, atSlice }]` — the union of every event the read model
103
+ consumes across all its later continuations, in timeline order — so implementing it never means
104
+ walking each continuation by hand to assemble the full event list.
62
105
 
63
106
  If the project ships pattern-specific implementation skills (for example an Axon/DCB skill
64
107
  set keyed on a slice doc's `pattern:` frontmatter), route by the slice's pattern and follow
65
108
  those.
66
109
 
67
- ## 3. Two modes: first version vs. ratified delta
110
+ ## 3. Three modes: first version, ratified delta, re-implementation/repair
68
111
 
69
112
  Check the doc's `version:` and `## Delta` section (or `em export`'s `slice.doc.driftSignal`):
70
113
 
@@ -78,6 +121,26 @@ Check the doc's `version:` and `## Delta` section (or `em export`'s `slice.doc.d
78
121
  **Never regenerate merged code wholesale from the model** — after merge, code is owned by
79
122
  the people who've edited it (generated-then-owned); regeneration is legal only for slices
80
123
  whose code never merged.
124
+ - **Re-implementation / repair** (`status: implemented`, `implementedIn` set, `driftSignal:
125
+ in-sync` — `--slice-ready` reports `ready: false` purely because `statusReady` fails, with no
126
+ other gate false and no doc content changed): the doc hasn't changed, but the shipped code
127
+ needs rebuilding or fixing — deleted code, a reverted PR, a bug in behavior the doc already
128
+ specifies. **The doc is still the spec.** The gate's `false` here means "nothing new is
129
+ ratified," not "stop" — it is not license to self-initiate: proceed only when a human has
130
+ asked for this specific re-work. Scope the change to what the repair needs, exactly like a
131
+ delta (generated-then-owned still applies — don't regenerate the whole slice wholesale just
132
+ because the gate reads oddly); if what you'd change is really a change in behavior rather than
133
+ a repair of it, that's a ratified delta (the bullet above), not this mode — when unsure which
134
+ one you're in, ask the human rather than guess.
135
+
136
+ No lifecycle flip is needed unless `implementedIn` changes. If it does,
137
+ `em slice mark-implemented <model>.em <slice-key> <new-pr-url>` will **refuse** rather than
138
+ overwrite: a doc already `implemented` with a different `implementedIn` URL is left untouched
139
+ and the command reports the conflict (`src/cli/markImplemented.ts`) instead of silently
140
+ replacing provenance. That refusal is correct, not a bug to route around — never hand-edit the
141
+ frontmatter to force it through. Surface the conflict to the human instead: they decide whether
142
+ the new PR supersedes the recorded one (and re-run `mark-implemented` themselves, or ask you to,
143
+ once they've decided) or whether the existing link should stand.
81
144
 
82
145
  ## 4. Gaps: propose, never decide
83
146
 
@@ -92,10 +155,27 @@ undocumented ordering, a contradiction with adjacent code. The discipline:
92
155
  a business person could have an opinion on. Silent divergence is the failure mode the whole
93
156
  conformance loop exists to catch — don't manufacture it.
94
157
  - Purely technical choices with no behavioral surface (private naming, idiomatic structure,
95
- which assertion library) are yours; anything observable in behavior, data, or contract is not.
158
+ which assertion library) are yours — **within the constitution's rules** (§2); anything
159
+ observable in behavior, data, or contract is not. If no constitution exists (or its
160
+ `ratifiedBy` is empty), surface that to the human and do not proceed on unilateral style or
161
+ stack decisions for a first slice: run the constitution step (§7) first.
96
162
 
97
163
  ## 5. Definition of done
98
164
 
165
+ **The unit is the slice doc: one slice doc = one PR.** A doc that `covers:` another slice (an
166
+ automation's to-do-list view and its reaction, MIL-121) is one spec, not two — it ships in one
167
+ PR, and `mark-implemented` runs for both keys against the same URL. A read model is one doc,
168
+ even when a `view X again` clause repeats it across later positions on the timeline (MIL-208):
169
+ the later instance is a **continuation** of the slice holding `X`'s first declaration, not a
170
+ spec unit of its own — no doc, no status, no ratification, no PR of its own. Its behavior
171
+ belongs in the originating doc's `## Scenarios` (one scenario per event the later instance
172
+ feeds), not a doc of its own; `em export --slice <originating-key>` lists the full union of
173
+ events the read model consumes across every position via `alsoReads` (§2). Never fold multiple
174
+ slice docs' implementations into one PR because they touch the same read model, ship together,
175
+ or seem small — see §10.
176
+
177
+ - The PR description cites exactly one slice doc (plus its `covers:` keys, if any) and lists
178
+ that doc's invariants alongside the tests that cover them.
99
179
  - Every `INV-<MNEMONIC>-n` invariant has at least one test that cites its ID — checked mechanically by
100
180
  `em coverage <model>.em --tests <dir>` (MIL-130); run it (add `--strict` in CI) rather than
101
181
  eyeballing citations by hand.
@@ -104,11 +184,15 @@ undocumented ordering, a contradiction with adjacent code. The discipline:
104
184
  - Alternate/error flows (idempotency included) are covered by tests.
105
185
  - The build and full test suite are green; the model still validates (`em validate` in CI —
106
186
  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 §7 —
187
+ - Nothing between the slice doc and the code was committed as a source of truth (see §9 —
108
188
  work containers are ephemeral; generated or symlinked specs are renderings).
109
189
 
110
190
  ## 6. At merge: the lifecycle flip
111
191
 
192
+ The PR being merged here is the one doc's PR (§5) — its description cites exactly this slice doc
193
+ (plus any `covers:` keys) and nothing else, which is what makes the flip below unambiguous: one
194
+ PR, one `implementedIn` URL, applied to every key that PR's doc covers.
195
+
112
196
  When the PR merges, exactly **two** frontmatter fields change on the slice doc:
113
197
 
114
198
  ```yaml
@@ -131,7 +215,128 @@ Then, if the project keeps a model README (from `../../event-modeling-shared/tem
131
215
  link — never hand-edit that table. The `implementedIn` link is what the `conform` phase later
132
216
  uses to anchor drift-checking — leaving it empty blinds the loop.
133
217
 
134
- ## 7. Spec-kit projects: the SDD adapter
218
+ ## 7. Before the first slice: the constitution
219
+
220
+ The first time this project's slices reach implementation — or any time §2 finds no constitution,
221
+ or one whose `ratifiedBy` is still empty — **stop and run this short conversation before writing
222
+ code.** It happens once per project, not once per slice.
223
+
224
+ Start from the template the skill bundle ships,
225
+ `../../event-modeling-shared/templates/constitution.md`. Each of its five sections opens with the
226
+ question to ask; ask them **conversationally, one section at a time**, and write the answers into
227
+ the document as you go — never fill a section by guessing, by reading the codebase and inferring
228
+ "what they probably do", or by pasting the template's own examples. Unanswerable questions get
229
+ parked in the document as open items, exactly like a slice doc's Open Questions:
230
+
231
+ 1. **Stack and architectural shape** — languages/runtimes, frameworks, the architectural pattern,
232
+ where a slice's code lives, and the routing table: which implementation skill or approach each
233
+ of the four slice patterns uses (for example, State Change slices → the `axon-*` skill set).
234
+ That table is what you obey in §2 when you read a slice's `pattern:`. This is also where the
235
+ **interface conventions** question gets asked — resource style, error/rejection mapping,
236
+ versioning, auth at the edge — so the shape of every endpoint the interface obligations
237
+ paragraph (§2) and the foundation step (§8) require is decided once, here, instead of
238
+ invented per slice.
239
+ 2. **Code style** — formatter/linter, naming, module layout, and what "idiomatic" means here.
240
+ 3. **Testing norms** — which test levels each pattern requires, where invariant and scenario
241
+ tests live, and the test-naming convention that lets `em coverage` trace `INV-<MNEMONIC>-n`
242
+ citations.
243
+ 4. **NFR baselines** — authz model, PII handling, performance defaults, observability: the
244
+ standing defaults every slice inherits where its own `## Non-Functional Requirements` section
245
+ is silent.
246
+ 5. **Review and merge norms** — who reviews, what blocks a merge, and who runs
247
+ `em slice mark-implemented` at merge (§6).
248
+
249
+ **A human ratifies it.** The answers are the project's, not yours — you drafted the wording, they
250
+ sign it off. In the em-native file that's the `ratifiedBy:`/`ratifiedOn:` frontmatter (a named
251
+ person and an ISO date, hand-filled — no `em` command writes this file, and an empty `ratifiedBy:`
252
+ means *draft*). In a spec-kit project it's that file's own `**Ratified**:` footer line — never add
253
+ frontmatter to spec-kit's document. Until it's ratified, treat it as a proposal: you may not
254
+ build a first slice on it.
255
+
256
+ **In a spec-kit project, merge — never duplicate.** The constitution IS
257
+ `.specify/memory/constitution.md`; em writes no second file and neither do you. Append em's five
258
+ sections to it under their own `##` headings, **leaving every existing section byte-untouched** —
259
+ including spec-kit's own `## Core Principles` and `## Governance`, and any principle a team
260
+ already wrote. If a heading of the same name is already there, add to it rather than replacing it,
261
+ and show the human the diff before writing. Two cautions: spec-kit's `/speckit.constitution`
262
+ command rewrites that whole file from its template, so run it (if at all) **before** this
263
+ conversation, never after — and never use it to author em's sections. If the file is still the
264
+ blank stock template (`[PROJECT_NAME]`, `[PRINCIPLE_1_NAME]`, … placeholders), say so: filling
265
+ spec-kit's own placeholders is the team's call, and em's sections go in alongside them either way.
266
+
267
+ `em status` will then report `constitution: present` for the model. That's the whole mechanical
268
+ check — em stores and locates this document, and never validates a word of it.
269
+
270
+ ## 8. Foundation: contracts first
271
+
272
+ Once per project, before the first slice PR ever opens, land one **foundation PR** that turns
273
+ the model's events — and the cross-cutting shell the constitution names — into code, and
274
+ nothing else. Skip this and the failure is the same on every project that's skipped it: the
275
+ first slice PR ships fine, then the second one needs an event the first slice already defined
276
+ informally, and every PR after that either redefines it slightly differently or reaches into a
277
+ sibling slice's package to reuse it — the boundary the constitution drew is gone within a week.
278
+
279
+ 1. **What it contains.** Every event `em export <model>.em` lists in `events[]`, each placed in
280
+ the home the constitution's "where a slice's code lives" rule assigns to its *emitting*
281
+ slice — not a separate shared "events" module, so nothing about where an event lives depends
282
+ on this PR existing rather than the constitution. Fields come verbatim from the slice docs'
283
+ Event tables, with types mapped per the constitution's stack conventions. Add the
284
+ cross-cutting shell the constitution names: shared ports, and the request/response boundary
285
+ and error mapping the interface obligations above (§2) plug their endpoints into. **No
286
+ handlers, no projections — contracts only.** Because: a handler or a projection belongs to
287
+ the slice that owns the behavior behind it; folding one into the foundation PR turns a shared
288
+ contract into a pre-empted slice.
289
+ 2. **It merges before any slice PR opens.** Every slice branch is cut from `main` *after* the
290
+ foundation PR has landed there — never from a commit that predates it, and never alongside an
291
+ open, unmerged foundation PR. A slice PR never carries foundation files. Because: a slice PR
292
+ opened while the foundation is still in review shows a diff dominated by files the slice
293
+ didn't write and can't be held accountable for, and its merge depends on someone else's
294
+ review timeline instead of its own.
295
+ 3. **A slice never creates, edits, or reaches into another slice's code.** It *imports* events —
296
+ only events — from wherever the foundation placed them; a sibling slice's handlers, storage,
297
+ and other internals stay off limits. Because: the boundary the constitution drew only holds if
298
+ every slice actually stays inside it — a slice that quietly builds on a sibling's internals has
299
+ erased that boundary informally, one import at a time.
300
+ 4. **A ratified delta that adds or changes an event re-runs this step for that event, first.**
301
+ Land the code change for the new or changed event — in its emitting slice's home, following
302
+ rule 1 — before the slice's delta PR opens, exactly as if it were the first pass. Because: the
303
+ same contract-before-consumer ordering that applies once per project applies again every time
304
+ the contract itself changes; an event isn't a stable shared type just because it was one
305
+ yesterday.
306
+
307
+ ### Order of work
308
+
309
+ The foundation PR above answers most of "which slice next" by itself — once every event exists
310
+ as a contract, a read slice no longer has to wait for the write slice that will eventually
311
+ produce it. What's left is ordering the slice PRs against each other, and that ordering comes
312
+ from the dependency graph, not from where a slice sits on the timeline:
313
+
314
+ 1. **Foundation first removes most ordering constraints.** With every event already landed as a
315
+ contract (rules 1–4 above), a slice's remaining dependency is on other *slices*, not on
316
+ events existing at all — that's what turns "order every slice against every other slice"
317
+ into the short, per-pattern list below.
318
+ 2. **Then take dependency order from the graph, not the timeline.** Before starting a slice,
319
+ run `em query upstream <model>.em --of <slice's command-or-view ref>` — anything it returns
320
+ that's still `ready-to-implement` is a candidate to build first; `em query producers
321
+ <model>.em --event <name>` names the slices that own a specific event's producing commands
322
+ when you need to check one directly. Concretely, per pattern:
323
+ - **State Change** with no upstream is always startable — nothing but the foundation gates it.
324
+ - **State View** is startable as soon as the events it reads exist as contracts (the
325
+ foundation alone satisfies this), but build it *after* their producing slices have merged
326
+ when you can — its fixture tests then exercise real commands instead of hand-rolled event
327
+ fixtures.
328
+ - **Automation** goes after both the command it triggers and the to-do-list view it reads
329
+ (bound via `covers:` when the two are written as one doc) — a reaction can't be tested
330
+ against a command handler or a to-do list that doesn't exist yet.
331
+ - **Translation** goes after the command it triggers, same reasoning as an Automation's
332
+ triggered-command dependency.
333
+ 3. **Timeline order is the ratification order, not the build order.** Ratifying slices in
334
+ timeline order is deliberate — it's the order stakeholders reason about the business process
335
+ in. Carrying that same order into implementation is the mistake this section exists to head
336
+ off: build order comes from the dependency graph above, and the two orders routinely
337
+ disagree.
338
+
339
+ ## 9. Spec-kit projects: the SDD adapter
135
340
 
136
341
  If the repository uses spec-kit (a `.specify/` directory exists), do not hand-author spec-kit
137
342
  artifacts — allocate through **em-sdd-bridge**, redirect mode preferred:
@@ -163,7 +368,7 @@ plan/tasks as FEATURE_SPEC. The rules that keep redirect mode safe:
163
368
  No spec-kit (or any SDD tool)? Implement straight from the slice doc — it already contains
164
369
  everything a spec holds. Don't introduce an intermediate spec document of your own.
165
370
 
166
- ## 8. Never do
371
+ ## 10. Never do
167
372
 
168
373
  | Rule | Because |
169
374
  |---|---|
@@ -172,10 +377,13 @@ everything a spec holds. Don't introduce an intermediate spec document of your o
172
377
  | Never edit the `.em` model | Model edits are ratified decisions — propose, don't write |
173
378
  | Never bump `version:` | Versions move only with ratified deltas; see `em ledger` |
174
379
  | Never silently decide unspecified behavior | Silent divergence is the disease the conformance loop exists to catch |
380
+ | 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
381
  | Never regenerate merged code from the model | Generated-then-owned: post-merge code belongs to its owners |
176
382
  | Never commit an authored intermediate spec | The slice is the spec; anything between it and the code is a rendering |
383
+ | Never open a slice PR before the foundation PR has merged | The foundation is what makes an event a stable shared contract — a slice built ahead of it is building on a moving target (§8) |
384
+ | Never implement more than one slice doc in a PR | The PR is the durable record of one spec's implementation; `mark-implemented`, coverage, and conformance all key on one doc ↔ one `implementedIn` |
177
385
 
178
- ## 9. Afterward: the loop closes
386
+ ## 11. Afterward: the loop closes
179
387
 
180
388
  Implementation isn't the end of the slice's story. On a cadence — or whenever someone asks —
181
389
  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.10.0
3
+ em-version: 1.12.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
- End of phase: state file's `Last stakeholder review:` marker updated, every issue captured
53
- live triaged (resolved on the spot, moved to Open questions / parking lot, or left open on
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