@milehimikey/em 1.20.0 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/.claude/agents/em-implementer.md +10 -0
  2. package/.claude/agents/em-validator.md +1 -0
  3. package/.claude/skills/event-modeling/SKILL.md +1 -1
  4. package/.claude/skills/event-modeling-conform/SKILL.md +7 -4
  5. package/.claude/skills/event-modeling-conform/reference/conform.md +82 -4
  6. package/.claude/skills/event-modeling-design/SKILL.md +23 -8
  7. package/.claude/skills/event-modeling-discover/SKILL.md +2 -2
  8. package/.claude/skills/event-modeling-discover/reference/extract.md +5 -1
  9. package/.claude/skills/event-modeling-engagement/SKILL.md +1 -1
  10. package/.claude/skills/event-modeling-engagement/reference/engagement.md +1 -0
  11. package/.claude/skills/event-modeling-implement/SKILL.md +5 -3
  12. package/.claude/skills/event-modeling-implement/reference/implement.md +14 -0
  13. package/.claude/skills/event-modeling-review/SKILL.md +19 -7
  14. package/.claude/skills/event-modeling-shared/reference/em-dsl.md +54 -9
  15. package/.claude/skills/event-modeling-shared/reference/methodology.md +35 -2
  16. package/.claude/skills/event-modeling-shared/reference/operating-principles.md +26 -15
  17. package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +2 -1
  18. package/.claude/skills/event-modeling-shared/templates/model-readme.md +10 -2
  19. package/.claude/skills/event-modeling-shared/templates/slice.md +7 -1
  20. package/.claude-plugin/marketplace.json +2 -2
  21. package/dist/catalog/build.js +6 -5
  22. package/dist/catalog/build.js.map +1 -1
  23. package/dist/catalog/coverage.d.ts +3 -0
  24. package/dist/catalog/coverage.js +12 -0
  25. package/dist/catalog/coverage.js.map +1 -1
  26. package/dist/catalog/docLocate.d.ts +17 -0
  27. package/dist/catalog/docLocate.js +97 -0
  28. package/dist/catalog/docLocate.js.map +1 -0
  29. package/dist/catalog/frontmatterCoherenceValidate.js +16 -1
  30. package/dist/catalog/frontmatterCoherenceValidate.js.map +1 -1
  31. package/dist/catalog/orphanedSliceDocValidate.js +15 -10
  32. package/dist/catalog/orphanedSliceDocValidate.js.map +1 -1
  33. package/dist/catalog/readSliceDoc.js +5 -4
  34. package/dist/catalog/readSliceDoc.js.map +1 -1
  35. package/dist/catalog/scenarioQualityValidate.js +2 -2
  36. package/dist/catalog/scenarioQualityValidate.js.map +1 -1
  37. package/dist/catalog/sliceDoc.d.ts +8 -0
  38. package/dist/catalog/sliceDoc.js +9 -0
  39. package/dist/catalog/sliceDoc.js.map +1 -1
  40. package/dist/catalog/sliceSections.d.ts +18 -1
  41. package/dist/catalog/sliceSections.js +38 -4
  42. package/dist/catalog/sliceSections.js.map +1 -1
  43. package/dist/cli/api.d.ts +84 -0
  44. package/dist/cli/api.js +146 -15
  45. package/dist/cli/api.js.map +1 -1
  46. package/dist/cli/bindings.d.ts +152 -0
  47. package/dist/cli/bindings.js +462 -0
  48. package/dist/cli/bindings.js.map +1 -0
  49. package/dist/cli/conformScope.d.ts +32 -0
  50. package/dist/cli/conformScope.js +68 -5
  51. package/dist/cli/conformScope.js.map +1 -1
  52. package/dist/cli/defer.js +3 -2
  53. package/dist/cli/defer.js.map +1 -1
  54. package/dist/cli/engagement.d.ts +24 -1
  55. package/dist/cli/engagement.js +50 -6
  56. package/dist/cli/engagement.js.map +1 -1
  57. package/dist/cli/engagementBrief.d.ts +127 -0
  58. package/dist/cli/engagementBrief.js +313 -0
  59. package/dist/cli/engagementBrief.js.map +1 -0
  60. package/dist/cli/engagementFile.d.ts +14 -0
  61. package/dist/cli/engagementFile.js +54 -0
  62. package/dist/cli/engagementFile.js.map +1 -1
  63. package/dist/cli/ledgerCheck.js +11 -8
  64. package/dist/cli/ledgerCheck.js.map +1 -1
  65. package/dist/cli/markImplemented.js +2 -2
  66. package/dist/cli/markImplemented.js.map +1 -1
  67. package/dist/cli/ratify.js +2 -2
  68. package/dist/cli/ratify.js.map +1 -1
  69. package/dist/cli/refsCheck.js +3 -2
  70. package/dist/cli/refsCheck.js.map +1 -1
  71. package/dist/cli/render-inputs.d.ts +1 -1
  72. package/dist/cli/render-inputs.js +3 -2
  73. package/dist/cli/render-inputs.js.map +1 -1
  74. package/dist/cli/review.js +2 -2
  75. package/dist/cli/review.js.map +1 -1
  76. package/dist/cli/revise.js +2 -2
  77. package/dist/cli/revise.js.map +1 -1
  78. package/dist/cli/skillDirs.d.ts +22 -0
  79. package/dist/cli/skillDirs.js +24 -0
  80. package/dist/cli/skillDirs.js.map +1 -1
  81. package/dist/cli/sliceConform.js +2 -1
  82. package/dist/cli/sliceConform.js.map +1 -1
  83. package/dist/cli/sliceIndex.d.ts +19 -3
  84. package/dist/cli/sliceIndex.js +81 -17
  85. package/dist/cli/sliceIndex.js.map +1 -1
  86. package/dist/cli/sliceNew.js +2 -0
  87. package/dist/cli/sliceNew.js.map +1 -1
  88. package/dist/cli/sliceStubAll.js +7 -2
  89. package/dist/cli/sliceStubAll.js.map +1 -1
  90. package/dist/cli/sliceSync.d.ts +12 -0
  91. package/dist/cli/sliceSync.js +42 -4
  92. package/dist/cli/sliceSync.js.map +1 -1
  93. package/dist/cli/status.d.ts +8 -4
  94. package/dist/cli/status.js +6 -4
  95. package/dist/cli/status.js.map +1 -1
  96. package/dist/cli/storylineSplit.d.ts +18 -0
  97. package/dist/cli/storylineSplit.js +110 -0
  98. package/dist/cli/storylineSplit.js.map +1 -0
  99. package/dist/cli/upgrade.js +47 -23
  100. package/dist/cli/upgrade.js.map +1 -1
  101. package/dist/cli/watchStoryline.d.ts +6 -0
  102. package/dist/cli/watchStoryline.js +10 -0
  103. package/dist/cli/watchStoryline.js.map +1 -1
  104. package/dist/cli.js +408 -78
  105. package/dist/cli.js.map +1 -1
  106. package/dist/emit/api.d.ts +8 -1
  107. package/dist/emit/api.js +68 -24
  108. package/dist/emit/api.js.map +1 -1
  109. package/dist/emit/apiSurfaceJson.d.ts +3 -0
  110. package/dist/emit/apiSurfaceJson.js +26 -0
  111. package/dist/emit/apiSurfaceJson.js.map +1 -0
  112. package/dist/emit/engagementJson.d.ts +8 -3
  113. package/dist/emit/engagementJson.js +31 -4
  114. package/dist/emit/engagementJson.js.map +1 -1
  115. package/dist/emit/json.d.ts +22 -1
  116. package/dist/emit/json.js +12 -1
  117. package/dist/emit/json.js.map +1 -1
  118. package/dist/mcp/server.js +111 -9
  119. package/dist/mcp/server.js.map +1 -1
  120. package/dist/model/edges.d.ts +1 -1
  121. package/dist/model/edges.js +8 -1
  122. package/dist/model/edges.js.map +1 -1
  123. package/dist/model/loadModel.d.ts +38 -0
  124. package/dist/model/loadModel.js +122 -0
  125. package/dist/model/loadModel.js.map +1 -0
  126. package/dist/model/model.d.ts +26 -9
  127. package/dist/model/model.js +22 -17
  128. package/dist/model/model.js.map +1 -1
  129. package/dist/model/rules.d.ts +23 -0
  130. package/dist/model/rules.js +23 -0
  131. package/dist/model/rules.js.map +1 -1
  132. package/dist/model/shapeLint.js +95 -0
  133. package/dist/model/shapeLint.js.map +1 -1
  134. package/dist/model/sliceDocIndex.js +13 -5
  135. package/dist/model/sliceDocIndex.js.map +1 -1
  136. package/dist/model/sliceDocPath.d.ts +19 -0
  137. package/dist/model/sliceDocPath.js +49 -0
  138. package/dist/model/sliceDocPath.js.map +1 -0
  139. package/dist/model/storylineMap.d.ts +20 -0
  140. package/dist/model/storylineMap.js +55 -0
  141. package/dist/model/storylineMap.js.map +1 -0
  142. package/dist/model/validate.d.ts +7 -0
  143. package/dist/model/validate.js +8 -0
  144. package/dist/model/validate.js.map +1 -1
  145. package/dist/parser/ast.d.ts +19 -0
  146. package/dist/parser/parser.d.ts +17 -1
  147. package/dist/parser/parser.js +91 -2
  148. package/dist/parser/parser.js.map +1 -1
  149. package/dist/pipeline.d.ts +16 -0
  150. package/dist/pipeline.js +19 -2
  151. package/dist/pipeline.js.map +1 -1
  152. package/dist/render/drawEdges.d.ts +5 -1
  153. package/dist/render/drawEdges.js +57 -4
  154. package/dist/render/drawEdges.js.map +1 -1
  155. package/dist/render/drawNotes.d.ts +4 -1
  156. package/dist/render/drawNotes.js +40 -10
  157. package/dist/render/drawNotes.js.map +1 -1
  158. package/dist/render/render.d.ts +11 -0
  159. package/dist/render/render.js +94 -11
  160. package/dist/render/render.js.map +1 -1
  161. package/dist/render/serve.d.ts +5 -0
  162. package/dist/render/serve.js +18 -2
  163. package/dist/render/serve.js.map +1 -1
  164. package/dist/render/sliceDiagram.js +3 -0
  165. package/dist/render/sliceDiagram.js.map +1 -1
  166. package/dist/render/sliceOverlay.d.ts +4 -5
  167. package/dist/render/sliceOverlay.js +4 -7
  168. package/dist/render/sliceOverlay.js.map +1 -1
  169. package/dist/render/sliceStatus.d.ts +8 -0
  170. package/dist/render/sliceStatus.js +22 -15
  171. package/dist/render/sliceStatus.js.map +1 -1
  172. package/dist/render/storylineBands.d.ts +0 -3
  173. package/dist/render/storylineBands.js +2 -22
  174. package/dist/render/storylineBands.js.map +1 -1
  175. package/dist/render/storylineDiagram.js +17 -69
  176. package/dist/render/storylineDiagram.js.map +1 -1
  177. package/dist/render/storylineMap.d.ts +18 -0
  178. package/dist/render/storylineMap.js +263 -0
  179. package/dist/render/storylineMap.js.map +1 -0
  180. package/dist/render/svgGeometry.d.ts +9 -0
  181. package/dist/render/svgGeometry.js +16 -0
  182. package/dist/render/svgGeometry.js.map +1 -1
  183. package/dist/render/viewerHtml.js +1 -1
  184. package/dist/render/viewerHtml.js.map +1 -1
  185. package/dist/templates.d.ts +5 -1
  186. package/dist/templates.js +39 -2
  187. package/dist/templates.js.map +1 -1
  188. package/package.json +1 -1
  189. package/plugin/.claude-plugin/plugin.json +2 -2
  190. package/plugin/agents/em-implementer.md +10 -0
  191. package/plugin/agents/em-validator.md +1 -0
  192. package/plugin/shared/reference/em-dsl.md +54 -9
  193. package/plugin/shared/reference/methodology.md +35 -2
  194. package/plugin/shared/reference/operating-principles.md +26 -15
  195. package/plugin/shared/reference/slice-doc-schema.md +2 -1
  196. package/plugin/shared/templates/model-readme.md +10 -2
  197. package/plugin/shared/templates/slice.md +7 -1
  198. package/plugin/skills/conform/SKILL.md +7 -4
  199. package/plugin/skills/conform/reference/conform.md +82 -4
  200. package/plugin/skills/design/SKILL.md +23 -8
  201. package/plugin/skills/discover/SKILL.md +2 -2
  202. package/plugin/skills/discover/reference/extract.md +5 -1
  203. package/plugin/skills/engagement/SKILL.md +1 -1
  204. package/plugin/skills/engagement/reference/engagement.md +1 -0
  205. package/plugin/skills/event-modeling/SKILL.md +1 -1
  206. package/plugin/skills/implement/SKILL.md +5 -3
  207. package/plugin/skills/implement/reference/implement.md +14 -0
  208. package/plugin/skills/review/SKILL.md +19 -7
