@milehimikey/em 0.2.1 → 1.1.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 (57) hide show
  1. package/.claude/skills/event-modeling/SKILL.md +75 -24
  2. package/.claude/skills/event-modeling/reference/em-dsl.md +15 -0
  3. package/.claude/skills/event-modeling/reference/frontmatter.md +129 -0
  4. package/.claude/skills/event-modeling/reference/methodology.md +10 -0
  5. package/.claude/skills/event-modeling/templates/model-readme.md +4 -4
  6. package/.claude/skills/event-modeling/templates/slice.md +4 -2
  7. package/.claude/skills/event-modeling/templates/state.md +9 -3
  8. package/README.md +43 -2
  9. package/dist/cli.js +227 -4
  10. package/dist/cli.js.map +1 -1
  11. package/dist/config.d.ts +15 -0
  12. package/dist/config.js +60 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/migrate/migrate.d.ts +26 -0
  15. package/dist/migrate/migrate.js +276 -0
  16. package/dist/migrate/migrate.js.map +1 -0
  17. package/dist/model/deriveSliceFields.d.ts +21 -0
  18. package/dist/model/deriveSliceFields.js +60 -0
  19. package/dist/model/deriveSliceFields.js.map +1 -0
  20. package/dist/model/edges.js +25 -1
  21. package/dist/model/edges.js.map +1 -1
  22. package/dist/model/frontmatter.d.ts +21 -0
  23. package/dist/model/frontmatter.js +38 -0
  24. package/dist/model/frontmatter.js.map +1 -0
  25. package/dist/model/model.d.ts +4 -0
  26. package/dist/model/model.js +15 -17
  27. package/dist/model/model.js.map +1 -1
  28. package/dist/model/sliceDoc.d.ts +56 -0
  29. package/dist/model/sliceDoc.js +28 -0
  30. package/dist/model/sliceDoc.js.map +1 -0
  31. package/dist/model/validate.d.ts +2 -0
  32. package/dist/model/validate.js +51 -6
  33. package/dist/model/validate.js.map +1 -1
  34. package/dist/model/validateSliceDocs.d.ts +7 -0
  35. package/dist/model/validateSliceDocs.js +195 -0
  36. package/dist/model/validateSliceDocs.js.map +1 -0
  37. package/dist/parser/ast.d.ts +2 -0
  38. package/dist/parser/parser.js +9 -0
  39. package/dist/parser/parser.js.map +1 -1
  40. package/dist/render/drawEdges.js +46 -1
  41. package/dist/render/drawEdges.js.map +1 -1
  42. package/dist/slice/generate.d.ts +17 -0
  43. package/dist/slice/generate.js +61 -0
  44. package/dist/slice/generate.js.map +1 -0
  45. package/dist/slice/query.d.ts +42 -0
  46. package/dist/slice/query.js +96 -0
  47. package/dist/slice/query.js.map +1 -0
  48. package/dist/slice/sync.d.ts +18 -0
  49. package/dist/slice/sync.js +104 -0
  50. package/dist/slice/sync.js.map +1 -0
  51. package/dist/util/findModel.d.ts +1 -0
  52. package/dist/util/findModel.js +27 -0
  53. package/dist/util/findModel.js.map +1 -0
  54. package/dist/util/slug.d.ts +4 -0
  55. package/dist/util/slug.js +32 -0
  56. package/dist/util/slug.js.map +1 -0
  57. package/package.json +6 -5
@@ -16,9 +16,10 @@ You are facilitating an Event Modeling session. Your job is to **extract an accu
16
16
  the user through Socratic questioning** — never to invent the domain. You drive the `em` CLI to
17
17
  render the model live, and you produce implementation-ready slice design docs.
18
18
 
19
- Read `reference/methodology.md` (the 7 steps + 4 patterns) and `reference/em-dsl.md` (DSL syntax
20
- + validation rules) before doing real work — they are the source of truth. Templates live in
21
- `templates/`.
19
+ Read `reference/methodology.md` (the 7 steps + 4 patterns), `reference/em-dsl.md` (DSL syntax +
20
+ validation rules), and — before the `slice` phase specifically — `reference/frontmatter.md` (the
21
+ slice-doc frontmatter schema, lifecycle, and `em slice` CLI) before doing real work; they are the
22
+ source of truth. Templates live in `templates/`.
22
23
 
23
24
  ## Operating principles (every phase)
