@milehimikey/em 1.17.0 → 1.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/em-implementer.md +7 -4
- package/.claude/agents/em-validator.md +2 -2
- 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 +46 -5
- package/.claude/skills/event-modeling-discover/SKILL.md +43 -8
- package/.claude/skills/event-modeling-discover/reference/extract.md +6 -1
- package/.claude/skills/event-modeling-discover/reference/prd-rubric.md +102 -0
- package/.claude/skills/event-modeling-discover/reference/prd-spec-path.md +171 -0
- package/.claude/skills/event-modeling-engagement/SKILL.md +21 -9
- package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
- package/.claude/skills/event-modeling-implement/reference/implement.md +18 -0
- package/.claude/skills/event-modeling-review/SKILL.md +4 -2
- package/.claude/skills/event-modeling-shared/reference/em-dsl.md +94 -6
- package/.claude/skills/event-modeling-shared/reference/methodology.md +268 -0
- package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +96 -2
- package/.claude/skills/event-modeling-shared/templates/slice.md +11 -3
- package/.claude-plugin/marketplace.json +2 -2
- package/dist/catalog/docModelConsistencyValidate.js +160 -0
- package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
- package/dist/catalog/invariantsValidate.d.ts +2 -0
- package/dist/catalog/invariantsValidate.js +67 -1
- package/dist/catalog/invariantsValidate.js.map +1 -1
- package/dist/catalog/scenarioQualityValidate.d.ts +4 -0
- package/dist/catalog/scenarioQualityValidate.js +148 -0
- package/dist/catalog/scenarioQualityValidate.js.map +1 -0
- package/dist/catalog/scenarios.d.ts +5 -0
- package/dist/catalog/scenarios.js +80 -0
- package/dist/catalog/scenarios.js.map +1 -1
- package/dist/catalog/sliceDoc.d.ts +4 -0
- package/dist/catalog/sliceDoc.js +16 -7
- package/dist/catalog/sliceDoc.js.map +1 -1
- package/dist/catalog/sliceReadyValidate.d.ts +11 -2
- package/dist/catalog/sliceReadyValidate.js +62 -3
- package/dist/catalog/sliceReadyValidate.js.map +1 -1
- package/dist/catalog/sliceSections.d.ts +3 -2
- package/dist/catalog/sliceSections.js +99 -9
- package/dist/catalog/sliceSections.js.map +1 -1
- package/dist/cli/ciInit.d.ts +4 -11
- package/dist/cli/ciInit.js +24 -6
- package/dist/cli/ciInit.js.map +1 -1
- package/dist/cli/coverage.d.ts +9 -0
- package/dist/cli/coverage.js +18 -0
- package/dist/cli/coverage.js.map +1 -1
- package/dist/cli/defer.d.ts +28 -0
- package/dist/cli/defer.js +87 -4
- package/dist/cli/defer.js.map +1 -1
- package/dist/cli/engagement.d.ts +13 -2
- package/dist/cli/engagement.js +60 -5
- package/dist/cli/engagement.js.map +1 -1
- package/dist/cli/engagementFile.d.ts +2 -0
- package/dist/cli/engagementFile.js +3 -1
- package/dist/cli/engagementFile.js.map +1 -1
- package/dist/cli/markImplemented.d.ts +14 -10
- package/dist/cli/markImplemented.js +49 -1
- package/dist/cli/markImplemented.js.map +1 -1
- package/dist/cli/prdTriage.d.ts +109 -0
- package/dist/cli/prdTriage.js +393 -0
- package/dist/cli/prdTriage.js.map +1 -0
- package/dist/cli/render-inputs.d.ts +2 -0
- package/dist/cli/render-inputs.js +4 -0
- package/dist/cli/render-inputs.js.map +1 -1
- package/dist/cli/review.d.ts +17 -2
- package/dist/cli/review.js +39 -10
- package/dist/cli/review.js.map +1 -1
- package/dist/cli/revise.d.ts +2 -0
- package/dist/cli/revise.js +7 -2
- package/dist/cli/revise.js.map +1 -1
- package/dist/cli/shape.d.ts +27 -0
- package/dist/cli/shape.js +77 -0
- package/dist/cli/shape.js.map +1 -0
- package/dist/cli/sliceIndex.d.ts +6 -1
- package/dist/cli/sliceIndex.js +28 -13
- package/dist/cli/sliceIndex.js.map +1 -1
- package/dist/cli/sliceNew.d.ts +4 -1
- package/dist/cli/sliceNew.js +26 -9
- package/dist/cli/sliceNew.js.map +1 -1
- package/dist/cli/status.d.ts +21 -1
- package/dist/cli/status.js +25 -3
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/storylineSuggest.d.ts +26 -0
- package/dist/cli/storylineSuggest.js +252 -0
- package/dist/cli/storylineSuggest.js.map +1 -0
- package/dist/cli/upgrade.d.ts +15 -3
- package/dist/cli/upgrade.js +516 -7
- package/dist/cli/upgrade.js.map +1 -1
- package/dist/cli/upgradeReshape.d.ts +60 -0
- package/dist/cli/upgradeReshape.js +425 -0
- package/dist/cli/upgradeReshape.js.map +1 -0
- package/dist/cli.js +311 -35
- package/dist/cli.js.map +1 -1
- package/dist/emit/dot.d.ts +2 -0
- package/dist/emit/dot.js +44 -8
- package/dist/emit/dot.js.map +1 -1
- package/dist/emit/engagementJson.d.ts +4 -3
- package/dist/emit/engagementJson.js +11 -4
- package/dist/emit/engagementJson.js.map +1 -1
- package/dist/emit/json.d.ts +21 -1
- package/dist/emit/json.js +26 -2
- package/dist/emit/json.js.map +1 -1
- package/dist/emit/queryJson.d.ts +1 -1
- package/dist/emit/queryJson.js +3 -1
- package/dist/emit/queryJson.js.map +1 -1
- package/dist/emit/statusJson.d.ts +1 -1
- package/dist/emit/statusJson.js +6 -1
- package/dist/emit/statusJson.js.map +1 -1
- package/dist/emit/theme.d.ts +1 -0
- package/dist/emit/theme.js +13 -0
- package/dist/emit/theme.js.map +1 -1
- package/dist/emit/validateJson.d.ts +9 -5
- package/dist/emit/validateJson.js +40 -5
- package/dist/emit/validateJson.js.map +1 -1
- package/dist/layout/grid.d.ts +5 -1
- package/dist/layout/grid.js +93 -2
- package/dist/layout/grid.js.map +1 -1
- package/dist/mcp/server.js +46 -11
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/edges.d.ts +7 -0
- package/dist/model/edges.js +33 -16
- package/dist/model/edges.js.map +1 -1
- package/dist/model/model.d.ts +33 -0
- package/dist/model/model.js +87 -3
- package/dist/model/model.js.map +1 -1
- package/dist/model/queryIndex.js +2 -2
- package/dist/model/queryIndex.js.map +1 -1
- package/dist/model/refs.js +8 -5
- package/dist/model/refs.js.map +1 -1
- package/dist/model/rules.d.ts +149 -0
- package/dist/model/rules.js +144 -0
- package/dist/model/rules.js.map +1 -1
- package/dist/model/shapeLint.d.ts +12 -0
- package/dist/model/shapeLint.js +170 -0
- package/dist/model/shapeLint.js.map +1 -0
- package/dist/model/storylines.d.ts +51 -0
- package/dist/model/storylines.js +188 -0
- package/dist/model/storylines.js.map +1 -0
- package/dist/model/validate.d.ts +6 -1
- package/dist/model/validate.js +317 -14
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/againSugar.d.ts +30 -0
- package/dist/parser/againSugar.js +105 -0
- package/dist/parser/againSugar.js.map +1 -0
- package/dist/parser/ast.d.ts +33 -0
- package/dist/parser/lexer.d.ts +2 -0
- package/dist/parser/lexer.js +4 -0
- package/dist/parser/lexer.js.map +1 -1
- package/dist/parser/parser.js +284 -4
- package/dist/parser/parser.js.map +1 -1
- package/dist/query/format.js +1 -0
- package/dist/query/format.js.map +1 -1
- package/dist/query/verbs.d.ts +4 -0
- package/dist/query/verbs.js +30 -3
- package/dist/query/verbs.js.map +1 -1
- package/dist/render/drawEdges.js +100 -4
- package/dist/render/drawEdges.js.map +1 -1
- package/dist/render/render.js +20 -2
- package/dist/render/render.js.map +1 -1
- package/dist/render/sliceDiagram.js +5 -5
- package/dist/render/sliceDiagram.js.map +1 -1
- package/dist/render/storylineBands.d.ts +11 -0
- package/dist/render/storylineBands.js +80 -0
- package/dist/render/storylineBands.js.map +1 -0
- package/dist/render/storylineDiagram.d.ts +14 -0
- package/dist/render/storylineDiagram.js +142 -0
- package/dist/render/storylineDiagram.js.map +1 -0
- package/dist/roster/check.d.ts +32 -0
- package/dist/roster/check.js +92 -0
- package/dist/roster/check.js.map +1 -0
- package/dist/roster/context.d.ts +3 -0
- package/dist/roster/context.js +23 -0
- package/dist/roster/context.js.map +1 -0
- package/dist/roster/init.d.ts +15 -0
- package/dist/roster/init.js +52 -0
- package/dist/roster/init.js.map +1 -0
- package/dist/roster/roster.d.ts +79 -0
- package/dist/roster/roster.js +298 -0
- package/dist/roster/roster.js.map +1 -0
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/agents/em-implementer.md +7 -4
- package/plugin/agents/em-validator.md +2 -2
- package/plugin/shared/reference/em-dsl.md +94 -6
- package/plugin/shared/reference/methodology.md +268 -0
- package/plugin/shared/reference/slice-doc-schema.md +96 -2
- package/plugin/shared/templates/slice.md +11 -3
- package/plugin/skills/conform/SKILL.md +1 -1
- package/plugin/skills/design/SKILL.md +46 -5
- package/plugin/skills/discover/SKILL.md +43 -8
- package/plugin/skills/discover/reference/extract.md +6 -1
- package/plugin/skills/discover/reference/prd-rubric.md +103 -0
- package/plugin/skills/discover/reference/prd-spec-path.md +172 -0
- package/plugin/skills/engagement/SKILL.md +21 -9
- package/plugin/skills/event-modeling/SKILL.md +1 -1
- package/plugin/skills/implement/SKILL.md +1 -1
- package/plugin/skills/implement/reference/implement.md +18 -0
- package/plugin/skills/review/SKILL.md +4 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-implement
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.18.1
|
|
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
|
|
@@ -34,6 +34,16 @@ every `## Open Questions` checkbox is checked, and no status/version/link incohe
|
|
|
34
34
|
— `gates` names each of those 4 conditions individually (`docBound`/`frontmatterUsable`/
|
|
35
35
|
`statusReady`/`noUncheckedOpenQuestions`) if you need to say which one is blocking.
|
|
36
36
|
|
|
37
|
+
`ready` is the named gates, plus error-severity diagnostics scoped to the slice, plus these warning-severity codes:
|
|
38
|
+
|
|
39
|
+
- `slice-ready-no-doc-bound`, `slice-ready-status-not-ready`, `slice-ready-open-questions-unchecked`: the gates themselves.
|
|
40
|
+
- `binding-missing-file`, `frontmatter-invalid`: the `frontmatterUsable` gate.
|
|
41
|
+
- `both-ends-of-a-flow/*`: a dangling slice is not a complete pattern.
|
|
42
|
+
- `fields-completeness/event-field-no-source`: the `assigned` marker contract (MIL-148).
|
|
43
|
+
- `invariants/public-command-without-invariants`: the API-first readiness requirement (`docs/process.md`).
|
|
44
|
+
|
|
45
|
+
A warning whose code is in this list blocks; any other warning never does (it stays in `diagnostics`; don't treat it as a blocker). `--strict` promotes advisory rules only.
|
|
46
|
+
|
|
37
47
|
**`ready: false` means stop** — with one named exception: a slice already `status: implemented`
|
|
38
48
|
with `driftSignal: in-sync` or `uncertified` (MIL-214) also reads `ready: false` (its
|
|
39
49
|
`statusReady` gate fails because nothing is newly ratified), and that specific case is
|
|
@@ -254,6 +264,14 @@ the question back to `- [ ]`; the version you built stays shipped) — a questio
|
|
|
254
264
|
slice defer` while the doc was ratified (GH #253) is one of those. If it prints `opened draft
|
|
255
265
|
v<N+1>`, say so in your report: the slice has known work, and a design session, not you, decides it.
|
|
256
266
|
|
|
267
|
+
**What the PR will show.** In that case the slice doc in your PR reads `status: draft` with
|
|
268
|
+
`version: <N+1>` — not `implemented`. That is correct, not a failed flip: `shippedVersion: <N>` and
|
|
269
|
+
`implementedIn:` are the record that v<N> was implemented, and `status:` is the next version's
|
|
270
|
+
state. The command prints a multi-line notice (what shipped, what opened, the reopened question
|
|
271
|
+
titles; `--json` gives `nextDraft: { version, reopened[] }`) — paste it into the PR description so a
|
|
272
|
+
reviewer who sees `status: draft` knows where to look. `em status` lists the slice as `implemented
|
|
273
|
+
(v<N>) · draft v<N+1> open`.
|
|
274
|
+
|
|
257
275
|
Then, if the project keeps a model README (from `../../event-modeling-shared/templates/model-readme.md`), run
|
|
258
276
|
`em slice index <model-name>.em` so its generated Slices table reflects the new status and
|
|
259
277
|
link — never hand-edit that table. The `implementedIn` link is what the `conform` phase later
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-review
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.18.1
|
|
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
|
|
@@ -65,7 +65,9 @@ review:` marker (mirrors `Last conformance:`).
|
|
|
65
65
|
|
|
66
66
|
Then, and only then: a slice with nothing left `- [ ]` and no open `issue` →
|
|
67
67
|
`em slice review <model>.em <key> --by <name>` (flips its doc to `status: reviewed` and records
|
|
68
|
-
`reviewedBy:`/`reviewedOn:`).
|
|
68
|
+
`reviewedBy:`/`reviewedOn:`). `em slice review` itself exits 1 on an unchecked Open Question
|
|
69
|
+
(`--allow-open` records a deliberately partial walk; `--again` re-records a review after a body edit).
|
|
70
|
+
Anything still open stays `draft` — the walkthrough doesn't decide
|
|
69
71
|
it, the next session or the open-questions list does.
|
|
70
72
|
|
|
71
73
|
**The facilitator never ratifies, never offers to ratify, and never suggests ratification in a
|
|
@@ -22,6 +22,7 @@ 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, preceded by dimmed stub columns for what they read from outside it (and the end state of a storyline it comes `after`) (default out: storylines/<kebab-slug>.svg)
|
|
25
26
|
em render <file> --emit-dot # print the generated DOT instead of rendering
|
|
26
27
|
em render <file> --keep-empty-lanes # keep the API lane even when empty
|
|
27
28
|
em export <file> # export a versioned JSON snapshot of the normalized model
|
|
@@ -68,13 +69,18 @@ em slice index <file> # rewrite th
|
|
|
68
69
|
em slice index <file> --check # verify the table is current; exit non-zero on drift without writing (CI)
|
|
69
70
|
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
|
|
70
71
|
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)
|
|
71
|
-
em slice
|
|
72
|
+
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)
|
|
73
|
+
em slice review <file> <slice-key> # flip a slice doc's frontmatter to `status: reviewed` and record `reviewedBy:`/`reviewedOn:` — the FIRST of the two human gates (MIL-201, docs/process.md#the-slice-lifecycle-gates): the room walked this slice and every open question it raised is resolved. Ratification is a separate, later gate (`em slice ratify`). Legal from `status: draft`; idempotent on the same --by/--on pair; refuses to overwrite a different one already recorded (--again re-records it); refuses a doc with an unchecked `## Open Questions` item unless --allow-open (GH #333); refuses a doc already `ready-to-implement`/`implemented`; never touches `version:` or the doc body
|
|
72
74
|
em slice review <file> <slice-key> --by <name> # the reviewer's (or facilitator's) name
|
|
73
75
|
em slice review <file> <slice-key> --on <date> # review date, YYYY-MM-DD (default: today, local date)
|
|
76
|
+
em slice review <file> <slice-key> --roster <path> # ratifier roster to check --by against (GH #259; default: the nearest ratifiers.yaml above the model, none = unrestricted)
|
|
77
|
+
em slice review <file> <slice-key> --again # re-record reviewedBy/reviewedOn on a doc already `status: reviewed` (prints old -> new); still refused on ready-to-implement/implemented
|
|
78
|
+
em slice review <file> <slice-key> --allow-open # record the review although `## Open Questions` has unchecked items (a deliberately partial walk); prints a notice with the open count
|
|
74
79
|
em slice ratify <file> <slice-key> # flip a slice doc's frontmatter to `status: ready-to-implement` and record `ratifiedBy:`/`ratifiedOn:` — the handoff sign-off (MIL-165, docs/process.md#the-slice-lifecycle-gates) that makes who ratified, and when, a first-class recorded fact. The review gate is a check on the doc's current `status:`, not on whether `reviewedBy:`/`reviewedOn:` are populated: a doc at `reviewed` passes; a `ready-to-implement` doc only when the same signer is completing their own record (since 1.15.0, MIL-283 — a new sign-off is a new version: `em slice revise`); any other status — a `draft` that never went through `em slice review` — is refused unless --skip-review is passed. Idempotent on the same --by/--on pair; refuses to overwrite a different one already recorded, and (MIL-284) a same-pair re-run on a doc whose body moved after sign-off; never touches `version:` or the doc body. Inside a git work tree also records `ratifiedRef:` (HEAD, refusing a doc with uncommitted changes) and always `ratifiedHash:`; with --no-ref (GH #255) only the hash — for a repo whose squash/rebase merges would leave the ref unreachable — and git is not consulted
|
|
75
80
|
em slice ratify <file> <slice-key> --by <name> # the ratifier's name
|
|
76
81
|
em slice ratify <file> <slice-key> --no-ref # record ratifiedHash: only, no ratifiedRef: (GH #255) — the signed content keeps its identity, nothing points at a commit a squash or rebase merge would orphan; the uncommitted-changes check does not apply
|
|
77
82
|
em slice ratify <file> <slice-key> --on <date> # ratification date, YYYY-MM-DD (default: today, local date)
|
|
83
|
+
em slice ratify <file> <slice-key> --roster <path> # ratifier roster to check --by against (GH #259; default: the nearest ratifiers.yaml above the model, none = unrestricted)
|
|
78
84
|
em slice ratify <file> <slice-key> --skip-review # ratify without a recorded review — prints a loud notice on stderr and records `reviewSkipped: <status>` on the doc (GH #260) so the bypass is visible to later readers, `em export` and `--slice-ready --json`; cleared by `em slice revise`
|
|
79
85
|
em slice ratify <file> <slice-key> --meaning-unchanged # API-first sign-off (MIL-238): this version does not change what the public contract means — records `meaningConfirmed: true`; required (or --contract-change) on a slice touching a `public` element
|
|
80
86
|
em slice ratify <file> <slice-key> --contract-change <why> # API-first sign-off (MIL-238): a consumer must read this change differently, and why — records `contractChange: "<why>"`
|
|
@@ -128,6 +134,10 @@ em conform-supersede <file> <report-path> --locus <locus> # who/what t
|
|
|
128
134
|
em conform-supersede <file> <report-path> --by <name> # who ruled on the named finding(s) (requires --locus)
|
|
129
135
|
em conform-findings check <path> # shape-validate a conformance/<date>-findings.json file (findingsSchemaVersion, required fields, enum values, ids sorted+unique, a ruled finding carries resolvedBy+resolvedOn) — exit 1 on shape errors. The conform skill writes this file directly alongside its report; this is how a headless run verifies what it just wrote.
|
|
130
136
|
em conform-findings check <path> --json # print a JSON document instead of the text report
|
|
137
|
+
em discover triage-check <file> # validate a discovery/prd-triage.json (prdTriageSchemaVersion 1.0): shape, the shipped rubric version, every statement/storyline quote appearing verbatim in the input document, and every statement carrying a category, an outcome and (modeled/rewritten) a group + storyline — exit 1 on errors. The discover skill writes this file directly; this is how a headless run verifies it.
|
|
138
|
+
em discover triage-check <file> --source <path> # the input PRD/spec to check quotes against (default: the file's own `source`, relative to it)
|
|
139
|
+
em discover triage-check <file> --markdown # after a passing check, print the Markdown view of the record instead of the summary
|
|
140
|
+
em discover triage-check <file> --json # print a JSON document instead of the text report
|
|
131
141
|
em watch <file> # re-render on every save
|
|
132
142
|
em watch <file> -o, --out <path> # output path (extension picks the format)
|
|
133
143
|
em watch <file> -T, --format <fmt> # output format (svg, png, pdf, ...)
|
|
@@ -141,7 +151,11 @@ em validate <file> --list-public # print only
|
|
|
141
151
|
em validate <file> --fail-on-issues # exit non-zero if the model has any open `issue`s (opt-in — issues are warnings and don't block by default)
|
|
142
152
|
em validate <file> --slice-ready <key> # readiness gate for one slice (export key): status ready-to-implement, doc resolvable via note binding, zero unchecked Open Questions, a recorded ratifiedBy, and — for a slice touching a `public` element — a current contracts/<model key>.tsp; exits non-zero if not ready (MIL-87, MIL-259, MIL-238)
|
|
143
153
|
em validate <file> --require-ratified-hash # with --slice-ready (GH #256): strict mode — a ready-to-implement doc with no `ratifiedHash:` is NOT ready (`slice-ready-missing-ratified-hash`, error; `ready: false` in --json). Off by default so docs ratified before em 1.15 keep passing; turn it on once legacy docs are re-ratified
|
|
154
|
+
em validate <file> --strict # promote advisory lints (GH #293: scenario-quality warnings) to errors: they fail the run and, with --slice-ready, block readiness
|
|
155
|
+
em validate <file> --roster <path> # with --slice-ready (GH #259): the ratifier roster to check `ratifiedBy` against (default: the nearest ratifiers.yaml above the model; none = unrestricted). A name the roster does not permit for the slice's context is `ratified-by-not-in-roster` (error)
|
|
144
156
|
em validate <file> --check-signed-bodies # opt-in (GH #257): compare every slice doc that records a `ratifiedHash:` — ready, implemented, any status — to its body; a mismatch is `slice-body-changed-since-ratification` (error). A pre-1.17 whole-body hash with an intact body passes; a deferral written by `em slice defer` is outside the hash. The one check that still watches a shipped doc's signed content
|
|
157
|
+
em validate <file> --shape # GH #282: run only the advisory shape-family lints (storyline shape) and print rule / count / first ref / docs anchor; exit 0 always. With --json: `shapeSchemaVersion` 1.0 with per-rule finding arrays
|
|
158
|
+
em validate <file> --waive-file <path> # with --shape: a baseline file (`<rule-code> <slice-key>` per line, or a bare slice key for every shape rule; `#` comments) whose shape findings are listed as waived and not counted; missing file = no waivers
|
|
145
159
|
em validate <file> --json # print a JSON document instead of text — works on a model WITH errors, unlike `em export` (MIL-128, see docs/cli.md); exit codes are unchanged
|
|
146
160
|
em migrate <file> # rewrite the old two-slice Automation/Translation shape into the merged single-slice shape MIL-120 made canonical (see docs/cli.md)
|
|
147
161
|
em migrate <file> --write # apply the rewrite to the file (default: dry run — report only, write nothing)
|
|
@@ -195,6 +209,7 @@ em query slices <files> --status <s> # the slice'
|
|
|
195
209
|
em query slices <files> --context <c> # match a slice with an event in this @Context
|
|
196
210
|
em query slices <files> --persona <p> # match a slice with a ui in this @Persona
|
|
197
211
|
em query slices <files> --tag <t> # match a slice with an event carrying this tag key
|
|
212
|
+
em query slices <files> --storyline <name> # match a slice declared in this `storyline` block
|
|
198
213
|
em query slices <files> --json # print a JSON document instead of the text report
|
|
199
214
|
em query invariant <files> # declaring slice + doc facts for one INV-* id, and (with --tests) its test citations
|
|
200
215
|
em query invariant <files> --id <inv-id> # the INV-* id to look up
|
|
@@ -215,6 +230,7 @@ em engagement new <file> <slug> --downstream-of <ref> # a slice ke
|
|
|
215
230
|
em engagement new <file> <slug> --parallel <n> # how many slices of one level may be in flight at once
|
|
216
231
|
em engagement new <file> <slug> --by <name> # who created the engagement (createdBy)
|
|
217
232
|
em engagement new <file> <slug> --tracking <key> # an issue-tracker key or URL the slice PRs cite (a slice doc's own tracking: wins)
|
|
233
|
+
em engagement new <file> <slug> --pr-title <template> # PR title template for the slice PRs; {key} = tracking key, {slice} = slice name, {sliceKey} = slice key (default "{key}: {slice}", or "{slice}" without a key)
|
|
218
234
|
em engagement new <file> <slug> --force # overwrite an existing engagement file with this slug
|
|
219
235
|
em engagement plan <file> <slug> # the engagement's build plan: dependency levels over model.edges (loops-to excluded), and per slice its readiness, branch impl/<key>, base (always main — MIL-280), and any hold
|
|
220
236
|
em engagement plan <file> <slug> --json # print a JSON document instead of text (same document as the MCP engagement_plan tool)
|
|
@@ -229,6 +245,12 @@ em engagement set <file> <slug> <key> --pr <url> # the slice'
|
|
|
229
245
|
em engagement status <file> <slug> # the Ledger joined with each slice doc's current status, plus whether the engagement is closable
|
|
230
246
|
em engagement status <file> <slug> --json # print a JSON document instead of text (same document as the MCP engagement_status tool)
|
|
231
247
|
em engagement close <file> <slug> # set status: closed — refuses unless every slice is merged (recorded or inferred) or gap
|
|
248
|
+
em roster init <file> # write ratifiers.yaml beside the model, seeded from the names already recorded in the slice docs' `ratifiedBy:`/`reviewedBy:` (whole-model entries; narrow them with `contexts:` by hand). Refuses to overwrite an existing file unless --force; `em upgrade`'s grandfathered placeholder is not a name
|
|
249
|
+
em roster init <file> --roster <path> # write the roster here instead of <model dir>/ratifiers.yaml
|
|
250
|
+
em roster init <file> --force # overwrite an existing roster file
|
|
251
|
+
em roster check <file> # check EVERY slice doc's recorded signers against the ratifier roster (GH #259) - `ratifiedBy` on ready-to-implement and implemented docs, `reviewedBy` on any doc - the whole-model CI gate that `--slice-ready <key>` (one ready slice) is not. Exit 1 on any violation or an invalid roster; no roster file = nothing to check, exit 0. The `grandfathered ...` placeholder is exempt (counted)
|
|
252
|
+
em roster check <file> --roster <path> # roster to check against (default: the nearest ratifiers.yaml above the model)
|
|
253
|
+
em roster check <file> --json # print a JSON document (per-doc results, diagnostics with refs); exit codes unchanged
|
|
232
254
|
em system [target] # verify a system — every model's `consumes` refs resolved against the other models' `public` events/views, the cross-model half of "both ends of a flow" (MIL-194/MIL-235, see docs/cli.md). Reads system.yaml when given (or found in the directory), else discovers every *.em in the repo
|
|
233
255
|
em system [target] --json # print a JSON document instead of the text report (see docs/cli.md)
|
|
234
256
|
em system codeowners [target] # generate (or --check) the managed CODEOWNERS block that routes review: each model's team on its design directory, and every team that `consumes` a model's public surface on that model's contract file (MIL-234, see docs/ci.md and docs/cli.md)
|
|
@@ -253,10 +275,13 @@ em ci init <model> # install .g
|
|
|
253
275
|
em ci init <model> --tests <dir> # test directory the coverage/status steps scan for INV-* citations
|
|
254
276
|
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
|
|
255
277
|
em ci init <model> --check # verify both files match the current preset; exit non-zero on drift without writing (CI)
|
|
278
|
+
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
|
|
256
279
|
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
|
|
257
280
|
em upgrade <file> --apply # apply every applicable mechanical step, one git commit each, then a final `Em version:` commit
|
|
258
281
|
em upgrade <file> --check # exit non-zero only on a hard incompatibility (an existing but unparseable state file, an un-migratable .em shape) — writes nothing; what CI runs; the final line says why
|
|
259
282
|
em upgrade <file> --json # print a JSON document instead of text (dry-run/--check only, never with --apply)
|
|
283
|
+
em upgrade <file> --fold-continuations # also run the opt-in fold-continuations step (stack consecutive continuations of one view into the first; continuationOf, doc join and index rows unchanged)
|
|
284
|
+
em upgrade <file> --to-sugar # (implies --fold-continuations; without --apply it is a dry run listing exactly what would fold): fold continuations into their host command slice as `view X again … shown on` lines — CHANGES continuationOf and the doc join to `<host>--again` and removes the folded slices' index rows
|
|
260
285
|
```
|
|
261
286
|
<!-- GENERATED:cli:end -->
|
|
262
287
|
|
|
@@ -273,6 +298,10 @@ model "Name" [owner "Team"] # diagram title; optional owning team(s), quote
|
|
|
273
298
|
persona Name # a UI swimlane row (actor)
|
|
274
299
|
context Name # an event swimlane row (bounded context / aggregate)
|
|
275
300
|
|
|
301
|
+
storyline "Name" [source "url"] [after "Other"] { # optional chapter grouping slices (see Storylines)
|
|
302
|
+
slice "Name" { ... }
|
|
303
|
+
}
|
|
304
|
+
|
|
276
305
|
slice "Name" [source "url"] { # one vertical time step (a column); source is optional
|
|
277
306
|
ui Free Text @Persona # screen; @Persona picks its row (defaults to first/"User")
|
|
278
307
|
command Free Text # state-changing request (API band)
|
|
@@ -295,7 +324,7 @@ type Name { field: Type, ... } # named structured type, reusable from any f
|
|
|
295
324
|
| `ui` | persona | screen / interface | `@Persona` | `note`, `issue`, `divergence`, `{ fields }` |
|
|
296
325
|
| `command` | API | state-changing request | — | `note`, `issue`, `divergence`, `renamed from`, `{ fields }`, standalone `invariant` line |
|
|
297
326
|
| `view` | API | read model / projection | — | `from "Event"…`, `note`, `issue`, `divergence`, `public`, `{ fields }` |
|
|
298
|
-
| `event` | context | recorded fact (past tense) | `@Context` | `note`, `issue`, `divergence`, `public`, `tag`, `renamed from`, `loops-to`, field-level `assigned`, `{ fields }`, standalone `invariant` line |
|
|
327
|
+
| `event` | context | recorded fact (past tense); `event A \| B @Context` = alternative outcomes of ONE command, one slice, one shared cell | `@Context` | `note`, `issue`, `divergence`, `public`, `tag`, `renamed from`, `loops-to`, field-level `assigned`, `{ fields }`, standalone `invariant` line |
|
|
299
328
|
| `processor` / `automation` / `saga` / `translation` | automation | system reaction / adapter | — | `from "…"`, `note`, `issue`, `divergence`, `{ fields }`; `translation` only: `consumes` |
|
|
300
329
|
|
|
301
330
|
### Clauses
|
|
@@ -311,6 +340,15 @@ type Name { field: Type, ... } # named structured type, reusable from any f
|
|
|
311
340
|
"to-do list") and pointing the reaction at that view. Name that view after the pending work
|
|
312
341
|
(`Payments To Process`), never after the triggering event — a view reusing the event's name
|
|
313
342
|
collides in the shared namespace and draws a duplicate-name warning.
|
|
343
|
+
- **One event recorded by several commands** (two intents, one fact — `Create Product` and
|
|
344
|
+
`Create Product Variant` both ending in `Product Created`): repeat the event BARE in the later
|
|
345
|
+
slice with the same name and context. A bare repeat of an event with the same name and context is
|
|
346
|
+
ONE logical event — no `duplicate-name`, no marker (`again` stays view-only). The repeat inherits
|
|
347
|
+
the first declaration's fields, element-level `tag` clauses and `public`; declaring different ones
|
|
348
|
+
is the error `shared-event-field-mismatch`. A view's `from "E"` draws an arrow from every recording
|
|
349
|
+
site at or before it, and EVERY site needs a reader at or after it (add `view V again from "E"`
|
|
350
|
+
after the last site, or `event-unread` warns for that site). The same name in a different context
|
|
351
|
+
is still a `duplicate-name` warning.
|
|
314
352
|
- **`again`** (views only): `view <Name> again [from "Event", …]` declares a later instance of an
|
|
315
353
|
already-declared read model — the forward-only device for a view that evolves as later events
|
|
316
354
|
land. Instances are ONE logical view: the first declaration owns the `note` binding; each
|
|
@@ -442,7 +480,11 @@ type Name { field: Type, ... } # named structured type, reusable from any f
|
|
|
442
480
|
into doc-only prose** — the marker keeps `em export`/the model aware the field exists (the
|
|
443
481
|
`doc-model-field-mismatch` doc↔model check does not compare view field tables at all today —
|
|
444
482
|
see the slice template's field-table guidance — so this is an export-side win specifically,
|
|
445
|
-
not yet a doc-drift check).
|
|
483
|
+
not yet a doc-drift check). **Collection fields (GH #288):** a view field typed `T[]` for a
|
|
484
|
+
declared `type T`, with `derived from "Child Created", "Child Deleted"`, embeds a child entity:
|
|
485
|
+
each field of `T` must trace to a named event (`fields-completeness/view-field-no-source`
|
|
486
|
+
otherwise). No add/remove/key clauses — `em slice sync` writes a `Collection of` note plus
|
|
487
|
+
one Given/Then scenario stub per named event in the view region (copy into `## Scenarios`), and `em export` sets `collection: true`.
|
|
446
488
|
- **Fields:** `command Place Order { orderId: UUID, items: LineItem[], customerId }` — inline or
|
|
447
489
|
one-per-line. Types are free text (no semantic checking) UNLESS the type string names a
|
|
448
490
|
declared `type` (see Named types below), in which case it resolves to a structured
|
|
@@ -471,6 +513,22 @@ type Name { field: Type, ... } # named structured type, reusable from any f
|
|
|
471
513
|
of relying on prose. Purely metadata — no visual marker, not validated. Don't confuse it with
|
|
472
514
|
an element's `note "path.md"` (a markdown file link, not a URL).
|
|
473
515
|
|
|
516
|
+
- **`storyline "Name" [source "url"] [after "Other"] { slice … }`** (GH #277) groups slices into a
|
|
517
|
+
named chapter — the main journey, and secondary stories (retire a product, extend an attribute).
|
|
518
|
+
Slices keep their file-order timeline position; a slice outside any storyline is allowed;
|
|
519
|
+
storylines don't nest and a repeated name continues that storyline (its slices join it; a continuation may not add or change
|
|
520
|
+
`source`/`after` — parse error). The full render draws a
|
|
521
|
+
labelled band above the slice headers; `em render --storyline "Name"` draws one story alone, with the
|
|
522
|
+
elements it reads from outside as dimmed stub columns. `em export` carries `slice.storyline` and
|
|
523
|
+
`model.storylines[]`; `em query slices --storyline`; `em slice index` adds a Storyline column. Once
|
|
524
|
+
any storyline exists a slice outside every one is the advisory warning `slice-outside-storyline`.
|
|
525
|
+
`after "<other>"` reads the storyline as if its slices followed the referenced storyline's last
|
|
526
|
+
slice: `from`/`again`/reaction `from` resolve against the composed timeline (referenced → this), the
|
|
527
|
+
forward-only checks use it, a backward feed into the referenced storyline, an `after` cycle
|
|
528
|
+
(`storyline-after-cycle`), an unknown target (`storyline-after-unknown`) or a storyline declared above
|
|
529
|
+
the one it comes after when a flow would draw right-to-left (`storyline-after-out-of-order`) is an
|
|
530
|
+
error. Without `after`, file order is the only timeline.
|
|
531
|
+
|
|
474
532
|
### Named types
|
|
475
533
|
|
|
476
534
|
`type Name { field: Type, ... }` declares a reusable structured shape at the top level (any
|
|
@@ -633,8 +691,9 @@ slice "Read Quote — created" {
|
|
|
633
691
|
**prefer `view X again`** for every instance after the first (see Clauses) — **each instance
|
|
634
692
|
carries its own consumer** (the `ui` that reads it, or a reaction), not just the last one. `again`
|
|
635
693
|
instances are exempt from the duplicate-name warning even when referenced, and each reference
|
|
636
|
-
resolves to the right instance — a plain repeat only stays warning-free while nothing references it by name, and
|
|
637
|
-
resolves to the *first* declaration when something does
|
|
694
|
+
resolves to the right instance — a plain repeat of a view only stays warning-free while nothing references it by name, and
|
|
695
|
+
resolves to the *first* declaration when something does (the exception is a same-context event
|
|
696
|
+
repeat, which is one logical event — see above). **Wire each event to a read model exactly
|
|
638
697
|
once:** a repeated instance's `from` lists only the **new** events since the previous instance
|
|
639
698
|
(not cumulative), or the event draws a duplicate arrow to the same read model at every repeat. (An
|
|
640
699
|
event may still feed several *different* read models, once each.)
|
|
@@ -655,6 +714,13 @@ consumer is an obligation to ship an endpoint, no `ui` means internal-only, and
|
|
|
655
714
|
the published integration surface — see `reference/implement.md`'s "Interface obligations"
|
|
656
715
|
paragraph in the `event-modeling-implement` skill (§2).
|
|
657
716
|
|
|
717
|
+
- **Continuations without ceremony (GH #287).** Several `view X again` lines may share one
|
|
718
|
+
continuation slice (they stack in the `api` cell); `view X again from "E"` written inside a
|
|
719
|
+
command's own slice is sugar for a synthesized continuation column right after it (one column per host slice, lines stacked; key
|
|
720
|
+
`<slice-key>--again`, no doc, not in `em slice index`; consumer = the slice's first `ui`,
|
|
721
|
+
or `shown on "Screen"` — required in a reaction slice with no `ui`); and a continuation slice may omit its name — it is auto-named
|
|
722
|
+
`"<View> View: <Event>"`. Instances still never connect.
|
|
723
|
+
|
|
658
724
|
### Reaction wiring — no positional gotcha
|
|
659
725
|
|
|
660
726
|
A reaction's command is inferred from **same-slice presence**, exactly like `ui -> command`: put
|
|
@@ -675,7 +741,13 @@ it to the slice that displays the read model, or drop it.
|
|
|
675
741
|
|
|
676
742
|
**Errors (must fix):**
|
|
677
743
|
1. **Band collision** — two elements of the same band in one slice (e.g. two `command`s, or two
|
|
678
|
-
`ui`s in the *same* persona row). Split them into separate slices/personas.
|
|
744
|
+
`ui`s in the *same* persona row). Split them into separate slices/personas. Two events on one
|
|
745
|
+
context that are alternative outcomes of one command are NOT a split: write
|
|
746
|
+
`event A | B @Context` (identical payloads) or `oneof { event A @Context { … } event B @Context { … } }`
|
|
747
|
+
(own fields/clauses per alternative) — one slice, one shared cell, one command, one shared context; each
|
|
748
|
+
alternative is a full event, and a standalone `invariant` after them binds to all.
|
|
749
|
+
Alternatives with no command in the slice are an error (`alternative-events-no-command`), and the same
|
|
750
|
+
command repeated across slices warns (`command-repeated-across-slices`).
|
|
679
751
|
2. **Unknown event source** — `view X from "Event"` where the event doesn't exist anywhere.
|
|
680
752
|
3. **Unknown read-model source** — `processor X from "View"` where the view doesn't exist.
|
|
681
753
|
4. **Arrow endpoint mismatch** — `arrow A -> B` where A or B matches no element name.
|
|
@@ -773,9 +845,11 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
773
845
|
<!-- GENERATED:validate-rules:start -- run `npm run docs:generate` to refresh, do not hand-edit -->
|
|
774
846
|
| Code | Severity | Title | Fix |
|
|
775
847
|
|---|---|---|---|
|
|
848
|
+
| `alternative-events-no-command` | error | Alternative events without a command | Add the command whose decision records one of the alternatives, in the same slice. |
|
|
776
849
|
| `arrow-backward` | error | Backward arrow | Restructure so the target comes later. |
|
|
777
850
|
| `arrow-unresolved-source` | error | Arrow source unresolved | Fix the arrow's source name. |
|
|
778
851
|
| `arrow-unresolved-target` | error | Arrow target unresolved | Fix the arrow's target name. |
|
|
852
|
+
| `automation-split-by-outcome` | warning | Reaction split into one slice per outcome | Model one Automation slice recording the outcomes as alternative events — `event A | B @Context` (docs/patterns.md#automation). |
|
|
779
853
|
| `binding-missing-file` | warning | Doc binding points at a missing file | Create the slice doc, or fix the `note` path. |
|
|
780
854
|
| `both-ends-of-a-flow/command-no-event` | warning | Command without event | Add the event this command records. |
|
|
781
855
|
| `both-ends-of-a-flow/command-untriggered` | warning | Command with no trigger | Add a `ui` or the reaction that issues it, both in this slice. |
|
|
@@ -785,6 +859,8 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
785
859
|
| `both-ends-of-a-flow/ui-unbacked` | warning | `ui` with no read model or command | Add a `view` it displays, or the command it triggers. |
|
|
786
860
|
| `both-ends-of-a-flow/view-unconsumed` | warning | Read model with no consumer | Add a `ui` or reaction that consumes it, or drop this instance. |
|
|
787
861
|
| `code-spans-seam` | warning | Code change spans a seam | Keep one code module per model and change the two sides of a seam in separate change sets. |
|
|
862
|
+
| `command-repeated-across-slices` | warning | Command repeated across slices | Merge the slices: one command with several outcomes is one slice — `event A | B @Context`. |
|
|
863
|
+
| `command-second-intent` | warning | Command carries a second intent | Split the conditional rule set into its own command; both commands may record the same event (a bare repeat of the event is legal). |
|
|
788
864
|
| `connection-legality/illegal-pair` | error | Illegal connection | Only ui→command→event→view→ui and view→reaction→command are legal — the message names the missing step. |
|
|
789
865
|
| `consumer-not-adapted` | error | Consuming translation no longer matches the producer's public element | Update the translation's field block to the producer's current fields (a renamed field names its new name in the message). Additive producer changes never raise this — consumers tolerate unknown fields. |
|
|
790
866
|
| `consumes-unknown-element` | error | `consumes` names no public element of that model | Point the ref at an element the producer marks `public` (`em export` lists them), or ask the producer to publish it. |
|
|
@@ -797,6 +873,8 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
797
873
|
| `doc-model-element-not-in-model` | warning | Doc names an element the model doesn't have | Add the element to the model, or fix/remove it in the doc. |
|
|
798
874
|
| `doc-model-field-mismatch` | warning | Doc/model field mismatch | Reconcile the field table with the model's fields — names and types. |
|
|
799
875
|
| `doc-model-pattern-mismatch` | warning | Doc/model pattern mismatch | Fix the doc's `pattern:` frontmatter to match the model, or restructure the slice to match the doc. |
|
|
876
|
+
| `doc-names-unfed-event` | warning | Doc names an event its view does not read | Add the event to the view's `from` in the model (if the edge is real), or fix the doc's Source column / scenario. |
|
|
877
|
+
| `doc-omits-fed-event` | warning | Doc omits an event its view reads | Mention the event in the view's Source column (run `em slice sync`), or drop it from the view's `from`. |
|
|
800
878
|
| `duplicate-element-ref` | warning | Duplicate element ref | Rename the element so its export ref is unique. |
|
|
801
879
|
| `duplicate-model-key` | warning | Duplicate model key | Give each model a unique `model "Name"` so its key (and every cross-model ref) is stable. |
|
|
802
880
|
| `duplicate-name` | warning | Duplicate name | Rename one of the duplicates. |
|
|
@@ -808,6 +886,7 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
808
886
|
| `frontmatter-coherence-implemented-without-link` | warning | Implemented without a link | Add `implementedIn` once the slice ships. |
|
|
809
887
|
| `frontmatter-invalid` | warning | Invalid or missing frontmatter | Add the required frontmatter keys, or add a frontmatter block. |
|
|
810
888
|
| `grid-collision` | error | Band collision | Split the colliding elements into separate slices. |
|
|
889
|
+
| `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. |
|
|
811
890
|
| `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. |
|
|
812
891
|
| `invariants/doc-cites-undeclared` | warning | Slice doc cites an undeclared invariant | Declare the ID in the model (or in a slice doc's Invariants section), or fix the citation. |
|
|
813
892
|
| `invariants/duplicate-id` | error | Duplicate invariant ID | Give each model-declared invariant its own ID — a rule is declared once, on the element it guards. |
|
|
@@ -832,18 +911,27 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
|
|
|
832
911
|
| `public-name-not-unique` | error | Two public elements of one kind share a name | Rename one of them (or drop `public` from one): a consumer's `consumes <model>:<kind>.<slug>` must name exactly one element. |
|
|
833
912
|
| `reaction-from-future-view` | error | Backward timeline (reaction reads a future view) | Declare the view in or before the reaction's slice. |
|
|
834
913
|
| `reaction-from-unresolved` | error | Unknown read-model source | Project the event into a view first, or fix the `from` reference. |
|
|
914
|
+
| `retry-slice-of` | warning | Slice only retries another command | Re-fire the same reaction via `view … again from` the retry-scheduled event; a different actor's override is its own slice with its own command (docs/patterns.md#automation). |
|
|
915
|
+
| `scenario-then-not-outcome` | warning | Scenario's Then names no event or rejection | Make the Then bullets name the event(s) the command records, or the rejection/error it returns. |
|
|
916
|
+
| `scenario-when-not-command` | warning | Scenario's When does not name the slice's command | Make the When bullet name the slice's command (for a reaction slice: the command, the reaction element, or a view of the slice) — each scenario exercises exactly one command. For a Translation, naming the translation element satisfies it. |
|
|
835
917
|
| `seam-consumer-not-reaction` | error | Seam consumer is not a reaction | Point `to` at a translation/automation element (or a slice containing exactly one). |
|
|
836
918
|
| `seam-crossing` | error | Change set alters a contract and its consumer together | Split the change set: land the producer's public-surface change first, then adapt the consuming model in a later change. Review on the contract file is the only override. |
|
|
837
919
|
| `seam-crossing-greenfield` | warning | New public surface lands with its first consumer | Nothing to fix: a public element no consumer was bound to at the base revision is new surface, not a crossing. Later changes to it are crossings. |
|
|
838
920
|
| `seam-duplicate` | warning | Duplicate seam | Remove the repeated `from`/`to` pair. |
|
|
839
921
|
| `seam-endpoint-unresolved` | error | Seam endpoint does not resolve | Fix the ref to an element the named model actually exports (`em export` lists every ref), or re-declare the seam after a rename. |
|
|
840
922
|
| `seam-source-not-public` | error | Seam source is not `public` | Mark the event/view `public` in its model, or point the seam at the element that is. |
|
|
923
|
+
| `shared-event-field-mismatch` | error | Shared event declared with different fields, tags or public | Repeat the event bare to inherit the first declaration's fields, tags and public, or make them identical. |
|
|
841
924
|
| `slice-doc/structured-section-malformed` | warning | Malformed structured section | Balance the `<!-- GENERATED:em-slice-…:start -->`/`:end -->` markers (re-create the doc with `em slice new --force` if they are lost), restore the template's table header and run `em slice sync`, and give every `### Scenario:` block a Given, When and Then bullet. |
|
|
925
|
+
| `slice-outside-storyline` | warning | Slice outside every storyline | Move the slice inside one of the model's `storyline` blocks (advisory: storylines can be adopted incrementally). |
|
|
926
|
+
| `storyline-after-cycle` | error | Storyline `after` cycle | Remove an `after` clause so no storyline comes after itself. |
|
|
927
|
+
| `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. |
|
|
928
|
+
| `storyline-after-unknown` | error | `after` names an unknown storyline | Name a storyline declared in this model, or drop the `after` clause. |
|
|
842
929
|
| `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`). |
|
|
843
930
|
| `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. |
|
|
844
931
|
| `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. |
|
|
845
932
|
| `tag-composite-unknown-field` | error | Composite tag names an unknown field | Fix the field name, or add it to the event's fields. |
|
|
846
933
|
| `tag-duplicate-key` | error | Duplicate tag key | Rename one of the tags so every key on the event is unique. |
|
|
934
|
+
| `timeline-entity-clustered` | warning | Lifecycle-per-entity shape (storyline order) | If these are create/update/archive steps on one entity, order the slices by the business journey, interleaving contexts as the story does; if they are steps of one journey, show a screen (a view) after each step. See docs/storyline.md. |
|
|
847
935
|
| `translation-name-collision` | warning | Translation name reused for different producers | Use a distinct name per producer to avoid confusion. |
|
|
848
936
|
| `type-cycle` | error | Cyclic type reference | Break the cycle, or route the self/mutual reference through an array. |
|
|
849
937
|
| `ui-shares-slice-with-automation` | warning | `ui` shares slice with a reaction | Move the `ui` to the slice that displays the read model, or drop it. |
|