@@ -15,14 +15,15 @@ Keep `.em` files focused on **structure**; put deep design in markdown linked vi
15
15
  em --version # print the installed em version
16
16
  em init [file] # scaffold a starter .em model
17
17
  em init [file] -f, --force # overwrite if the file exists
18
- em scaffold <name> # scaffold a full project: <slug>/<slug>.em, README.md, .event-modeling.md, 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)
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), plus the standard slices/, contracts/, model-versions/ and conformance/bindings/ directories (each seeded with a one-line README naming what lands there and which command writes it, instead of a .gitkeep) (see docs/cli.md — for just a starter .em, use `em init`; for a multi-model project, pass --under to nest it under a shared parent directory)
19
19
  em scaffold <name> -f, --force # overwrite the directory's contents if it already exists
20
20
  em scaffold <name> --under <dir> # parent directory to scaffold into — writes <dir>/<slug>/ instead of ./<slug>/, the supported multi-model layout (docs/cli.md, "Multi-model projects"): one directory per model, so each model's slices/ never collides with a sibling model's
21
21
  em render <file> # transpile a model and render it (or emit DOT)
22
22
  em render <file> -o, --out <path> # output path (extension picks the format)
23
23
  em render <file> -T, --format <fmt> # output format (svg, png, pdf, ...)
24
24
  em render <file> --slice <name> # render only this slice, redrawn in its own canonical pattern shape (default out: slices/<kebab-slug>.svg)
25
- em render <file> --storyline <name> # render only this storyline: its slices in order, preceded by dimmed stub columns for what they read from outside it (and the end state of a storyline it comes `after`) (default out: storylines/<kebab-slug>.svg)
25
+ em render <file> --storyline <name> # render only this storyline: its own slices in order, nothing from outside it (default out: storylines/<kebab-slug>.svg)
26
+ em render <file> --map # render every storyline to storylines/<kebab-slug>.svg plus a draggable canvas of them all, with the flow between storylines, at storylines/map.html (-o picks the html path)
26
27
  em render <file> --emit-dot # print the generated DOT instead of rendering
27
28
  em render <file> --keep-empty-lanes # keep the API lane even when empty
28
29
  em export <file> # export a versioned JSON snapshot of the normalized model
@@ -36,6 +37,8 @@ em api generate <file> --stdout # print the
36
37
  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)
37
38
  em api check <file> --base <rev> # git revision to diff the public surface against
38
39
  em api check <file> --json # print a JSON document instead of the text report (see docs/cli.md)
40
+ em api surface <file> # the model's public commands, events, views and reachable declared types as a versioned JSON document for companion tools (GH #448, see docs/cli.md)
41
+ em api surface <file> --json # print a JSON document instead of the text listing (see docs/cli.md)
39
42
  em typespec <file> # DEPRECATED alias of `em api generate --stdout` (use em api generate)
40
43
  em typespec <file> -o, --out <path> # write to a file instead of stdout
41
44
  em diff <old> [new] # compare two models structurally (two files, or one file across git revisions)
@@ -70,6 +73,7 @@ em slice stub-all <file> --implemented-in <url> # PR/commit
70
73
  em slice stub-all <file> --dry-run # list what would be stubbed/wired without writing anything
71
74
  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
72
75
  em slice index <file> --check # verify the table is current; exit non-zero on drift without writing (CI)
76
+ em slice index <file> --full # every lifecycle column (reviewed/ratified/owner/tracking/implemented/conformed) instead of the reader's five
73
77
  em slice mark-implemented <file> <slice-key> <pr-url> # flip a slice doc's frontmatter to `status: implemented` / `implementedIn: <pr-url>` — the one edit an implementing agent makes to a ratified doc at merge (MIL-103, replaces the em-sdd-bridge `em-sdd-mark-implemented` script; see reference/implement.md §6). Applies only to a `ready-to-implement` doc (MIL-277: a `draft`/`reviewed` doc refuses — ratify first). Also records the shipped version beside the link (MIL-284): `shippedVersion:`, `shippedRef:` (the doc's `ratifiedRef:`, when it has one) and `shippedOn:`, and opens the next version as a `draft` when an Open Question was deferred to it (MIL-283). Idempotent on the same URL — also after that draft opened; refuses to overwrite a different one; never touches the doc body except to re-open those deferred questions
