@milehimikey/em 1.16.1 → 1.18.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 (219) hide show
  1. package/.claude/skills/event-modeling/SKILL.md +1 -1
  2. package/.claude/skills/event-modeling-conform/SKILL.md +3 -2
  3. package/.claude/skills/event-modeling-conform/reference/conform.md +7 -0
  4. package/.claude/skills/event-modeling-design/SKILL.md +46 -5
  5. package/.claude/skills/event-modeling-discover/SKILL.md +43 -8
  6. package/.claude/skills/event-modeling-discover/reference/extract.md +6 -1
  7. package/.claude/skills/event-modeling-discover/reference/prd-rubric.md +102 -0
  8. package/.claude/skills/event-modeling-discover/reference/prd-spec-path.md +171 -0
  9. package/.claude/skills/event-modeling-engagement/SKILL.md +28 -6
  10. package/.claude/skills/event-modeling-engagement/reference/engagement.md +5 -4
  11. package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
  12. package/.claude/skills/event-modeling-implement/reference/implement.md +18 -8
  13. package/.claude/skills/event-modeling-review/SKILL.md +1 -1
  14. package/.claude/skills/event-modeling-shared/reference/em-dsl.md +107 -10
  15. package/.claude/skills/event-modeling-shared/reference/methodology.md +268 -0
  16. package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +122 -15
  17. package/.claude/skills/event-modeling-shared/templates/slice.md +11 -3
  18. package/.claude-plugin/marketplace.json +2 -2
  19. package/dist/catalog/docJoin.d.ts +13 -5
  20. package/dist/catalog/docJoin.js +6 -1
  21. package/dist/catalog/docJoin.js.map +1 -1
  22. package/dist/catalog/docModelConsistencyValidate.js +160 -0
  23. package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
  24. package/dist/catalog/invariantsValidate.d.ts +2 -0
  25. package/dist/catalog/invariantsValidate.js +67 -1
  26. package/dist/catalog/invariantsValidate.js.map +1 -1
  27. package/dist/catalog/scenarioQualityValidate.d.ts +4 -0
  28. package/dist/catalog/scenarioQualityValidate.js +148 -0
  29. package/dist/catalog/scenarioQualityValidate.js.map +1 -0
  30. package/dist/catalog/scenarios.d.ts +5 -0
  31. package/dist/catalog/scenarios.js +80 -0
  32. package/dist/catalog/scenarios.js.map +1 -1
  33. package/dist/catalog/signedBodyValidate.d.ts +7 -0
  34. package/dist/catalog/signedBodyValidate.js +29 -0
  35. package/dist/catalog/signedBodyValidate.js.map +1 -0
  36. package/dist/catalog/sliceDoc.d.ts +53 -7
  37. package/dist/catalog/sliceDoc.js +89 -10
  38. package/dist/catalog/sliceDoc.js.map +1 -1
  39. package/dist/catalog/sliceReadyValidate.d.ts +23 -2
  40. package/dist/catalog/sliceReadyValidate.js +54 -22
  41. package/dist/catalog/sliceReadyValidate.js.map +1 -1
  42. package/dist/catalog/sliceSections.d.ts +3 -2
  43. package/dist/catalog/sliceSections.js +99 -9
  44. package/dist/catalog/sliceSections.js.map +1 -1
  45. package/dist/cli/ciInit.d.ts +4 -11
  46. package/dist/cli/ciInit.js +24 -6
  47. package/dist/cli/ciInit.js.map +1 -1
  48. package/dist/cli/coverage.d.ts +9 -0
  49. package/dist/cli/coverage.js +18 -0
  50. package/dist/cli/coverage.js.map +1 -1
  51. package/dist/cli/defer.d.ts +60 -17
  52. package/dist/cli/defer.js +187 -86
  53. package/dist/cli/defer.js.map +1 -1
  54. package/dist/cli/engagement.d.ts +46 -0
  55. package/dist/cli/engagement.js +156 -1
  56. package/dist/cli/engagement.js.map +1 -1
  57. package/dist/cli/engagementFoundation.d.ts +47 -0
  58. package/dist/cli/engagementFoundation.js +164 -0
  59. package/dist/cli/engagementFoundation.js.map +1 -0
  60. package/dist/cli/frontmatterSurgery.d.ts +5 -0
  61. package/dist/cli/frontmatterSurgery.js +15 -0
  62. package/dist/cli/frontmatterSurgery.js.map +1 -1
  63. package/dist/cli/ledgerCheck.d.ts +5 -1
  64. package/dist/cli/ledgerCheck.js +50 -20
  65. package/dist/cli/ledgerCheck.js.map +1 -1
  66. package/dist/cli/markImplemented.d.ts +14 -10
  67. package/dist/cli/markImplemented.js +49 -1
  68. package/dist/cli/markImplemented.js.map +1 -1
  69. package/dist/cli/prdTriage.d.ts +109 -0
  70. package/dist/cli/prdTriage.js +378 -0
  71. package/dist/cli/prdTriage.js.map +1 -0
  72. package/dist/cli/ratify.d.ts +14 -2
  73. package/dist/cli/ratify.js +34 -6
  74. package/dist/cli/ratify.js.map +1 -1
  75. package/dist/cli/refsCheck.d.ts +78 -0
  76. package/dist/cli/refsCheck.js +153 -0
  77. package/dist/cli/refsCheck.js.map +1 -0
  78. package/dist/cli/render-inputs.d.ts +2 -0
  79. package/dist/cli/render-inputs.js +4 -0
  80. package/dist/cli/render-inputs.js.map +1 -1
  81. package/dist/cli/revise.d.ts +12 -3
  82. package/dist/cli/revise.js +43 -10
  83. package/dist/cli/revise.js.map +1 -1
  84. package/dist/cli/shape.d.ts +27 -0
  85. package/dist/cli/shape.js +77 -0
  86. package/dist/cli/shape.js.map +1 -0
  87. package/dist/cli/sliceConform.js +9 -0
  88. package/dist/cli/sliceConform.js.map +1 -1
  89. package/dist/cli/sliceIndex.d.ts +6 -1
  90. package/dist/cli/sliceIndex.js +28 -13
  91. package/dist/cli/sliceIndex.js.map +1 -1
  92. package/dist/cli/sliceNew.d.ts +4 -1
  93. package/dist/cli/sliceNew.js +26 -9
  94. package/dist/cli/sliceNew.js.map +1 -1
  95. package/dist/cli/status.d.ts +26 -5
  96. package/dist/cli/status.js +28 -6
  97. package/dist/cli/status.js.map +1 -1
  98. package/dist/cli/storylineSuggest.d.ts +26 -0
  99. package/dist/cli/storylineSuggest.js +252 -0
  100. package/dist/cli/storylineSuggest.js.map +1 -0
  101. package/dist/cli/upgrade.d.ts +15 -3
  102. package/dist/cli/upgrade.js +537 -8
  103. package/dist/cli/upgrade.js.map +1 -1
  104. package/dist/cli/upgradeReshape.d.ts +60 -0
  105. package/dist/cli/upgradeReshape.js +425 -0
  106. package/dist/cli/upgradeReshape.js.map +1 -0
  107. package/dist/cli.js +430 -57
  108. package/dist/cli.js.map +1 -1
  109. package/dist/emit/dot.d.ts +2 -0
  110. package/dist/emit/dot.js +44 -8
  111. package/dist/emit/dot.js.map +1 -1
  112. package/dist/emit/engagementJson.d.ts +4 -1
  113. package/dist/emit/engagementJson.js +27 -1
  114. package/dist/emit/engagementJson.js.map +1 -1
  115. package/dist/emit/json.d.ts +21 -1
  116. package/dist/emit/json.js +29 -2
  117. package/dist/emit/json.js.map +1 -1
  118. package/dist/emit/ledgerJson.d.ts +1 -1
  119. package/dist/emit/ledgerJson.js +6 -1
  120. package/dist/emit/ledgerJson.js.map +1 -1
  121. package/dist/emit/queryJson.d.ts +1 -1
  122. package/dist/emit/queryJson.js +3 -1
  123. package/dist/emit/queryJson.js.map +1 -1
  124. package/dist/emit/refsJson.d.ts +4 -0
  125. package/dist/emit/refsJson.js +19 -0
  126. package/dist/emit/refsJson.js.map +1 -0
  127. package/dist/emit/statusJson.d.ts +1 -1
  128. package/dist/emit/statusJson.js +6 -1
  129. package/dist/emit/statusJson.js.map +1 -1
  130. package/dist/emit/theme.d.ts +1 -0
  131. package/dist/emit/theme.js +13 -0
  132. package/dist/emit/theme.js.map +1 -1
  133. package/dist/emit/validateJson.d.ts +5 -2
  134. package/dist/emit/validateJson.js +41 -2
  135. package/dist/emit/validateJson.js.map +1 -1
  136. package/dist/layout/grid.d.ts +5 -1
  137. package/dist/layout/grid.js +93 -2
  138. package/dist/layout/grid.js.map +1 -1
  139. package/dist/mcp/server.js +79 -14
  140. package/dist/mcp/server.js.map +1 -1
  141. package/dist/model/edges.d.ts +7 -0
  142. package/dist/model/edges.js +33 -16
  143. package/dist/model/edges.js.map +1 -1
  144. package/dist/model/model.d.ts +33 -0
  145. package/dist/model/model.js +87 -3
  146. package/dist/model/model.js.map +1 -1
  147. package/dist/model/queryIndex.js +2 -2
  148. package/dist/model/queryIndex.js.map +1 -1
  149. package/dist/model/refs.js +8 -5
  150. package/dist/model/refs.js.map +1 -1
  151. package/dist/model/rules.d.ts +167 -1
  152. package/dist/model/rules.js +164 -3
  153. package/dist/model/rules.js.map +1 -1
  154. package/dist/model/shapeLint.d.ts +12 -0
  155. package/dist/model/shapeLint.js +170 -0
  156. package/dist/model/shapeLint.js.map +1 -0
  157. package/dist/model/storylines.d.ts +51 -0
  158. package/dist/model/storylines.js +188 -0
  159. package/dist/model/storylines.js.map +1 -0
  160. package/dist/model/validate.d.ts +6 -1
  161. package/dist/model/validate.js +317 -14
  162. package/dist/model/validate.js.map +1 -1
  163. package/dist/parser/againSugar.d.ts +30 -0
  164. package/dist/parser/againSugar.js +105 -0
  165. package/dist/parser/againSugar.js.map +1 -0
  166. package/dist/parser/ast.d.ts +33 -0
  167. package/dist/parser/lexer.d.ts +9 -1
  168. package/dist/parser/lexer.js +17 -2
  169. package/dist/parser/lexer.js.map +1 -1
  170. package/dist/parser/parser.js +284 -4
  171. package/dist/parser/parser.js.map +1 -1
  172. package/dist/query/format.js +1 -0
  173. package/dist/query/format.js.map +1 -1
  174. package/dist/query/verbs.d.ts +4 -0
  175. package/dist/query/verbs.js +30 -3
  176. package/dist/query/verbs.js.map +1 -1
  177. package/dist/render/drawEdges.js +100 -4
  178. package/dist/render/drawEdges.js.map +1 -1
  179. package/dist/render/render.js +20 -2
  180. package/dist/render/render.js.map +1 -1
  181. package/dist/render/sliceDiagram.js +5 -5
  182. package/dist/render/sliceDiagram.js.map +1 -1
  183. package/dist/render/storylineBands.d.ts +11 -0
  184. package/dist/render/storylineBands.js +80 -0
  185. package/dist/render/storylineBands.js.map +1 -0
  186. package/dist/render/storylineDiagram.d.ts +14 -0
  187. package/dist/render/storylineDiagram.js +142 -0
  188. package/dist/render/storylineDiagram.js.map +1 -0
  189. package/dist/roster/check.d.ts +32 -0
  190. package/dist/roster/check.js +92 -0
  191. package/dist/roster/check.js.map +1 -0
  192. package/dist/roster/context.d.ts +3 -0
  193. package/dist/roster/context.js +23 -0
  194. package/dist/roster/context.js.map +1 -0
  195. package/dist/roster/init.d.ts +15 -0
  196. package/dist/roster/init.js +52 -0
  197. package/dist/roster/init.js.map +1 -0
  198. package/dist/roster/roster.d.ts +79 -0
  199. package/dist/roster/roster.js +298 -0
  200. package/dist/roster/roster.js.map +1 -0
  201. package/package.json +1 -1
  202. package/plugin/.claude-plugin/plugin.json +2 -2
  203. package/plugin/shared/reference/em-dsl.md +107 -10
  204. package/plugin/shared/reference/methodology.md +268 -0
  205. package/plugin/shared/reference/slice-doc-schema.md +122 -15
  206. package/plugin/shared/templates/slice.md +11 -3
  207. package/plugin/skills/conform/SKILL.md +3 -2
  208. package/plugin/skills/conform/reference/conform.md +7 -0
  209. package/plugin/skills/design/SKILL.md +46 -5
  210. package/plugin/skills/discover/SKILL.md +43 -8
  211. package/plugin/skills/discover/reference/extract.md +6 -1
  212. package/plugin/skills/discover/reference/prd-rubric.md +103 -0
  213. package/plugin/skills/discover/reference/prd-spec-path.md +172 -0
  214. package/plugin/skills/engagement/SKILL.md +28 -6
  215. package/plugin/skills/engagement/reference/engagement.md +5 -4
  216. package/plugin/skills/event-modeling/SKILL.md +1 -1
  217. package/plugin/skills/implement/SKILL.md +1 -1
  218. package/plugin/skills/implement/reference/implement.md +18 -8
  219. package/plugin/skills/review/SKILL.md +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: design