24
25
 
@@ -58,7 +59,13 @@ Read `reference/methodology.md` (the 7 steps + 4 patterns) and `reference/em-dsl
58
59
  2. Locate the model. Look for an existing `<dir>/.event-modeling.md` and `*.em` in the working
59
60
  directory (or a `models/` subfolder). If found, read the state file. If not, and the phase
60
61
  needs one, ask the user for the model name and where to create it.
61
- 3. Parse the argument (`$ARGUMENTS`) to pick the phase below. With **no argument**, read the
62
+ 3. **Pre-1.0 model check.** If a `slices/*.md` doc exists with no YAML frontmatter block (run
63
+ `em validate <model>.em` — a missing-frontmatter doc errors with a message pointing at this),
64
+ tell the user this model predates the frontmatter standard and offer to run
65
+ `em migrate <model-dir>` before continuing (it refuses a dirty git tree by default — commit
66
+ first, or pass `--force`). Don't hand-edit old-format docs around this; migrate once, then
67
+ proceed normally.
68
+ 4. Parse the argument (`$ARGUMENTS`) to pick the phase below. With **no argument**, read the
62
69
  state file and resume the recorded phase/step; if no model exists, propose starting `discover`.
63
70
 
64
71
  ## Project layout this skill creates
@@ -69,14 +76,24 @@ Read `reference/methodology.md` (the 7 steps + 4 patterns) and `reference/em-dsl
69
76
  <model-name>.svg # render target for em watch
70
77
  live.html # auto-refresh viewer (copy of templates/live.html, SVG_FILE set)
71
78
  README.md # overview + slice index (from templates/model-readme.md)
72
- .event-modeling.md # resumable state (from templates/state.md)
73
- slices/<slice-name>.md # one rich slice doc per slice (from templates/slice.md)
79
+ .event-modeling.md # resumable state (from templates/state.md, with frontmatter)
80
+ em.config.json # optional: { "sliceTemplate": "..." } for a team's own slice template
81
+ slices/<slice-id>.md # one rich slice doc per slice, scaffolded via `em slice new`
74
82
  ```
75
83
 
76
- When creating a new model, scaffold the directory, copy the templates in (filling the
77
- placeholders), and set `SVG_FILE` in the copied `live.html` to `<model-name>.svg`. You may use
78
- `em init` for a starter `.em`, but usually you'll build it up from the discovery conversation
79
- instead. Fill template placeholders — never leave `{{...}}` in delivered files.
84
+ When creating a new model, scaffold the directory, copy the `model-readme.md`/`state.md`
85
+ templates in (filling the placeholders), and set `SVG_FILE` in the copied `live.html` to
86
+ `<model-name>.svg`. You may use `em init` for a starter `.em`, but usually you'll build it up from
87
+ the discovery conversation instead. Fill template placeholders — never leave `{{...}}` in
88
+ delivered files. **Slice docs are the one exception**: don't hand-copy `templates/slice.md` —
89
+ use `em slice new` (see the `slice` phase below), which injects the required frontmatter and
90
+ respects a project's `em.config.json` custom template if one is configured.
91
+
92
+ Ask the **Regulatory scope** session input (state.md) up front, alongside Scope line / PRD
93
+ reference / Headless-API-model: does this domain have compliance requirements (PCI-DSS, SOX,
94
+ HIPAA, GDPR, ...) or none? This decides whether the `slice` phase asks about the `compliance:`
95
+ frontmatter block per slice (see `reference/frontmatter.md`) — don't ask about compliance at all
96
+ for a model with no regulatory scope.
80
97
 
81
98
  ---
82
99
 
@@ -85,7 +102,11 @@ instead. Fill template placeholders — never leave `{{...}}` in delivered files
85
102
  Goal: a draft model of events, storyboard, commands, and views. Loose is OK; structure comes next.
86
103
 
87
104
  1. **Brainstorm events (step 1).** Ask the user to name everything that happens, as past-tense
88
- facts. Capture a flat list. Probe for missed state changes.
105
+ facts. Probe for missed state changes. For each candidate, apply the **"is it an event?"
106
+ test** (`reference/methodology.md` step 1 — the "would this wake the CEO at 3am" heuristic):
107
+ reject derived values (belong in a read model) and telemetry/activity (not business state).
108
+ Don't silently drop rejections — park them in the state file's Decisions log with why, so
109
+ they aren't re-proposed later. Capture the survivors as a flat list.
89
110
  2. **Plot / storyboard (step 2).** Order the events into the narrative. Identify **personas**
90
111
  (actors) and the **UI** screens at each step. Add `persona` declarations and `ui` elements.
91
112
  In a **headless/API** model there are no personas or screens — identify the external
@@ -138,17 +159,33 @@ the corresponding event/slice to the `.em` and re-render. The happy-path spine f
138
159
  phases is the starting point, not the finished event set.
139
160
 
140
161
  For each slice:
141
- 1. Hold a Socratic deep-dive to fill every section of `templates/slice.md`: intent, trigger/actor,
142
- command + field table (types & rules), event(s) + payload (mark immutable facts), invariants
143
- (give each a stable ID), Given/When/Then scenarios (happy path + rule boundaries + edge cases),
162
+ 1. Scaffold the doc: `em slice new "<Slice Name>" --pattern <state-change|state-view|automation|translation>`.
163
+ This writes `slices/<id>.md` with the required frontmatter already filled in (`id`, `pattern`,
164
+ `status: draft`, `version: 1`, …) and the body template (custom, if `em.config.json` configures
165
+ one; the shipped default otherwise) ready to fill in.
166
+ 2. Hold a Socratic deep-dive to fill every body section: intent, trigger/actor, command + field
167
+ table (types & rules), event(s) + payload (mark immutable facts), invariants (give each a
168
+ stable ID), Given/When/Then scenarios (happy path + rule boundaries + edge cases),
144
169
  alternate/error flows (retries, idempotency, compensations), read models affected, open
145
- questions. Park anything unresolved rather than guessing.
146
- 2. Write the doc to `slices/<slice-name>.md` (kebab-case the slice name).
147
- 3. Wire it into the `.em`: add `note "slices/<slice-name>.md"` to the slice's primary element
148
- (the command for State Change, the view for State View, the processor for Automation, the
149
- translation for Translation).
150
- 4. Update `README.md`'s slice index and the state file's slice inventory (`draft` → `ready`).
151
- 5. Re-render and `em validate`.
170
+ questions. Park anything unresolved rather than guessing. Pattern and status are frontmatter
171
+ now, not prose — see `reference/frontmatter.md`. If the model's **Regulatory scope** (state
172
+ file) isn't "none," additionally ask whether *this* slice touches regulated data or processes;
173
+ if so, hand-add a `compliance:` block to the doc's frontmatter (see `reference/frontmatter.md`
174
+ for the suggested shape — `em` never validates it, so use whatever sub-fields fit). Skip this
175
+ question entirely for non-regulated models, and skip the block for slices with no compliance
176
+ relevance even in a regulated model — don't ask by rote.
177
+ 3. Wire it into the `.em`: add `note "slices/<id>.md"` to the slice's primary element (the command
178
+ for State Change, the view for State View, the processor for Automation, the translation for
179
+ Translation).
180
+ 4. Run `em slice sync <id>` — it discovers the linked element from that `note` and fills in the
181
+ generated frontmatter fields (`commands`/`events`/`readModels`/`contexts`/`personas`, and
182
+ `triggers`/`triggeredBy` for automation/translation). **Re-run `em slice sync <id>` (or
183
+ `--all`) after any later `.em` edit that touches this slice's elements** — generated fields
184
+ drift otherwise, and `em validate` will flag it.
185
+ 5. When the doc is solid, move it forward: `em slice update <id> --status reviewed` (and later
186
+ `--status ready-to-implement`). Update `README.md`'s slice index.
187
+ 6. Re-render and `em validate` (validates the `.em` **and** every slice doc's frontmatter by
188
+ default).
152
189
 
153
190
  ## Phase: `watch` — live team view
154
191
 
@@ -163,8 +200,13 @@ For each slice:
163
200
  ## Phase: `validate`
164
201
 
165
202
  Run `em validate <model-name>.em` and walk through each diagnostic with the user, explaining the
166
- rule (see `reference/em-dsl.md`) and proposing the fix (e.g. split an automation's command into
167
- the next slice, add a missing `from`, give a command its event). Apply fixes on agreement.
203
+ rule (see `reference/em-dsl.md` for `.em` rules, `reference/frontmatter.md` for slice-doc
204
+ frontmatter rules) and proposing the fix. Apply fixes on agreement:
205
+ - `.em`-level fixes: split an automation's command into the next slice, add a missing `from`, give
206
+ a command its event.
207
+ - Slice-doc-level fixes: no frontmatter block → run `em migrate` (pre-1.0 model); "out of sync
208
+ with .em" → run `em slice sync <id>`; orphan doc → wire a `note "slices/<id>.md"` onto the
209
+ right element, then sync.
168
210
 
169
211
  Then do one check `em validate` can't: scan every `translation`/`processor`/`automation` slice and
170
212
  confirm none contains an `event` — each reaction must trigger a `command` in the next slice
@@ -178,11 +220,20 @@ two slices and route it through a command.
178
220
  ```bash
179
221
  em --version
180
222
  em init <name>.em # optional starter scaffold
181
- em validate <name>.em # check rules; exit 0 if clean/warnings only
223
+ em validate <name>.em # check .em rules + slice-doc frontmatter
182
224
  em render <name>.em -o <name>.svg # render (svg/png/pdf by extension)
183
225
  em render <name>.em --emit-dot # inspect generated Graphviz DOT
184
226
  em watch <name>.em -o <name>.svg # re-render on save (run in background)
227
+
228
+ em slice new "<Slice Name>" --pattern <pattern> # scaffold slices/<id>.md with frontmatter
229
+ em slice sync <id> # after wiring note "slices/<id>.md" into the .em
230
+ em slice update <id> --status <status> # move a slice's lifecycle status forward
231
+ em slice list / show <id> / search "<query>" # query slice docs by frontmatter (--format json)
232
+ em slice search "<q>" --format json --full # ...with every field, not just the summary row
233
+ em migrate <model-dir> # one-time upgrade from a pre-1.0 model
185
234
  ```
186
235
 
236
+ See `reference/frontmatter.md` for the full slice-doc frontmatter schema and CLI reference.
237
+
187
238
  Always finish a working session by: re-rendering, running `em validate`, and updating
188
239
  `.event-modeling.md` with the current phase/step, decisions, and open questions.
@@ -20,6 +20,21 @@ em validate <file> # check event-modeling rules; exit 0 if only warn
20
20
  Install if missing: `npm i -g @milehimikey/em`. PNG works with no system deps; PDF needs
21
21
  `rsvg-convert`.
22
22
 
23
+ **Slice docs** (frontmatter, lifecycle, search — see `reference/frontmatter.md` for the schema):
24
+
25
+ ```bash
26
+ em slice new "Slice Name" [--pattern state-change] [--id <id>] # scaffold slices/<id>.md
27
+ em slice sync <id> # after wiring note "slices/<id>.md" into the .em
28
+ em slice sync --all # re-sync every doc in the model directory
29
+ em slice list [--status <s>] [--pattern <p>] [--context <c>] [--tag <t>] [--format json] [--full]
30
+ em slice show <id> [--body] [--format json]
31
+ em slice search "<query>" [--pattern <p>] [--status <s>] [--context <c>] [--tag <t>] [--format json] [--full]
32
+ em slice update <id> [--status <s>] [--bump-version]
33
+ em migrate <model-dir> [--dry-run] [--report <path>] # one-time upgrade from a pre-1.0 model
34
+ ```
35
+
36
+ `em validate <file>` also validates every doc in `slices/` by default (`--skip-slices` to opt out).
37
+
23
38
  ---
24
39
 
25
40
  ## Grammar
@@ -0,0 +1,129 @@
1
+ # Slice Frontmatter Reference
2
+
3
+ Every slice doc (`slices/<id>.md`) starts with a required YAML frontmatter block, injected by
4
+ `em slice new` and kept fresh by `em slice sync`. This is what makes slices searchable and
5
+ versionable by AI agents across a model with hundreds of slices, without reading every doc's body.
6
+ Full rationale: `docs/1.0.0-spec.md` in the `em` repo. This file is the quick reference for
7
+ day-to-day use.
8
+
9
+ ---
10
+
11
+ ## Fields
12
+
13
+ **Core identity** (required, `em slice new` sets these):
14
+
15
+ | Field | Meaning |
16
+ |---|---|
17
+ | `schemaVersion` | Frontmatter format version. `1`. |
18
+ | `id` | Stable key, kebab-case, generated once. **Never** re-derived from the title. Reference slices by `id`, never by title or filename. |
19
+ | `title` | Human display name. |
20
+ | `pattern` | `state-change \| state-view \| automation \| translation` — the read/write/automation/translation facet. |
21
+ | `status` | See Lifecycle below. |
22
+ | `version` | Integer, bumped via `em slice update --bump-version` on a meaningful content change. Git log is the real history — this is just a "has it changed" signal. |
23
+ | `model` | Relative path to the `.em` file. |
24
+ | `sliceElement` | The `.em` `Element.id` this doc is linked from (via `note "slices/<id>.md"`). |
25
+
26
+ **Generated** (never hand-edit — run `em slice sync` after any `.em` edit that touches this
27
+ slice's elements):
28
+
29
+ | Field | Meaning |
30
+ |---|---|
31
+ | `commands`, `events`, `readModels` | Names of the command/event/view elements in this slice. |
32
+ | `contexts`, `personas` | Contexts/personas touched by this slice's event/ui elements. |
33
+ | `triggers` | (automation/translation only) The `id` of the slice doc for the command this reaction triggers, in the next slice. |
34
+ | `triggeredBy` | (command slices only) The inverse — set on the doc for the command an automation/translation triggers. |
35
+
36
+ `em validate` warns "frontmatter out of sync with .em; run \`em slice sync\`" if these drift from
37
+ what the `.em` actually says. It never auto-fixes this — you have to run `sync` yourself.
38
+
39
+ **Optional / authored:**
40
+
41
+ | Field | Meaning |
42
+ |---|---|
43
+ | `swimlane` | `{ persona, context }` — structured form of the body's `**Swimlane:**` line. |
44
+ | `upstreamEvents` | Only for dependencies **not** visible in the `.em`'s wiring (an invariant reading state from an event not consumed via `from`). If the `.em` already expresses it, it belongs in the generated fields above, not here. |
45
+ | `relatedSlices` | Freeform cross-references to other slice `id`s. |
46
+ | `tags` | Free text, searchable via `em slice search --tag`. |
47
+ | `owner`, `created`, `updated` | |
48
+ | `supersededBy`, `implementedRef` | Written by external build tools, not by `em` — see Handoff below. |
49
+
50
+ **`compliance` — reserved, unvalidated.** For regulated domains (financial, medical, etc.). `em`
51
+ never writes, reads, or validates this key — it's a documented convention only, so it works the
52
+ same way across industries without `em` having to know any regulation's specifics. Only ask about
53
+ it when the model's Regulatory scope (state file) isn't "none" — see the `slice` phase below.
54
+
55
+ ```yaml
56
+ compliance:
57
+ frameworks: [PCI-DSS, SOX, GAAP] # or [HIPAA], [GDPR], etc. — whatever applies
58
+ dataClassification: restricted # public | internal | confidential | restricted
59
+ sensitiveDataCategories: [PCI, financial] # freeform: PCI, PHI, PII, financial, biometric, ...
60
+ controlRefs: [PCI-DSS-3.4, SOX-404] # specific control/citation ids
61
+ retention: 7y
62
+ dataResidency: US-only
63
+ reviewedBy: jane@co.com
64
+ reviewedAt: 2026-06-01
65
+ ```
66
+
67
+ `em slice search` includes this block in its free-text match, so it stays findable even though
68
+ it's unvalidated (e.g. `em slice search "PCI-DSS"`).
69
+
70
+ ---
71
+
72
+ ## Lifecycle
73
+
74
+ ```
75
+ draft → reviewed → ready-to-implement → in-progress → implemented → (deprecated | superseded)
76
+ ```
77
+
78
+ - `draft` / `reviewed` / `ready-to-implement` — the `slice` phase drives these. Move a doc forward
79
+ with `em slice update <id> --status <status>`.
80
+ - `in-progress` / `implemented` / `deprecated` / `superseded` — **post-handoff.** `em` never writes
81
+ these; they exist so validation tolerates a build tool writing them back into the same file.
82
+ Don't set these yourself during a design session.
83
+
84
+ ---
85
+
86
+ ## Handoff to build / SDD tooling
87
+
88
+ A slice is **ready** when `status` is `ready-to-implement` or later, **and** `em validate` is
89
+ clean for both the `.em` and this doc. At that point, here's what's authoritative for whatever
90
+ implements it:
91
+
92
+ - **`id`** — the only stable key. Never key generated code, tests, or tickets on title/filename.
93
+ - **Command/Input field table** — the real parameter contract (richer than the `.em`'s lightweight
94
+ inline `{ field: Type }`, which is a structural preview only — they aren't cross-validated in
95
+ 1.0, so the doc wins if they disagree).
96
+ - **Event table's "Immutable Fact?" column** — treat as compile-time-enforced immutability.
97
+ - **`INV-n` invariant ids** — cite them in generated tests (`test("INV-1: ...")`).
98
+ - **Given/When/Then** — acceptance criteria. Happy path is the floor; rule-boundary scenarios
99
+ trace to their `INV-n`.
100
+ - **Alternate & Error Flows** — required test cases, not optional.
101
+ - `triggers`/`triggeredBy` plus upstream/downstream (joining doc + `.em`) — a sequencing hint for
102
+ a build orchestrator (don't build a slice until its upstream slices are `implemented`),
103
+ advisory only.
104
+
105
+ `em` never clobbers fields it doesn't recognize on write (`sync`/`update` shallow-merge) — a build
106
+ tool's own bookkeeping fields survive.
107
+
108
+ ---
109
+
110
+ ## CLI
111
+
112
+ ```bash
113
+ em slice new "Place Order" [--pattern state-change] [--id <id>] # scaffold slices/<id>.md
114
+ em slice sync <id> # after wiring `note "slices/<id>.md"` into the .em
115
+ em slice sync --all # re-sync every doc in the directory
116
+ em slice list [--status <s>] [--pattern <p>] [--context <c>] [--tag <t>] [--format json] [--full]
117
+ em slice show <id> [--body] [--format json]
118
+ em slice search "<query>" [--pattern <p>] [--status <s>] [--context <c>] [--tag <t>] [--format json] [--full]
119
+ em slice update <id> [--status <s>] [--bump-version]
120
+ em migrate <model-dir> [--dry-run] [--report <path>] # one-time upgrade from a pre-1.0 model
121
+ ```
122
+
123
+ All commands take `--dir <path>` (default `.`) and `--model <path.em>` if a directory has more
124
+ than one `.em` file. `list`/`show`/`search` read **frontmatter only** — never the `.em`, never the
125
+ doc body — so they stay cheap across a large model.
126
+
127
+ `list`/`search` emit a summary row per slice by default. Add **`--full`** (with `--format json`)
128
+ to get every frontmatter field instead — use it when you need the filtered slices' commands,
129
+ events, or contexts, so you don't follow a search with one `slice show` per hit.
@@ -111,6 +111,16 @@ List the domain **events** as past-tense facts, unordered at first. Go wide; cap
111
111
  state change anyone can think of. No commands, no UI yet — just facts.
112
112
  - Prompts: *"What are all the things that happen in this process? Say each as something that
113
113
  already occurred. What changed when that happened?"*
114
+ - **Is it an event?** Events here are *business* facts, not technical ones. Test: if this fact
115
+ failed to occur, would it wake the CEO at 3am? Yes → event. No → not an event.
116
+ - **Yes:** Order Created, Item Added to Order, Order Shipped, Order Delivered, Order
117
+ Cancelled, User Registered, Item Provisioned.
118
+ - **No — derived values** (a read model computes these from other events; they aren't
119
+ independent facts): Order Total Calculated, Order Tax Calculated, Discount Applied.
120
+ - **No — activity, not business state** (telemetry, not something the domain decides on):
121
+ User Clicked Button, User Viewed Page, User Logged In.
122
+ - Model the process the business **needs**, not how the current system happens to work. Existing
123
+ system behavior is a common source of fake events — screens and tables leaking in as facts.
114
124
  - Output: a flat list of candidate `event` names.
115
125
 
116
126
  ### Step 2 — The Plot / Storyboard *(discover)*
@@ -19,10 +19,10 @@ Static render: `em render {{model-name}}.em -o {{model-name}}.svg`
19
19
  - **Translation** — External input (or Read Model) → Translation → (next slice) Command → Event
20
20
 
21
21
  ## Slices
22
- <!-- Keep this index in sync as slice docs are written. -->
23
- | # | Slice | Pattern | Design doc |
24
- |---|-------|---------|------------|
25
- | 1 | {{Slice Name}} | {{Pattern}} | [slices/{{slice-name}}.md](slices/{{slice-name}}.md) |
22
+ <!-- Keep this index in sync as slice docs are written (or regenerate from `em slice list`). -->
23
+ | # | Slice | Pattern | Status | Design doc |
24
+ |---|-------|---------|--------|------------|
25
+ | 1 | {{Slice Name}} | {{Pattern}} | {{status}} | [slices/{{slice-id}}.md](slices/{{slice-id}}.md) |
26
26
 
27
27
  ## Status
28
28
  See [`.event-modeling.md`](.event-modeling.md) for current phase, decisions, and open questions.
@@ -3,13 +3,15 @@ Rich slice design document. One per slice, stored in <model>/slices/<slice-name>
3
3
  linked from the .em model with: note "slices/<slice-name>.md" on the slice's defining element.
4
4
  Fill every section through Socratic questioning. Leave "Open Questions" rather than guessing.
5
5
  Replace the bracketed placeholders; delete guidance comments before finishing.
6
+
7
+ This is the body template only — `em slice new` injects the required frontmatter block above
8
+ this content (id, pattern, status, version, sliceElement, and the generated search fields).
9
+ Pattern and status live there now, not as prose here — see reference/frontmatter.md.
6
10
  -->
7
11
 
8
12
  # Slice: {{Slice Name}}
9
13
 
10
- - **Pattern:** {{State Change | State View | Automation | Translation}}
11
14
  - **Swimlane:** {{Persona/Actor}} → {{Context/Aggregate}}
12
- - **Status:** {{draft | reviewed | ready-to-implement}}
13
15
 
14
16
  ## Intent
15
17
  {{Why this slice exists — the user or business goal it serves, in one or two sentences.}}
@@ -4,6 +4,11 @@ The skill reads this on `/event-modeling` (no arg) to resume where you left off.
4
4
  Keep it current at the end of every working session.
5
5
  -->
6
6
 
7
+ ---
8
+ schemaVersion: 1
9
+ model: {{model-name}}.em
10
+ ---
11
+
7
12
  # Event Modeling Progress — {{Model Name}}
8
13
 
9
14
  - **Model file:** `{{model-name}}.em`
@@ -15,6 +20,7 @@ Keep it current at the end of every working session.
15
20
  - **Scope line:** {{one-line description of what's in/out of bounds for this model}}
16
21
  - **PRD / spec reference:** {{path, link, or "none"}}
17
22
  - **Headless/API model:** {{yes | no}}
23
+ - **Regulatory scope:** {{e.g. PCI-DSS, SOX, HIPAA, or "none"}}
18
24
 
19
25
  ## Steps completed
20
26
  - [ ] 1. Brainstorm events
@@ -34,6 +40,6 @@ Keep it current at the end of every working session.
34
40
  - [ ] {{question}}
35
41
 
36
42
  ## Slice inventory
37
- | Slice | Pattern | Doc status |
38
- |-------|---------|------------|
39
- | {{Slice Name}} | {{State Change/View/Automation/Translation}} | {{none / draft / ready}} |
43
+ | Slice | Id | Pattern | Doc status |
44
+ |-------|-----|---------|------------|
45
+ | {{Slice Name}} | {{slice-id}} | {{state-change/state-view/automation/translation}} | {{none / draft / reviewed / ready-to-implement}} |
package/README.md CHANGED
@@ -98,6 +98,12 @@ read model. The empty API lane is dropped when a model has neither; pass `--keep
98
98
  to keep it.
99
99
 
100
100
  `@Persona` / `@Context` choose the row within a band (undeclared tags create a new row).
101
+ `view <Name> again [from "Event", …]` declares a LATER INSTANCE of an already-declared read
102
+ model — the Event Modeling device for keeping the timeline forward-only as a view evolves.
103
+ Instances are one logical view: the first declaration owns the `note` doc; each instance lists
104
+ the events that reach it there; instances are linked left-to-right with a continuity arrow, and
105
+ reactions (`processor … from "View"`) read the nearest instance at-or-before their slice.
106
+
101
107
  `view … from "Event"[, "Event2"]` declares which events feed a read model and draws the
102
108
  data-flow arrow. Arrows within a slice are inferred from the pattern; use `arrow A -> B` for
103
109
  anything extra (e.g. a read model feeding a different screen).
@@ -148,13 +154,22 @@ em render <file> -o out.png # PNG (in-process, no system deps)
148
154
  em render <file> --emit-dot # print the generated DOT instead of rendering
149
155
  em render <file> --keep-empty-lanes # don't collapse the API lane when empty
150
156
  em watch <file> [-o out.svg] # re-render on every save
151
- em validate <file> # check event-modeling rules (non-zero exit on errors)
157
+ em validate <file> # check event-modeling rules + slice-doc frontmatter
158
+ em migrate <model-dir> # one-time upgrade of a pre-1.0 model to the frontmatter standard
152
159
  ```
153
160
 
161
+ See [Slice docs & frontmatter](#slice-docs--frontmatter) below for the `em slice` command group.
162
+
154
163
  ## Validation rules (`em validate`)
155
164
 
156
165
  - two same-band elements in one slice (collision) → **error** (split into separate slices)
157
166
  - a read model whose `from "Event"` doesn't exist → **error**
167
+ - **time flows left to right** (the Two Laws): an event feeding an EARLIER view instance,
168
+ a reaction reading a view that only exists later, or an explicit backward `arrow` → **error**
169
+ (fix: add `view X again` at the point on the timeline where the event lands)
170
+ - `again` on a view with no earlier declaration → **error**; `again` on non-views → parse error
171
+ - multi-event slices always render as a FAN from the command (never event→event); fanned
172
+ arrows route around the column gutter so they cannot read as a chain
158
173
  - an automation/translation whose `from "<read model>"` doesn't exist → **error**
159
174
  - an `arrow` endpoint that matches no element → **error**
160
175
  - an automation/translation slice that also holds the command it triggers → **warning**
@@ -162,8 +177,34 @@ em validate <file> # check event-modeling rules (non-zero exi
162
177
  - a read model with no source event → **warning**
163
178
  - a name defined more than once and referenced → **warning** (resolves to first)
164
179
 
180
+ ## Slice docs & frontmatter
181
+
182
+ Slice design docs (`slices/<id>.md`, written during the skill's `slice` phase or via
183
+ `em slice new`) carry a required YAML frontmatter block — a stable `id`, lifecycle `status`,
184
+ integer `version`, and fields generated from the `.em` (`commands`/`events`/`readModels`/
185
+ `contexts`/`personas`, plus `triggers`/`triggeredBy` for automation/translation) — so an AI agent
186
+ can search and filter across a model with hundreds of slices from frontmatter alone, without
187
+ reading every doc's body or re-parsing the `.em`:
188
+
189
+ ```bash
190
+ em slice new "Place Order" --pattern state-change # scaffold slices/place-order.md
191
+ em slice sync place-order # after wiring note "slices/..." into the .em
192
+ em slice list --status ready-to-implement
193
+ em slice search --pattern automation --context Payment --format json
194
+ em slice search --status ready-to-implement --format json --full # every field, not just a summary
195
+ em slice update place-order --status reviewed --bump-version
196
+ ```
197
+
198
+ The doc body itself is **yours to define** — point `em.config.json` at a custom template
199
+ (`{ "sliceTemplate": "path/to/template.md" }`) and `em` injects the frontmatter on top of it
200
+ regardless of what sections you ask for. Full schema, lifecycle model, and the handoff contract a
201
+ build/SDD tool should treat as authoritative once a slice is `ready-to-implement`:
202
+ [docs/1.0.0-spec.md](docs/1.0.0-spec.md).
203
+
165
204
  ## Documentation
166
205
 
206
+ - [docs/1.0.0-spec.md](docs/1.0.0-spec.md) — slice frontmatter standard, config, `em slice`/
207
+ `em migrate`, and the SDD handoff contract
167
208
  - [docs/why-dot-not-plantuml.md](docs/why-dot-not-plantuml.md) — why DOT + the strict-grid /
168
209
  self-drawn-edges architecture
169
210
  - [docs/features.md](docs/features.md) — full feature list and roadmap
@@ -195,7 +236,7 @@ Then, in Claude Code, run:
195
236
  /event-modeling # start (or resume) a guided session
196
237
  /event-modeling discover # steps 1–4: brainstorm events, timeline, commands, read models
197
238
  /event-modeling model # steps 5–7: swimlanes, patterns, completeness check
198
- /event-modeling slice # deep implementation specs, one per slice
239
+ /event-modeling slice # deep implementation specs, one per slice (frontmatter via `em slice new`)
199
240
  /event-modeling watch # open a live browser view for team modeling sessions
200
241
  /event-modeling validate # run em validate and resolve all diagnostics
201
242
  ```