74
78
  em slice mark-implemented <file> <slice-key> <pr-url> --on <date> # merge date recorded as `shippedOn:`, YYYY-MM-DD (default: today, local date; MIL-284)
75
79
  em slice mark-implemented <file> <slice-key> <pr-url> --json # print a JSON document instead of text: { path, changed, implementedIn, nextDraft: { version, reopened[] } | null } (GH #285)
@@ -140,6 +144,11 @@ em conform-supersede <file> <report-path> --locus <locus> # who/what t
140
144
  em conform-supersede <file> <report-path> --by <name> # who ruled on the named finding(s) (requires --locus)
141
145
  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.
142
146
  em conform-findings check <path> --json # print a JSON document instead of the text report
147
+ em conform bindings check <file> # verify every per-slice bindings manifest (conformance/bindings/<slice-key>.yaml, see docs/bindings.md): each bound element's `ref` resolves against the compiled model, and each bound `file` exists under --repo and contains its `identifier` as a plain substring (grep-level only, never code-parsed — language-agnostic). Distinct failure kinds: an unknown `--slice` key, a missing bindings file, malformed YAML, an unknown slice named inside a file, and an unknown element ref. Advisory only — exit code stays 0 unless --exit-code is given and a binding failed (the opt-in CI gate, same posture as `em refs --reachable-from`).
148
+ em conform bindings check <file> --repo <path> # path to the target codebase (bound `file`s resolve relative to it; never required to be a git repository)
149
+ em conform bindings check <file> --slice <key> # check only this slice's bindings file (default: every conformance/bindings/*.yaml)
150
+ em conform bindings check <file> --json # print a JSON document instead of the text report
151
+ em conform bindings check <file> --exit-code # exit 1 if any binding failed (git-diff convention) — the opt-in CI gate
143
152
  em discover triage-check <file> # validate a discovery/prd-triage.json (prdTriageSchemaVersion 1.0): shape, the shipped rubric version, every statement/storyline quote appearing verbatim in the input document, and every statement carrying a category, an outcome and (modeled/rewritten) a group + storyline — exit 1 on errors. The discover skill writes this file directly; this is how a headless run verifies it.
144
153
  em discover triage-check <file> --source <path> # the input PRD/spec to check quotes against (default: the file's own `source`, relative to it)
145
154
  em discover triage-check <file> --markdown # after a passing check, print the Markdown view of the record instead of the summary
@@ -240,17 +249,23 @@ em engagement new <file> <slug> --parallel <n> # how many s
240
249
  em engagement new <file> <slug> --by <name> # who created the engagement (createdBy)
241
250
  em engagement new <file> <slug> --tracking <key> # an issue-tracker key or URL the slice PRs cite (a slice doc's own tracking: wins)
242
251
  em engagement new <file> <slug> --pr-title <template> # PR title template for the slice PRs; {key} = tracking key, {slice} = slice name, {sliceKey} = slice key (default "{key}: {slice}", or "{slice}" without a key)
252
+ em engagement new <file> <slug> --context-doc <path> # repo-relative path to a document implementers need beyond the slice doc — the constitution, an NFR doc, an ADR (repeatable; GH #455)
243
253
  em engagement new <file> <slug> --force # overwrite an existing engagement file with this slug
244
254
  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 (always main — MIL-280), and any hold
245
255
  em engagement plan <file> <slug> --json # print a JSON document instead of text (same document as the MCP engagement_plan tool)
246
256
  em engagement foundation <file> <slug> # GH #240: is the foundation PR (implement.md §8) actually in the code for the events this engagement's slices emit and consume? A text scan of --code: an event is present when a file carries an identifier derived from its name (OrderPlaced / order_placed / ORDER_PLACED / order-placed), its model fields and tag fields are then looked for in those files. Per event: present | incomplete (missing-field / missing-tag, named) | missing-event — so "foundation absent" and "foundation incomplete" are different reports. Exits 1 unless every event is present. Proves the contract was written down, not that it type-checks
247
257
  em engagement foundation <file> <slug> --code <dir> # the target repository (or the directory the constitution's "where a slice's code lives" rule points at)
248
258
  em engagement foundation <file> <slug> --json # print a JSON document instead of text (same document as the MCP engagement_foundation tool)
249
- 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
250
- em engagement set <file> <slug> <key> --state <state> # one of: planned | building | validating | review | awaiting-merge | merged | held | gap
251
- em engagement set <file> <slug> <key> --branch <name> # the slice's branch
252
- em engagement set <file> <slug> <key> --base <name> # the branch the slice's PR targets
253
- em engagement set <file> <slug> <key> --pr <url> # the slice's PR URL
259
+ em engagement brief <file> <slug> # GH #454: a deterministic, self-contained per-slice work brief for implementers em does not control (a ticket-driven cloud agent) — the bound slice doc verbatim (or the model's own elements when there is none), model context from the edge list, the public-contract surface, a definition-of-done (bindings manifest skeleton + conform check + isolation + PR title), and the engagement's context: documents. One brief per engagement slice unless --slice narrows it
260
+ em engagement brief <file> <slug> --slice <key> # only this slice's brief (export key, display name, or unique prefix)
261
+ em engagement brief <file> <slug> --inline-context # embed each context document's full text instead of just its path
262
+ em engagement brief <file> <slug> --json # print a JSON document instead of text (same document as the MCP engagement_brief tool)
263
+ 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. Or, on its own (no slice key), --context-doc replaces the engagement-level context: list (GH #455)
264
+ em engagement set <file> <slug> [key] --state <state> # one of: planned | building | validating | review | awaiting-merge | merged | held | gap
265
+ em engagement set <file> <slug> [key] --branch <name> # the slice's branch
266
+ em engagement set <file> <slug> [key] --base <name> # the branch the slice's PR targets
267
+ em engagement set <file> <slug> [key] --pr <url> # the slice's PR URL
268
+ em engagement set <file> <slug> [key] --context-doc <path> # repo-relative path to a document implementers need beyond the slice doc (repeatable; replaces the whole engagement-level context: list; GH #455)
254
269
  em engagement status <file> <slug> # the Ledger joined with each slice doc's current status, plus whether the engagement is closable
255
270
  em engagement status <file> <slug> --json # print a JSON document instead of text (same document as the MCP engagement_status tool)
256
271
  em engagement close <file> <slug> # set status: closed — refuses unless every slice is merged (recorded or inferred) or gap
@@ -275,15 +290,25 @@ em mcp # start an M
275
290
  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)
276
291
  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)
277
292
  em skill install --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
293
+ em skill install --skills-dir <dir> # where the vendored skill bundle lives, relative to the repo root (default .claude/skills; .agents/skills when that exists and .claude/skills does not — GH #412)
294
+ em skill install --agents-dir <dir> # where the four em sub-agent definitions live, relative to the repo root (default .claude/agents, or .agents/agents beside an .agents/skills bundle — GH #412)
278
295
  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)
279
296
  em skill sync [path] --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
297
+ em skill sync [path] --skills-dir <dir> # where the vendored skill bundle lives, relative to the repo root (default .claude/skills; .agents/skills when that exists and .claude/skills does not — GH #412)
298
+ em skill sync [path] --agents-dir <dir> # where the four em sub-agent definitions live, relative to the repo root (default .claude/agents, or .agents/agents beside an .agents/skills bundle — GH #412)
280
299
  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)
281
300
  em skill check [path] --json # print a JSON document instead of the text report (see docs/cli.md)
282
301
  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
302
+ em skill check [path] --skills-dir <dir> # where the vendored skill bundle lives, relative to the repo root (default .claude/skills; .agents/skills when that exists and .claude/skills does not — GH #412)
303
+ em skill check [path] --agents-dir <dir> # where the four em sub-agent definitions live, relative to the repo root (default .claude/agents, or .agents/agents beside an .agents/skills bundle — GH #412)
283
304
  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)
284
305
  em ci init <model> --tests <dir> # test directory the coverage/status steps scan for INV-* citations
285
306
  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
286
307
  em ci init <model> --check # verify both files match the current preset; exit non-zero on drift without writing (CI)
