@milehimikey/em 1.20.0 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/event-modeling/SKILL.md +1 -1
- package/.claude/skills/event-modeling-conform/SKILL.md +1 -1
- package/.claude/skills/event-modeling-design/SKILL.md +23 -8
- package/.claude/skills/event-modeling-discover/SKILL.md +2 -2
- package/.claude/skills/event-modeling-discover/reference/extract.md +5 -1
- package/.claude/skills/event-modeling-engagement/SKILL.md +1 -1
- package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
- package/.claude/skills/event-modeling-review/SKILL.md +19 -7
- package/.claude/skills/event-modeling-shared/reference/em-dsl.md +35 -3
- package/.claude/skills/event-modeling-shared/reference/methodology.md +35 -2
- package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +2 -1
- package/.claude/skills/event-modeling-shared/templates/model-readme.md +10 -2
- package/.claude/skills/event-modeling-shared/templates/slice.md +7 -1
- package/.claude-plugin/marketplace.json +2 -2
- package/dist/catalog/build.js +6 -5
- package/dist/catalog/build.js.map +1 -1
- package/dist/catalog/coverage.d.ts +3 -0
- package/dist/catalog/coverage.js +12 -0
- package/dist/catalog/coverage.js.map +1 -1
- package/dist/catalog/docLocate.d.ts +17 -0
- package/dist/catalog/docLocate.js +97 -0
- package/dist/catalog/docLocate.js.map +1 -0
- package/dist/catalog/frontmatterCoherenceValidate.js +16 -1
- package/dist/catalog/frontmatterCoherenceValidate.js.map +1 -1
- package/dist/catalog/orphanedSliceDocValidate.js +15 -10
- package/dist/catalog/orphanedSliceDocValidate.js.map +1 -1
- package/dist/catalog/readSliceDoc.js +5 -4
- package/dist/catalog/readSliceDoc.js.map +1 -1
- package/dist/catalog/scenarioQualityValidate.js +2 -2
- package/dist/catalog/scenarioQualityValidate.js.map +1 -1
- package/dist/catalog/sliceDoc.d.ts +8 -0
- package/dist/catalog/sliceDoc.js +9 -0
- package/dist/catalog/sliceDoc.js.map +1 -1
- package/dist/catalog/sliceSections.d.ts +18 -1
- package/dist/catalog/sliceSections.js +38 -4
- package/dist/catalog/sliceSections.js.map +1 -1
- package/dist/cli/defer.js +3 -2
- package/dist/cli/defer.js.map +1 -1
- package/dist/cli/ledgerCheck.js +11 -8
- package/dist/cli/ledgerCheck.js.map +1 -1
- package/dist/cli/markImplemented.js +2 -2
- package/dist/cli/markImplemented.js.map +1 -1
- package/dist/cli/ratify.js +2 -2
- package/dist/cli/ratify.js.map +1 -1
- package/dist/cli/refsCheck.js +3 -2
- package/dist/cli/refsCheck.js.map +1 -1
- package/dist/cli/render-inputs.d.ts +1 -1
- package/dist/cli/render-inputs.js +3 -2
- package/dist/cli/render-inputs.js.map +1 -1
- package/dist/cli/review.js +2 -2
- package/dist/cli/review.js.map +1 -1
- package/dist/cli/revise.js +2 -2
- package/dist/cli/revise.js.map +1 -1
- package/dist/cli/skillDirs.d.ts +22 -0
- package/dist/cli/skillDirs.js +24 -0
- package/dist/cli/skillDirs.js.map +1 -1
- package/dist/cli/sliceConform.js +2 -1
- package/dist/cli/sliceConform.js.map +1 -1
- package/dist/cli/sliceIndex.d.ts +19 -3
- package/dist/cli/sliceIndex.js +81 -17
- package/dist/cli/sliceIndex.js.map +1 -1
- package/dist/cli/sliceNew.js +2 -0
- package/dist/cli/sliceNew.js.map +1 -1
- package/dist/cli/sliceStubAll.js +7 -2
- package/dist/cli/sliceStubAll.js.map +1 -1
- package/dist/cli/sliceSync.d.ts +12 -0
- package/dist/cli/sliceSync.js +42 -4
- package/dist/cli/sliceSync.js.map +1 -1
- package/dist/cli/status.d.ts +3 -4
- package/dist/cli/status.js +5 -4
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/storylineSplit.d.ts +18 -0
- package/dist/cli/storylineSplit.js +110 -0
- package/dist/cli/storylineSplit.js.map +1 -0
- package/dist/cli/upgrade.js +39 -14
- package/dist/cli/upgrade.js.map +1 -1
- package/dist/cli/watchStoryline.d.ts +6 -0
- package/dist/cli/watchStoryline.js +10 -0
- package/dist/cli/watchStoryline.js.map +1 -1
- package/dist/cli.js +265 -67
- package/dist/cli.js.map +1 -1
- package/dist/emit/json.d.ts +22 -1
- package/dist/emit/json.js +12 -1
- package/dist/emit/json.js.map +1 -1
- package/dist/mcp/server.js +20 -6
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/edges.d.ts +1 -1
- package/dist/model/edges.js +8 -1
- package/dist/model/edges.js.map +1 -1
- package/dist/model/loadModel.d.ts +38 -0
- package/dist/model/loadModel.js +122 -0
- package/dist/model/loadModel.js.map +1 -0
- package/dist/model/model.d.ts +9 -4
- package/dist/model/model.js +4 -0
- package/dist/model/model.js.map +1 -1
- package/dist/model/rules.d.ts +23 -0
- package/dist/model/rules.js +23 -0
- package/dist/model/rules.js.map +1 -1
- package/dist/model/shapeLint.js +95 -0
- package/dist/model/shapeLint.js.map +1 -1
- package/dist/model/sliceDocIndex.js +13 -5
- package/dist/model/sliceDocIndex.js.map +1 -1
- package/dist/model/sliceDocPath.d.ts +19 -0
- package/dist/model/sliceDocPath.js +49 -0
- package/dist/model/sliceDocPath.js.map +1 -0
- package/dist/model/storylineMap.d.ts +20 -0
- package/dist/model/storylineMap.js +55 -0
- package/dist/model/storylineMap.js.map +1 -0
- package/dist/model/validate.d.ts +7 -0
- package/dist/model/validate.js +8 -0
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/ast.d.ts +19 -0
- package/dist/parser/parser.d.ts +17 -1
- package/dist/parser/parser.js +91 -2
- package/dist/parser/parser.js.map +1 -1
- package/dist/pipeline.d.ts +16 -0
- package/dist/pipeline.js +19 -2
- package/dist/pipeline.js.map +1 -1
- package/dist/render/drawEdges.d.ts +5 -1
- package/dist/render/drawEdges.js +57 -4
- package/dist/render/drawEdges.js.map +1 -1
- package/dist/render/drawNotes.d.ts +4 -1
- package/dist/render/drawNotes.js +40 -10
- package/dist/render/drawNotes.js.map +1 -1
- package/dist/render/render.d.ts +11 -0
- package/dist/render/render.js +94 -11
- package/dist/render/render.js.map +1 -1
- package/dist/render/serve.d.ts +5 -0
- package/dist/render/serve.js +18 -2
- package/dist/render/serve.js.map +1 -1
- package/dist/render/sliceDiagram.js +3 -0
- package/dist/render/sliceDiagram.js.map +1 -1
- package/dist/render/sliceOverlay.d.ts +4 -5
- package/dist/render/sliceOverlay.js +4 -7
- package/dist/render/sliceOverlay.js.map +1 -1
- package/dist/render/sliceStatus.d.ts +8 -0
- package/dist/render/sliceStatus.js +22 -15
- package/dist/render/sliceStatus.js.map +1 -1
- package/dist/render/storylineBands.d.ts +0 -3
- package/dist/render/storylineBands.js +2 -22
- package/dist/render/storylineBands.js.map +1 -1
- package/dist/render/storylineDiagram.js +17 -69
- package/dist/render/storylineDiagram.js.map +1 -1
- package/dist/render/storylineMap.d.ts +18 -0
- package/dist/render/storylineMap.js +263 -0
- package/dist/render/storylineMap.js.map +1 -0
- package/dist/render/svgGeometry.d.ts +9 -0
- package/dist/render/svgGeometry.js +16 -0
- package/dist/render/svgGeometry.js.map +1 -1
- package/dist/render/viewerHtml.js +1 -1
- package/dist/render/viewerHtml.js.map +1 -1
- package/dist/templates.d.ts +1 -1
- package/dist/templates.js +10 -2
- package/dist/templates.js.map +1 -1
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/shared/reference/em-dsl.md +35 -3
- package/plugin/shared/reference/methodology.md +35 -2
- package/plugin/shared/reference/slice-doc-schema.md +2 -1
- package/plugin/shared/templates/model-readme.md +10 -2
- package/plugin/shared/templates/slice.md +7 -1
- package/plugin/skills/conform/SKILL.md +1 -1
- package/plugin/skills/design/SKILL.md +23 -8
- package/plugin/skills/discover/SKILL.md +2 -2
- package/plugin/skills/discover/reference/extract.md +5 -1
- package/plugin/skills/engagement/SKILL.md +1 -1
- package/plugin/skills/event-modeling/SKILL.md +1 -1
- package/plugin/skills/implement/SKILL.md +1 -1
- package/plugin/skills/review/SKILL.md +19 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when the user runs `/event-modeling` (with or without a phase name), or wants to resume an
|
|
6
6
|
event-modeling session without specifying which part of the process applies. Reads the model's
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-conform
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when checking a ratified event model (and its slice docs) for drift against the codebase
|
|
6
6
|
that implements it — advisory only, never a gate, never an unprompted edit — or when walking
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-design
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when structuring a draft event model into swimlanes and the four patterns (State Change,
|
|
6
6
|
State View, Automation, Translation), evaluating a model's structural completeness, or writing
|
|
@@ -71,7 +71,13 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
|
|
|
71
71
|
optional `after "<storyline>"` timeline clause: `em-dsl.md`) so the diagram gets a band per
|
|
72
72
|
story and `em render --storyline "Name"` can show one alone; slices keep their file order, and
|
|
73
73
|
a model can adopt storylines incrementally (`slice-outside-storyline` is only an advisory
|
|
74
|
-
warning) — but name them before you slice, not after.
|
|
74
|
+
warning) — but name them before you slice, not after. **Once the storylines are named, give
|
|
75
|
+
each its own file** (GH #421): run `em storyline split <root>.em` so the root keeps the
|
|
76
|
+
vocabulary and the storyline list with its flow (`storyline "Name" [after "Other"]`) and each
|
|
77
|
+
story's slices live in `<slug>/<slug>.em` with its docs in `<slug>/slices/` — do this before any
|
|
78
|
+
doc is wired, so nothing moves twice. **A storyline that reads another story's events declares
|
|
79
|
+
`after` it** (`storyline-reads-without-after` flags the ones you miss); two stories that run in
|
|
80
|
+
parallel read nothing from each other. Then group events into **contexts** (bounded contexts /
|
|
75
81
|
aggregates) — ask which events share a consistency boundary and who owns them. Classify each
|
|
76
82
|
slice as one of the 4 patterns. **Share the slice between every automation or translation and
|
|
77
83
|
the command it triggers** (the reaction — processor/translation — together with the command
|
|
@@ -91,17 +97,26 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
|
|
|
91
97
|
read model; a child view only when its query needs what the parent view lacks), the
|
|
92
98
|
**views-as-lookups check** per `from "E"` on a view (does E add, change or remove a row here? if
|
|
93
99
|
it only fills a column, put the column on the event that creates the row and drop E — see
|
|
94
|
-
`../event-modeling-shared/reference/methodology.md`, "Views as lookups"),
|
|
100
|
+
`../event-modeling-shared/reference/methodology.md`, "Views as lookups"), then the
|
|
101
|
+
**trigger / housekeeping split** on what is left (*which event is the reason this row appears?*
|
|
102
|
+
that one stays in `from`; every event that only keeps a row current or removes it moves to
|
|
103
|
+
`updates from` — the view still reads it, the diagram no longer draws it; a to-do list with more
|
|
104
|
+
than one or two inbound arrows is missing this split), the **continuation check** per `view X
|
|
105
|
+
again` (it names only the events that changed the view since the previous instance, never the
|
|
106
|
+
first instance's list again), and the
|
|
95
107
|
**conditional-invariant signal** (invariants or fields that apply only "if `<field>` is set"
|
|
96
|
-
mean two intents in one command: split it).
|
|
97
|
-
`
|
|
98
|
-
|
|
99
|
-
|
|
108
|
+
mean two intents in one command: split it). Read each story on its own render and on the canvas
|
|
109
|
+
(`em render <root>.em --map`), not on the full timeline. The `timeline-entity-clustered`,
|
|
110
|
+
`command-second-intent`, `automation-split-by-outcome`, `view-lookup-source`,
|
|
111
|
+
`again-restates-sources` and `storyline-reads-without-after` lints are the
|
|
112
|
+
mechanical half (the lookup one only catches the cross-context cases — do the check by eye too); the
|
|
113
|
+
design exit gate is `em validate --shape`. Shape the model first, scaffold docs after: a rename,
|
|
100
114
|
split or merge from the reshape would orphan docs already wired with `--wire`. The `slice` phase is unchanged (timeline order).
|
|
101
115
|
3. **Elaborate scenarios — first pass (step 6).** Scaffold every slice's doc now, one per
|
|
102
116
|
slice, none skipped: `em slice new "<slice name>" --pattern <state-change|state-view|
|
|
103
117
|
automation|translation> --swimlane "<Persona> → <Context>" --wire <model>.em` writes
|
|
104
|
-
`slices/<slice-name>.md` at `status: draft` (the
|
|
118
|
+
`slices/<slice-name>.md` at `status: draft` (into the slice's own storyline folder when the model
|
|
119
|
+
is split — pass the ROOT model to `--wire`) (the same command, flags, and `--wire`
|
|
105
120
|
note-binding the `slice` phase's step 2 below documents in full). A slice whose only element
|
|
106
121
|
is a `view X again` instance is a **continuation** (MIL-208), not a slice to scaffold —
|
|
107
122
|
`--wire` refuses it and names the originating slice holding `X`'s first declaration; its
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-discover
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when starting a brand-new event model from scratch — greenfield discovery: brainstorming
|
|
6
6
|
past-tense events, storyboarding the happy path, finding the commands and read models — or when
|
|
@@ -68,7 +68,7 @@ Goal: a draft model of events, storyboard, commands, and views. Loose is OK; str
|
|
|
68
68
|
**Close the loop before leaving this step:** every event from step 3 must be read by at least one
|
|
69
69
|
read model. Walk the event list and ask, for each one, *"who looks at this, and what do they do
|
|
70
70
|
with it?"* An event with no answer is either missing its read model or shouldn't be recorded —
|
|
71
|
-
both are worth raising with the user rather than leaving dangling.
|
|
71
|
+
both are worth raising with the user rather than leaving dangling. Keep the draft in one file with inline `storyline` blocks; the design phase splits it into one file per story (`em storyline split`) once the names are settled.
|
|
72
72
|
|
|
73
73
|
End of phase: write/refresh the `.em`, render it, update `.event-modeling.md` (steps done,
|
|
74
74
|
decisions, open questions — run `em state set-phase model` rather than hand-editing `Current
|
|
@@ -103,7 +103,11 @@ it is fine to finish a round with `# TBD`s still parked.
|
|
|
103
103
|
here, that would be inventing desired state. Note it as a finding in the Decisions log the same
|
|
104
104
|
way as an unread event, and leave it for `model`/`slice` to apply the views-as-lookups rule
|
|
105
105
|
(`../../event-modeling-shared/reference/methodology.md`, "Views as lookups") once the as-is
|
|
106
|
-
model is agreed.
|
|
106
|
+
model is agreed. **Housekeeping handlers are `updates from`, as-is:** when the projection code
|
|
107
|
+
handles an event only to update or delete a row it already holds (a status flip, a due date
|
|
108
|
+
moved, an address changed, a row removed), write that event in `updates from "…"`, not `from` —
|
|
109
|
+
that is what the code does today, it keeps the field tracing complete, and the as-is render then
|
|
110
|
+
shows the one line that puts work on the list instead of every handler.
|
|
107
111
|
- **R5 — Boundaries & reactions.** Current automations and integrations as-is: schedulers,
|
|
108
112
|
listeners, outbound syncs, inbound webhooks. Model each as a reaction sharing its slice with
|
|
109
113
|
the `command` + `event` it triggers (`reaction → command → event`, per `em-dsl.md`) — the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-engagement
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when leading an engagement: building a named set of ratified event-modeling slices
|
|
6
6
|
(`em engagement`) into one independent PR per slice, each against main, by dispatching the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-implement
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when building a single ratified event-modeling slice (status: ready-to-implement) into
|
|
6
6
|
merged, tested code — the one phase where the agent builds rather than facilitates. Gates on
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-review
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.21.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when starting em's live browser viewer (`em watch --serve`) so a team can watch a model
|
|
6
6
|
update in real time, or facilitating a SCHEDULED stakeholder walkthrough that steps through
|
|
@@ -15,8 +15,16 @@ description: >-
|
|
|
15
15
|
Start the watcher with `--serve` in the background:
|
|
16
16
|
`em watch <model-name>.em -o <model-name>.svg --serve` (run_in_background). It re-renders on every
|
|
17
17
|
save and pushes an instant reload to the browser over Server-Sent Events. Tell the user to open the
|
|
18
|
-
URL it prints
|
|
19
|
-
|
|
18
|
+
URL it prints and share their screen — updates appear the moment you save, with no polling and no
|
|
19
|
+
idle churn between edits.
|
|
20
|
+
|
|
21
|
+
What that URL opens depends on the model. A model that declares storylines opens on the
|
|
22
|
+
**storyline canvas** (`http://localhost:5173/map`): every storyline's own diagram in a draggable
|
|
23
|
+
frame, the flow between storylines drawn between frames, reloaded live on every save with the
|
|
24
|
+
layout kept. A frame's **open ›** drills into that storyline — the viewer on its own slices and
|
|
25
|
+
nothing from outside it — and **‹ Storylines** in the header returns to the canvas. A model
|
|
26
|
+
without storylines opens on the timeline (`http://localhost:5173/?svg=<model-name>.svg`). Never
|
|
27
|
+
send a room to the full timeline of a storyline model; the storyline is the unit people read.
|
|
20
28
|
|
|
21
29
|
The viewer navigates like a map — drag to pan, scroll/pinch to zoom, **Fit** to reset — and its
|
|
22
30
|
**Review mode** steps through slices one at a time (see the `review` phase below). A save that
|
|
@@ -34,10 +42,14 @@ speculation.** Don't propose this phase proactively; it exists for facilitated r
|
|
|
34
42
|
non-engineer stakeholders in the room, not routine model editing.
|
|
35
43
|
|
|
36
44
|
Start the same live server as `watch`: `em watch <model-name>.em -o <model-name>.svg --serve`
|
|
37
|
-
(run_in_background). Open the printed URL
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
(run_in_background). Open the printed URL and share the screen. With storylines, review one
|
|
46
|
+
storyline at a time: open it from the canvas (or start inside it with `--storyline "<name>"`),
|
|
47
|
+
then click **Review mode** in the header — Prev/Next walk that storyline's slices only. Between
|
|
48
|
+
storylines, **‹ Storylines** returns to the canvas, where the arrows between frames are the
|
|
49
|
+
order to take them in. Without storylines, click **Review mode** on the timeline. Use Prev/Next
|
|
50
|
+
(or the left/right arrow keys) to step through slices in declaration order — each one
|
|
51
|
+
pans/zooms into view with everything else dimmed, so the room's attention tracks one slice at
|
|
52
|
+
a time.
|
|
41
53
|
|
|
42
54
|
**When a State View slice is on screen, ask who reads it (MIL-215):** a person or client in the
|
|
43
55
|
room → the `ui` should draw it; another system → `public`; only an automation → nothing, it's
|
|
@@ -22,7 +22,8 @@ em render <file> # transpile
|
|
|
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,
|
|
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
|
|
@@ -70,6 +71,7 @@ em slice stub-all <file> --implemented-in <url> # PR/commit
|
|
|
70
71
|
em slice stub-all <file> --dry-run # list what would be stubbed/wired without writing anything
|
|
71
72
|
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
73
|
em slice index <file> --check # verify the table is current; exit non-zero on drift without writing (CI)
|
|
74
|
+
em slice index <file> --full # every lifecycle column (reviewed/ratified/owner/tracking/implemented/conformed) instead of the reader's five
|
|
73
75
|
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
76
|
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
77
|
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)
|
|
@@ -275,15 +277,25 @@ em mcp # start an M
|
|
|
275
277
|
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
278
|
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
279
|
em skill install --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
|
|
280
|
+
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)
|
|
281
|
+
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
282
|
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
283
|
em skill sync [path] --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
|
|
284
|
+
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)
|
|
285
|
+
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
286
|
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
287
|
em skill check [path] --json # print a JSON document instead of the text report (see docs/cli.md)
|
|
282
288
|
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
|
|
289
|
+
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)
|
|
290
|
+
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
291
|
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
292
|
em ci init <model> --tests <dir> # test directory the coverage/status steps scan for INV-* citations
|
|
285
293
|
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
294
|
em ci init <model> --check # verify both files match the current preset; exit non-zero on drift without writing (CI)
|
|
295
|
+
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)
|
|
296
|
+
em storyline split <file> --storyline <name> # split only this storyline
|
|
297
|
+
em storyline split <file> --dry-run # print what would be written without touching anything
|
|
298
|
+
em storyline split <file> -f, --force # overwrite a storyline model file that already exists
|
|
287
299
|
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
300
|
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
301
|
em upgrade <file> --apply # apply every applicable mechanical step, one git commit each, then a final `Em version:` commit
|
|
@@ -310,12 +322,14 @@ context Name # an event swimlane row (bounded context / aggr
|
|
|
310
322
|
storyline "Name" [source "url"] [after "Other"] { # optional chapter grouping slices (see Storylines)
|
|
311
323
|
slice "Name" { ... }
|
|
312
324
|
}
|
|
325
|
+
storyline "Name" [after "Other"] [in "path.em"] # a storyline MODEL: its slices live in <slug>/<slug>.em (see Storylines)
|
|
313
326
|
|
|
314
327
|
slice "Name" [source "url"] { # one vertical time step (a column); source is optional
|
|
315
328
|
ui Free Text @Persona # screen; @Persona picks its row (defaults to first/"User")
|
|
316
329
|
command Free Text # state-changing request (API band)
|
|
317
330
|
invariant INV-ORD-1 "Rule" # rule guarding the command/event just above (see Clauses)
|
|
318
331
|
view Free Text from "Event A", "Event B" # read model fed by event(s)
|
|
332
|
+
view Free Text from "Event A" updates from "Event B", "Event C" # B, C keep rows current: read, never drawn (see Clauses)
|
|
319
333
|
view Free Text again from "Event C" # later instance of an evolving read model (see Clauses)
|
|
320
334
|
event Free Text @Context # recorded fact; @Context picks its row (defaults to "Domain")
|
|
321
335
|
processor Free Text from "View" # automation; aliases: automation | saga | translation
|
|
@@ -359,6 +373,14 @@ type Name { field: Type, ... } # named structured type, reusable from any f
|
|
|
359
373
|
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
374
|
after the last site, or `event-unread` warns for that site). The same name in a different context
|
|
361
375
|
is still a `duplicate-name` warning.
|
|
376
|
+
- **`updates from "Event", …`** (views only, GH #414): the subset of a view's sources that only keep a
|
|
377
|
+
row current or remove it (a due date moved, an address changed, a loan returned). They are folded
|
|
378
|
+
into the view's `from` for every check — `derived from`, completeness, the generated built-from
|
|
379
|
+
list — but never drawn as arrows: the diagram shows the line from the event that puts work on the
|
|
380
|
+
list, and lists the rest under "Kept current by". The author chooses the triggers: `view Holds To
|
|
381
|
+
Fulfill from "Hold Placed", "Tool Returned" updates from "Hold Collected", "Hold Cancelled"`.
|
|
382
|
+
Valid on an `again` instance too. A to-do view with more than one or two inbound arrows is missing
|
|
383
|
+
this split.
|
|
362
384
|
- **`again`** (views only): `view <Name> again [from "Event", …]` declares a later instance of an
|
|
363
385
|
already-declared read model — the forward-only device for a view that evolves as later events
|
|
364
386
|
land. Instances are ONE logical view: the first declaration owns the `note` binding; each
|
|
@@ -549,8 +571,15 @@ type Name { field: Type, ... } # named structured type, reusable from any f
|
|
|
549
571
|
Slices keep their file-order timeline position; a slice outside any storyline is allowed;
|
|
550
572
|
storylines don't nest and a repeated name continues that storyline (its slices join it; a continuation may not add or change
|
|
551
573
|
`source`/`after` — parse error). The full render draws a
|
|
552
|
-
labelled band above the slice headers; `em render --storyline "Name"` draws one story alone
|
|
553
|
-
|
|
574
|
+
labelled band above the slice headers; `em render --storyline "Name"` draws one story alone — its own
|
|
575
|
+
slices only, nothing from outside it — and `em render <root>.em --map` puts every story's real
|
|
576
|
+
diagram on one draggable canvas with the flow between stories (`after` thick, reads dashed and
|
|
577
|
+
labelled). **Storyline models (GH #421):** `storyline "Name" [after "Other"] [in "path.em"]` with no
|
|
578
|
+
body declares a storyline whose slices live in `<slug>/<slug>.em` — a file that starts with
|
|
579
|
+
`storyline "Name" [source "url"]` and holds slice blocks only — with its docs in `<slug>/slices/`;
|
|
580
|
+
the root is the compile unit (always give em the root), and `em storyline split <root>.em` turns
|
|
581
|
+
inline blocks into files, moving each story's docs. A storyline that reads another declares `after`
|
|
582
|
+
it (`storyline-reads-without-after`). `em export` carries `slice.storyline` and
|
|
554
583
|
`model.storylines[]`; `em query slices --storyline`; `em slice index` adds a Storyline column. Once
|
|
555
584
|
any storyline exists a slice outside every one is the advisory warning `slice-outside-storyline`.
|
|
556
585
|
`after "<other>"` reads the storyline as if its slices followed the referenced storyline's last
|
|
@@ -876,6 +905,7 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
876
905
|
<!-- GENERATED:validate-rules:start -- run `npm run docs:generate` to refresh, do not hand-edit -->
|
|
877
906
|
| Code | Severity | Title | Fix |
|
|
878
907
|
|---|---|---|---|
|
|
908
|
+
| `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
909
|
| `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
910
|
| `arrow-backward` | error | Backward arrow | Restructure so the target comes later. |
|
|
881
911
|
| `arrow-unresolved-source` | error | Arrow source unresolved | Fix the arrow's source name. |
|
|
@@ -916,6 +946,7 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
916
946
|
| `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
947
|
| `frontmatter-coherence-implemented-without-link` | warning | Implemented without a link | Add `implementedIn` once the slice ships. |
|
|
918
948
|
| `frontmatter-invalid` | warning | Invalid or missing frontmatter | Add the required frontmatter keys, or add a frontmatter block. |
|
|
949
|
+
| `frontmatter-status-unrecognized` | warning | Unrecognized slice status | Set `status:` to one of draft, reviewed, ready-to-implement, implemented. |
|
|
919
950
|
| `grid-collision` | error | Band collision | Split the colliding elements into separate slices. |
|
|
920
951
|
| `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
952
|
| `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 +990,7 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
959
990
|
| `storyline-after-cycle` | error | Storyline `after` cycle | Remove an `after` clause so no storyline comes after itself. |
|
|
960
991
|
| `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
992
|
| `storyline-after-unknown` | error | `after` names an unknown storyline | Name a storyline declared in this model, or drop the `after` clause. |
|
|
993
|
+
| `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
994
|
| `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
995
|
| `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
996
|
| `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
|
|
@@ -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 `` | 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 |
|
|
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
|

|
|
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-
|
|
2
|
+
"name": "em-1-21-0",
|
|
3
3
|
"owner": {
|
|
4
4
|
"name": "Mike Key"
|
|
5
5
|
},
|
|
6
|
-
"description": "em v1.
|
|
6
|
+
"description": "em v1.21.0: the Event Modeling skill bundle and MCP server as a Claude Code plugin.",
|
|
7
7
|
"plugins": [
|
|
8
8
|
{
|
|
9
9
|
"name": "em",
|
package/dist/catalog/build.js
CHANGED
|
@@ -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 {
|
|
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 ??=
|
|
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 =
|
|
99
|
-
if (
|
|
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 =
|
|
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,
|
|
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>;
|
package/dist/catalog/coverage.js
CHANGED
|
@@ -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;
|
|
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[];
|