3
- em-version: 1.16.1
3
+ em-version: 1.18.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
@@ -66,7 +66,13 @@ evidence"). In short:
66
66
 
67
67
  Goal: a structurally complete, **validated** model with correct patterns and swimlanes.
68
68
 
69
- 1. **Swimlanes & patterns (step 5).** Group events into **contexts** (bounded contexts /
69
+ 1. **Swimlanes & patterns (step 5).** **Name the storylines first**: the one main storyline (the
70
+ end-to-end journey) and the secondary ones (retire a thing, extend an attribute, reorganize).
71
+ Wrap each one's slices in a `storyline "Name" [source "url"] { slice … }` block (grammar and the
72
+ optional `after "<storyline>"` timeline clause: `em-dsl.md`) so the diagram gets a band per
73
+ story and `em render --storyline "Name"` can show one alone; slices keep their file order, and
74
+ a model can adopt storylines incrementally (`slice-outside-storyline` is only an advisory
75
+ warning) — but name them before you slice, not after. Then group events into **contexts** (bounded contexts /
70
76
  aggregates) — ask which events share a consistency boundary and who owns them. Classify each
71
77
  slice as one of the 4 patterns. **Share the slice between every automation or translation and
72
78
  the command it triggers** (the reaction — processor/translation — together with the command
@@ -75,7 +81,21 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
75
81
  directly**. Add `translation` slices for external inputs (externally triggered: external →
76
82
  translation → command → event, no slice before) and for the system reacting to its own state
77
83
  (internally triggered: read model in the slice before → translation → command → event).
78
- 2. **Elaborate scenarios — first pass (step 6).** Scaffold every slice's doc now, one per
84
+ 2. **Storyline review — before any slice doc is scaffolded.** Read the timeline as a story, not a schema
85
+ (`${CLAUDE_PLUGIN_ROOT}/shared/reference/methodology.md`, "The story, not the schema"; em repo
86
+ `docs/storyline.md`). Name the **main storyline** (end-to-end happy path) and every
87
+ **secondary storyline** (retire, extend, reorganize), and group the slices under them; one
88
+ lifecycle block per entity (N × create/update/archive, one trailing view each) is the CRUD
89
+ shape — reshape it with the "Reshaping an existing model" checklist. Then the **intent test**
90
+ per command (would a business person say this name at this step in the story? an endpoint-shaped
91
+ name fails), the **question test** per view (write the question it answers; no question, no
92
+ read model; a child view only when its query needs what the parent view lacks), and the
93
+ **conditional-invariant signal** (invariants or fields that apply only "if `<field>` is set"
94
+ mean two intents in one command: split it). The `timeline-entity-clustered`,
95
+ `command-second-intent` and `automation-split-by-outcome` lints are the mechanical half; the
96
+ 1.18.0 design exit gate is `em validate --shape`. Shape the model first, scaffold docs after: a rename,
97
+ split or merge from the reshape would orphan docs already wired with `--wire`. The `slice` phase is unchanged (timeline order).
98
+ 3. **Elaborate scenarios — first pass (step 6).** Scaffold every slice's doc now, one per
79
99
  slice, none skipped: `em slice new "<slice name>" --pattern <state-change|state-view|
80
100
  automation|translation> --swimlane "<Persona> → <Context>" --wire <model>.em` writes
81
101
  `slices/<slice-name>.md` at `status: draft` (the same command, flags, and `--wire`
@@ -96,7 +116,7 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
96
116
  the one-command fast path: a near-free stub per undocumented slice, wired, in slice order
97
117
  (MIL-184) — skip the per-slice `em slice new` calls above and deepen individual docs later
98
118
  when the team is ready.
99
- 3. **Evaluate completeness (step 7).** Walk the model: every slice is a **complete** pattern, not a
119
+ 4. **Evaluate completeness (step 7).** Walk the model: every slice is a **complete** pattern, not a
100
120
  half-slice — **every command has something that triggers it**, every command emits an event,
101
121
  **every event is read by a read model**, **every read model has a consumer**, every view has a
102
122
  source, every UI is reachable, every connection is
@@ -125,6 +145,19 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
125
145
  session and stage `contracts/<model key>.tsp` with the model edit — the one derived artifact
126
146
  a design session produces, always by the command, never by hand.
127
147
 
148
+ 5. **Shape exit gate (GH #282).** The model phase ends on the shape lints, not on your judgement
149
+ of the storyline: run `em validate <model>.em --shape` (add `--json` to read it; exit code is
150
+ always 0, so read the output). Every finding is either **fixed** in the model, or **accepted**
151
+ as one bullet in `.event-modeling.md` `## Decisions log`:
152
+ `- YYYY-MM-DD: shape-accepted: <rule> <refs> — <reason>`
153
+ The gate passes only when **every remaining finding, waived or not,** has such a bullet. A
154
+ baseline passed as `--waive-file <path>` (lines `<rule-code> <slice-key>`) only silences the CLI
155
+ count for an estate; it never replaces the bullet. Re-run until each remaining finding has its
156
+ bullet. **Refuse to move to the slice phase otherwise** (`em state set-phase slice` waits): the
157
+ same kind of exit gate as asserting the generated contract above. Do not accept a finding
158
+ without asking the user for the reason. The gate runs after doc scaffolding, so update or retire
159
+ wired docs for renamed, merged or split slices.
160
+
128
161
  End of phase: render, update state (`em state set-phase slice` — the mechanical marker the state
129
162
  machine expects), and stop. Every slice already has a draft doc ready to receive the deep spec,
130
163
  but slicing is deliberate work the team starts when it's ready for it, not this phase's automatic
@@ -140,9 +173,17 @@ events already being settled, so working out of order means re-litigating an ear
140
173
  contract mid-spec. Check `README.md`'s Slices table for what's already done (run `em slice index
141
174
  <model-name>.em` first if it looks stale).
142
175
 
176
+ **Outcomes stay in the slice.** When the deep dive surfaces failure, retry or timeout, add the
177
+ outcome events (`Fulfilment Failed`, `Fulfilment Retry Scheduled`, ...) and their Given/When/Then
178
+ scenarios to the SAME slice, with retry policy and failure handling as invariants in its doc —
179
+ never a sibling slice per control-flow branch (1.18.0 adds the lint `automation-split-by-outcome`). A new slice
180
+ only when a different actor or a different trigger is involved. Canon: Dilger, "one business
181
+ action… two different possible outcomes" and "Linearize it!"; Dymitruk, "a few of these stories
182
+ to show how a command can and cannot succeed".
183
+
143
184
  This is also where **branch / unhappy-path events** are discovered and added to the model — as a
144
185
  slice's alternate/error flows surface (a rejection, removal, cancellation, decline, expiry), add
145
- the corresponding event/slice to the `.em` and re-render. The happy-path spine from earlier
186
+ the outcome event to the same slice unless a different actor or trigger is involved, then re-render. The happy-path spine from earlier
146
187
  phases is the starting point, not the finished event set. **Every new event needs its reader too**
147
188
  — a rejection or cancellation that nothing projects will warn, and usually the missing piece is
148
189
  real (someone has to see that the request was declined).
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: discover
3
- em-version: 1.16.1
3
+ em-version: 1.18.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
@@ -22,28 +22,40 @@ layout, the Socratic/validation discipline every phase follows) and
22
22
  work — they are the source of truth. Run the preconditions there first.
23
23
 
24
24
  **Existing system?** Use the `extract` phase below. **New feature inside an existing codebase,
25
- not a whole-system extraction?** Stay in `discover`, but before locking in command/event names,
26
- Grep/Read adjacent real sources (OpenAPI specs, DB migrations, existing DTOs/event classes in
27
- sibling contexts) rather than guessing conventions — same check the `slice` phase applies to
28
- field tables (`em:design`).
25
+ not a whole-system extraction?** Stay in `discover`, but **only after the storyboard exists**
26
+ (step 2) and before locking in command/event names, Grep/Read adjacent real sources (OpenAPI
27
+ specs, DB migrations, existing DTOs/event classes in sibling contexts) rather than guessing
28
+ conventions — same check the `slice` phase applies to field tables (`em:design`).
29
+ Those sources fill operations no walkthrough touches; they never supply the story.
29
30
 
30
31
  ## Phase: `discover` — steps 1-4
31
32
 
32
33
  Goal: a draft model of events, storyboard, commands, and views. Loose is OK; structure comes next.
33
34
 
34
- 1. **Brainstorm events (step 1).** Ask the user to name everything that happens, as past-tense
35
+ 1. **Brainstorm events (step 1).** Draw the candidate events **from the walkthroughs and
36
+ journeys** (ask for them first; no walkthrough → *"what does success look like, start to
37
+ finish?"*): *"what happened, in the story's words?"* — business terms, never table or endpoint
38
+ vocabulary. Ask the user to name everything that happens, as past-tense
35
39
  facts. Probe for missed state changes. For each candidate, apply the **"is it an event?"
36
40
  test** (`methodology.md` step 1 — the "would this wake the CEO at 3am" heuristic):
37
41
  reject derived values (belong in a read model) and telemetry/activity (not business state).
38
42
  Don't silently drop rejections — park them in the state file's Decisions log with why, so
39
43
  they aren't re-proposed later. Capture the survivors as a flat list.
40
- 2. **Plot / storyboard (step 2).** Order the events into the narrative. Identify **personas**
44
+ 2. **Plot / storyboard (step 2).** Start from the story, not the schema: ask for the spec's
45
+ **walkthroughs**, use cases and user journeys — or *"what does success look like, start to
46
+ finish?"* — and build the timeline from those (`methodology.md`, "The story, not the schema").
47
+ Name the **main storyline** (the end-to-end happy path) and each **secondary storyline**
48
+ (retire, extend, reorganize) before ordering anything; never one lifecycle block per entity
49
+ (the CRUD shape). The OpenAPI/migrations/resource reference comes **after** the storyboard,
50
+ only to fill operations no walkthrough touches. Order the events into the narrative. Identify **personas**
41
51
  (actors) and the **UI** screens at each step. Add `persona` declarations and `ui` elements.
42
52
  In a **headless/API** model there are no human personas or screens — identify the external
43
53
  **callers** at each step instead; declare one persona per caller/role, and its `ui` boxes are
44
54
  the API calls (see `methodology.md`).
45
55
  3. **Inputs (step 3).** For each event, find the **command** that causes it (imperative name).
46
- Form `command → event` slices (State Change pattern). Every command needs a **trigger** in the
56
+ Form `command → event` slices (State Change pattern). Apply the **intent test**: name the
57
+ command for the intent a business person would say at this step of the story, not the
58
+ endpoint that carries it (`methodology.md`, "The story, not the schema"). Every command needs a **trigger** in the
47
59
  same breath: the screen the user issues it from (a `ui` in the slice), or — for the Automation
48
60
  and Translation patterns — the reaction that triggers it, also in this slice. A command
49
61
  nothing points at is a write nobody can start. *"Who does this, and where are they when they
@@ -66,6 +78,29 @@ slice already reads "no doc yet" — no slice docs exist until the `slice` phase
66
78
  Tell the user they can stop here and resume with `/em:event-modeling` (or invoke
67
79
  `em:design` directly).
68
80
 
81
+ ## Path: PRD or spec in (a document is the input)
82
+
83
+ Use this path when the user hands you a **PRD, requirements document or API spec** instead of
84
+ starting from a blank page. **Entry:** `/em:discover` (plugin) or `/em:event-modeling discover`
85
+ (repo skills), with the opening message **`Discover from this PRD/spec: <path>`**. **Read `reference/prd-spec-path.md`
86
+ and `reference/prd-rubric.md` before doing any work on it** — the path is a triage, not a
87
+ transcription: a document describes the system its authors imagined (resources, endpoints,
88
+ stack, quality targets), and a model copied from it comes out as CRUD-per-entity.
89
+
90
+ The steps, in order (detail in the reference): **0** pull the walkthroughs and name the main and
91
+ secondary **storylines** (the resource/endpoint reference is consulted last); **1** split into
92
+ single-claim statements, each quoting the source verbatim; **2** classify each against the
93
+ shipped rubric, plus the independent *"is this about the business, independent of how it's
94
+ built?"* check; **3** group by reaction (shared trigger + acting system = one slice; failure,
95
+ retry and timeout become outcome events and scenarios of that slice, never new slices); **4**
96
+ rewrite, don't drop (implementation details become business language linked to their source;
97
+ real tech choices and NFRs go to a constraints list that feeds the constitution); **5** record
98
+ `discovery/prd-triage.json` and run `em discover triage-check discovery/prd-triage.json`
99
+ (MCP: `discover_triage_check`) until it passes; **6** every low-confidence or disagreeing
100
+ statement becomes a Socratic question — never an invented answer. Rejections and parked
101
+ statements go in the state file's Decisions log with why, as in step 1. Then continue with
102
+ `discover` steps 1-4 on the surviving groups, with the storylines as the timeline's spine.
103
+
69
104
  ## Phase: `extract` — current-state model of an existing system
70
105
 
71
106
  Goal: a faithful **current-state** model extracted from an existing system — the as-is sibling
@@ -77,7 +77,12 @@ it is fine to finish a round with `# TBD`s still parked.
77
77
 
78
78
  - **R1 — Candidate events.** Extract (event-driven) or synthesize (procedural) the past-tense
79
79
  facts; apply the event test; user confirms/renames/rejects. Ambiguous candidates → `# TBD`.
80
- - **R2 — Timeline order.** Order the confirmed events into the as-is narrative. Identify the
80
+ - **R2 — Timeline order.** First **name the as-is process(es)** — which business journey does the
81
+ system run today, and what is its outcome? Take it from the system's walkthroughs, user journeys
82
+ and docs, and from the people who use it — not from the OpenAPI/migrations/DTO grep, which fills
83
+ operations no journey touches and comes **after** (`methodology.md`, "The story, not the
84
+ schema"). Name the main storyline and each secondary one, then order the confirmed events into
85
+ that as-is narrative, never one block per entity. Identify the
81
86
  *actual* actors/callers and the *real* UI or API surfaces (headless systems: still `ui`/`persona`
82
87
  — one persona per caller/role, its `ui` boxes are the API calls, per `em-dsl.md`). **First
83
88
  `em render` here.**
@@ -0,0 +1,103 @@
1
+ <!-- GENERATED FILE from .claude/skills/event-modeling-discover/reference/prd-rubric.md by scripts/build-plugin.ts — do not hand-edit; run npm run docs:generate -->
2
+ # PRD/spec triage rubric — version 1.0
3
+
4
+ The shipped classification rubric for the PRD/spec path (`prd-spec-path.md`, step 2). It is data:
5
+ `em discover triage-check` rejects a `discovery/prd-triage.json` whose `rubricVersion` is not the
6
+ version below. Do not edit it per project; a changed rubric ships with a new `rubricVersion` in a
7
+ new `em` release.
8
+
9
+ ## The independent check
10
+
11
+ Run on every statement in addition to its category: **"Is this about the business, independent of
12
+ how it is built?"** Record the answer as `aboutBusiness` (true/false), answering it separately from
13
+ the category. The table's `aboutBusiness` column is what the category *expects*.
14
+
15
+ ## Categories
16
+
17
+ | Category id | What it is | aboutBusiness expected | Allowed outcomes |
18
+ |---|---|---|---|
19
+ | `business-fact` | Something that happens or is true in the business; candidate event or field. | true | modeled, rewritten, parked, question |
20
+ | `user-intent` | What an actor wants to accomplish; candidate command with its trigger. | true | modeled, rewritten, parked, question |
21
+ | `information-need` | What an actor needs to see or know to act; candidate read model. | true | modeled, rewritten, parked, question |
22
+ | `actor` | A person, role or calling system; candidate persona. | true | modeled, parked, question |
23
+ | `business-rule` | A constraint the business imposes; candidate invariant or scenario. | true | modeled, rewritten, parked, question |
24
+ | `external-system` | A system outside the boundary; candidate translation slice or constraint. | either | modeled, rewritten, constraint, parked, question |
25
+ | `implementation-detail` | How it is built. Rewritten in business language when it implies a business fact; a real tech choice goes to the constraints list. | false | rewritten, constraint, parked, question |
26
+ | `nfr` | Performance, availability, security, compliance: feeds the constitution, never a slice. | either | constraint, parked, question |
27
+ | `goal-background` | Why the product exists; context for the main storyline, not a slice. | true | parked, rewritten, question |
28
+ | `question` | An open question in the source; becomes a Socratic question, never an invented answer. | either | question, parked |
29
+ | `resource-or-endpoint` | Describes an API resource or endpoint. Rewritten to the intent it serves (one endpoint may carry several); never promoted to a command as-is. | false | rewritten, parked, question |
30
+
31
+ ## Outcomes
32
+
33
+ `modeled` (joins a slice group as stated), `rewritten` (joins a group in business language, the
34
+ original linked through `quote`), `constraint` (constraints list), `parked` (a `reason`; also a
35
+ Decisions-log entry), `question` (a Socratic `question` for the human). `question` and `parked`
36
+ are allowed for every category: a doubt can always be asked, and an explicitly deferred intent is
37
+ legitimate when its `reason` says so.
38
+
39
+ ## Rules the checker enforces
40
+
41
+ All of these are checked by `em discover triage-check`; write the record so they hold.
42
+
43
+ 1. **Disagreement is a question.** If `aboutBusiness` contradicts the category's expectation
44
+ (a `business-fact` that names a table; an `implementation-detail` that states a business
45
+ fact), the outcome MUST be `question`. Put the proposed rewrite in the question text
46
+ ("Is this a business fact? proposed: Stock is decremented when a pick is confirmed."); the
47
+ human resolves it and a later pass records `rewritten`.
48
+ 2. **Low confidence is a question.** `confidence: low` means outcome `question`, whatever the category.
49
+ 3. **An endpoint is never modeled as-is.** `resource-or-endpoint` is `rewritten` (to the intent it
50
+ serves), `parked` or `question` — never `modeled`.
51
+ 4. **Only modeled and rewritten statements join a slice group.** They carry a declared `group` and
52
+ the `storyline` of that group. Every other outcome has `group: null` (and `storyline: null`),
53
+ except that a `question` may name the group it would join once answered (with that group's
54
+ storyline); that is a pointer only, never an anchor (rule 7).
55
+ 5. `rewritten` needs `rewrite`; `parked` needs `reason`; `question` needs `question`; every
56
+ `constraint` appears in `constraints[]`.
57
+ 6. **Provenance is checked, not declared.** Every statement says whether it came from a
58
+ `walkthrough` or from the `reference` (resource/endpoint reference, operational notes). A
59
+ `walkthrough` statement's quote must lie inside some storyline's span; a `reference`
60
+ statement's quote must lie outside every storyline span.
61
+ 7. **A group is either anchored or reference-only.** An anchored group names a storyline and has at
62
+ least one `modeled` or `rewritten` `walkthrough` statement whose quote lies inside that storyline's span (a `question` never anchors: a group anchored by questions only is an error). A **reference-only
63
+ group** has only `reference` statements and **no storyline**: `storyline: null` on the group and
64
+ on its statements. It never joins a walkthrough storyline. The report lists reference-only
65
+ groups outside every storyline — operations no walkthrough touches; check these are not CRUD fill.
66
+ 8. **One statement per claim.** A statement's normalised quote may not equal, contain or be contained in another statement's quote; the error names both.
67
+ 9. **Quotes are verbatim** (Markdown emphasis marks, smart quotes and whitespace aside) and at
68
+ least 12 characters. A storyline `quote` is the **full** walkthrough span, start to finish.
69
+
70
+ ## Rubric decisions
71
+
72
+ - `nfr` expects `aboutBusiness: either`: a retention or audit rule is a business NFR, so the check
73
+ must not force a disagreement on it.
74
+ - `external-system` also stays `either`: a system outside the boundary can be named in business
75
+ terms (the payment provider) or technical ones (a queue broker).
76
+
77
+ The checker cannot judge whether a classification is right, nor whether every claim in the
78
+ walkthrough has a statement; that is what the human review is for.
79
+
80
+ ## Machine-readable copy
81
+
82
+ The same data as JSON. The checker's built-in copy is asserted identical to this block, and the
83
+ table above is asserted to match it, by `test/prdTriage.test.ts`.
84
+
85
+ ```json
86
+ {
87
+ "rubricVersion": "1.0",
88
+ "independentCheck": "Is this about the business, independent of how it is built?",
89
+ "categories": [
90
+ { "id": "business-fact", "aboutBusiness": true, "outcomes": ["modeled", "rewritten", "parked", "question"], "meaning": "Something that happens or is true in the business; candidate event or field." },
91
+ { "id": "user-intent", "aboutBusiness": true, "outcomes": ["modeled", "rewritten", "parked", "question"], "meaning": "What an actor wants to accomplish; candidate command with its trigger." },
92
+ { "id": "information-need", "aboutBusiness": true, "outcomes": ["modeled", "rewritten", "parked", "question"], "meaning": "What an actor needs to see or know to act; candidate read model." },
93
+ { "id": "actor", "aboutBusiness": true, "outcomes": ["modeled", "parked", "question"], "meaning": "A person, role or calling system; candidate persona." },
94
+ { "id": "business-rule", "aboutBusiness": true, "outcomes": ["modeled", "rewritten", "parked", "question"], "meaning": "A constraint the business imposes; candidate invariant or scenario." },
95
+ { "id": "external-system", "aboutBusiness": "either", "outcomes": ["modeled", "rewritten", "constraint", "parked", "question"], "meaning": "A system outside the boundary; candidate translation slice or constraint." },
96
+ { "id": "implementation-detail", "aboutBusiness": false, "outcomes": ["rewritten", "constraint", "parked", "question"], "meaning": "How it is built. Rewritten in business language when it implies a business fact; a real tech choice goes to the constraints list." },
97
+ { "id": "nfr", "aboutBusiness": "either", "outcomes": ["constraint", "parked", "question"], "meaning": "Performance, availability, security, compliance: feeds the constitution, never a slice." },
98
+ { "id": "goal-background", "aboutBusiness": true, "outcomes": ["parked", "rewritten", "question"], "meaning": "Why the product exists; context for the main storyline, not a slice." },
99
+ { "id": "question", "aboutBusiness": "either", "outcomes": ["question", "parked"], "meaning": "An open question in the source; becomes a Socratic question, never an invented answer." },
100
+ { "id": "resource-or-endpoint", "aboutBusiness": false, "outcomes": ["rewritten", "parked", "question"], "meaning": "Describes an API resource or endpoint. Rewritten to the intent it serves (one endpoint may carry several); never promoted to a command as-is." }
101
+ ]
102
+ }
103
+ ```
@@ -0,0 +1,172 @@
1
+ <!-- GENERATED FILE from .claude/skills/event-modeling-discover/reference/prd-spec-path.md by scripts/build-plugin.ts — do not hand-edit; run npm run docs:generate -->
2
+ # PRD/spec path — a document is the input
3
+
4
+ Read this **before doing any work on a PRD, requirements document or API spec**, together with
5
+ `prd-rubric.md` (the shipped classification rubric).
6
+
7
+ **Entry:** `/em:discover` (plugin) or `/em:event-modeling discover` (repo skills), with the opening
8
+ message **`Discover from this PRD/spec: <path>`**. This is the exact entry the eval protocol's
9
+ arm C cites. The path is a **triage**: a document
10
+ describes the system its authors imagined (resources, endpoints, stack, quality targets). Handed
11
+ one cold, the failure modes are over-decomposition along control flow, implementation flavour,
12
+ and CRUD-per-entity models shaped like the resource reference. The steps below prevent all three
13
+ by making every claim in the document earn its place in the model, visibly.
14
+
15
+ **Stance.** You are still extracting the domain from people, not inventing it. The document is
16
+ evidence. Anything it does not say, or says ambiguously, is a question (step 6), never a guess.
17
+
18
+ Setup: run the shared preconditions (`../../../shared/reference/operating-principles.md`),
19
+ agree the input path with the user, and create `discovery/` next to the model. Record the input
20
+ path in the state file's Session inputs.
21
+
22
+ ## Step 0 — Walkthroughs become storylines
23
+
24
+ Before splitting anything, find the document's **walkthroughs**: a PRD's user stories and
25
+ journeys, an API spec's Walkthroughs / use-case / "getting started" section.
26
+
27
+ - The **end-to-end journey** is the **main storyline** — the happy path, on a timeline, with no
28
+ branching ("a story of what success looks like"). Every other walkthrough is a **secondary
29
+ storyline** (retire, extend, reorganize...). Exactly one is main.
30
+ - The timeline is built from these. The resource/endpoint reference is consulted **last**, only to
31
+ fill operations no walkthrough touches.
32
+ - No walkthrough at all? Ask: *"what does success look like, start to finish?"* and have the
33
+ human first add the answer to the source document (or to a `discovery/walkthroughs.md` companion
34
+ that then becomes the triage `source`); a quote that is not in the source is rejected by design.
35
+ Do not synthesize a journey from the endpoint list.
36
+ - Record each storyline in `storylines[]` with its `id`, `name`, `main`, and `quote` — the **full**
37
+ walkthrough span, start to finish success story, verbatim (not its first sentence: the checker
38
+ anchors every group to this span). These become the design phase's `storyline` blocks, so the provenance travels
39
+ (`../../em:design/SKILL.md`, step 5; syntax in `../../../shared/reference/em-dsl.md`).
40
+
41
+ ## Step 1 — Split into single-claim statements
42
+
43
+ Split the input into **single-claim statements** — one fact, rule, need or description each. A
44
+ sentence with "and" usually holds two. Number them `S1`, `S2`, ... in source order. Each carries a
45
+ `quote` copied **verbatim** from the document (whitespace, Markdown emphasis marks and smart
46
+ quotes may differ; words may not; at least 12 characters). You may reword later (step 4) but never
47
+ in `quote`: the checker searches the document for it, and a quote it cannot find is an invented
48
+ claim. Every statement also records `provenance`: `walkthrough` for a claim made inside a
49
+ walkthrough span, `reference` for one from the resource/endpoint reference or operational notes.
50
+ **Every claim in a walkthrough gets a statement** — the carrier collecting, the delivery being
51
+ confirmed, the return before the due date — so nothing in the story is silently dropped; the
52
+ checker cannot see a missing one, so walk each walkthrough sentence by sentence.
53
+
54
+ ## Step 2 — Classify
55
+
56
+ For each statement set:
57
+
58
+ - `category` — one id from `prd-rubric.md`.
59
+ - `aboutBusiness` — the independent check: *"is this about the business, independent of how it is
60
+ built?"* Answer it separately from the category, without looking at the category.
61
+ - `confidence` — `high` or `low`. Any doubt: `low` (a low-confidence statement is always a question).
62
+
63
+ When `aboutBusiness` contradicts what the category expects (the rubric's `aboutBusiness expected`
64
+ column), that disagreement is data, not judgement: the outcome MUST be `question` (step 4, step 6).
65
+
66
+ A `resource-or-endpoint` statement is **never promoted to a command as-is**: ask which intent(s)
67
+ the resource serves (one endpoint may carry several intents) and rewrite to those (step 4).
68
+
69
+ ## Step 3 — Group by reaction
70
+
71
+ A **group** is one future slice. Statements sharing a **trigger** and an **acting system** are one
72
+ group (`groups[]`: `id`, `name`, `trigger`, `actor`, `storyline`). Follow the merged reaction
73
+ shape (`../../../shared/reference/methodology.md`): a reaction, its command and its
74
+ event share one slice.
75
+
76
+ - **Failure, retry and timeout statements are not new slices.** They become outcome events and
77
+ Given/When/Then scenarios of the slice whose trigger they belong to; set `scenarioOf` to that
78
+ group's id.
79
+ - **Storyline check.** A statement joins the storyline whose **journey it advances**, not the
80
+ entity it mentions. A "Product" sentence in the retire walkthrough belongs to "Retire a
81
+ product", not to a Product lifecycle.
82
+ - One group per trigger-and-actor; never one group per entity or per endpoint.
83
+ - **A group is anchored or reference-only, never both.** An anchored group names a storyline and
84
+ holds at least one `walkthrough` statement quoted from inside that storyline's span. A group
85
+ built only from `reference` statements (operations no walkthrough touches) is reference-only:
86
+ `storyline: null` on the group and on its statements. It never joins a walkthrough storyline,
87
+ and the report lists it outside every storyline for the human to inspect.
88
+ - A claim is quoted once: no statement's quote may equal, contain or be contained in another's. Only `modeled`/`rewritten` walkthrough statements anchor a group; a `question` never does.
89
+
90
+ ## Step 4 — Rewrite, don't drop
91
+
92
+ Nothing is silently discarded.
93
+
94
+ - An **implementation detail that implies a business fact** (*"the service writes a row to
95
+ `stock_levels` when a pick is confirmed"*): classify it `implementation-detail` with
96
+ `aboutBusiness: false` — they agree, so it is `rewritten`, with the business-language form in
97
+ `rewrite` (*"Stock is decremented when a pick is confirmed"*); the original stays in `quote`,
98
+ which is the link to its source. If you classified the same sentence `business-fact` but the
99
+ independent check says `false`, they **disagree**: the outcome is `question`, with the proposed
100
+ rewrite in the question text (*"Is this a business fact? proposed: Stock is decremented when a
101
+ pick is confirmed."*). The human resolves it and a later pass records `rewritten`.
102
+ - A **real technology choice or NFR** (*"must run on Postgres"*, *"p95 under 300 ms"*) gets outcome
103
+ `constraint` and an entry in `constraints[]` listing its statement ids. That list feeds the
104
+ project's constitution: hand it to the constitution's owner (the skills read the constitution,
105
+ never write it); it never becomes a slice.
106
+ - Anything else you set aside is `parked` with a `reason`, **and** recorded in the state file's
107
+ Decisions log with why (the same rule as rejected events in `discover` step 1), so it is not
108
+ re-proposed later.
109
+
110
+ ## Step 5 — Record
111
+
112
+ Write `discovery/prd-triage.json` (UTF-8, 2-space indent):
113
+
114
+ ```json
115
+ {
116
+ "prdTriageSchemaVersion": "1.0",
117
+ "rubricVersion": "1.0",
118
+ "source": "prd.md",
119
+ "storylines": [{ "id": "L1", "name": "Order to delivery", "main": true, "quote": "A customer places an order. We pick and ship it, and they get a tracking link." }],
120
+ "groups": [{ "id": "G1", "name": "Place Order", "trigger": "customer submits checkout", "actor": "Storefront", "storyline": "L1" }],
121
+ "statements": [
122
+ { "id": "S1", "quote": "A customer places an order.", "category": "user-intent", "aboutBusiness": true, "confidence": "high", "provenance": "walkthrough", "outcome": "modeled", "group": "G1", "storyline": "L1" },
123
+ { "id": "S2", "quote": "must respond within 300 ms", "category": "nfr", "aboutBusiness": false, "confidence": "high", "provenance": "reference", "outcome": "constraint", "group": null, "storyline": null },
124
+ { "id": "S3", "quote": "writes a row to stock_levels", "category": "business-fact", "aboutBusiness": false, "confidence": "high", "provenance": "reference", "outcome": "question", "group": null, "storyline": null, "question": "Is this a business fact? proposed: Stock is decremented when a pick is confirmed." }
125
+ ],
126
+ "constraints": [{ "id": "C1", "text": "Checkout responds within 300 ms", "statements": ["S2"] }]
127
+ }
128
+ ```
129
+
130
+ Per statement: `id`, `quote`, `category`, `aboutBusiness`, `confidence`, `provenance`, `outcome`
131
+ (`modeled | rewritten | constraint | parked | question`), `group` and `storyline` (set for
132
+ `modeled`/`rewritten`, otherwise `null`), plus `rewrite` / `reason` / `question` /
133
+ `scenarioOf` where the outcome needs them. **Every statement has a category and an outcome;
134
+ every modeled or rewritten statement has a group.** The rules the checker enforces are listed in
135
+ `prd-rubric.md` ("Rules the checker enforces"): disagreement and low confidence are questions, an
136
+ endpoint is never modeled, group and storyline only for modeled/rewritten (otherwise `null`),
137
+ provenance verified against the storyline spans (a `walkthrough` quote lies inside one, a
138
+ `reference` quote outside all), no shared quotes, and every group either anchored by a walkthrough
139
+ statement inside its storyline's span or reference-only (`"storyline": null` on the group and its
140
+ statements, listed in the report outside every storyline).
141
+
142
+ Then run, and fix until it passes:
143
+
144
+ ```
145
+ em discover triage-check discovery/prd-triage.json # MCP: discover_triage_check
146
+ em discover triage-check discovery/prd-triage.json --markdown > discovery/prd-triage.md
147
+ ```
148
+
149
+ `--markdown` prints the human-readable view (storylines, slice groups with their statements,
150
+ constraints, parked, questions); save it next to the JSON. The checker verifies shape, the rubric
151
+ version, verbatim quotes, and the outcome rules; **it cannot judge whether your classification is
152
+ right**, whether every walkthrough claim has a statement, or whether the Decisions-log entry for
153
+ each parked or rejected statement was actually written (that entry is prose-only and unchecked) —
154
+ that is what the human review is for. Read the report's **reference-only groups** list: those
155
+ are operations no walkthrough touches; check they are not CRUD fill. Also confirm each
156
+ **storyline quote really is a walkthrough span**: storyline spans are self-declared and the
157
+ checker cannot know which sections of the document are walkthroughs. The `--markdown` view lists
158
+ the storylines with their quotes for exactly this review.
159
+
160
+ ## Step 6 — Questions, never inventions
161
+
162
+ Every `low` confidence statement, every statement where `aboutBusiness` contradicts the
163
+ category's expectation, and every `question` category statement gets outcome `question` and a
164
+ Socratic `question` (a disagreement's question carries the proposed rewrite). Ask them one concern at a time, in the story's words. Record each answer in the state
165
+ file and update the record (the statement is re-classified; re-run the checker). If the document
166
+ and the human disagree, the human wins and the disagreement is a Decisions-log entry.
167
+
168
+ ## Hand-off
169
+
170
+ Continue with `discover` steps 1-4 (`../SKILL.md`) on the surviving groups: the storylines are the
171
+ timeline's spine, each group seeds one slice, and the constraints list goes to the project
172
+ constitution. `discovery/prd-triage.json` stays in the repo as provenance for the model.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: engagement
3
- em-version: 1.16.1
3
+ em-version: 1.18.0
4
4
  description: >-
5
5
  Use when leading an engagement: building a named set of ratified event-modeling slices
6
6
  (`em engagement`) into one independent PR per slice, each against main, by dispatching the
@@ -48,9 +48,17 @@ Run the shared preconditions first (tool check, bundle currency, locate the mode
48
48
  beside the model, or `.specify/memory/constitution.md`). STOP if it is missing or its
49
49
  `ratifiedBy:` is empty (spec-kit: no `**Ratified**:` footer). Say so and point at
50
50
  `em:implement`'s §7; never draft house rules to get moving.
51
- 2. **Foundation PR merged.** Ask the human for the foundation PR (implement.md §8) and confirm it
52
- has merged into `main` (`gh pr view <n> --json state` shows `MERGED`). STOP if there is none
53
- or it is still open. No slice branch is cut before it lands.
51
+ 2. **Foundation is in the code.** Do not ask the human whether the foundation PR (implement.md
52
+ §8) landed — check: `em engagement foundation <model>.em <slug> --code <repo root>` (GH #240;
53
+ `--json` when you need the fields). It reports every event the engagement's slices emit or
54
+ consume as `present`, `incomplete` (which fields, which tag fields are missing — named), or
55
+ `missing-event`. Any `missing-event`: STOP — the foundation has not landed for that event; ask
56
+ for the foundation PR and confirm it merged into `main` (`gh pr view <n> --json state` shows
57
+ `MERGED`), then re-run. Any `incomplete`: **one question to the human**, listing every gap the
58
+ report names (an implementer never discovers these alone) — the fix is a foundation follow-up
59
+ on `main`, never a slice PR. All `present`: go on. No slice branch is cut before this is clean.
60
+ The check is a text scan of the target tree, not a compiler: a `present` event may still fail
61
+ to type-check in the slice PR, and that is the slice PR's job to surface.
54
62
  3. **Agent models.** Read the line `- **Agent models:** implementer=<model>,
55
63
  validator=<model>, reviewer=<model>, critic=<model|codex>`. If it is absent, say once:
56
64
  "no Agent models line — using implementer=sonnet, validator=sonnet, reviewer=sonnet,
@@ -73,12 +81,23 @@ Run the shared preconditions first (tool check, bundle currency, locate the mode
73
81
  Run `em engagement plan <model>.em <slug>` (`--json` when you need the fields). Present it in
74
82
  plain terms: each level, its width against the ceiling (`parallel`), each slice's branch (every
75
83
  base is `main`), and every held slice with its reason (`not-ready`,
76
- `upstream-outside-engagement-unmerged`, or `human`). Then ask exactly one question:
84
+ `upstream-outside-engagement-unmerged`, or `human`). Then the plan's **`pre-flight:` block** (GH
85
+ #239): the model-wide gaps the engagement's slices share — a `repeated-invariant` with no single
86
+ enforcing slice, an `event-without-tag` whose consistency boundary is undeclared, a
87
+ `shared-trigger` (one `ui`, two slices, no endpoint owner), a `doc-model-mismatch`, a `shape` (a
88
+ `em validate --shape` lint fires on the slices; the answer is a `shape-accepted: <rule> <refs> —
89
+ <reason>` bullet in `.event-modeling.md` `## Decisions log`, or a model fix). These are
90
+ exactly what every implementer would otherwise stop on and report separately. Put them to the
91
+ human **in the same single question round** as the ceiling, one bullet each with the slices it
92
+ spans, and ask for a ruling on each (the answer goes where it belongs: the model, the foundation
93
+ PR, a slice doc, or `.event-modeling.md` for a deferral). Then ask exactly one question:
77
94
 
78
95
  > "Ceiling N from the plan; proceed?"
79
96
 
80
97
  Ask it once per engagement. If the human names a lower number, use it for this session. **Never
81
98
  ask "which slice first"**: the levels decide the order, and the ceiling decides how many at once.
99
+ A pre-flight finding never holds a slice: if the human says "proceed anyway" on one, dispatch
100
+ and make sure each implementer's brief carries the ruling, so no agent rediscovers it.
82
101
  A held slice is never started; the plan releases it when its hold clears.
83
102
 
84
103
  ## 3. Per level: cut the worktree, then dispatch the implementer
@@ -155,7 +174,10 @@ You never merge.
155
174
  `main`: `git switch -c engagement/<slug>-level-<n> main`, run
156
175
  `em slice mark-implemented <model>.em <key> <pr-url>` for each slice merged in the level,
157
176
  then `em slice index <model>.em`, commit, and `gh pr create --base main`. The human merges it
158
- like any other PR.
177
+ like any other PR. If `mark-implemented` printed `opened draft v<n+1>` for a slice, its doc in
178
+ this PR reads `status: draft`: say so in the hand-back and paste the command's notice into the PR
179
+ body — `shippedVersion:`/`implementedIn:` are the record that v<n> was implemented, `status:` is
180
+ the next version's state, so the reviewer does not read it as a slice that was never marked.
159
181
  4. Recompute: `em engagement plan <model>.em <slug>`. A merge can release an
160
182
  `upstream-outside-engagement-unmerged` hold once that upstream's doc reads `implemented`.
161
183
  Continue with step 3 for anything newly startable.
@@ -75,11 +75,12 @@ constitution. The implementer stops and reports it as the doc line plus the ques
75
75
  4. Carry on with every other startable slice. Never answer the question yourself, never edit the
76
76
  doc, and never let the implementer guess.
77
77
 
78
- A question the build can finish without (it does not block the slice) is not a gap: queue it with
78
+ A question the build can finish without (it does not block the slice) is not a gap: defer it with
79
79
  `em slice defer <model>.em <key> "<question>" --until v<n> --decision "<what this version does>"`
80
- (GH #236). On a ratified doc that never edits the body — `ratifiedHash` and `--slice-ready` stay
81
- green — and records the question in `.event-modeling.md` for `<key>@v<N+1>`; `mark-implemented`
82
- at merge opens v<N+1> as a draft with it in Open Questions. Never write the `- [ ]` into the
80
+ (GH #253). On a ratified doc that appends the already-deferred `- [x]` item to the doc's Open
81
+ Questions, outside `ratifiedHash` — the hash and `--slice-ready` stay green, and the question is
82
+ visible in the ratified doc; `mark-implemented` at merge opens v<n> as a draft with it reopened
83
+ as `- [ ]`. Never write a `- [ ]` into the
83
84
  ratified doc, and do not run `em slice revise` for it (an unshipped ratified doc refuses
84
85
  `revise` without `--withdraw`).
85
86
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: event-modeling
3
- em-version: 1.16.1
3
+ em-version: 1.18.0
4
4
  description: >-
5
5
  Use when the user runs `/em: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: implement
3
- em-version: 1.16.1
3
+ em-version: 1.18.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