@milehimikey/em 1.13.1 → 1.14.1

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 (235) hide show
  1. package/.claude/agents/em-critic.md +26 -0
  2. package/.claude/agents/em-implementer.md +34 -0
  3. package/.claude/agents/em-reviewer.md +31 -0
  4. package/.claude/agents/em-validator.md +27 -0
  5. package/.claude/skills/event-modeling/SKILL.md +50 -11
  6. package/.claude/skills/event-modeling-conform/SKILL.md +1 -1
  7. package/.claude/skills/event-modeling-design/SKILL.md +127 -18
  8. package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
  9. package/.claude/skills/event-modeling-engagement/SKILL.md +192 -0
  10. package/.claude/skills/event-modeling-engagement/reference/engagement.md +143 -0
  11. package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
  12. package/.claude/skills/event-modeling-implement/reference/implement.md +38 -11
  13. package/.claude/skills/event-modeling-review/SKILL.md +2 -2
  14. package/.claude/skills/event-modeling-shared/reference/em-dsl.md +279 -189
  15. package/.claude/skills/event-modeling-shared/reference/operating-principles.md +61 -0
  16. package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +116 -5
  17. package/.claude/skills/event-modeling-shared/templates/constitution.md +18 -1
  18. package/.claude/skills/event-modeling-shared/templates/slice.md +64 -39
  19. package/.claude/skills/event-modeling-shared/templates/state.md +5 -1
  20. package/.claude-plugin/marketplace.json +14 -0
  21. package/README.md +25 -11
  22. package/dist/catalog/apiFirst.d.ts +28 -0
  23. package/dist/catalog/apiFirst.js +49 -0
  24. package/dist/catalog/apiFirst.js.map +1 -0
  25. package/dist/catalog/docJoin.d.ts +13 -0
  26. package/dist/catalog/docJoin.js +11 -0
  27. package/dist/catalog/docJoin.js.map +1 -1
  28. package/dist/catalog/docModelConsistencyValidate.js +44 -4
  29. package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
  30. package/dist/catalog/invariantsValidate.d.ts +4 -0
  31. package/dist/catalog/invariantsValidate.js +102 -0
  32. package/dist/catalog/invariantsValidate.js.map +1 -0
  33. package/dist/catalog/scenarios.d.ts +15 -0
  34. package/dist/catalog/scenarios.js +97 -0
  35. package/dist/catalog/scenarios.js.map +1 -0
  36. package/dist/catalog/sliceDoc.d.ts +8 -0
  37. package/dist/catalog/sliceDoc.js +9 -0
  38. package/dist/catalog/sliceDoc.js.map +1 -1
  39. package/dist/catalog/sliceReadyValidate.d.ts +31 -4
  40. package/dist/catalog/sliceReadyValidate.js +66 -8
  41. package/dist/catalog/sliceReadyValidate.js.map +1 -1
  42. package/dist/catalog/sliceSections.d.ts +55 -0
  43. package/dist/catalog/sliceSections.js +317 -0
  44. package/dist/catalog/sliceSections.js.map +1 -0
  45. package/dist/cli/agentsMd.js +7 -1
  46. package/dist/cli/agentsMd.js.map +1 -1
  47. package/dist/cli/api.d.ts +90 -0
  48. package/dist/cli/api.js +318 -0
  49. package/dist/cli/api.js.map +1 -0
  50. package/dist/cli/ciInit.d.ts +82 -21
  51. package/dist/cli/ciInit.js +468 -64
  52. package/dist/cli/ciInit.js.map +1 -1
  53. package/dist/cli/conformScope.d.ts +28 -0
  54. package/dist/cli/conformScope.js +67 -0
  55. package/dist/cli/conformScope.js.map +1 -1
  56. package/dist/cli/coverage.d.ts +9 -0
  57. package/dist/cli/coverage.js +60 -8
  58. package/dist/cli/coverage.js.map +1 -1
  59. package/dist/cli/defer.d.ts +55 -0
  60. package/dist/cli/defer.js +244 -0
  61. package/dist/cli/defer.js.map +1 -0
  62. package/dist/cli/engagement.d.ts +210 -0
  63. package/dist/cli/engagement.js +444 -0
  64. package/dist/cli/engagement.js.map +1 -0
  65. package/dist/cli/engagementFile.d.ts +86 -0
  66. package/dist/cli/engagementFile.js +255 -0
  67. package/dist/cli/engagementFile.js.map +1 -0
  68. package/dist/cli/metrics.d.ts +10 -0
  69. package/dist/cli/metrics.js +49 -1
  70. package/dist/cli/metrics.js.map +1 -1
  71. package/dist/cli/pluginPin.d.ts +55 -0
  72. package/dist/cli/pluginPin.js +188 -0
  73. package/dist/cli/pluginPin.js.map +1 -0
  74. package/dist/cli/ratify.d.ts +27 -2
  75. package/dist/cli/ratify.js +112 -13
  76. package/dist/cli/ratify.js.map +1 -1
  77. package/dist/cli/reratify.d.ts +4 -2
  78. package/dist/cli/reratify.js +41 -16
  79. package/dist/cli/reratify.js.map +1 -1
  80. package/dist/cli/scopeInputs.d.ts +48 -0
  81. package/dist/cli/scopeInputs.js +176 -0
  82. package/dist/cli/scopeInputs.js.map +1 -0
  83. package/dist/cli/skillCheck.d.ts +15 -1
  84. package/dist/cli/skillCheck.js +22 -1
  85. package/dist/cli/skillCheck.js.map +1 -1
  86. package/dist/cli/skillDirs.d.ts +5 -0
  87. package/dist/cli/skillDirs.js +13 -1
  88. package/dist/cli/skillDirs.js.map +1 -1
  89. package/dist/cli/skillSync.d.ts +4 -0
  90. package/dist/cli/skillSync.js +23 -0
  91. package/dist/cli/skillSync.js.map +1 -1
  92. package/dist/cli/sliceNew.d.ts +11 -7
  93. package/dist/cli/sliceNew.js +91 -18
  94. package/dist/cli/sliceNew.js.map +1 -1
  95. package/dist/cli/sliceSync.d.ts +50 -0
  96. package/dist/cli/sliceSync.js +170 -0
  97. package/dist/cli/sliceSync.js.map +1 -0
  98. package/dist/cli/status.d.ts +24 -1
  99. package/dist/cli/status.js +20 -1
  100. package/dist/cli/status.js.map +1 -1
  101. package/dist/cli/systemInputs.d.ts +53 -10
  102. package/dist/cli/systemInputs.js +186 -11
  103. package/dist/cli/systemInputs.js.map +1 -1
  104. package/dist/cli/upgrade.d.ts +16 -3
  105. package/dist/cli/upgrade.js +366 -30
  106. package/dist/cli/upgrade.js.map +1 -1
  107. package/dist/cli/usageLog.d.ts +4 -2
  108. package/dist/cli/usageLog.js +4 -2
  109. package/dist/cli/usageLog.js.map +1 -1
  110. package/dist/cli.js +599 -94
  111. package/dist/cli.js.map +1 -1
  112. package/dist/emit/api.d.ts +29 -0
  113. package/dist/emit/api.js +220 -0
  114. package/dist/emit/api.js.map +1 -0
  115. package/dist/emit/apiCheckJson.d.ts +3 -0
  116. package/dist/emit/apiCheckJson.js +21 -0
  117. package/dist/emit/apiCheckJson.js.map +1 -0
  118. package/dist/emit/codeownersJson.d.ts +3 -0
  119. package/dist/emit/codeownersJson.js +19 -0
  120. package/dist/emit/codeownersJson.js.map +1 -0
  121. package/dist/emit/diffJson.d.ts +1 -1
  122. package/dist/emit/diffJson.js +8 -1
  123. package/dist/emit/diffJson.js.map +1 -1
  124. package/dist/emit/engagementJson.d.ts +8 -0
  125. package/dist/emit/engagementJson.js +46 -0
  126. package/dist/emit/engagementJson.js.map +1 -0
  127. package/dist/emit/glossaryJson.d.ts +1 -1
  128. package/dist/emit/glossaryJson.js +4 -1
  129. package/dist/emit/glossaryJson.js.map +1 -1
  130. package/dist/emit/json.d.ts +17 -1
  131. package/dist/emit/json.js +30 -1
  132. package/dist/emit/json.js.map +1 -1
  133. package/dist/emit/metricsJson.d.ts +1 -1
  134. package/dist/emit/metricsJson.js +4 -1
  135. package/dist/emit/metricsJson.js.map +1 -1
  136. package/dist/emit/queryJson.d.ts +1 -1
  137. package/dist/emit/queryJson.js +7 -1
  138. package/dist/emit/queryJson.js.map +1 -1
  139. package/dist/emit/scopeJson.d.ts +12 -0
  140. package/dist/emit/scopeJson.js +26 -0
  141. package/dist/emit/scopeJson.js.map +1 -0
  142. package/dist/emit/skillCheckJson.d.ts +3 -2
  143. package/dist/emit/skillCheckJson.js +10 -2
  144. package/dist/emit/skillCheckJson.js.map +1 -1
  145. package/dist/emit/statusJson.d.ts +1 -1
  146. package/dist/emit/statusJson.js +15 -1
  147. package/dist/emit/statusJson.js.map +1 -1
  148. package/dist/emit/systemJson.d.ts +15 -8
  149. package/dist/emit/systemJson.js +28 -13
  150. package/dist/emit/systemJson.js.map +1 -1
  151. package/dist/emit/validateJson.d.ts +3 -3
  152. package/dist/emit/validateJson.js +10 -4
  153. package/dist/emit/validateJson.js.map +1 -1
  154. package/dist/mcp/server.d.ts +1 -1
  155. package/dist/mcp/server.js +163 -31
  156. package/dist/mcp/server.js.map +1 -1
  157. package/dist/model/diff.d.ts +4 -1
  158. package/dist/model/diff.js +44 -8
  159. package/dist/model/diff.js.map +1 -1
  160. package/dist/model/glossary.d.ts +2 -0
  161. package/dist/model/glossary.js +1 -0
  162. package/dist/model/glossary.js.map +1 -1
  163. package/dist/model/model.d.ts +55 -2
  164. package/dist/model/model.js +57 -0
  165. package/dist/model/model.js.map +1 -1
  166. package/dist/model/qualifiedRef.d.ts +18 -0
  167. package/dist/model/qualifiedRef.js +26 -0
  168. package/dist/model/qualifiedRef.js.map +1 -1
  169. package/dist/model/queryIndex.d.ts +9 -1
  170. package/dist/model/queryIndex.js +18 -2
  171. package/dist/model/queryIndex.js.map +1 -1
  172. package/dist/model/rules.d.ts +143 -2
  173. package/dist/model/rules.js +162 -3
  174. package/dist/model/rules.js.map +1 -1
  175. package/dist/model/validate.d.ts +40 -0
  176. package/dist/model/validate.js +147 -1
  177. package/dist/model/validate.js.map +1 -1
  178. package/dist/parser/ast.d.ts +31 -3
  179. package/dist/parser/parser.js +148 -14
  180. package/dist/parser/parser.js.map +1 -1
  181. package/dist/query/format.js +1 -1
  182. package/dist/query/format.js.map +1 -1
  183. package/dist/query/verbs.d.ts +6 -0
  184. package/dist/query/verbs.js +6 -2
  185. package/dist/query/verbs.js.map +1 -1
  186. package/dist/system/adaptation.d.ts +14 -0
  187. package/dist/system/adaptation.js +49 -0
  188. package/dist/system/adaptation.js.map +1 -0
  189. package/dist/system/codeowners.d.ts +77 -0
  190. package/dist/system/codeowners.js +242 -0
  191. package/dist/system/codeowners.js.map +1 -0
  192. package/dist/system/manifest.d.ts +10 -5
  193. package/dist/system/manifest.js +54 -26
  194. package/dist/system/manifest.js.map +1 -1
  195. package/dist/system/migrateManifest.d.ts +28 -0
  196. package/dist/system/migrateManifest.js +155 -0
  197. package/dist/system/migrateManifest.js.map +1 -0
  198. package/dist/system/scope.d.ts +46 -0
  199. package/dist/system/scope.js +132 -0
  200. package/dist/system/scope.js.map +1 -0
  201. package/dist/system/verify.d.ts +50 -13
  202. package/dist/system/verify.js +179 -58
  203. package/dist/system/verify.js.map +1 -1
  204. package/dist/templates.d.ts +2 -2
  205. package/dist/templates.js +23 -2
  206. package/dist/templates.js.map +1 -1
  207. package/package.json +5 -2
  208. package/plugin/.claude-plugin/plugin.json +18 -0
  209. package/plugin/agents/em-critic.md +27 -0
  210. package/plugin/agents/em-implementer.md +35 -0
  211. package/plugin/agents/em-reviewer.md +32 -0
  212. package/plugin/agents/em-validator.md +28 -0
  213. package/plugin/shared/reference/em-dsl.md +871 -0
  214. package/plugin/shared/reference/methodology.md +329 -0
  215. package/plugin/shared/reference/operating-principles.md +222 -0
  216. package/plugin/shared/reference/slice-doc-schema.md +574 -0
  217. package/plugin/shared/templates/conformance-report.md +85 -0
  218. package/plugin/shared/templates/constitution.md +136 -0
  219. package/plugin/shared/templates/model-readme.md +46 -0
  220. package/plugin/shared/templates/slice.md +251 -0
  221. package/plugin/shared/templates/state.md +77 -0
  222. package/plugin/skills/conform/SKILL.md +93 -0
  223. package/plugin/skills/conform/reference/conform.md +428 -0
  224. package/plugin/skills/design/SKILL.md +298 -0
  225. package/plugin/skills/discover/SKILL.md +90 -0
  226. package/plugin/skills/discover/reference/extract.md +147 -0
  227. package/plugin/skills/engagement/SKILL.md +193 -0
  228. package/plugin/skills/engagement/reference/engagement.md +144 -0
  229. package/plugin/skills/event-modeling/SKILL.md +132 -0
  230. package/plugin/skills/implement/SKILL.md +61 -0
  231. package/plugin/skills/implement/reference/implement.md +439 -0
  232. package/plugin/skills/review/SKILL.md +74 -0
  233. package/dist/emit/typespec.d.ts +0 -26
  234. package/dist/emit/typespec.js +0 -356
  235. package/dist/emit/typespec.js.map +0 -1