308
+ em storyline split <file> # move each inline `storyline "X" { … }` block into its own storyline model file <slug>/<slug>.em (a `storyline "X" [source]` header, then the block's slices) and leave the one-line declaration `storyline "X" [after "Y"]` in the root (GH #421). Slice docs stay under the root's slices/. A storyline declared in several blocks is left alone (merge them first)
309
+ em storyline split <file> --storyline <name> # split only this storyline
310
+ em storyline split <file> --dry-run # print what would be written without touching anything
311
+ em storyline split <file> -f, --force # overwrite a storyline model file that already exists
287
312
  em storyline suggest <file> # advisory (GH #290): propose `storyline` blocks for a model that has none — one per distinct slice `source "url"`, the remaining slices grouped by the view-instance chains (`again`) they feed — printed as a unified diff on stdout (apply with `patch -p1` or `git apply`); never writes the model
288
313
  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
289
314
  em upgrade <file> --apply # apply every applicable mechanical step, one git commit each, then a final `Em version:` commit
@@ -310,12 +335,14 @@ context Name # an event swimlane row (bounded context / aggr
310
335
  storyline "Name" [source "url"] [after "Other"] { # optional chapter grouping slices (see Storylines)
311
336
  slice "Name" { ... }
312
337
  }
338
+ storyline "Name" [after "Other"] [in "path.em"] # a storyline MODEL: its slices live in <slug>/<slug>.em (see Storylines)
313
339
 
314
340
  slice "Name" [source "url"] { # one vertical time step (a column); source is optional
315
341
  ui Free Text @Persona # screen; @Persona picks its row (defaults to first/"User")
316
342
  command Free Text # state-changing request (API band)
317
343
  invariant INV-ORD-1 "Rule" # rule guarding the command/event just above (see Clauses)
318
344
  view Free Text from "Event A", "Event B" # read model fed by event(s)
345
+ view Free Text from "Event A" updates from "Event B", "Event C" # B, C keep rows current: read, never drawn (see Clauses)
319
346
  view Free Text again from "Event C" # later instance of an evolving read model (see Clauses)
320
347
  event Free Text @Context # recorded fact; @Context picks its row (defaults to "Domain")
321
348
  processor Free Text from "View" # automation; aliases: automation | saga | translation
@@ -359,6 +386,14 @@ type Name { field: Type, ... } # named structured type, reusable from any f
359
386
  previous instance of V that also reads E), and EVERY site needs a reader at or after it (add `view V again from "E"`
360
387
  after the last site, or `event-unread` warns for that site). The same name in a different context
361
388
  is still a `duplicate-name` warning.
389
+ - **`updates from "Event", …`** (views only, GH #414): the subset of a view's sources that only keep a
390
+ row current or remove it (a due date moved, an address changed, a loan returned). They are folded
391
+ into the view's `from` for every check — `derived from`, completeness, the generated built-from
392
+ list — but never drawn as arrows: the diagram shows the line from the event that puts work on the
393
+ list, and lists the rest under "Kept current by". The author chooses the triggers: `view Holds To
394
+ Fulfill from "Hold Placed", "Tool Returned" updates from "Hold Collected", "Hold Cancelled"`.
395
+ Valid on an `again` instance too. A to-do view with more than one or two inbound arrows is missing
396
+ this split.
362
397
  - **`again`** (views only): `view <Name> again [from "Event", …]` declares a later instance of an
363
398
  already-declared read model — the forward-only device for a view that evolves as later events
364
399
  land. Instances are ONE logical view: the first declaration owns the `note` binding; each
@@ -549,8 +584,15 @@ type Name { field: Type, ... } # named structured type, reusable from any f
549
584
  Slices keep their file-order timeline position; a slice outside any storyline is allowed;
550
585
  storylines don't nest and a repeated name continues that storyline (its slices join it; a continuation may not add or change
551
586
  `source`/`after` — parse error). The full render draws a