@@ -12,189 +12,233 @@ Keep `.em` files focused on **structure**; put deep design in markdown linked vi
12
12
 
13
13
  <!-- GENERATED:cli:start -- run `npm run docs:generate` to refresh, do not hand-edit -->
14
14
  ```bash
15
- em --version # print the installed em version
16
- em init [file] # scaffold a starter .em model
17
- em init [file] -f, --force # overwrite if the file exists
18
- em scaffold <name> # scaffold a full project: <slug>/<slug>.em, README.md, .event-modeling.md, and constitution.md (the implementation constitution — skipped, with a note, in a spec-kit project, where `.specify/memory/constitution.md` IS that document) (see docs/cli.md — for just a starter .em, use `em init`; for a multi-model project, pass --under to nest it under a shared parent directory)
19
- em scaffold <name> -f, --force # overwrite the directory's contents if it already exists
20
- em scaffold <name> --under <dir> # parent directory to scaffold into — writes <dir>/<slug>/ instead of ./<slug>/, the supported multi-model layout (docs/cli.md, "Multi-model projects"): one directory per model, so each model's slices/ never collides with a sibling model's
21
- em render <file> # transpile a model and render it (or emit DOT)
22
- em render <file> -o, --out <path> # output path (extension picks the format)
23
- em render <file> -T, --format <fmt> # output format (svg, png, pdf, ...)
24
- em render <file> --slice <name> # render only this slice, redrawn in its own canonical pattern shape (default out: slices/<kebab-slug>.svg)
25
- em render <file> --emit-dot # print the generated DOT instead of rendering
26
- em render <file> --keep-empty-lanes # keep the API lane even when empty
27
- em export <file> # export a versioned JSON snapshot of the normalized model
28
- em export <file> -o, --out <path> # write to a file instead of stdout
29
- em export <file> --slice <key> # export only this slice's object (pattern/fields/doc) instead of the whole model (export key, MIL-128) — refuses only if THIS slice has an error; an unrelated slice's breakage elsewhere in the model doesn't block it (see docs/cli.md)
30
- em typespec <file> # EXPERIMENTAL/POC (MIL-159): generate a TypeSpec contract for a model's commands, public events, and public views (see docs/cli.md)
31
- em typespec <file> -o, --out <path> # write to a file instead of stdout
32
- em diff <old> [new] # compare two models structurally (two files, or one file across git revisions)
33
- em diff <old> [new] --from <rev> # diff <old> against this git revision instead of a second file
34
- em diff <old> [new] --to <rev> # diff against this git revision instead of the current file (requires --from)
35
- em diff <old> [new] --exit-code # exit 1 if the models differ, 0 if identical (git-diff convention)
36
- em diff <old> [new] --json # print a JSON document instead of the text report (see docs/cli.md)
37
- em glossary <files> # cross-model glossary of terms, with consistency checks across models (see docs/cli.md)
38
- em glossary <files> --json # print the full glossary document instead of the text report
39
- em glossary <files> -o, --out <path> # write the JSON document to a file instead of stdout (requires --json)
40
- em glossary <files> --list-conflicts # print only the conflict lines, no summary
41
- em glossary <files> --fail-on-conflicts # exit non-zero if any cross-model term conflicts were found (opt-in — conflicts are warnings and don't block by default)
42
- em catalog <files> # generate a browsable static HTML catalog site over one or more .em models (see docs/cli.md)
43
- em catalog <files> -o, --out <dir> # output directory
44
- em catalog <files> -T, --format <fmt> # diagram format embedded in the catalog (svg or png)
45
- em catalog <files> --title <text> # catalog site title
46
- em catalog <files> --keep-empty-lanes # keep the API lane even when empty
47
- em slice new <name> # scaffold a fresh slices/<key>.md doc — the 5 frontmatter keys required at `status: draft` plus the `# Slice:` heading and diagram-image stub; judgment sections (Intent, Scenarios, Open Questions, ...) stay hand-authored (see .claude/skills/event-modeling-shared/reference/slice-doc-schema.md, templates/slice.md)
48
- em slice new <name> --pattern <pattern> # slice pattern: state-change | state-view | automation | translation
49
- em slice new <name> --swimlane <swimlane> # swimlane, e.g. "Persona → Context"
50
- em slice new <name> -f, --force # overwrite the file if it already exists
51
- em slice new <name> --wire <model-file> # also insert the `note "slices/<key>.md"` line onto the slice's primary element in this .em file (matched by export key), instead of just printing it to paste by hand (MIL-161)
52
- em slice new <name> --stub # write a near-free stub instead: same 5 frontmatter keys, but a one-line placeholder body instead of the diagram-image stub and every judgment section (MIL-184) — deepen it later by re-running without --stub and -f
53
- em slice stub-all <file> # scaffold + wire a near-free stub (`em slice new --stub`'s content, MIL-184) for every slice in <file> with no resolvable doc — the fast path to status coloring for an exploratory/backbone model without hand-running `slice new` per slice. Skips a continuation slice (MIL-208, it has no doc of its own), an already-documented slice, and a slice whose pattern can't be classified
54
- em slice stub-all <file> --status <status> # target status for every stub: draft | reviewed | ready-to-implement | implemented
55
- em slice stub-all <file> --by <name> # identity for reviewedBy/ratifiedBy — required unless --status draft
56
- em slice stub-all <file> --implemented-in <url> # PR/commit URL for implementedIn — required with --status implemented
57
- em slice stub-all <file> --dry-run # list what would be stubbed/wired without writing anything
58
- em slice index <file> # rewrite the model's sibling README.md's GENERATED Slices table from `em export`'s slice facts (key, pattern, doc status/implementedIn) — the hand-maintained table is deprecated
59
- em slice index <file> --check # verify the table is current; exit non-zero on drift without writing (CI)
60
- em slice mark-implemented <file> <slice-key> <pr-url> # flip a slice doc's frontmatter to `status: implemented` / `implementedIn: <pr-url>` — the one edit an implementing agent makes to a ratified doc at merge (MIL-103, replaces the em-sdd-bridge `em-sdd-mark-implemented` script; see reference/implement.md §6). Idempotent on the same URL; refuses to overwrite a different one; never touches `version:` or the doc body
61
- em slice review <file> <slice-key> # flip a slice doc's frontmatter to `status: reviewed` and record `reviewedBy:`/`reviewedOn:` — the FIRST of the two human gates (MIL-201, docs/process.md#the-slice-lifecycle-gates): the room walked this slice and every open question it raised is resolved. Ratification is a separate, later gate (`em slice ratify`). Legal from `status: draft`; idempotent on the same --by/--on pair; refuses to overwrite a different one already recorded; refuses a doc already `ready-to-implement`/`implemented`; never touches `version:` or the doc body
62
- em slice review <file> <slice-key> --by <name> # the reviewer's (or facilitator's) name
63
- em slice review <file> <slice-key> --on <date> # review date, YYYY-MM-DD (default: today, local date)
64
- em slice ratify <file> <slice-key> # flip a slice doc's frontmatter to `status: ready-to-implement` and record `ratifiedBy:`/`ratifiedOn:` — the handoff sign-off (MIL-165, docs/process.md#the-slice-lifecycle-gates) that makes who ratified, and when, a first-class recorded fact. The review gate is a check on the doc's current `status:`, not on whether `reviewedBy:`/`reviewedOn:` are populated: a doc at `reviewed` or `ready-to-implement` passes (the latter is where `em slice reratify` leaves a doc, so the follow-up ratify needs no --skip-review); any other status — a `draft` that never went through `em slice review` — is refused unless --skip-review is passed. Idempotent on the same --by/--on pair; refuses to overwrite a different one already recorded; never touches `version:` or the doc body
65
- em slice ratify <file> <slice-key> --by <name> # the ratifier's name
66
- em slice ratify <file> <slice-key> --on <date> # ratification date, YYYY-MM-DD (default: today, local date)
67
- em slice ratify <file> <slice-key> --skip-review # ratify without a recorded review — prints a loud notice on stderr
68
- em slice reratify <file> <slice-key> # bump `version:` and flip a shipped slice doc's frontmatter back to `status: ready-to-implement` — the re-ratification mechanical edit (MIL-161, mirrors `em slice mark-implemented`). Applies to a doc at `status: implemented`, or (MIL-258) to a `ready-to-implement` doc that is ratified but not yet shipped — there it bumps `version:` and clears the sign-off but leaves `status:` alone; a `ready-to-implement` doc with no `ratifiedBy:` refuses (awaiting `em slice ratify --by`). Clears any stale `ratifiedBy:`/`ratifiedOn:`/`reviewedBy:`/`reviewedOn:` (they describe the PRIOR version's review and sign-off) so a follow-up `em slice ratify --by` applies cleanly — and needs no fresh review; never touches `implementedIn:` or the doc body
69
- em slice conform <file> <slice-key> # record per-slice-per-version conformance certification: sets `conformedVersion:`/`conformedAt:`/`conformedOn:` on a slice doc (MIL-214) — the fact `driftSignal: in-sync` now depends on. Legal only for `status: implemented` with an `implementedIn:` link. Idempotent on the same (version, --at) pair; a different --at simply overwrites (a later re-certification is normal — there's no way for em to tell 'later' from 'earlier' for an arbitrary revision string, so there's no --force to reach for). Refuses when the newest conformance/*-findings.json matching --at still has an unruled finding in scope for this slice; --skip-findings-check overrides with a loud notice.
70
- em slice conform <file> <slice-key> --at <rev> # the target-repo revision this certification sweep diffed against
71
- em slice conform <file> <slice-key> --on <date> # certification date, YYYY-MM-DD (default: today, local date)
72
- em slice conform <file> <slice-key> --skip-findings-check # certify even with unruled findings in scope — prints a loud notice on stderr
73
- em changelog <file> # render a model's git history as a business-readable ledger (see docs/cli.md)
74
- em changelog <file> --from <rev> # start the walk at this revision (inclusive)
75
- em changelog <file> --to <rev> # end the walk at this revision (inclusive; default HEAD)
76
- em changelog <file> -o, --out <path> # write to a file instead of stdout
77
- em state read [dir] # print the state file's mechanical fields as JSON
78
- em state set-phase <phase> [dir] # rewrite Current phase: (and Last updated:); --step also rewrites Current step:
79
- em state set-phase <phase> [dir] --step <n> # also set Current step: to this value
80
- em state set-conformance <revision> [dir] # rewrite Last conformance: (and Last updated:) in the exact format reference/conform.md parses. Refuses (MIL-214) while any `implemented` slice has an unruled conformance finding in the findings JSON beside --report (a `slice: null` finding blocks every slice); --partial records the marker with a ` (partial)` suffix instead, with a loud notice. Without a findings JSON beside --report: warns once and records the marker as given (migration path for a report predating `em conform-findings`)
81
- em state set-conformance <revision> [dir] --report <path> # path to the conformance report just written
82
- em state set-conformance <revision> [dir] --partial # record the marker as PARTIAL even though some in-scope findings are still unruled
83
- em state set-review <date> [dir] # rewrite Last stakeholder review: (and Last updated:)
84
- em state log-usage <file> # append one Usage log line — phase(s) touched + em validate's diagnostic categories hit, deduped and canonically formatted (MIL-161, docs/usage-data.md) — the mechanical half of 'save state at the end of every session' that used to be run-validate-then-hand-format; state file resolved next to <file>, same convention as em conform-scope
85
- em state log-usage <file> --phases <list> # comma-separated phase(s) touched this session: discover, extract, model, slice, implement, conform, review, validate, watch
86
- em model version bump <file> # bump the model's design version: write model-versions/v<N+1>.json (sibling of slices/, conformance/) and rewrite the state file's `Model version:` bullet (MIL-218). Refuses when the state file is missing (run `em scaffold` first), when --by is empty, and when nothing has changed since the current version (same model content hash AND same slice-version vector) unless --force — a no-op bump is the one case --force is right for.
87
- em model version bump <file> --by <name> # the bumper's name
88
- em model version bump <file> --on <date> # bump date, YYYY-MM-DD (default: today, local date)
89
- em model version bump <file> --force # bump even though nothing has changed since the current version
90
- em model version show <file> # print the model's current design version and the most recently certified version, if any (model-versions/*.json — MIL-218)
91
- em model version show <file> --json # print a JSON document instead of text
92
- em usage-report [root] # aggregate every .event-modeling.md's Usage log under [root] into phase/diagnostic-category tallies (MIL-161) — replaces docs/usage-data.md's hand-rolled grep/awk/sort pipeline; a logged line that doesn't match the canonical em state log-usage format is reported under unparseableLines rather than silently mistallied or dropped
93
- em usage-report [root] --json # print a JSON document instead of the text report
94
- em conform-scope <file> # mechanize conform phase step 1 (reference/conform.md): map the target repo's changed paths since Last conformance: to slices via each slice doc's implementedIn, JSON to stdout — --seed-asis also seeds the <model>-asis.em scratch model (see docs/cli.md)
95
- em conform-scope <file> --repo <path> # path to (or inside) the target codebase's git repository
96
- em conform-scope <file> --full # ignore Last conformance:/changed paths; scope every implemented slice
97
- em conform-scope <file> --seed-asis # write <model>-asis.em as a byte copy of the canonical model and ensure it's gitignored
98
- em conform-supersede <file> <report-path> # stamp a conformance report with a "superseded as of <rev>" banner once its findings have been ruled on (MIL-164, docs/process.md#what-ratified-means) — the companion step to run at ratification time so a reader following the report's file:line citations knows they describe an ancestor of the current model. Additive-only splice, never a rewrite of the report; idempotent on the same --as-of/--findings/--on stamp; refuses if the report doesn't exist. --locus/--by (MIL-214, both required together) additionally record the ruling itself — locus/resolvedBy/resolvedOn — on the findings named by --findings in the sibling conformance/<date>-findings.json, when one exists (warns once and stamps the banner only when it doesn't — the migration path for a report predating em conform-findings)
99
- em conform-supersede <file> <report-path> --as-of <rev> # the revision this ruling was made against — same value passed to `em state set-conformance`
100
- em conform-supersede <file> <report-path> --findings <spec> # which finding number(s) this stamps as ruled, e.g. "1-3" or "1,2,4"
101
- em conform-supersede <file> <report-path> --on <date> # ruling date, YYYY-MM-DD (default: today, local date)
102
- em conform-supersede <file> <report-path> --locus <locus> # who/what the named finding(s) say is wrong: model | doc | code | none (requires --by)
103
- em conform-supersede <file> <report-path> --by <name> # who ruled on the named finding(s) (requires --locus)
104
- em conform-findings check <path> # shape-validate a conformance/<date>-findings.json file (findingsSchemaVersion, required fields, enum values, ids sorted+unique, a ruled finding carries resolvedBy+resolvedOn) — exit 1 on shape errors. The conform skill writes this file directly alongside its report; this is how a headless run verifies what it just wrote.
105
- em conform-findings check <path> --json # print a JSON document instead of the text report
106
- em watch <file> # re-render on every save
107
- em watch <file> -o, --out <path> # output path (extension picks the format)
108
- em watch <file> -T, --format <fmt> # output format (svg, png, pdf, ...)
109
- em watch <file> --keep-empty-lanes # keep the API lane even when empty
110
- em watch <file> --serve # serve a live viewer with instant push-reload (no polling)
111
- em watch <file> --port <n> # port for --serve (default 5173)
112
- em validate <file> # check a model against event-modeling rules
113
- em validate <file> --list-issues # print only open `issue` diagnostics (slice, element, line, text)
114
- em validate <file> --list-divergences # print only accepted-divergence annotations (slice, element, line, text) — never fails the build
115
- em validate <file> --list-public # print only events and views marked `public` (slice, kind, name, line) — an integration-surface audit, never fails the build
116
- em validate <file> --fail-on-issues # exit non-zero if the model has any open `issue`s (opt-in — issues are warnings and don't block by default)
117
- em validate <file> --slice-ready <key> # readiness gate for one slice (export key): status ready-to-implement, doc resolvable via note binding, zero unchecked Open Questions — exits non-zero if not ready (MIL-87)
118
- em validate <file> --json # print a JSON document instead of text — works on a model WITH errors, unlike `em export` (MIL-128, see docs/cli.md); exit codes are unchanged
119
- em migrate <file> # rewrite the old two-slice Automation/Translation shape into the merged single-slice shape MIL-120 made canonical (see docs/cli.md)
120
- em migrate <file> --write # apply the rewrite to the file (default: dry run — report only, write nothing)
121
- em ledger <file> # check slice docs' version: field agrees with their content across two git revisions (opt-in CI check, MIL-89 — never part of `em validate`, see docs/ci.md)
122
- em ledger <file> --from <rev> # baseline revision
123
- em ledger <file> --to <rev> # compare revision (default: current working tree)
124
- em ledger <file> --waive <slice-key> # excuse a doc-content-without-version-bump finding for this slice key (repeatable; MIL-185, see docs/cli.md) — never waives a version regression or bump-without-content-change
125
- em ledger <file> --json # print a JSON document instead of the text report (see docs/cli.md)
126
- em coverage <file> # check that every INV-* invariant ID cited in an implemented slice doc is cited by a test under --tests <dir> (MIL-130/MIL-207) — mechanizes reference/implement.md's definition-of-done citation check; advisory by default, --strict for CI; --include-ready also counts ready-to-implement docs (forward-looking report); a continuation slice (an `again` view instance with no doc of its own, MIL-208) is excluded from the report — its invariants, if any, live in the originating slice's own doc; --slice <key> scopes the report to one slice whatever its status (MIL-255), the pre-merge definition-of-done check
127
- em coverage <file> --tests <dir> # directory to scan recursively for test files citing invariant IDs
128
- em coverage <file> --slice <key> # only this slice (export key), whether ready-to-implement or implemented — no --include-ready needed; --strict then fails on this slice's uncited invariants, or if the slice is not in scope (draft/reviewed/unbound: nothing checked) (MIL-255)
129
- em coverage <file> --strict # exit non-zero if any invariant ID has zero citations (CI)
130
- em coverage <file> --include-ready # also count ready-to-implement docs, not just implemented (MIL-207)
131
- em coverage <file> --json # print a JSON document instead of the text report (see docs/cli.md)
132
- em status <files> # deterministic state-of-the-system rollup over one or more .em models: slices by lifecycle status, driftSignal breakdown, invariant coverage totals (with --tests), open issue markers + unchecked Open Questions, and last-conformance commits-behind-HEAD (MIL-163, see docs/cli.md)
133
- em status <files> --tests <dir> # directory to scan for INV-* test citations — enables invariant coverage totals
134
- em status <files> --repo <path> # git repo to compute commits-behind-HEAD in (default: each model's own directory)
135
- em status <files> --json # print a JSON document instead of the text report (see docs/cli.md)
136
- em status <files> --md # print a markdown block suited for README embedding
137
- em status <files> --badge # print a generated SVG badge
138
- em status <files> -o, --out <path> # write output to a file instead of stdout
139
- em freshness <file> # standalone freshness signal for one model's conformance record (MIL-164): "last conformed <rev> — N commits and M slice-PRs behind HEAD", computed from the same conform-scope machinery `em status`'s conformance clause uses — for when you want just this fact, no full state-of-the-system rollup (see docs/cli.md)
140
- em freshness <file> --repo <path> # git repo to compute behind-HEAD in (default: the model's own directory)
141
- em freshness <file> --json # print a JSON document instead of the text line
142
- em metrics <file> # the pilot metrics named in advance by the register, computed from git history alone (MIL-170): ratification turnaround (reviewed -> ratified -> implemented), conform-cycle cadence + finding counts, and status-vs-reality disagreement over time — plus a fourth, reported as not computable from history (see docs/usage-data.md). `<file>` is an anchor .em file, used only to locate slices/, conformance/, and .event-modeling.md relative to it — same convention as em ledger; never parsed or compiled
143
- em metrics <file> --from <rev> # baseline revision
144
- em metrics <file> --to <rev> # compare revision (default: HEAD)
145
- em metrics <file> --json # print a JSON document instead of the text report (see docs/cli.md)
146
- em query consumers <files> # views/reactions consuming an event, plus their slices
147
- em query consumers <files> --event <ref-or-name> # the event's export ref or display name
148
- em query consumers <files> --json # print a JSON document instead of the text report
149
- em query producers <files> # commands producing an event, plus their slices and ui triggers
150
- em query producers <files> --event <ref-or-name> # the event's export ref or display name
151
- em query producers <files> --json # print a JSON document instead of the text report
152
- em query downstream <files> # transitive closure along legal edges from an element — impact analysis
153
- em query downstream <files> --of <ref-or-name> # the starting element's export ref or display name
154
- em query downstream <files> --depth <n> # limit traversal to n hops (default: unlimited)
155
- em query downstream <files> --json # print a JSON document instead of the text report
156
- em query upstream <files> # transitive closure against legal-edge direction from an element
157
- em query upstream <files> --of <ref-or-name> # the starting element's export ref or display name
158
- em query upstream <files> --depth <n> # limit traversal to n hops (default: unlimited)
159
- em query upstream <files> --json # print a JSON document instead of the text report
160
- em query slices <files> # filtered slice list — pattern/status/context/persona/tag filters AND-combine
161
- em query slices <files> --pattern <p> # state-change | state-view | automation | translation | unclassified
162
- em query slices <files> --status <s> # the slice's joined doc status (draft, reviewed, ready-to-implement, implemented, ...)
163
- em query slices <files> --context <c> # match a slice with an event in this @Context
164
- em query slices <files> --persona <p> # match a slice with a ui in this @Persona
165
- em query slices <files> --tag <t> # match a slice with an event carrying this tag key
166
- em query slices <files> --json # print a JSON document instead of the text report
167
- em query invariant <files> # declaring slice + doc facts for one INV-* id, and (with --tests) its test citations
168
- em query invariant <files> --id <inv-id> # the INV-* id to look up
169
- em query invariant <files> --tests <dir> # directory to scan for test files citing this id
170
- em query invariant <files> --json # print a JSON document instead of the text report
171
- em query field <files> # one field's facts on an element — type, tag/assigned markers, renamed-from chain
172
- em query field <files> --of <element-ref> # the element's export ref or display name
173
- em query field <files> --name <field> # the field's name
174
- em query field <files> --json # print a JSON document instead of the text report
175
- em query path <files> # shortest path between two elements through the six legal connection types
176
- em query path <files> --from <ref-or-name> # the starting element's export ref or display name
177
- em query path <files> --to <ref-or-name> # the ending element's export ref or display name
178
- em query path <files> --json # print a JSON document instead of the text report
179
- em system <manifest> # verify a seam manifest (system.yaml) against its models' exports — every `public` event/view bound to a reaction in another model, the cross-model half of "both ends of a flow" (MIL-194, see docs/cli.md)
180
- em system <manifest> --json # print a JSON document instead of the text report (see docs/cli.md)
181
- em contract # print the packaged implementation contract (reference/implement.md) to stdout — the agent-neutral discovery path for any agent that can run a shell, not just Claude Code (MIL-129); see docs/cli.md
182
- em mcp # start an MCP (Model Context Protocol) server over stdio (MIL-21) — a structured, agent-facing alternative to shelling out to `em`; every tool mirrors a CLI `--json` surface byte-for-byte. docs/mcp.md isn't vendored into the skill bundle — for the handshake and the full, current tool table (the list changes as commands gain MCP parity, so it's not repeated here — MIL-187) see https://github.com/milehimikey/em/blob/main/docs/mcp.md. Equivalent to running the `em-mcp` bin directly
183
- em skill install # copy the event-modeling skill bundle into .claude/skills/ (event-modeling, event-modeling-discover/-design/-implement/-conform/-review, event-modeling-shared); across a structural bundle change (e.g. the MIL-157 split of the old single event-modeling/ directory into this six-directory bundle), `em skill sync` is the migration path — --force now performs the same reconcile (MIL-180)
184
- em skill install -f, --force # overwrite an existing installation, reconciling added/updated/removed files within the bundle's own managed directories the same way `em skill sync` does — never touching an unrelated sibling skill (MIL-180)
185
- em skill install --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
186
- em skill sync [path] # update the vendored .claude/skills/ event-modeling skill bundle in [path] to match the installed em package (overwrites unconditionally; local edits are never merged, MIL-93)
187
- em skill sync [path] --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
188
- em skill check [path] # check the vendored .claude/skills/ event-modeling skill bundle in [path] for drift against the installed em package; exits non-zero on any mismatch (CI-ready, MIL-93)
189
- em skill check [path] --json # print a JSON document instead of the text report (see docs/cli.md)
190
- em ci init <model> # install .github/workflows/em-ci.yml (PR gates: em validate, em slice index --check, em coverage --strict, em ledger, em skill check, em glossary --fail-on-conflicts, plus a push-triggered status-badge rebuild) and em-conform.yml (scheduled, advisory-only conformance cadence) — same install discipline as `em skill install`: marker-delimited, idempotent, --check for CI self-verification (MIL-166, see docs/ci.md)
191
- em ci init <model> --tests <dir> # test directory the coverage/status steps scan for INV-* citations
192
- em ci init <model> -f, --force # replace an existing workflow file that has no GENERATED markers, or a managed block generated for a different model
193
- em ci init <model> --check # verify both files match the current preset; exit non-zero on drift without writing (CI)
194
- em upgrade <file> # bring a model repo authored under an older em (1.6 forward) up to the installed version: an ordered list of mechanical steps (skill bundle, reaction shape, state-file bullets, generated CI blocks, constitution scaffold) plus a human list of things no command can safely decide by itself (MIL-219, see docs/upgrading.md). Dry-run by default; --apply makes one git commit per applicable step, refusing on a dirty working tree
195
- em upgrade <file> --apply # apply every applicable mechanical step, one git commit each, then a final `Em version:` commit
196
- em upgrade <file> --check # exit non-zero only on a hard incompatibility (an existing but unparseable state file, an un-migratable .em shape) — writes nothing; what CI runs; the final line says why
197
- em upgrade <file> --json # print a JSON document instead of text (dry-run/--check only, never with --apply)
15
+ em --version # print the installed em version
16
+ em init [file] # scaffold a starter .em model
17
+ em init [file] -f, --force # overwrite if the file exists
18
+ em scaffold <name> # scaffold a full project: <slug>/<slug>.em, README.md, .event-modeling.md, and constitution.md (the implementation constitution — skipped, with a note, in a spec-kit project, where `.specify/memory/constitution.md` IS that document) (see docs/cli.md — for just a starter .em, use `em init`; for a multi-model project, pass --under to nest it under a shared parent directory)
19
+ em scaffold <name> -f, --force # overwrite the directory's contents if it already exists
20
+ em scaffold <name> --under <dir> # parent directory to scaffold into — writes <dir>/<slug>/ instead of ./<slug>/, the supported multi-model layout (docs/cli.md, "Multi-model projects"): one directory per model, so each model's slices/ never collides with a sibling model's
21
+ em render <file> # transpile a model and render it (or emit DOT)
22
+ em render <file> -o, --out <path> # output path (extension picks the format)
23
+ em render <file> -T, --format <fmt> # output format (svg, png, pdf, ...)
24
+ em render <file> --slice <name> # render only this slice, redrawn in its own canonical pattern shape (default out: slices/<kebab-slug>.svg)
25
+ em render <file> --emit-dot # print the generated DOT instead of rendering
26
+ em render <file> --keep-empty-lanes # keep the API lane even when empty
27
+ em export <file> # export a versioned JSON snapshot of the normalized model
28
+ em export <file> -o, --out <path> # write to a file instead of stdout
29
+ em export <file> --slice <key> # export only this slice's object (pattern/fields/doc) instead of the whole model (export key, MIL-128) — refuses only if THIS slice has an error; an unrelated slice's breakage elsewhere in the model doesn't block it (see docs/cli.md)
30
+ em api generate <file> # write the TypeSpec contract for the model's public commands, events and views to <model dir>/contracts/<model key>.tsp
31
+ em api generate <file> -o, --out <path> # write to this path instead of <model dir>/contracts/<model key>.tsp
32
+ em api generate <file> --stdout # print the contract instead of writing it
33
+ em api check <file> # is the committed contract current? With --base, annotate each public-surface change since that revision additive or breaking (annotation only — exits 1 only when stale)
34
+ em api check <file> --base <rev> # git revision to diff the public surface against
35
+ em api check <file> --json # print a JSON document instead of the text report (see docs/cli.md)
36
+ em typespec <file> # DEPRECATED alias of `em api generate --stdout` (use em api generate)
37
+ em typespec <file> -o, --out <path> # write to a file instead of stdout
38
+ em diff <old> [new] # compare two models structurally (two files, or one file across git revisions)
39
+ em diff <old> [new] --from <rev> # diff <old> against this git revision instead of a second file
40
+ em diff <old> [new] --to <rev> # diff against this git revision instead of the current file (requires --from)
41
+ em diff <old> [new] --exit-code # exit 1 if the models differ, 0 if identical (git-diff convention)
42
+ em diff <old> [new] --json # print a JSON document instead of the text report (see docs/cli.md)
43
+ em glossary <files> # cross-model glossary of terms, with consistency checks across models (see docs/cli.md)
44
+ em glossary <files> --json # print the full glossary document instead of the text report
45
+ em glossary <files> -o, --out <path> # write the JSON document to a file instead of stdout (requires --json)
46
+ em glossary <files> --list-conflicts # print only the conflict lines, no summary
47
+ em glossary <files> --fail-on-conflicts # exit non-zero if any cross-model term conflicts were found (opt-in — conflicts are warnings and don't block by default)
48
+ em catalog <files> # generate a browsable static HTML catalog site over one or more .em models (see docs/cli.md)
49
+ em catalog <files> -o, --out <dir> # output directory
50
+ em catalog <files> -T, --format <fmt> # diagram format embedded in the catalog (svg or png)
51
+ em catalog <files> --title <text> # catalog site title
52
+ em catalog <files> --keep-empty-lanes # keep the API lane even when empty
53
+ em slice new <name> # scaffold a fresh slices/<key>.md doc — the 5 frontmatter keys required at `status: draft`, the `# Slice:` heading and diagram-image stub, then every template section: the generated regions (command/event/view field tables, Invariants) filled from the model with --wire (template placeholders otherwise — `em slice sync` fills them), the authored sections (Intent, Scenarios, Open Questions, ...) with placeholder bullets (see .claude/skills/event-modeling-shared/reference/slice-doc-schema.md, templates/slice.md)
54
+ em slice new <name> --pattern <pattern> # slice pattern: state-change | state-view | automation | translation
55
+ em slice new <name> --swimlane <swimlane> # swimlane, e.g. "Persona → Context"
56
+ em slice new <name> -f, --force # overwrite the file if it already exists
57
+ em slice new <name> --wire <model-file> # also insert the `note "slices/<key>.md"` line onto the slice's primary element in this .em file (matched by export key), instead of just printing it to paste by hand (MIL-161)
58
+ em slice new <name> --stub # write a near-free stub instead: same 5 frontmatter keys, but a one-line placeholder body instead of the diagram-image stub and every judgment section (MIL-184) — deepen it later by re-running without --stub and -f
59
+ em slice sync <model-file> [key] # regenerate the GENERATED regions (command/event/view field tables, the Invariants list) of existing slice docs in place from the model, authored sections untouched (MIL-266); docs without regions are skipped with a note. --check never writes and exits 1 when a doc is stale
60
+ em slice sync <model-file> [key] --check # report ok / stale / no-regions per doc without writing; exit 1 when any is stale
61
+ em slice sync <model-file> [key] --json # print the machine-readable report (sliceSyncSchemaVersion 1.0)
62
+ em slice stub-all <file> # scaffold + wire a near-free stub (`em slice new --stub`'s content, MIL-184) for every slice in <file> with no resolvable doc — the fast path to status coloring for an exploratory/backbone model without hand-running `slice new` per slice. Skips a continuation slice (MIL-208, it has no doc of its own), an already-documented slice, and a slice whose pattern can't be classified
63
+ em slice stub-all <file> --status <status> # target status for every stub: draft | reviewed | ready-to-implement | implemented
64
+ em slice stub-all <file> --by <name> # identity for reviewedBy/ratifiedBy — required unless --status draft
65
+ em slice stub-all <file> --implemented-in <url> # PR/commit URL for implementedIn — required with --status implemented
66
+ em slice stub-all <file> --dry-run # list what would be stubbed/wired without writing anything
67
+ em slice index <file> # rewrite the model's sibling README.md's GENERATED Slices table from `em export`'s slice facts (key, pattern, doc status/implementedIn) — the hand-maintained table is deprecated
68
+ em slice index <file> --check # verify the table is current; exit non-zero on drift without writing (CI)
69
+ em slice mark-implemented <file> <slice-key> <pr-url> # flip a slice doc's frontmatter to `status: implemented` / `implementedIn: <pr-url>` — the one edit an implementing agent makes to a ratified doc at merge (MIL-103, replaces the em-sdd-bridge `em-sdd-mark-implemented` script; see reference/implement.md §6). Idempotent on the same URL; refuses to overwrite a different one; never touches `version:` or the doc body
70
+ em slice review <file> <slice-key> # flip a slice doc's frontmatter to `status: reviewed` and record `reviewedBy:`/`reviewedOn:` — the FIRST of the two human gates (MIL-201, docs/process.md#the-slice-lifecycle-gates): the room walked this slice and every open question it raised is resolved. Ratification is a separate, later gate (`em slice ratify`). Legal from `status: draft`; idempotent on the same --by/--on pair; refuses to overwrite a different one already recorded; refuses a doc already `ready-to-implement`/`implemented`; never touches `version:` or the doc body
71
+ em slice review <file> <slice-key> --by <name> # the reviewer's (or facilitator's) name
72
+ em slice review <file> <slice-key> --on <date> # review date, YYYY-MM-DD (default: today, local date)
73
+ em slice ratify <file> <slice-key> # flip a slice doc's frontmatter to `status: ready-to-implement` and record `ratifiedBy:`/`ratifiedOn:` — the handoff sign-off (MIL-165, docs/process.md#the-slice-lifecycle-gates) that makes who ratified, and when, a first-class recorded fact. The review gate is a check on the doc's current `status:`, not on whether `reviewedBy:`/`reviewedOn:` are populated: a doc at `reviewed` or `ready-to-implement` passes (the latter is where `em slice reratify` leaves a doc, so the follow-up ratify needs no --skip-review); any other status — a `draft` that never went through `em slice review` — is refused unless --skip-review is passed. Idempotent on the same --by/--on pair; refuses to overwrite a different one already recorded; never touches `version:` or the doc body
74
+ em slice ratify <file> <slice-key> --by <name> # the ratifier's name
75
+ em slice ratify <file> <slice-key> --on <date> # ratification date, YYYY-MM-DD (default: today, local date)
76
+ em slice ratify <file> <slice-key> --skip-review # ratify without a recorded review — prints a loud notice on stderr
77
+ em slice ratify <file> <slice-key> --meaning-unchanged # API-first sign-off (MIL-238): this version does not change what the public contract means — records `meaningConfirmed: true`; required (or --contract-change) on a slice touching a `public` element
78
+ em slice ratify <file> <slice-key> --contract-change <why> # API-first sign-off (MIL-238): a consumer must read this change differently, and why — records `contractChange: "<why>"`
79
+ em slice reratify <file> <slice-key> # bump `version:` and flip a shipped slice doc's frontmatter back to `status: ready-to-implement` — the re-ratification mechanical edit (MIL-161, mirrors `em slice mark-implemented`). Applies to a doc at `status: implemented`, or (MIL-258) to a `ready-to-implement` doc that is ratified but not yet shipped — there it bumps `version:` and clears the sign-off but leaves `status:` alone; a `ready-to-implement` doc with no `ratifiedBy:` refuses (awaiting `em slice ratify --by`). Clears any stale `ratifiedBy:`/`ratifiedOn:`/`reviewedBy:`/`reviewedOn:` (they describe the PRIOR version's review and sign-off) so a follow-up `em slice ratify --by` applies cleanly — and needs no fresh review; never touches `implementedIn:` or the doc body
80
+ em slice reratify <file> <slice-key> --meaning-unchanged # API-first sign-off (MIL-238): the new version does not change what the public contract means — records `meaningConfirmed: true`; required (or --contract-change) on a slice touching a `public` element
81
+ em slice reratify <file> <slice-key> --contract-change <why> # API-first sign-off (MIL-238): a consumer must read the new version differently, and why — records `contractChange: "<why>"`
82
+ em slice defer <file> <slice-key> <question> # record a question this version will not answer as deferred to a later version (MIL-275): rewrites the single unchecked `## Open Questions` item containing <question> as `- [x] <item> — v<current>: <decision>; deferred to v<n> (<date>[, <by>])` so `--slice-ready` passes without a guess, and mirrors it into `.event-modeling.md` (the parking lot and a dated Decisions-log bullet; the file must exist, it is never created). Idempotent; `em slice reratify` re-opens the item when it bumps to v<n>
83
+ em slice defer <file> <slice-key> <question> --until <version> # the version that must answer it, v<n> (greater than the doc's version)
84
+ em slice defer <file> <slice-key> <question> --decision <text> # what this version does instead
85
+ em slice defer <file> <slice-key> <question> --by <name> # who deferred it
86
+ em slice defer <file> <slice-key> <question> --on <date> # deferral date, YYYY-MM-DD (default: today, local date)
87
+ em slice conform <file> <slice-key> # record per-slice-per-version conformance certification: sets `conformedVersion:`/`conformedAt:`/`conformedOn:` on a slice doc (MIL-214) — the fact `driftSignal: in-sync` now depends on. Legal only for `status: implemented` with an `implementedIn:` link. Idempotent on the same (version, --at) pair; a different --at simply overwrites (a later re-certification is normal — there's no way for em to tell 'later' from 'earlier' for an arbitrary revision string, so there's no --force to reach for). Refuses when the newest conformance/*-findings.json matching --at still has an unruled finding in scope for this slice; --skip-findings-check overrides with a loud notice.
88
+ em slice conform <file> <slice-key> --at <rev> # the target-repo revision this certification sweep diffed against
89
+ em slice conform <file> <slice-key> --on <date> # certification date, YYYY-MM-DD (default: today, local date)
90
+ em slice conform <file> <slice-key> --skip-findings-check # certify even with unruled findings in scope — prints a loud notice on stderr
91
+ em changelog <file> # render a model's git history as a business-readable ledger (see docs/cli.md)
92
+ em changelog <file> --from <rev> # start the walk at this revision (inclusive)
93
+ em changelog <file> --to <rev> # end the walk at this revision (inclusive; default HEAD)
94
+ em changelog <file> -o, --out <path> # write to a file instead of stdout
95
+ em state read [dir] # print the state file's mechanical fields as JSON
96
+ em state set-phase <phase> [dir] # rewrite Current phase: (and Last updated:); --step also rewrites Current step:
97
+ em state set-phase <phase> [dir] --step <n> # also set Current step: to this value
98
+ em state set-conformance <revision> [dir] # rewrite Last conformance: (and Last updated:) in the exact format reference/conform.md parses. Refuses (MIL-214) while any `implemented` slice has an unruled conformance finding in the findings JSON beside --report (a `slice: null` finding blocks every slice); --partial records the marker with a ` (partial)` suffix instead, with a loud notice. Without a findings JSON beside --report: warns once and records the marker as given (migration path for a report predating `em conform-findings`)
99
+ em state set-conformance <revision> [dir] --report <path> # path to the conformance report just written
100
+ em state set-conformance <revision> [dir] --partial # record the marker as PARTIAL even though some in-scope findings are still unruled
101
+ em state set-review <date> [dir] # rewrite Last stakeholder review: (and Last updated:)
102
+ em state log-usage <file> # append one Usage log line — phase(s) touched + em validate's diagnostic categories hit, deduped and canonically formatted (MIL-161, docs/usage-data.md) — the mechanical half of 'save state at the end of every session' that used to be run-validate-then-hand-format; state file resolved next to <file>, same convention as em conform-scope
103
+ em state log-usage <file> --phases <list> # comma-separated phase(s) touched this session: discover, extract, model, slice, implement, conform, review, validate, watch, engagement
104
+ em model version bump <file> # bump the model's design version: write model-versions/v<N+1>.json (sibling of slices/, conformance/) and rewrite the state file's `Model version:` bullet (MIL-218). Refuses when the state file is missing (run `em scaffold` first), when --by is empty, and when nothing has changed since the current version (same model content hash AND same slice-version vector) unless --force — a no-op bump is the one case --force is right for.
105
+ em model version bump <file> --by <name> # the bumper's name
106
+ em model version bump <file> --on <date> # bump date, YYYY-MM-DD (default: today, local date)
107
+ em model version bump <file> --force # bump even though nothing has changed since the current version
108
+ em model version show <file> # print the model's current design version and the most recently certified version, if any (model-versions/*.json — MIL-218)
109
+ em model version show <file> --json # print a JSON document instead of text
110
+ em usage-report [root] # aggregate every .event-modeling.md's Usage log under [root] into phase/diagnostic-category tallies (MIL-161) — replaces docs/usage-data.md's hand-rolled grep/awk/sort pipeline; a logged line that doesn't match the canonical em state log-usage format is reported under unparseableLines rather than silently mistallied or dropped
111
+ em usage-report [root] --json # print a JSON document instead of the text report
112
+ em conform-scope <file> # mechanize conform phase step 1 (reference/conform.md): map the target repo's changed paths since Last conformance: to slices via each slice doc's implementedIn, JSON to stdout — --seed-asis also seeds the <model>-asis.em scratch model (see docs/cli.md)
113
+ em conform-scope <file> --repo <path> # path to (or inside) the target codebase's git repository
114
+ em conform-scope <file> --full # ignore Last conformance:/changed paths; scope every implemented slice
115
+ em conform-scope <file> --seed-asis # write <model>-asis.em as a byte copy of the canonical model and ensure it's gitignored
116
+ em conform-supersede <file> <report-path> # stamp a conformance report with a "superseded as of <rev>" banner once its findings have been ruled on (MIL-164, docs/process.md#what-ratified-means) — the companion step to run at ratification time so a reader following the report's file:line citations knows they describe an ancestor of the current model. Additive-only splice, never a rewrite of the report; idempotent on the same --as-of/--findings/--on stamp; refuses if the report doesn't exist. --locus/--by (MIL-214, both required together) additionally record the ruling itself — locus/resolvedBy/resolvedOn — on the findings named by --findings in the sibling conformance/<date>-findings.json, when one exists (warns once and stamps the banner only when it doesn't — the migration path for a report predating em conform-findings)
117
+ em conform-supersede <file> <report-path> --as-of <rev> # the revision this ruling was made against — same value passed to `em state set-conformance`
118
+ em conform-supersede <file> <report-path> --findings <spec> # which finding number(s) this stamps as ruled, e.g. "1-3" or "1,2,4"
119
+ em conform-supersede <file> <report-path> --on <date> # ruling date, YYYY-MM-DD (default: today, local date)
120
+ em conform-supersede <file> <report-path> --locus <locus> # who/what the named finding(s) say is wrong: model | doc | code | none (requires --by)
121
+ em conform-supersede <file> <report-path> --by <name> # who ruled on the named finding(s) (requires --locus)
122
+ em conform-findings check <path> # shape-validate a conformance/<date>-findings.json file (findingsSchemaVersion, required fields, enum values, ids sorted+unique, a ruled finding carries resolvedBy+resolvedOn) — exit 1 on shape errors. The conform skill writes this file directly alongside its report; this is how a headless run verifies what it just wrote.
123
+ em conform-findings check <path> --json # print a JSON document instead of the text report
124
+ em watch <file> # re-render on every save
125
+ em watch <file> -o, --out <path> # output path (extension picks the format)
126
+ em watch <file> -T, --format <fmt> # output format (svg, png, pdf, ...)
127
+ em watch <file> --keep-empty-lanes # keep the API lane even when empty
128
+ em watch <file> --serve # serve a live viewer with instant push-reload (no polling)
129
+ em watch <file> --port <n> # port for --serve (default 5173)
130
+ em validate <file> # check a model against event-modeling rules
131
+ em validate <file> --list-issues # print only open `issue` diagnostics (slice, element, line, text)
132
+ em validate <file> --list-divergences # print only accepted-divergence annotations (slice, element, line, text) — never fails the build
133
+ em validate <file> --list-public # print only commands, events and views marked `public` (slice, kind, name, line) — an integration-surface audit, never fails the build
134
+ em validate <file> --fail-on-issues # exit non-zero if the model has any open `issue`s (opt-in — issues are warnings and don't block by default)
135
+ em validate <file> --slice-ready <key> # readiness gate for one slice (export key): status ready-to-implement, doc resolvable via note binding, zero unchecked Open Questions, a recorded ratifiedBy, and — for a slice touching a `public` element — a current contracts/<model key>.tsp; exits non-zero if not ready (MIL-87, MIL-259, MIL-238)
136
+ em validate <file> --json # print a JSON document instead of text — works on a model WITH errors, unlike `em export` (MIL-128, see docs/cli.md); exit codes are unchanged
137
+ em migrate <file> # rewrite the old two-slice Automation/Translation shape into the merged single-slice shape MIL-120 made canonical (see docs/cli.md)
138
+ em migrate <file> --write # apply the rewrite to the file (default: dry run — report only, write nothing)
139
+ em ledger <file> # check slice docs' version: field agrees with their content across two git revisions (opt-in CI check, MIL-89 — never part of `em validate`, see docs/ci.md)
140
+ em ledger <file> --from <rev> # baseline revision
141
+ em ledger <file> --to <rev> # compare revision (default: current working tree)
142
+ em ledger <file> --waive <slice-key> # excuse a doc-content-without-version-bump finding for this slice key (repeatable; MIL-185, see docs/cli.md) — never waives a version regression or bump-without-content-change
143
+ em ledger <file> --json # print a JSON document instead of the text report (see docs/cli.md)
144
+ em coverage <file> # check that every INV-* invariant ID cited in an implemented slice doc is cited by a test under --tests <dir> (MIL-130/MIL-207) — mechanizes reference/implement.md's definition-of-done citation check; advisory by default, --strict for CI; --include-ready also counts ready-to-implement docs (forward-looking report); a continuation slice (an `again` view instance with no doc of its own, MIL-208) is excluded from the report — its invariants, if any, live in the originating slice's own doc; --slice <key> scopes the report to one slice whatever its status (MIL-255), the pre-merge definition-of-done check
145
+ em coverage <file> --tests <dir> # directory to scan recursively for test files citing invariant IDs
146
+ em coverage <file> --slice <key> # only this slice (export key), whether ready-to-implement or implemented — no --include-ready needed; --strict then fails on this slice's uncited invariants, or if the slice is not in scope (draft/reviewed/unbound: nothing checked) (MIL-255)
147
+ em coverage <file> --strict # exit non-zero if any invariant ID has zero citations (CI)
148
+ em coverage <file> --include-ready # also count ready-to-implement docs, not just implemented (MIL-207)
149
+ em coverage <file> --json # print a JSON document instead of the text report (see docs/cli.md)
150
+ em status <files> # deterministic state-of-the-system rollup over one or more .em models: slices by lifecycle status, driftSignal breakdown, invariant coverage totals (with --tests), open issue markers + unchecked Open Questions, and last-conformance commits-behind-HEAD (MIL-163, see docs/cli.md)
151
+ em status <files> --tests <dir> # directory to scan for INV-* test citations — enables invariant coverage totals
152
+ em status <files> --repo <path> # git repo to compute commits-behind-HEAD in (default: each model's own directory)
153
+ em status <files> --json # print a JSON document instead of the text report (see docs/cli.md)
154
+ em status <files> --md # print a markdown block suited for README embedding
155
+ em status <files> --badge # print a generated SVG badge
156
+ em status <files> -o, --out <path> # write output to a file instead of stdout
157
+ em freshness <file> # standalone freshness signal for one model's conformance record (MIL-164): "last conformed <rev> — N commits and M slice-PRs behind HEAD", computed from the same conform-scope machinery `em status`'s conformance clause uses — for when you want just this fact, no full state-of-the-system rollup (see docs/cli.md)
158
+ em freshness <file> --repo <path> # git repo to compute behind-HEAD in (default: the model's own directory)
159
+ em freshness <file> --json # print a JSON document instead of the text line
160
+ em metrics <file> # the pilot metrics named in advance by the register, computed from git history alone (MIL-170): ratification turnaround (reviewed -> ratified -> implemented), conform-cycle cadence + finding counts, and status-vs-reality disagreement over time — plus a fourth, reported as not computable from history (see docs/usage-data.md). `<file>` is an anchor .em file, used only to locate slices/, conformance/, and .event-modeling.md relative to it — same convention as em ledger; never parsed or compiled
161
+ em metrics <file> --from <rev> # baseline revision
162
+ em metrics <file> --to <rev> # compare revision (default: HEAD)
163
+ em metrics <file> --json # print a JSON document instead of the text report (see docs/cli.md)
164
+ em query consumers <files> # views/reactions consuming an event, plus their slices
165
+ em query consumers <files> --event <ref-or-name> # the event's export ref or display name
166
+ em query consumers <files> --json # print a JSON document instead of the text report
167
+ em query producers <files> # commands producing an event, plus their slices and ui triggers
168
+ em query producers <files> --event <ref-or-name> # the event's export ref or display name
169
+ em query producers <files> --json # print a JSON document instead of the text report
170
+ em query downstream <files> # transitive closure along legal edges from an element — impact analysis
171
+ em query downstream <files> --of <ref-or-name> # the starting element's export ref or display name
172
+ em query downstream <files> --depth <n> # limit traversal to n hops (default: unlimited)
173
+ em query downstream <files> --json # print a JSON document instead of the text report
174
+ em query upstream <files> # transitive closure against legal-edge direction from an element
175
+ em query upstream <files> --of <ref-or-name> # the starting element's export ref or display name
176
+ em query upstream <files> --depth <n> # limit traversal to n hops (default: unlimited)
177
+ em query upstream <files> --json # print a JSON document instead of the text report
178
+ em query slices <files> # filtered slice list — pattern/status/context/persona/tag filters AND-combine
179
+ em query slices <files> --pattern <p> # state-change | state-view | automation | translation | unclassified
180
+ em query slices <files> --status <s> # the slice's joined doc status (draft, reviewed, ready-to-implement, implemented, ...)
181
+ em query slices <files> --context <c> # match a slice with an event in this @Context
182
+ em query slices <files> --persona <p> # match a slice with a ui in this @Persona
183
+ em query slices <files> --tag <t> # match a slice with an event carrying this tag key
184
+ em query slices <files> --json # print a JSON document instead of the text report
185
+ em query invariant <files> # declaring slice + doc facts for one INV-* id, and (with --tests) its test citations
186
+ em query invariant <files> --id <inv-id> # the INV-* id to look up
187
+ em query invariant <files> --tests <dir> # directory to scan for test files citing this id
188
+ em query invariant <files> --json # print a JSON document instead of the text report
189
+ em query field <files> # one field's facts on an element — type, tag/assigned markers, renamed-from chain
190
+ em query field <files> --of <element-ref> # the element's export ref or display name
191
+ em query field <files> --name <field> # the field's name
192
+ em query field <files> --json # print a JSON document instead of the text report
193
+ em query path <files> # shortest path between two elements through the six legal connection types
194
+ em query path <files> --from <ref-or-name> # the starting element's export ref or display name
195
+ em query path <files> --to <ref-or-name> # the ending element's export ref or display name
196
+ em query path <files> --json # print a JSON document instead of the text report
197
+ em engagement new <file> <slug> # write <model dir>/engagements/<slug>.md — frontmatter (slices, parallel ceiling) plus the generated Ledger table; selection by --slices, --context, or --downstream-of (exactly one)
198
+ em engagement new <file> <slug> --slices <keys> # comma-separated slice export keys
199
+ em engagement new <file> <slug> --context <name> # every slice with an event in this context
200
+ em engagement new <file> <slug> --downstream-of <ref> # a slice key, element ref, or display name: it and everything downstream of it (loops-to excluded)
201
+ em engagement new <file> <slug> --parallel <n> # how many slices of one level may be in flight at once
202
+ em engagement new <file> <slug> --by <name> # who created the engagement (createdBy)
203
+ em engagement new <file> <slug> --force # overwrite an existing engagement file with this slug
204
+ em engagement plan <file> <slug> # the engagement's build plan: dependency levels over model.edges (loops-to excluded), and per slice its readiness, branch impl/<key>, base (main or impl/<upstream>), and any hold
205
+ em engagement plan <file> <slug> --json # print a JSON document instead of text (same document as the MCP engagement_plan tool)
206
+ em engagement set <file> <slug> <key> # the only write path to the Ledger: set one slice's state (and optionally branch/base/pr); idempotent; merged is terminal; --state held records a human hold
207
+ em engagement set <file> <slug> <key> --state <state> # one of: planned | building | validating | review | awaiting-merge | merged | held | gap
208
+ em engagement set <file> <slug> <key> --branch <name> # the slice's branch
209
+ em engagement set <file> <slug> <key> --base <name> # the branch the slice's PR targets
210
+ em engagement set <file> <slug> <key> --pr <url> # the slice's PR URL
211
+ em engagement status <file> <slug> # the Ledger joined with each slice doc's current status, plus whether the engagement is closable
212
+ em engagement status <file> <slug> --json # print a JSON document instead of text (same document as the MCP engagement_status tool)
213
+ em engagement close <file> <slug> # set status: closed — refuses unless every slice is merged (recorded or inferred) or gap
214
+ em system [target] # verify a system — every model's `consumes` refs resolved against the other models' `public` events/views, the cross-model half of "both ends of a flow" (MIL-194/MIL-235, see docs/cli.md). Reads system.yaml when given (or found in the directory), else discovers every *.em in the repo
215
+ em system [target] --json # print a JSON document instead of the text report (see docs/cli.md)
216
+ em system codeowners [target] # generate (or --check) the managed CODEOWNERS block that routes review: each model's team on its design directory, and every team that `consumes` a model's public surface on that model's contract file (MIL-234, see docs/ci.md and docs/cli.md)
217
+ em system codeowners [target] -o, --output <path> # the CODEOWNERS file to splice into (default: the first of CODEOWNERS, .github/CODEOWNERS, docs/CODEOWNERS that exists, else CODEOWNERS at the repo root)
218
+ em system codeowners [target] --check # verify the committed file already carries the generated block; never writes, exit 1 on drift (CI)
219
+ em system codeowners [target] --json # print a JSON document instead of the text report (see docs/cli.md)
220
+ em system scope [target] # check a change set against the seams (MIL-240): fail only when it alters a producer's public surface (or contract file) AND a consuming model's design dir together (`seam-crossing`); warn on other multi-model change sets. Files changed only by `Em-Upgrade:` commits are exempt. There is no override - review on the contract file is the gate (see docs/cli.md, docs/ci.md)
221
+ em system scope [target] --base <rev> # the change set committed since <rev> (merge-base form, <rev>...HEAD); CI passes the PR base
222
+ em system scope [target] --staged # also (or only) check what is staged right now; never exempted
223
+ em system scope [target] --json # print a JSON document instead of the text report (see docs/cli.md)
224
+ em contract # print the packaged implementation contract (reference/implement.md) to stdout — the agent-neutral discovery path for any agent that can run a shell, not just Claude Code (MIL-129); see docs/cli.md
225
+ em mcp # start an MCP (Model Context Protocol) server over stdio (MIL-21) — a structured, agent-facing alternative to shelling out to `em`; every tool mirrors a CLI `--json` surface byte-for-byte. docs/mcp.md isn't vendored into the skill bundle — for the handshake and the full, current tool table (the list changes as commands gain MCP parity, so it's not repeated here — MIL-187) see https://github.com/milehimikey/em/blob/main/docs/mcp.md. Equivalent to running the `em-mcp` bin directly
226
+ em skill install # copy the event-modeling skill bundle into .claude/skills/ (event-modeling, event-modeling-discover/-design/-implement/-conform/-review, event-modeling-shared); across a structural bundle change (e.g. the MIL-157 split of the old single event-modeling/ directory into this six-directory bundle), `em skill sync` is the migration path — --force now performs the same reconcile (MIL-180)
227
+ em skill install -f, --force # overwrite an existing installation, reconciling added/updated/removed files within the bundle's own managed directories the same way `em skill sync` does — never touching an unrelated sibling skill (MIL-180)
228
+ em skill install --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
229
+ em skill sync [path] # update the vendored .claude/skills/ event-modeling skill bundle in [path] to match the installed em package (overwrites unconditionally; local edits are never merged, MIL-93)
230
+ em skill sync [path] --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
231
+ em skill check [path] # check [path]'s em skills for drift against the installed em package: the em Claude Code plugin's pin (settings + this machine's marketplace registry) when the repo declares it, and the vendored .claude/skills/ bundle when present; exits non-zero on any mismatch (CI-ready, MIL-93, MIL-231)
232
+ em skill check [path] --json # print a JSON document instead of the text report (see docs/cli.md)
233
+ em skill check [path] --ci # also fail (exit 1) when the declared plugin is not registered on this machine (implied by CI=true in the environment); without it that finding prints the install commands on stderr and exits 0
234
+ em ci init <model> # install .github/workflows/em-ci.yml (PR gates: em validate, em slice index --check, em coverage --strict, em ledger, em skill check, em glossary --fail-on-conflicts, plus a push-triggered status-badge rebuild) and em-conform.yml (scheduled, advisory-only conformance cadence) — same install discipline as `em skill install`: marker-delimited, idempotent, --check for CI self-verification (MIL-166, see docs/ci.md). Give it a system.yaml (or its directory) instead of a model to cover every model in the system: one workflow, per-model jobs, a conform matrix (MIL-233)
235
+ em ci init <model> --tests <dir> # test directory the coverage/status steps scan for INV-* citations
236
+ em ci init <model> -f, --force # replace an existing workflow file that has no GENERATED markers, or a managed block generated for a different set of models
237
+ em ci init <model> --check # verify both files match the current preset; exit non-zero on drift without writing (CI)
238
+ em upgrade <file> # bring a model repo authored under an older em (1.6 forward) up to the installed version: an ordered list of mechanical steps (skill bundle, reaction shape, state-file bullets, generated CI blocks, constitution scaffold) plus a human list of things no command can safely decide by itself (MIL-219, see docs/upgrading.md). Dry-run by default; --apply makes one git commit per applicable step, refusing on a dirty working tree
239
+ em upgrade <file> --apply # apply every applicable mechanical step, one git commit each, then a final `Em version:` commit
240
+ em upgrade <file> --check # exit non-zero only on a hard incompatibility (an existing but unparseable state file, an un-migratable .em shape) — writes nothing; what CI runs; the final line says why
241
+ em upgrade <file> --json # print a JSON document instead of text (dry-run/--check only, never with --apply)
198
242
  ```
199
243
  <!-- GENERATED:cli:end -->
200
244
 
@@ -206,7 +250,7 @@ deps; only rarer formats (ps, eps, ...) need `rsvg-convert`.
206
250
  ## Grammar
207
251
 
208
252
  ```
209
- model "Name" # diagram title
253
+ model "Name" [owner "Team"] # diagram title; optional owning team(s), quoted free text
210
254
 
211
255
  persona Name # a UI swimlane row (actor)
212
256
  context Name # an event swimlane row (bounded context / aggregate)
@@ -214,10 +258,12 @@ context Name # an event swimlane row (bounded context / aggr
214
258
  slice "Name" [source "url"] { # one vertical time step (a column); source is optional
215
259
  ui Free Text @Persona # screen; @Persona picks its row (defaults to first/"User")
216
260
  command Free Text # state-changing request (API band)
261
+ invariant INV-ORD-1 "Rule" # rule guarding the command/event just above (see Clauses)
217
262
  view Free Text from "Event A", "Event B" # read model fed by event(s)
218
263
  view Free Text again from "Event C" # later instance of an evolving read model (see Clauses)
219
264
  event Free Text @Context # recorded fact; @Context picks its row (defaults to "Domain")
220
265
  processor Free Text from "View" # automation; aliases: automation | saga | translation
266
+ translation Free Text consumes other-model:event.slug # binds another model's public event/view
221
267
  }
222
268
 
223
269
  arrow From Element -> To Element # explicit cross-slice edge (overrides inferred flow)
@@ -229,10 +275,10 @@ type Name { field: Type, ... } # named structured type, reusable from any f
229
275
  | Keyword | Band | Meaning | Tag | Extra clauses |