552
- labelled band above the slice headers; `em render --storyline "Name"` draws one story alone, with the
553
- elements it reads from outside as dimmed stub columns. `em export` carries `slice.storyline` and
587
+ labelled band above the slice headers; `em render --storyline "Name"` draws one story alone — its own
588
+ slices only, nothing from outside it — and `em render <root>.em --map` puts every story's real
589
+ diagram on one draggable canvas with the flow between stories (`after` thick, reads dashed and
590
+ labelled). **Storyline models (GH #421):** `storyline "Name" [after "Other"] [in "path.em"]` with no
591
+ body declares a storyline whose slices live in `<slug>/<slug>.em` — a file that starts with
592
+ `storyline "Name" [source "url"]` and holds slice blocks only — with its docs in `<slug>/slices/`;
593
+ the root is the compile unit (always give em the root), and `em storyline split <root>.em` turns
594
+ inline blocks into files, moving each story's docs. A storyline that reads another declares `after`
595
+ it (`storyline-reads-without-after`). `em export` carries `slice.storyline` and
554
596
  `model.storylines[]`; `em query slices --storyline`; `em slice index` adds a Storyline column. Once
555
597
  any storyline exists a slice outside every one is the advisory warning `slice-outside-storyline`.
556
598
  `after "<other>"` reads the storyline as if its slices followed the referenced storyline's last
@@ -876,6 +918,7 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
876
918
  <!-- GENERATED:validate-rules:start -- run `npm run docs:generate` to refresh, do not hand-edit -->
877
919
  | Code | Severity | Title | Fix |
878
920
  |---|---|---|---|
921
+ | `again-restates-sources` | warning | Continuation restates sources an earlier instance already read | Name only the events that changed the view since the previous instance on the `again` line; the view's field sources are the union across instances, so nothing is lost (docs/dsl.md#view--again). |
879
922
  | `alternative-events-no-command` | error | Alternative events without a command | Add the command whose decision records one of the alternatives, in the same slice. |
880
923
  | `arrow-backward` | error | Backward arrow | Restructure so the target comes later. |
881
924
  | `arrow-unresolved-source` | error | Arrow source unresolved | Fix the arrow's source name. |
@@ -916,6 +959,7 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
916
959
  | `fields-completeness/view-field-no-source` | warning | View field with no source | Add the field to a source event, or remove it from the view. |
917
960
  | `frontmatter-coherence-implemented-without-link` | warning | Implemented without a link | Add `implementedIn` once the slice ships. |
918
961
  | `frontmatter-invalid` | warning | Invalid or missing frontmatter | Add the required frontmatter keys, or add a frontmatter block. |
962
+ | `frontmatter-status-unrecognized` | warning | Unrecognized slice status | Set `status:` to one of draft, reviewed, ready-to-implement, implemented. |
919
963
  | `grid-collision` | error | Band collision | Split the colliding elements into separate slices. |
920
964
  | `invariant-without-scenario` | warning | Invariant cited by no scenario | Cite the INV id in the Given/When/Then (or title) of the scenario that exercises it, or add one. |
921
965
  | `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. |
@@ -959,6 +1003,7 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
959
1003
  | `storyline-after-cycle` | error | Storyline `after` cycle | Remove an `after` clause so no storyline comes after itself. |
960
1004
  | `storyline-after-out-of-order` | error | Backward timeline (storyline declared above the one it comes after) | Move the storyline block below the storyline it comes `after`, or restructure the feed. |
961
1005
  | `storyline-after-unknown` | error | `after` names an unknown storyline | Name a storyline declared in this model, or drop the `after` clause. |
1006
+ | `storyline-reads-without-after` | warning | Storyline reads another without declaring `after` it | Add `after "<the storyline it reads>"` to the reading storyline (or to one between them); if the two stories are parallel on purpose, accept it on the shape exit gate (docs/storyline.md). |
962
1007
  | `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`). |
963
1008
  | `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. |
964
1009
  | `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. |
@@ -218,7 +218,11 @@ drift into **CRUD laid on a timeline**; these rules stop that. Quoted lines are
218
218
  reorganize are **secondary storylines** (chapters; Dilger: "one linear flow from left to right. No
219
219
  exceptions… Linearize it!", "Model one process at a time, each with its own clear ending"). Never one
220
220
  lifecycle block per entity. Name the main and every secondary storyline; a `storyline "Name" { … }`
221
- block groups the slices (`dsl.md`, Storylines).
221
+ block groups the slices (`dsl.md`, Storylines). **A storyline is the unit a reader consumes, so it
222
+ is the unit an author edits too (GH #421):** the root model lists the storylines and their flow
223
+ (`storyline "Name" [after "Other"]`), and each story's slices live in `<slug>/<slug>.em` with its
224
+ docs in `<slug>/slices/`. Draft with inline blocks if that is faster, then `em storyline split
225
+ <root>.em` once the storylines are named — before docs are wired, so nothing moves twice.
222
226
  - **Build from walkthroughs first.** The story already lives in the spec's walkthroughs, use cases and
223
227
  user journeys. Build the timeline from those; the resource/API reference (OpenAPI, endpoint tables,
224
228
  migrations) fills only the operations no walkthrough touches, and is read last. Headless: a persona
@@ -332,12 +336,41 @@ drift into **CRUD laid on a timeline**; these rules stop that. Quoted lines are
332
336
  `view-lookup-source` is the mechanical, advisory half — it catches the cross-context cases with a few
333
337
  false positives; a within-context lookup (`Tool Checked Out` read only to learn whose loan a later
334
338
  event concerns) is invisible to it, so this check still has to be done by eye.
339
+ **Then split what is left into trigger and housekeeping** (Dilger: show the line from the event
340
+ that triggers the automation, not every event that touches its read model; GH #414). Of the
341
+ events a view legitimately reads, only the ones that **put work on the list** are the story — they
342
+ go in `from` and are drawn. Every event that merely **keeps a row current or removes it** (a due
343
+ date moved, an address changed, a loan returned) goes in `updates from`: still a source for
344
+ `derived from`, completeness and the generated built-from list, never an arrow. Write the to-do
345
+ list as `view Overdue Loans To Notify from "Tool Checked Out" updates from "Loan Extended",
346
+ "Neighbor Email Changed", "Tool Returned"`. The author chooses the triggers — `Holds To Fulfill`
347
+ keeps two (`from "Hold Placed", "Tool Returned"`) because both put a fulfillable hold on the
348
+ list. **Per-view check:** *which of these events is the reason this row appears? That is `from`;
349
+ everything else is `updates from`.* The render's "Kept current by" legend is the readback: if a
350
+ to-do view shows more than one or two inbound arrows, the split is missing. A State View that is
351
+ not a to-do list gets the same treatment — its screen's story is the event that creates the row.
335
352
  - **Write side: children belong in the parent's context** when the child's invariants are checks against
336
353
  the parent. A sub-resource schema shared across parent types is one event per parent on the parent's
337
354
  context, not a shared aggregate — check the spec's event reference, not its resource section. Where
338
355
  two slices record the same fact, repeat the event bare (same name, same context). *(em ruling)*
339
356
  - **Repeat the view after every command that changes it** (`again`, span-1 — see State View above), so
340
- the reader sees the information arrive rather than a view at the end.
357
+ the reader sees the information arrive rather than a view at the end. **A continuation names only
358
+ what changed:** `view X again from "E"` lists the event(s) that changed the view since the previous
359
+ instance — never the originating instance's whole source list again. Field sources are the union
360
+ across instances, so restating loses nothing and only draws the same arrows twice;
361
+ `again-restates-sources` (GH #424) is the mechanical half.
362
+ - **Storylines read as stories** (owner rulings 2026-11-03, after Dilger). (1) **A storyline that reads
363
+ another declares `after` it:** an event of story A feeding a view of story B means B comes after A
364
+ in the telling — write `storyline "B" after "A"` (or on a storyline between them); two stories that
365
+ really run in parallel read nothing from each other. `storyline-reads-without-after` (GH #420) is
366
+ the mechanical half. (2) **Review each story on its own render and on the canvas, never on the
367
+ full timeline:** `em render <root>.em --map` draws every storyline's real diagram as a frame with
368
+ the flow between stories (`after` thick, reads dashed and labelled by event); the full timeline is
369
+ for `em diff` and ordering checks, not for reading. A storyline render shows only the storyline —
370
+ nothing from outside it is drawn, so an inbound arrow you miss there is a connector on the canvas.
371
+ (3) **Housekeeping is not drawn** (`updates from`, above) and **continuations name only what
372
+ changed** (above): together these are what keeps a story's render to one line per cause. *(em
373
+ ruling, built on Dilger's "the line from the event that triggers it")*
341
374
  - **Outcomes are events of one slice** (Dilger: "One decision. One event. One state change."; one
342
375
  action with two outcomes is the legitimate exception): alternative events on one context in one slice
343
376
  (`event A | B @Ctx`, GH #278), failure as a scenario first, a chapter only when core (it changes what the user does next, or has
@@ -173,25 +173,36 @@ including sessions started from bare `/event-modeling`.
173
173
  <model-name>.svg # render target for em watch
174
174
  README.md # overview + slice index (from templates/model-readme.md)
175
175
  .event-modeling.md # resumable state (from templates/state.md)
176
+ constitution.md # implementation constitution (skipped, with a note, in a spec-kit project)
176
177
  slices/<slice-name>.md # one rich slice doc per slice (from templates/slice.md)
177
- conformance/<date>-report.md
178
- # conform-phase reports (from templates/conformance-report.md)
178
+ contracts/<model-name>.tsp
179
+ # `em api generate`'s generated TypeSpec contract — never hand-edit
180
+ model-versions/v<N>.json # `em model version bump`'s design-version snapshots
181
+ conformance/
182
+ <date>-report.md # conform-phase reports (from templates/conformance-report.md)
183
+ bindings/<slice-key>.yaml
184
+ # per-slice bindings manifests (`em conform bindings check`, GH #449)
179
185
  <model-name>-asis.em # conform-phase scratch model, regenerated per run — git-ignore this
180
186
  ```
181
187
 
182
- When creating a new model, run `em scaffold <model-name>` — it creates `<model-name>/` and
183
- writes all three starter files in one step (`<model-name>.em`, `README.md`,
184
- `.event-modeling.md`), filling the Model Name/model-name placeholders and the state file's
185
- mechanical fields (model path, `Current phase: discover`, `Current step: 1`, dates) for you, so
186
- there's nothing left to hand-copy or fill in. Refuses if `<model-name>/` already exists; pass
187
- `--force` to overwrite. You'll
188
- usually replace the scaffolded `.em`'s content as the discovery conversation builds up the real
189
- model — it starts out as the same starter model `em init` writes, titled from `<model-name>`.
190
- `slices/*.md` and `conformance/` aren't part of `em scaffold`; they come from the `slice` and
191
- `conform` phases (`event-modeling-design` and `event-modeling-conform`). The `conformance/`
192
- directory and `<model-name>-asis.em` only appear once the `conform` phase runs; `em conform-scope
193
- --seed-asis` creates `<model-name>-asis.em` and gitignores `*-asis.em` for you (see
194
- `event-modeling-conform`'s `reference/conform.md`) — it's scratch, never committed.
188
+ When creating a new model, run `em scaffold <model-name>` — it creates `<model-name>/`, writes
189
+ the four starter files in one step (`<model-name>.em`, `README.md`, `.event-modeling.md`,
190
+ `constitution.md`), filling the Model Name/model-name placeholders and the state file's
191
+ mechanical fields (model path, `Current phase: discover`, `Current step: 1`, dates) for you, and
192
+ also creates the standard `slices/`, `contracts/`, `model-versions/` and `conformance/bindings/`
193
+ directories — each seeded with a one-line README (never a `.gitkeep`) naming what lands there and
194
+ which command writes it. There's nothing left to hand-copy or fill in. Refuses if
195
+ `<model-name>/` already exists; pass `--force` to overwrite. You'll usually replace the
196
+ scaffolded `.em`'s content as the discovery conversation builds up the real model — it starts out
197
+ as the same starter model `em init` writes, titled from `<model-name>`.
198
+ Those directories exist from the start, but their real content doesn't — `slices/*.md` slice
199
+ docs come from the `slice` phase (`event-modeling-design`), `conformance/<date>-report.md`
200
+ reports from the `conform` phase (`event-modeling-conform`), and `contracts/*.tsp` /
201
+ `model-versions/*.json` / `conformance/bindings/*.yaml` only once `em api generate` / `em model
202
+ version bump` / an implementing agent's bindings manifest actually run. `<model-name>-asis.em` is
203
+ separate conform-phase scratch, not part of the scaffold at all; `em conform-scope --seed-asis`
204
+ creates it and gitignores `*-asis.em` for you (see `event-modeling-conform`'s
205
+ `reference/conform.md`) — it's scratch, never committed.
195
206
 
196
207
  ### Multi-model projects
197
208
 
@@ -56,7 +56,7 @@ to decide `frontmatter-invalid` without re-deriving frontmatter-shape rules of i
56
56
  | `schemaVersion` | integer | `1` (current dialect version) | its *value* is not read back by any `em` command today (reserved) — but its *presence* is required by `hasUsableFrontmatter()`: a doc omitting it is `frontmatter-invalid` (see below) |
57
57
  | `pattern` | string | `state-change` \| `state-view` \| `automation` \| `translation` | authored/informational only — `em catalog` and `em export` both derive pattern from the `.em` AST instead (`em export`'s `slice.pattern`, schema `1.4`) |
58
58
  | `swimlane` | string | free text, `<Persona> → <Context>` | display-only |
59
- | `status` | string, case-insensitive | `draft` \| `reviewed` \| `ready-to-implement` \| `implemented` | written by `em slice review` (→ `reviewed`, MIL-201), `em slice ratify`/`em slice reratify` (→ `ready-to-implement`) and `em slice mark-implemented` (→ `implemented`); read by `em catalog`, `em render`/`em watch` header coloring; joined into `em export`'s `slice.doc.status` (schema `1.4`); paired with `implementedIn` to compute `slice.doc.driftSignal` (schema `1.5`, MIL-85) and `em validate`'s frontmatter-coherence check (MIL-85 — see [validation.md#frontmatter-coherence](https://github.com/milehimikey/em/blob/main/docs/validation.md#frontmatter-coherence)) |
59
+ | `status` | string, case-insensitive | `draft` \| `reviewed` \| `ready-to-implement` \| `implemented` | written by `em slice review` (→ `reviewed`, MIL-201), `em slice ratify`/`em slice reratify` (→ `ready-to-implement`) and `em slice mark-implemented` (→ `implemented`); read by `em catalog`, `em render`/`em watch` header coloring; joined into `em export`'s `slice.doc.status` (schema `1.4`); paired with `implementedIn` to compute `slice.doc.driftSignal` (schema `1.5`, MIL-85) and `em validate`'s frontmatter-coherence check (MIL-85 — see [validation.md#frontmatter-coherence](https://github.com/milehimikey/em/blob/main/docs/validation.md#frontmatter-coherence)); any other value is read as written but `em validate` warns `frontmatter-status-unrecognized` (GH #411) |
60
60
  | `version` | integer | positive integer, starts at `1` | joined into `em export`'s `slice.doc.version` (schema `1.4`, MIL-91) |
61
61
  | `implementedIn` | string | free text (PR/commit link) | joined into `em export`'s `slice.doc.implementedIn` (schema `1.4`, MIL-91); paired with `status` to compute `slice.doc.driftSignal` (schema `1.5`, MIL-85) and `em validate`'s frontmatter-coherence check (MIL-85 — see [validation.md#frontmatter-coherence](https://github.com/milehimikey/em/blob/main/docs/validation.md#frontmatter-coherence)) |
62
62
  | `split-from` | single ref | `<slice-key>@v<N>` | joined into `em export`'s `slice.doc.splitFrom` (schema `1.4`, MIL-91) and `em diff`'s `slice-added` entries (schema `1.6`, MIL-84); current-tree referential checks by `em validate` (MIL-84 — see [validation.md#lineage](https://github.com/milehimikey/em/blob/main/docs/validation.md#lineage)) |
@@ -472,6 +472,7 @@ re-run `em slice sync`.
472
472
 
473
473
  | Region | Section | Body |
474
474
  |---|---|---|
475
+ | `em-slice-story` | right under `![Diagram](…)` | one line: `Step N of M in **<Storyline>** · after <Prev> · before <Next> · <Pattern>` (Prev and Next link to the neighbouring slices' docs; a continuation neighbour is named, not linked) — where the slice sits in its story; the one region `em slice sync` inserts when missing on an unsigned doc (see `em slice sync` in the CLI reference) |
475
476
  | `em-slice-command` | `## Command / Input` | `**Command:** \`Name\`` + `\| Field \| Type \| Required \| Rules / Validation \|` (Required is `no` for a `name?: Type` field) |
476
477
  | `em-slice-event` | `## Event(s) Emitted` | `**Event:** \`Name\` → context \`Ctx\`` + `\| Field \| Type \| Immutable Fact? \| Source / Notes \|` (Source: the same-slice command field it is copied from; failing that, the command from another slice that also records the event, written `not supplied by this command (from \`A\`, slice "Create")` (GH #344 / #362, the same union `fields-completeness/event-field-no-source` checks; worded as a statement about this slice, since the repeat's own command does not take the field); `assigned` for a system-assigned field, else `{{ }}`) |
477
478
  | `em-slice-view` | `## Read Model / View` | `- **View:** \`Name\` built from events: …` (the union across the originating and every `again` instance; each later event is annotated `(via "<slice>")` with the slice of the instance that adds it) + `\| Field \| Type \| Source / Notes \|` (Source: the source event, from that union, carrying the field, `Derived` for a `derived` field, `Collection of \`T\`, fed by …` for a `T[] derived from …` field — followed by one neutral Given/Then scenario stub per named event under the table, to copy into `## Scenarios` and complete there (the region itself stays read-only); `em slice sync` retires a stub once an authored scenario covers that field and event, by the stub's `<field> after <Event>` title or by a Given naming the event with the field named in the block (GH #368), and drops the `Scenario stubs for` line when none is left — else `{{ }}`) |
@@ -31,14 +31,22 @@ Change slice is paired with the State View slice that projects its event. A read
31
31
  along the timeline (`view X again`) shows the same projection at a later point; the instances are
32
32
  never connected to one another.
33
33
 
34
+ ## Storylines
35
+ <!-- Generated — `em slice index {{model-name}}.em` writes one row per storyline between the
36
+ markers (count, implemented, diagram); the canvas is `em render {{model-name}}.em --map`. -->
37
+ <!-- GENERATED:storylines:start -->
38
+ | Storyline | Slices | Implemented | Diagram |
39
+ |-----------|--------|-------------|---------|
40
+ <!-- GENERATED:storylines:end -->
41
+
34
42
  ## Slices
35
43
  <!-- The canonical slice index — the ONE place slices are enumerated (the state file
36
44
  points here rather than keeping its own copy). Generated — run
37
45
  `em slice index {{model-name}}.em` to (re)write the table below from the model and its
38
46
  slice docs; never hand-edit between the markers. -->
39
47
  <!-- GENERATED:slices:start -->
40
- | # | Slice | Pattern | Status | Reviewed by | Ratified by | Owner | Tracking | Implemented in | Design doc |
41
- |---|-------|---------|--------|-------------|-------------|-------|----------|----------------|------------|
48
+ | # | Slice | Pattern | Status | Design doc |
49
+ |---|-------|---------|--------|------------|
42
50
  <!-- GENERATED:slices:end -->
43
51
 
44
52
  ## Status
@@ -79,6 +79,10 @@ implementedIn: {{PR/commit link — fill in once status is `implemented`}}
79
79
 
80
80
  ![Diagram](./{{slice-name}}.svg)
81
81
 
82
+ <!-- GENERATED:em-slice-story:start — generated from the model by `em slice sync`; do not hand-edit -->
83
+ _Run `em slice sync` to place this slice in its story._
84
+ <!-- GENERATED:em-slice-story:end -->
85
+
82
86
  <!-- Only on re-ratification of an already-`implemented` slice — omit this whole section on a
83
87
  slice's first version (v1 has no delta yet). The heading is always the literal `## Delta`,
84
88
  never `## Delta: vX → vY` — hop metadata is a display line inside the section instead (see
@@ -169,7 +173,9 @@ an event directly.}}
169
173
  own rows, a lookup of some other entity's name/email/etc. so it can display it — that is the
170
174
  views-as-lookups smell (methodology reference, "Views as lookups"): the field belongs on the
171
175
  event that creates this view's row instead, copied from state the command/decider already
172
- reads to enforce its own invariants. Fix the `.em`, not the prose. -->
176
+ reads to enforce its own invariants. Fix the `.em`, not the prose. The built-from list names
177
+ every source, trigger and housekeeping alike; in the `.em` only the triggering event(s) sit in
178
+ `from`, the rest in `updates from` (methodology reference, "trigger and housekeeping"). -->
173
179
  <!-- GENERATED:em-slice-view:start — generated from the model by `em slice sync`; do not hand-edit -->
174
180
  - **View:** `{{View Name}}` built from events: {{"Event A", "Event B"}}
175
181
 
@@ -1,9 +1,9 @@
1
1
  {
2
- "name": "em-1-20-0",
2
+ "name": "em-1-22-0",
3
3
  "owner": {
4
4
  "name": "Mike Key"
5
5
  },
6
- "description": "em v1.20.0: the Event Modeling skill bundle and MCP server as a Claude Code plugin.",
6
+ "description": "em v1.22.0: the Event Modeling skill bundle and MCP server as a Claude Code plugin.",
7
7
  "plugins": [
8
8
  {
9
9
  "name": "em",
@@ -18,7 +18,8 @@ import { layoutDot, composeSvg, writeRendered } from "../render/render.js";
18
18
  import { buildSliceDiagram } from "../render/sliceDiagram.js";
19
19
  import { dedupe, kebabSlug } from "../util/slug.js";
20
20
  import { classifySlicePattern } from "./classify.js";
21
- import { readCoverageDocs } from "./coverage.js";
21
+ import { readCoverageDocsAll } from "./coverage.js";
22
+ import { docAbsPath, locateDoc } from "./docLocate.js";
22
23
  import { detectSliceDocCollisions } from "./modelCollisionValidate.js";
23
24
  import { parseSliceDoc } from "./sliceDoc.js";
24
25
  import { renderIndexPage, renderSlicePage } from "./pages.js";
@@ -81,7 +82,7 @@ export async function buildCatalog(inputs, opts) {
81
82
  let doc = ownDoc;
82
83
  let coveredBy = null;
83
84
  if (!ownDoc) {
84
- coverageDocs ??= readCoverageDocs(join(dirname(file), "slices"));
85
+ coverageDocs ??= readCoverageDocsAll(dirname(file)); // GH #421: every doc folder
85
86
  const covering = coverageDocs.get(sliceKey);
86
87
  if (covering) {
87
88
  doc = covering.doc;
@@ -95,8 +96,8 @@ export async function buildCatalog(inputs, opts) {
95
96
  // the own-file and MIL-121 covers: lookups have already come up empty.
96
97
  const continuation = continuationOf(model, refs, i);
97
98
  if (continuation) {
98
- const originatingPath = join(dirname(file), "slices", `${continuation.sliceKey}.md`);
99
- if (existsSync(originatingPath)) {
99
+ const originatingPath = locateDoc(dirname(file), `slices/${continuation.sliceKey}.md`); // GH #421
100
+ if (originatingPath) {
100
101
  doc = parseSliceDoc(readFileSync(originatingPath, "utf8"));
101
102
  const originatingSlice = model.slices[continuation.sliceIndex];
102
103
  coveredBy = { key: continuation.sliceKey, name: originatingSlice.name, kind: "continuation" };
@@ -109,7 +110,7 @@ export async function buildCatalog(inputs, opts) {
109
110
  // is copied in as-is so the catalog stays self-contained; otherwise built
110
111
  // fresh via buildSliceDiagram, written only into the catalog's own output
111
112
  // tree — `em catalog` never writes back into the source tree.
112
- const sliceSvgSrcPath = join(dirname(file), "slices", `${sliceKey}.svg`);
113
+ const sliceSvgSrcPath = docAbsPath(dirname(file), `slices/${sliceKey}.svg`, model.slices[i]); // GH #421
113
114
  const sliceDiagramFile = `${sliceKey}.svg`;
114
115
  if (existsSync(sliceSvgSrcPath)) {
115
116
  await copyFile(sliceSvgSrcPath, join(slicesDir, sliceDiagramFile));
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/catalog/build.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,0EAA0E;AAC1E,4EAA4E;AAC5E,EAAE;AACF,cAAc;AACd,iBAAiB;AACjB,mBAAmB;AACnB,8BAA8B;AAC9B,gBAAgB;AAChB,2BAA2B;AAC3B,2FAA2F;AAE3F,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAG9D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAe,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,eAAe,EAA4C,MAAM,YAAY,CAAC;AAmCxG,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAA2B,EAC3B,IAAoB;IAEpB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,qBAAqB,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAE3B,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,MAAM,cAAc,GAA0B,EAAE,CAAC;IACjD,MAAM,WAAW,GAAkD,EAAE,CAAC;IACtE,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,yFAAyF;IACzF,sFAAsF;IACtF,6FAA6F;IAC7F,sFAAsF;IACtF,yFAAyF;IACzF,MAAM,UAAU,GAAG,wBAAwB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;IACnH,KAAK,MAAM,CAAC,IAAI,UAAU;QAAE,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAE5F,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,CAAC;QACtD,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;QACtF,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC3C,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE5C,MAAM,WAAW,GAAG,WAAW,MAAM,EAAE,CAAC;QACxC,mFAAmF;QACnF,sFAAsF;QACtF,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;QACtE,MAAM,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;QAElE,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC3F,MAAM,cAAc,GAA0B,EAAE,CAAC;QACjD,oFAAoF;QACpF,uFAAuF;QACvF,oFAAoF;QACpF,oCAAoC;QACpC,IAAI,YAAY,GAAoC,IAAI,CAAC;QAEzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;YAE5C,mFAAmF;YACnF,oFAAoF;YACpF,mFAAmF;YACnF,sFAAsF;YACtF,qFAAqF;YACrF,6EAA6E;YAC7E,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,QAAQ,KAAK,CAAC,CAAC;YACpD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC;YAChD,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAEzF,yFAAyF;YACzF,yFAAyF;YACzF,wFAAwF;YACxF,0FAA0F;YAC1F,yFAAyF;YACzF,wFAAwF;YACxF,QAAQ;YACR,IAAI,GAAG,GAAG,MAAM,CAAC;YACjB,IAAI,SAAS,GAA0E,IAAI,CAAC;YAC5F,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,YAAY,KAAK,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;gBACjE,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAC5C,IAAI,QAAQ,EAAE,CAAC;oBACb,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC;oBACnB,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;oBAC3D,SAAS,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,aAAa,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;gBAChI,CAAC;qBAAM,CAAC;oBACN,qFAAqF;oBACrF,gFAAgF;oBAChF,qFAAqF;oBACrF,uEAAuE;oBACvE,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;oBACpD,IAAI,YAAY,EAAE,CAAC;wBACjB,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC,QAAQ,KAAK,CAAC,CAAC;wBACrF,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;4BAChC,GAAG,GAAG,aAAa,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;4BAC3D,MAAM,gBAAgB,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;4BAC/D,SAAS,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;wBAChG,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAED,8EAA8E;YAC9E,+EAA+E;YAC/E,0EAA0E;YAC1E,0EAA0E;YAC1E,8DAA8D;YAC9D,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,QAAQ,MAAM,CAAC,CAAC;YACzE,MAAM,gBAAgB,GAAG,GAAG,QAAQ,MAAM,CAAC;YAC3C,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;gBAChC,MAAM,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC,CAAC;YACrE,CAAC;iBAAM,CAAC;gBACN,+EAA+E;gBAC/E,8EAA8E;gBAC9E,6EAA6E;gBAC7E,8EAA8E;gBAC9E,4EAA4E;gBAC5E,sEAAsE;gBACtE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,iBAAiB,CAAC,KAAK,EAAE,CAAC,EAAE;oBACxF,cAAc,EAAE,IAAI,CAAC,cAAc;iBACpC,CAAC,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;gBAC3C,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC;gBACvF,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;YACvE,CAAC;YAED,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC9C,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAChC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACpC,IAAI,GAAG;oBAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YACvC,CAAC;YAED,MAAM,IAAI,GAAG,eAAe,CAAC;gBAC3B,SAAS,EAAE,KAAK,CAAC,IAAI;gBACrB,WAAW,EAAE,MAAM,WAAW,EAAE;gBAChC,gBAAgB;gBAChB,KAAK;gBACL,QAAQ;gBACR,OAAO;gBACP,WAAW;gBACX,GAAG;gBACH,SAAS;gBACT,eAAe,EAAE,UAAU;aAC5B,CAAC,CAAC;YACH,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,QAAQ,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAEnE,cAAc,CAAC,IAAI,CAAC;gBAClB,GAAG,EAAE,QAAQ;gBACb,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO;gBACP,MAAM,EAAE,GAAG,KAAK,IAAI;gBACpB,MAAM,EAAE,GAAG,EAAE,MAAM,IAAI,IAAI;aAC5B,CAAC,CAAC;YACH,UAAU,EAAE,CAAC;QACf,CAAC;QAED,cAAc,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;IACtG,CAAC;IAED,MAAM,SAAS,GAAG,eAAe,CAAC,cAAc,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACjE,MAAM,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAE/D,OAAO,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;AAC5E,CAAC"}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/catalog/build.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,kEAAkE;AAClE,0EAA0E;AAC1E,4EAA4E;AAC5E,EAAE;AACF,cAAc;AACd,iBAAiB;AACjB,mBAAmB;AACnB,8BAA8B;AAC9B,gBAAgB;AAChB,2BAA2B;AAC3B,2FAA2F;AAE3F,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAG9D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAe,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,eAAe,EAA4C,MAAM,YAAY,CAAC;AAmCxG,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAA2B,EAC3B,IAAoB;IAEpB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,qBAAqB,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAE3B,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,MAAM,cAAc,GAA0B,EAAE,CAAC;IACjD,MAAM,WAAW,GAAkD,EAAE,CAAC;IACtE,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,yFAAyF;IACzF,sFAAsF;IACtF,6FAA6F;IAC7F,sFAAsF;IACtF,yFAAyF;IACzF,MAAM,UAAU,GAAG,wBAAwB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;IACnH,KAAK,MAAM,CAAC,IAAI,UAAU;QAAE,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAE5F,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,CAAC;QACtD,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;QACtF,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC3C,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE5C,MAAM,WAAW,GAAG,WAAW,MAAM,EAAE,CAAC;QACxC,mFAAmF;QACnF,sFAAsF;QACtF,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;QACtE,MAAM,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;QAElE,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC3F,MAAM,cAAc,GAA0B,EAAE,CAAC;QACjD,oFAAoF;QACpF,uFAAuF;QACvF,oFAAoF;QACpF,oCAAoC;QACpC,IAAI,YAAY,GAAoC,IAAI,CAAC;QAEzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;YAE5C,mFAAmF;YACnF,oFAAoF;YACpF,mFAAmF;YACnF,sFAAsF;YACtF,qFAAqF;YACrF,6EAA6E;YAC7E,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,QAAQ,KAAK,CAAC,CAAC;YACpD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC;YAChD,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAEzF,yFAAyF;YACzF,yFAAyF;YACzF,wFAAwF;YACxF,0FAA0F;YAC1F,yFAAyF;YACzF,wFAAwF;YACxF,QAAQ;YACR,IAAI,GAAG,GAAG,MAAM,CAAC;YACjB,IAAI,SAAS,GAA0E,IAAI,CAAC;YAC5F,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,YAAY,KAAK,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,4BAA4B;gBACjF,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAC5C,IAAI,QAAQ,EAAE,CAAC;oBACb,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC;oBACnB,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;oBAC3D,SAAS,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,aAAa,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;gBAChI,CAAC;qBAAM,CAAC;oBACN,qFAAqF;oBACrF,gFAAgF;oBAChF,qFAAqF;oBACrF,uEAAuE;oBACvE,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;oBACpD,IAAI,YAAY,EAAE,CAAC;wBACjB,MAAM,eAAe,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,YAAY,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,UAAU;wBAClG,IAAI,eAAe,EAAE,CAAC;4BACpB,GAAG,GAAG,aAAa,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;4BAC3D,MAAM,gBAAgB,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;4BAC/D,SAAS,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;wBAChG,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAED,8EAA8E;YAC9E,+EAA+E;YAC/E,0EAA0E;YAC1E,0EAA0E;YAC1E,8DAA8D;YAC9D,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,UAAU,QAAQ,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU;YACxG,MAAM,gBAAgB,GAAG,GAAG,QAAQ,MAAM,CAAC;YAC3C,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;gBAChC,MAAM,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC,CAAC;YACrE,CAAC;iBAAM,CAAC;gBACN,+EAA+E;gBAC/E,8EAA8E;gBAC9E,6EAA6E;gBAC7E,8EAA8E;gBAC9E,4EAA4E;gBAC5E,sEAAsE;gBACtE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,iBAAiB,CAAC,KAAK,EAAE,CAAC,EAAE;oBACxF,cAAc,EAAE,IAAI,CAAC,cAAc;iBACpC,CAAC,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;gBAC3C,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC;gBACvF,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;YACvE,CAAC;YAED,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC9C,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAChC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACpC,IAAI,GAAG;oBAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YACvC,CAAC;YAED,MAAM,IAAI,GAAG,eAAe,CAAC;gBAC3B,SAAS,EAAE,KAAK,CAAC,IAAI;gBACrB,WAAW,EAAE,MAAM,WAAW,EAAE;gBAChC,gBAAgB;gBAChB,KAAK;gBACL,QAAQ;gBACR,OAAO;gBACP,WAAW;gBACX,GAAG;gBACH,SAAS;gBACT,eAAe,EAAE,UAAU;aAC5B,CAAC,CAAC;YACH,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,QAAQ,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAEnE,cAAc,CAAC,IAAI,CAAC;gBAClB,GAAG,EAAE,QAAQ;gBACb,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO;gBACP,MAAM,EAAE,GAAG,KAAK,IAAI;gBACpB,MAAM,EAAE,GAAG,EAAE,MAAM,IAAI,IAAI;aAC5B,CAAC,CAAC;YACH,UAAU,EAAE,CAAC;QACf,CAAC;QAED,cAAc,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;IACtG,CAAC;IAED,MAAM,SAAS,GAAG,eAAe,CAAC,cAAc,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACjE,MAAM,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAE/D,OAAO,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC;AAC5E,CAAC"}
@@ -13,3 +13,6 @@ export interface CoveringDoc {
13
13
  * uses — the one precedent for it is `em ledger`'s (src/cli/ledgerCheck.ts) own
14
14
  * `readdirSync(slicesDir)` sweep. */
15
15
  export declare function readCoverageDocs(slicesDir: string): Map<string, CoveringDoc>;
16
+ /** GH #421: the same sweep over every doc folder under the model's directory (the root's
17
+ * `slices/` and each storyline folder's), root first, first claim wins. */
18
+ export declare function readCoverageDocsAll(baseDir: string): Map<string, CoveringDoc>;
@@ -11,6 +11,7 @@
11
11
  import { existsSync, readdirSync, readFileSync } from "node:fs";
12
12
  import { join } from "node:path";
13
13
  import { parseSliceDoc } from "./sliceDoc.js";
14
+ import { docDirs } from "./docLocate.js";
14
15
  /** Scans every `slices/*.md` file (sorted, for deterministic first-wins on an overlapping
15
16
  * `covers:` claim) and maps each covered slice key to the doc — and that doc's own key — that
16
17
  * covers it. Directory-scan, not the single-file existsSync check every other doc lookup in em
@@ -31,4 +32,15 @@ export function readCoverageDocs(slicesDir) {
31
32
  }
32
33
  return coverage;
33
34
  }
35
+ /** GH #421: the same sweep over every doc folder under the model's directory (the root's
36
+ * `slices/` and each storyline folder's), root first, first claim wins. */
37
+ export function readCoverageDocsAll(baseDir) {
38
+ const coverage = new Map();
39
+ for (const dir of docDirs(baseDir)) {
40
+ for (const [k, v] of readCoverageDocs(dir))
41
+ if (!coverage.has(k))
42
+ coverage.set(k, v);
43
+ }
44
+ return coverage;
45
+ }
34
46
  //# sourceMappingURL=coverage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../src/catalog/coverage.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,6FAA6F;AAC7F,6FAA6F;AAC7F,2FAA2F;AAC3F,gGAAgG;AAChG,4FAA4F;AAC5F,4FAA4F;AAC5F,gGAAgG;AAChG,0FAA0F;AAC1F,uDAAuD;AAEvD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAY,MAAM,eAAe,CAAC;AAWxD;;;;sCAIsC;AACtC,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IAChD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5C,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACvE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACzC,KAAK,MAAM,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACpC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC;gBAAE,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../src/catalog/coverage.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,6FAA6F;AAC7F,6FAA6F;AAC7F,2FAA2F;AAC3F,gGAAgG;AAChG,4FAA4F;AAC5F,4FAA4F;AAC5F,gGAAgG;AAChG,0FAA0F;AAC1F,uDAAuD;AAEvD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAY,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAWzC;;;;sCAIsC;AACtC,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IAChD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5C,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACvE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACzC,KAAK,MAAM,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACpC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC;gBAAE,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;4EAC4E;AAC5E,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IAChD,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,gBAAgB,CAAC,GAAG,CAAC;YAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvF,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /** Doc folder prefixes under `baseDir`: `""` (the root's `slices/`) first, then `"<sub>/"` for
2
+ * every immediate subdirectory that is a storyline model folder with a `slices/` directory,
3
+ * sorted. Never cached: a split or a new storyline folder mid-session must be seen on the next
4
+ * call. */
5
+ export declare function docFolders(baseDir: string): string[];
6
+ /** Absolute path of the existing file `relPath` (a `slices/<key>.md`-shaped path, or any path
7
+ * relative to the declaring file's directory), searched root first across the doc folders;
8
+ * `null` when no folder has it. A path that already starts with a folder prefix is honoured
9
+ * as written. */
10
+ export declare function locateDoc(baseDir: string, relPath: string): string | null;
11
+ /** Where `relPath` is — or, when it does not exist yet, where it belongs: the folder of the
12
+ * slice that declares it (`slice.file`'s directory), the root for a root slice. */
13
+ export declare function docAbsPath(baseDir: string, relPath: string, slice?: {
14
+ file?: string;
15
+ }): string;
16
+ /** Every existing `slices/` directory under `baseDir` (root first), absolute. */
17
+ export declare function docDirs(baseDir: string): string[];