230
276
  |---|---|---|---|---|
231
277
  | `ui` | persona | screen / interface | `@Persona` | `note`, `issue`, `divergence`, `{ fields }` |
232
- | `command` | API | state-changing request | — | `note`, `issue`, `divergence`, `renamed from`, `{ fields }` |
278
+ | `command` | API | state-changing request | — | `note`, `issue`, `divergence`, `renamed from`, `{ fields }`, standalone `invariant` line |
233
279
  | `view` | API | read model / projection | — | `from "Event"…`, `note`, `issue`, `divergence`, `public`, `{ fields }` |
234
- | `event` | context | recorded fact (past tense) | `@Context` | `note`, `issue`, `divergence`, `public`, `tag`, `renamed from`, `loops-to`, field-level `assigned`, `{ fields }` |
235
- | `processor` / `automation` / `saga` / `translation` | automation | system reaction / adapter | — | `from "…"`, `note`, `issue`, `divergence`, `{ fields }` |
280
+ | `event` | context | recorded fact (past tense) | `@Context` | `note`, `issue`, `divergence`, `public`, `tag`, `renamed from`, `loops-to`, field-level `assigned`, `{ fields }`, standalone `invariant` line |
281
+ | `processor` / `automation` / `saga` / `translation` | automation | system reaction / adapter | — | `from "…"`, `note`, `issue`, `divergence`, `{ fields }`; `translation` only: `consumes` |
236
282
 
237
283
  ### Clauses
238
284
  - **Tags:** `@Persona` only on `ui`; `@Context` only on `event`. Undeclared tags auto-create a
@@ -302,12 +348,28 @@ type Name { field: Type, ... } # named structured type, reusable from any f
302
348
  view flip reads `view "X"`); `em validate --list-public` audits the whole public surface.
303
349
  **Exposure of a read model (MIL-215) is three cases, no dedicated keyword:** a person/client
304
350
  reads it → draw the `ui` that reads it (ships the endpoint); another model/system reads it →
305
- `public` (a cross-model contract, verified by `em system <manifest>`, not `em validate`); only
351
+ `public` (a cross-model contract its consumer binds with `consumes`, verified by `em system`, not `em validate`); only
306
352
  an automation reads it → nothing — internal by design, the read a reaction is required to
307
353
  make, not an endpoint. `em validate --list-public` flags a `public` view with no `ui`/reaction
308
354
  reading it anywhere in this model as an audit note ("no in-model reader"), not a warning — a
309
355
  cross-model `public` view's reader legitimately lives outside this file (see "`em validate`
310
356
  rules" below).
357
+ - **`consumes`** (translation only, MIL-235): `translation X consumes <modelKey>:<kind>.<slug>[, …]`
358
+ binds this boundary-crossing reaction to another model's `public` event or view. The binding is
359
+ declared on the consumer and has no version. `kind` is `event` or `view` (never `command`).
360
+ `modelKey` is the kebab-slug of the producer's `model "Name"`, and `slug` is the kebab-slug of
361
+ the element's name. There is no slice segment, so the producer can move the element between
362
+ slices without breaking consumers. Refs are unquoted and comma-separated. Write the clause before
363
+ or after `from "…"`, before or after a `{ … }` block, never inside the braces. On any other kind
364
+ it is a parse error: ``line N: `consumes` is only valid on translation — only a boundary-crossing
365
+ reaction binds to another model's public surface``. `em validate` checks the grammar only.
366
+ `em system` resolves the ref (`consumes-unknown-model` / `consumes-unknown-element`) and
367
+ derives `dangling-public-event` / `unbound-translation` from it. Two `public` elements of one
368
+ kind sharing a slug are a `public-name-not-unique` error, because a ref couldn't tell them
369
+ apart. Exported as `consumes: string[] | null`.
370
+ - **`owner`** (model header, MIL-235): `model "Checkout" owner "Storefront team"[, "…"]`. Quoted
371
+ free text, kept as written, exported as `model.owner: string[]`. It replaces a 1.0
372
+ `system.yaml`'s per-model `owner:`.
311
373
  - **`tag`** (events only): declares a DCB (Dynamic Consistency Boundary) tag key. Three forms:
312
374
  a trailing `tag` on a field line inside the event's `{ … }` block (`priceId: UUID tag`, or
313
375
  typeless `priceId tag`) — an identity tag, key defaults to the field's own name; a bare field
@@ -367,6 +429,17 @@ type Name { field: Type, ... } # named structured type, reusable from any f
367
429
  one-per-line. Types are free text (no semantic checking) UNLESS the type string names a
368
430
  declared `type` (see Named types below), in which case it resolves to a structured
369
431
  reference. Keep these light; full field specs with rules live in the slice doc.
432
+ - **`invariant`** (command/event only, MIL-265): a standalone line directly after the element,
433
+ `invariant INV-ORD-1 "Order total must be positive"` — ID, then an optional quoted rule
434
+ sentence (always write one). Several lines accumulate in order. Parse error after a
435
+ view/`ui`/reaction, before any element, or inside a `{ … }` block. The ID must match
436
+ `INV-<MNEMONIC>-<n>` (2-4 uppercase letters/digits, a number) — `invariants/malformed-id` and
437
+ `invariants/duplicate-id` are errors. **The model declares the ID and the rule; the slice doc's
438
+ Invariants section cites the ID and elaborates** (`- INV-ORD-1 — why, edge cases`), never
439
+ restating it as a `**INV-ORD-1:**` rule (`invariants/declared-in-both`). A model-declared ID
440
+ belongs to its element's slice for `em coverage`/`em query invariant`; doc-declared IDs (the
441
+ 1.13 style) still work as the fallback. `em export` carries `invariants: [{ id, rule }] | null`
442
+ per element.
370
443
  - **Comments:** `# ...` anywhere outside quotes (full-line or trailing).
371
444
  - **Quoted strings:** everything between a `"` and its matching `"` is literal — `{`, `}`, `#`
372
445
  included, never re-interpreted as a field block or comment — so REST path-template
@@ -693,7 +766,11 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
693
766
  | `both-ends-of-a-flow/reaction-no-command` | warning | Reaction with no command | Add the command it triggers, in this slice, or an explicit arrow to one. |
694
767
  | `both-ends-of-a-flow/ui-unbacked` | warning | `ui` with no read model or command | Add a `view` it displays, or the command it triggers. |
695
768
  | `both-ends-of-a-flow/view-unconsumed` | warning | Read model with no consumer | Add a `ui` or reaction that consumes it, or drop this instance. |
769
+ | `code-spans-seam` | warning | Code change spans a seam | Keep one code module per model and change the two sides of a seam in separate change sets. |
696
770
  | `connection-legality/illegal-pair` | error | Illegal connection | Only ui→command→event→view→ui and view→reaction→command are legal — the message names the missing step. |
771
+ | `consumer-not-adapted` | error | Consuming translation no longer matches the producer's public element | Update the translation's field block to the producer's current fields (a renamed field names its new name in the message). Additive producer changes never raise this — consumers tolerate unknown fields. |
772
+ | `consumes-unknown-element` | error | `consumes` names no public element of that model | Point the ref at an element the producer marks `public` (`em export` lists them), or ask the producer to publish it. |
773
+ | `consumes-unknown-model` | error | `consumes` names a model the system does not have | Fix the model key (the kebab-slug of the producer's `model "Name"`), or add that model to the system. |
697
774
  | `continuation-has-own-doc` | warning | Continuation slice has its own doc | Fold this doc's scenarios into slices/<originating-key>.md and delete it; a later `view X again` instance is documented by the view's originating slice. |
698
775
  | `cross-model-slice-doc-collision` | warning | Colliding slice doc path across models | Give each model its own directory (see docs/cli.md, "Multi-model projects"). |
699
776
  | `dangling-public-event` | warning | Public event/view no seam consumes | Declare the seam that reads it, or drop `public` if nothing outside the model does. |
@@ -713,6 +790,11 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
713
790
  | `frontmatter-coherence-implemented-without-link` | warning | Implemented without a link | Add `implementedIn` once the slice ships. |
714
791
  | `frontmatter-invalid` | warning | Invalid or missing frontmatter | Add the required frontmatter keys, or add a frontmatter block. |
715
792
  | `grid-collision` | error | Band collision | Split the colliding elements into separate slices. |
793
+ | `invariants/declared-in-both` | warning | Invariant declared in the model and in a slice doc | Keep the model's `invariant` line; in the doc, cite the ID and elaborate instead of restating it as a `**INV-…:**` rule. |
794
+ | `invariants/doc-cites-undeclared` | warning | Slice doc cites an undeclared invariant | Declare the ID in the model (or in a slice doc's Invariants section), or fix the citation. |
795
+ | `invariants/duplicate-id` | error | Duplicate invariant ID | Give each model-declared invariant its own ID — a rule is declared once, on the element it guards. |
796
+ | `invariants/malformed-id` | error | Malformed invariant ID | Rename the ID to the `INV-<MNEMONIC>-<n>` shape, e.g. `INV-ORD-1` (2-4 uppercase letters/digits, then a number). |
797
+ | `invariants/public-command-without-invariants` | warning | Public command declares no invariants | Add an `invariant INV-<MNEMONIC>-<n> "rule"` line after the command, or declare its rules in the slice doc's Invariants section. |
716
798
  | `lineage-forward-dangling` | error | Dangling forward lineage ref | Fix the key, or remove the stale successor. |
717
799
  | `lineage-ref-cycle` | error | Lineage cycle | Break the cycle — a slice can't be its own ancestor. |
718
800
  | `lineage-ref-malformed` | error | Malformed lineage ref | Fix the value to `<slice-key>@v<N>`, or remove it. |
@@ -720,19 +802,27 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
720
802
  | `loops-to-forward` | error | `loops-to` target not earlier on the timeline | Point `loops-to` at an earlier view, or use `from` on a later `view … again` instance instead. |
721
803
  | `loops-to-unresolved` | error | `loops-to` target unresolved | Name a view that exists, or declare it before this event. |
722
804
  | `model-version-stale` | warning | Model version stale | Run `em model version bump` to record the current model content/slice-version vector. |
805
+ | `multi-model-change-set` | warning | Change set touches more than one model | Prefer one model per change set. Unrelated models in one change set are fine; models joined by a seam are not, once a contract changes. |
723
806
  | `note-binding-dangling` | warning | Dangling cross-slice note | Create the doc at that path, or fix/remove the note. |
724
807
  | `note-binding-extra` | warning | Extra doc-binding note, ignored | Remove the note, or point it at the slice's actual bound doc. |
725
808
  | `note-binding-unratified` | warning | Unratified cross-slice note | Add `covers: <this-slice-key>` to that doc's frontmatter, or correct the note's path. |
726
809
  | `note-binding-unusable` | warning | Cross-slice note to a doc with unusable frontmatter | Fix that doc's frontmatter, or fix/remove the note. |
727
810
  | `open-issue` | warning | Open issue | Resolve the question, then remove the `issue` clause. |
728
811
  | `orphaned-slice-doc` | warning | Orphaned slice doc | Rename it to a current slice's key, add `covers:` (plus a `note` binding) to attach it to a live slice, or delete it. |
812
+ | `owner-not-a-handle` | warning | Model owner is not a CODEOWNERS handle | Write the owner as a GitHub user (`@alice`), a team (`@org/team`), or an email address, so `em system codeowners` can route review to it. |
813
+ | `public-field-type-unresolved` | error | Public field type unresolved | Give the field a type from the public type table (string, text, int, long, decimal, boolean, uuid, date, datetime, duration, bytes), `X[]` of one, or a declared `type` — or drop `public`. |
814
+ | `public-name-not-unique` | error | Two public elements of one kind share a name | Rename one of them (or drop `public` from one): a consumer's `consumes <model>:<kind>.<slug>` must name exactly one element. |
729
815
  | `reaction-from-future-view` | error | Backward timeline (reaction reads a future view) | Declare the view in or before the reaction's slice. |
730
816
  | `reaction-from-unresolved` | error | Unknown read-model source | Project the event into a view first, or fix the `from` reference. |
731
817
  | `seam-consumer-not-reaction` | error | Seam consumer is not a reaction | Point `to` at a translation/automation element (or a slice containing exactly one). |
818
+ | `seam-crossing` | error | Change set alters a contract and its consumer together | Split the change set: land the producer's public-surface change first, then adapt the consuming model in a later change. Review on the contract file is the only override. |
819
+ | `seam-crossing-greenfield` | warning | New public surface lands with its first consumer | Nothing to fix: a public element no consumer was bound to at the base revision is new surface, not a crossing. Later changes to it are crossings. |
732
820
  | `seam-duplicate` | warning | Duplicate seam | Remove the repeated `from`/`to` pair. |
733
821
  | `seam-endpoint-unresolved` | error | Seam endpoint does not resolve | Fix the ref to an element the named model actually exports (`em export` lists every ref), or re-declare the seam after a rename. |
734
822
  | `seam-source-not-public` | error | Seam source is not `public` | Mark the event/view `public` in its model, or point the seam at the element that is. |
735
- | `system-manifest-invalid` | error | Seam manifest invalid | Fix the manifest: required keys, `systemSchemaVersion: "1.0"`, a readable `source` per model, and only declared model keys in seam refs. |
823
+ | `slice-doc/structured-section-malformed` | warning | Malformed structured section | Balance the `<!-- GENERATED:em-slice-…:start -->`/`:end -->` markers (re-create the doc with `em slice new --force` if they are lost), restore the template's table header and run `em slice sync`, and give every `### Scenario:` block a Given, When and Then bullet. |
824
+ | `system-manifest-invalid` | error | Seam manifest invalid | Fix the manifest: `systemSchemaVersion: "2.0"`, `models:` with a readable `source` per model, and nothing else (`seams:`/`owner:` moved into the models — run `em upgrade`). |
825
+ | `system-manifest-outdated` | warning | Seam manifest is schema 1.0 | Run `em upgrade <model>.em --apply` once: it moves `seams:` into `consumes` clauses and `owner:` onto each model header, and rewrites the manifest to 2.0. |
736
826
  | `system-model-key-mismatch` | error | Manifest model key differs from the export's `model.key` | Rename the manifest's `models:` key to the computed key the message prints. |
737
827
  | `tag-composite-unknown-field` | error | Composite tag names an unknown field | Fix the field name, or add it to the event's fields. |
738
828
  | `tag-duplicate-key` | error | Duplicate tag key | Rename one of the tags so every key on the event is unique. |