@milehimikey/em 1.9.1 → 1.10.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 (77) hide show
  1. package/.claude/skills/event-modeling/SKILL.md +1 -1
  2. package/.claude/skills/event-modeling-conform/SKILL.md +1 -1
  3. package/.claude/skills/event-modeling-design/SKILL.md +1 -1
  4. package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
  5. package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
  6. package/.claude/skills/event-modeling-review/SKILL.md +1 -1
  7. package/.claude/skills/event-modeling-shared/reference/em-dsl.md +46 -1
  8. package/README.md +8 -1
  9. package/dist/cli/ciInit.d.ts +10 -3
  10. package/dist/cli/ciInit.js +22 -14
  11. package/dist/cli/ciInit.js.map +1 -1
  12. package/dist/cli/systemInputs.d.ts +34 -0
  13. package/dist/cli/systemInputs.js +129 -0
  14. package/dist/cli/systemInputs.js.map +1 -0
  15. package/dist/cli.js +220 -5
  16. package/dist/cli.js.map +1 -1
  17. package/dist/emit/json.d.ts +16 -1
  18. package/dist/emit/json.js +36 -1
  19. package/dist/emit/json.js.map +1 -1
  20. package/dist/emit/queryJson.d.ts +6 -0
  21. package/dist/emit/queryJson.js +29 -0
  22. package/dist/emit/queryJson.js.map +1 -0
  23. package/dist/emit/systemJson.d.ts +8 -0
  24. package/dist/emit/systemJson.js +38 -0
  25. package/dist/emit/systemJson.js.map +1 -0
  26. package/dist/mcp/server.d.ts +1 -1
  27. package/dist/mcp/server.js +185 -6
  28. package/dist/mcp/server.js.map +1 -1
  29. package/dist/model/edges.d.ts +13 -1
  30. package/dist/model/edges.js +43 -15
  31. package/dist/model/edges.js.map +1 -1
  32. package/dist/model/model.d.ts +2 -0
  33. package/dist/model/model.js +1 -0
  34. package/dist/model/model.js.map +1 -1
  35. package/dist/model/qualifiedRef.d.ts +47 -0
  36. package/dist/model/qualifiedRef.js +100 -0
  37. package/dist/model/qualifiedRef.js.map +1 -0
  38. package/dist/model/queryIndex.d.ts +50 -0
  39. package/dist/model/queryIndex.js +111 -0
  40. package/dist/model/queryIndex.js.map +1 -0
  41. package/dist/model/rules.d.ts +69 -0
  42. package/dist/model/rules.js +82 -0
  43. package/dist/model/rules.js.map +1 -1
  44. package/dist/model/sliceDocIndex.d.ts +30 -0
  45. package/dist/model/sliceDocIndex.js +110 -0
  46. package/dist/model/sliceDocIndex.js.map +1 -0
  47. package/dist/model/validate.js +4 -11
  48. package/dist/model/validate.js.map +1 -1
  49. package/dist/parser/ast.d.ts +4 -0
  50. package/dist/parser/parser.d.ts +2 -0
  51. package/dist/parser/parser.js +8 -2
  52. package/dist/parser/parser.js.map +1 -1
  53. package/dist/query/format.d.ts +8 -0
  54. package/dist/query/format.js +80 -0
  55. package/dist/query/format.js.map +1 -0
  56. package/dist/query/pipeline.d.ts +17 -0
  57. package/dist/query/pipeline.js +38 -0
  58. package/dist/query/pipeline.js.map +1 -0
  59. package/dist/query/system.d.ts +60 -0
  60. package/dist/query/system.js +87 -0
  61. package/dist/query/system.js.map +1 -0
  62. package/dist/query/verbs.d.ts +100 -0
  63. package/dist/query/verbs.js +306 -0
  64. package/dist/query/verbs.js.map +1 -0
  65. package/dist/render/drawEdges.js +8 -4
  66. package/dist/render/drawEdges.js.map +1 -1
  67. package/dist/render/sliceDiagram.js +1 -0
  68. package/dist/render/sliceDiagram.js.map +1 -1
  69. package/dist/system/manifest.d.ts +45 -0
  70. package/dist/system/manifest.js +178 -0
  71. package/dist/system/manifest.js.map +1 -0
  72. package/dist/system/verify.d.ts +88 -0
  73. package/dist/system/verify.js +263 -0
  74. package/dist/system/verify.js.map +1 -0
  75. package/dist/util/slug.js +16 -10
  76. package/dist/util/slug.js.map +1 -1
  77. package/package.json +10 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: event-modeling
3
- em-version: 1.9.1
3
+ em-version: 1.10.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.9.1
3
+ em-version: 1.10.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.9.1
3
+ em-version: 1.10.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
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: event-modeling-discover
3
- em-version: 1.9.1
3
+ em-version: 1.10.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
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: event-modeling-implement
3
- em-version: 1.9.1
3
+ em-version: 1.10.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.9.1
3
+ em-version: 1.10.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
@@ -111,8 +111,43 @@ em status <files> -o, --out <path> # write output to
111
111
  em freshness <file> # standalone freshness signal for one model's conformance record (MIL-164): "last conformed <rev> — N commits and M slice-PRs behind HEAD", computed from the same conform-scope machinery `em status`'s conformance clause uses — for when you want just this fact, no full state-of-the-system rollup (see docs/cli.md)
112
112
  em freshness <file> --repo <path> # git repo to compute behind-HEAD in (default: the model's own directory)
113
113
  em freshness <file> --json # print a JSON document instead of the text line
114
+ em query consumers <files> # views/reactions consuming an event, plus their slices
115
+ em query consumers <files> --event <ref-or-name> # the event's export ref or display name
116
+ em query consumers <files> --json # print a JSON document instead of the text report
117
+ em query producers <files> # commands producing an event, plus their slices and ui triggers
118
+ em query producers <files> --event <ref-or-name> # the event's export ref or display name
119
+ em query producers <files> --json # print a JSON document instead of the text report
120
+ em query downstream <files> # transitive closure along legal edges from an element — impact analysis
121
+ em query downstream <files> --of <ref-or-name> # the starting element's export ref or display name
122
+ em query downstream <files> --depth <n> # limit traversal to n hops (default: unlimited)
123
+ em query downstream <files> --json # print a JSON document instead of the text report
124
+ em query upstream <files> # transitive closure against legal-edge direction from an element
125
+ em query upstream <files> --of <ref-or-name> # the starting element's export ref or display name
126
+ em query upstream <files> --depth <n> # limit traversal to n hops (default: unlimited)
127
+ em query upstream <files> --json # print a JSON document instead of the text report
128
+ em query slices <files> # filtered slice list — pattern/status/context/persona/tag filters AND-combine
129
+ em query slices <files> --pattern <p> # state-change | state-view | automation | translation | unclassified
130
+ em query slices <files> --status <s> # the slice's joined doc status (draft, reviewed, ready-to-implement, implemented, ...)
131
+ em query slices <files> --context <c> # match a slice with an event in this @Context
132
+ em query slices <files> --persona <p> # match a slice with a ui in this @Persona
133
+ em query slices <files> --tag <t> # match a slice with an event carrying this tag key
134
+ em query slices <files> --json # print a JSON document instead of the text report
135
+ em query invariant <files> # declaring slice + doc facts for one INV-* id, and (with --tests) its test citations
136
+ em query invariant <files> --id <inv-id> # the INV-* id to look up
137
+ em query invariant <files> --tests <dir> # directory to scan for test files citing this id
138
+ em query invariant <files> --json # print a JSON document instead of the text report
139
+ em query field <files> # one field's facts on an element — type, tag/assigned markers, renamed-from chain
140
+ em query field <files> --of <element-ref> # the element's export ref or display name
141
+ em query field <files> --name <field> # the field's name
142
+ em query field <files> --json # print a JSON document instead of the text report
143
+ em query path <files> # shortest path between two elements through the six legal connection types
144
+ em query path <files> --from <ref-or-name> # the starting element's export ref or display name
145
+ em query path <files> --to <ref-or-name> # the ending element's export ref or display name
146
+ em query path <files> --json # print a JSON document instead of the text report
147
+ em system <manifest> # verify a seam manifest (system.yaml) against its models' exports — every `public` event/view bound to a reaction in another model, the cross-model half of "both ends of a flow" (MIL-194, see docs/cli.md)
148
+ em system <manifest> --json # print a JSON document instead of the text report (see docs/cli.md)
114
149
  em contract # print the packaged implementation contract (reference/implement.md) to stdout — the agent-neutral discovery path for any agent that can run a shell, not just Claude Code (MIL-129); see docs/cli.md
115
- em mcp # start an MCP (Model Context Protocol) server over stdio, exposing validate/slice_ready/list_markers/export_model/export_slice/coverage/contract as tools (MIL-21) — a structured, agent-facing alternative to shelling out to `em`; see docs/mcp.md. Equivalent to running the `em-mcp` bin directly
150
+ em mcp # start an MCP (Model Context Protocol) server over stdio (MIL-21) — a structured, agent-facing alternative to shelling out to `em`; see docs/mcp.md for the full, current tool table (the list changes as commands gain MCP parity, so it's not repeated here — MIL-187). Equivalent to running the `em-mcp` bin directly
116
151
  em skill install # copy the event-modeling skill bundle into .claude/skills/ (event-modeling, event-modeling-discover/-design/-implement/-conform/-review, event-modeling-shared)
117
152
  em skill install -f, --force # overwrite an existing installation
118
153
  em skill install --no-agents-md # skip writing/updating the AGENTS.md agent-contract section (on by default, MIL-129)
@@ -561,11 +596,13 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
561
596
  | `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. |
562
597
  | `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. |
563
598
  | `cross-model-slice-doc-collision` | warning | Colliding slice doc path across models | Give each model its own directory (see docs/cli.md, "Multi-model projects"). |
599
+ | `dangling-public-event` | warning | Public event/view no seam consumes | Declare the seam that reads it, or drop `public` if nothing outside the model does. |
564
600
  | `doc-model-element-not-in-doc` | warning | Model element the doc doesn't mention | Add the matching marker to the doc, or remove the element from the model. |
565
601
  | `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. |
566
602
  | `doc-model-field-mismatch` | warning | Doc/model field mismatch | Reconcile the field table with the model's fields — names and types. |
567
603
  | `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. |
568
604
  | `duplicate-element-ref` | warning | Duplicate element ref | Rename the element so its export ref is unique. |
605
+ | `duplicate-model-key` | warning | Duplicate model key | Give each model a unique `model "Name"` so its key (and every cross-model ref) is stable. |
569
606
  | `duplicate-name` | warning | Duplicate name | Rename one of the duplicates. |
570
607
  | `duplicate-slice-name` | warning | Duplicate slice name | Rename the slice so its export key is unique. |
571
608
  | `duplicate-type-name` | warning | Duplicate type name | Rename one of the duplicate `type` declarations. |
@@ -587,11 +624,19 @@ not the prose above has caught up yet. `--slice-ready <key>`-only codes are excl
587
624
  | `orphaned-slice-doc` | warning | Orphaned slice doc | Rename it to a current slice's key, add `covers:` (plus a `note` binding) to attach it to a live slice, or delete it. |
588
625
  | `reaction-from-future-view` | error | Backward timeline (reaction reads a future view) | Declare the view in or before the reaction's slice. |
589
626
  | `reaction-from-unresolved` | error | Unknown read-model source | Project the event into a view first, or fix the `from` reference. |
627
+ | `seam-consumer-not-reaction` | error | Seam consumer is not a reaction | Point `to` at a translation/automation element (or a slice containing exactly one). |
628
+ | `seam-duplicate` | warning | Duplicate seam | Remove the repeated `from`/`to` pair. |
629
+ | `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. |
630
+ | `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. |
631
+ | `system-manifest-invalid` | error | Seam manifest invalid | Fix the manifest: required keys, `systemSchemaVersion: "1.0"`, a readable `source` per model, and only declared model keys in seam refs. |
632
+ | `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. |
590
633
  | `tag-composite-unknown-field` | error | Composite tag names an unknown field | Fix the field name, or add it to the event's fields. |
591
634
  | `tag-duplicate-key` | error | Duplicate tag key | Rename one of the tags so every key on the event is unique. |
592
635
  | `translation-name-collision` | warning | Translation name reused for different producers | Use a distinct name per producer to avoid confusion. |
593
636
  | `type-cycle` | error | Cyclic type reference | Break the cycle, or route the self/mutual reference through an array. |
594
637
  | `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. |
638
+ | `unbound-translation` | warning | Externally-fed reaction no seam feeds | Declare the seam whose `to` is this reaction, or give it an in-model `from`. |
639
+ | `undeclared-seam-candidate` | warning | Looks connected across models, no seam declared | Declare the seam, or rename one side so the name match stops looking like a link. |
595
640
  | `view-again-without-earlier` | error | `again` without an earlier declaration | Declare the view plainly the first time it appears. |
596
641
  | `view-from-future-event` | error | Backward timeline (view reads a future event) | Move the source to a later `view X again` instance. |
597
642
  | `view-from-unresolved` | error | Unknown event source | Fix the `from` reference to name an existing event. |
package/README.md CHANGED
@@ -38,6 +38,13 @@ em diff model.em --from HEAD~1 # what this change did to the model
38
38
  em changelog model.em # the model's git history as a business ledger
39
39
  ```
40
40
 
41
+ A system of several models — one per team or sub-department, each in its own directory — gets
42
+ the same treatment across model boundaries: a seam manifest (`system.yaml`) declares which
43
+ model's `public` event feeds which other model's Translation slice, and `em system system.yaml`
44
+ verifies every binding against the models' exports and emits the org-level context map
45
+ ([docs/cli.md](docs/cli.md#em-system-manifest); worked example in
46
+ [examples/multi-model/](examples/multi-model/)).
47
+
41
48
  A model is a list of slices — vertical time steps, read left to right — whose elements land
42
49
  in swimlane rows:
43
50
 
@@ -117,7 +124,7 @@ built this way.
117
124
  | [docs/usage-data.md](docs/usage-data.md) | What usage data em captures, and how to roll it up for a retro |
118
125
  | [docs/architecture.md](docs/architecture.md) | How rendering works; why Graphviz, not PlantUML |
119
126
  | [docs/roadmap.md](docs/roadmap.md) | What's planned |
120
- | [docs/decisions/](docs/decisions/) | Write-ups for open design questions (starts with [MIL-162](docs/decisions/mil-162-teachable-navigator.md), the stakeholder-portal decision) |
127
+ | [docs/decisions/](docs/decisions/) | Write-ups for open design questions ([MIL-162](docs/decisions/mil-162-teachable-navigator.md), the stakeholder-portal decision; [MIL-194](docs/decisions/mil-194-seam-manifest.md), the seam manifest) |
121
128
 
122
129
  ## Development
123
130
 
@@ -4,13 +4,20 @@ export declare function ciWorkflowPath(repoRoot: string): string;
4
4
  export declare function conformWorkflowPath(repoRoot: string): string;
5
5
  export declare function findUnsafeCiInitArg(value: string): string | null;
6
6
  /** The managed block only (no header/`on:`/`jobs:` scaffolding) — what gets written between
7
- * the marker pair, both for a fresh file and to patch an existing marked one in place. */
8
- export declare function ciManagedBody(model: string, testsDir: string): string;
7
+ * the marker pair, both for a fresh file and to patch an existing marked one in place.
8
+ *
9
+ * Every `npx @milehimikey/em` invocation pins the generating em's own exact version
10
+ * (MIL-188): an unpinned line floats to whatever `latest` resolves to on the runner that
11
+ * day, which is the opposite of a preset. Because the pin lives inside the managed body,
12
+ * `--check` from a different em version reports the block as stale — the same
13
+ * upgrade-visibility `em skill check` gets from its version stamp — and a file scaffolded
14
+ * by a pre-pin em shows stale the same way. */
15
+ export declare function ciManagedBody(model: string, testsDir: string, emVersion: string): string;
9
16
  export declare function buildCiWorkflowFile(model: string, testsDir: string, emVersion: string): string;
10
17
  /** The managed block only (no header/`on:`/`permissions:`/`jobs:` scaffolding) — what gets
11
18
  * written between the marker pair, both for a fresh file and to patch an existing marked one
12
19
  * in place. */
13
- export declare function conformManagedBody(model: string): string;
20
+ export declare function conformManagedBody(model: string, emVersion: string): string;
14
21
  export declare function buildConformWorkflowFile(model: string, emVersion: string): string;
15
22
  export type CiFileStatus = {
16
23
  kind: "create";
@@ -45,8 +45,16 @@ export function findUnsafeCiInitArg(value) {
45
45
  }
46
46
  // ---- em-ci.yml (PR gates + push-triggered badge rebuild) ----
47
47
  /** The managed block only (no header/`on:`/`jobs:` scaffolding) — what gets written between
48
- * the marker pair, both for a fresh file and to patch an existing marked one in place. */
49
- export function ciManagedBody(model, testsDir) {
48
+ * the marker pair, both for a fresh file and to patch an existing marked one in place.
49
+ *
50
+ * Every `npx @milehimikey/em` invocation pins the generating em's own exact version
51
+ * (MIL-188): an unpinned line floats to whatever `latest` resolves to on the runner that
52
+ * day, which is the opposite of a preset. Because the pin lives inside the managed body,
53
+ * `--check` from a different em version reports the block as stale — the same
54
+ * upgrade-visibility `em skill check` gets from its version stamp — and a file scaffolded
55
+ * by a pre-pin em shows stale the same way. */
56
+ export function ciManagedBody(model, testsDir, emVersion) {
57
+ const em = `npx @milehimikey/em@${emVersion}`;
50
58
  return ` validate:
51
59
  name: em validate (changed .em files)
52
60
  if: github.event_name == 'pull_request'
@@ -71,8 +79,8 @@ export function ciManagedBody(model, testsDir) {
71
79
  status=0
72
80
  for f in $changed; do
73
81
  echo "::group::em validate $f"
74
- npx @milehimikey/em validate "$f" || status=1
75
- npx @milehimikey/em validate "$f" --list-issues
82
+ ${em} validate "$f" || status=1
83
+ ${em} validate "$f" --list-issues
76
84
  echo "::endgroup::"
77
85
  done
78
86
  exit $status
@@ -87,7 +95,7 @@ export function ciManagedBody(model, testsDir) {
87
95
  with:
88
96
  node-version: 20
89
97
  - name: Check README Slices table is current
90
- run: npx @milehimikey/em slice index "${model}" --check
98
+ run: ${em} slice index "${model}" --check
91
99
 
92
100
  coverage:
93
101
  name: "em coverage --strict (invariant citations)"
@@ -99,7 +107,7 @@ export function ciManagedBody(model, testsDir) {
99
107
  with:
100
108
  node-version: 20
101
109
  - name: Check invariant test coverage
102
- run: npx @milehimikey/em coverage "${model}" --tests "${testsDir}" --strict
110
+ run: ${em} coverage "${model}" --tests "${testsDir}" --strict
103
111
 
104
112
  ledger:
105
113
  name: em ledger (slice doc version/content agreement)
@@ -113,7 +121,7 @@ export function ciManagedBody(model, testsDir) {
113
121
  with:
114
122
  node-version: 20
115
123
  - name: Check slice doc version/content agreement
116
- run: npx @milehimikey/em ledger "${model}" --from "\${{ github.event.pull_request.base.sha }}"
124
+ run: ${em} ledger "${model}" --from "\${{ github.event.pull_request.base.sha }}"
117
125
 
118
126
  skill-check:
119
127
  name: em skill check (vendored skill drift)
@@ -127,7 +135,7 @@ export function ciManagedBody(model, testsDir) {
127
135
  - name: Check vendored skill matches installed em
128
136
  run: |
129
137
  if [ -d .claude/skills/event-modeling ]; then
130
- npx @milehimikey/em skill check
138
+ ${em} skill check
131
139
  else
132
140
  echo "no vendored skill at .claude/skills/event-modeling — skipping (run \`em skill install\` to opt in)"
133
141
  fi
@@ -142,7 +150,7 @@ export function ciManagedBody(model, testsDir) {
142
150
  with:
143
151
  node-version: 20
144
152
  - name: Check glossary consistency across models
145
- run: npx @milehimikey/em glossary $(git ls-files '*.em') --fail-on-conflicts
153
+ run: ${em} glossary $(git ls-files '*.em') --fail-on-conflicts
146
154
 
147
155
  status-badge:
148
156
  name: rebuild status badge (advisory — publish only, never a gate)
@@ -156,7 +164,7 @@ export function ciManagedBody(model, testsDir) {
156
164
  with:
157
165
  node-version: 20
158
166
  - name: Rebuild status badge
159
- run: npx @milehimikey/em status "${model}" --tests "${testsDir}" --badge -o status-badge.svg
167
+ run: ${em} status "${model}" --tests "${testsDir}" --badge -o status-badge.svg
160
168
  - name: Commit badge if changed
161
169
  run: |
162
170
  if git diff --quiet -- status-badge.svg; then
@@ -201,13 +209,13 @@ jobs:
201
209
  // closing marker's leading spaces vanished on a second `em ci init` run).
202
210
  export function buildCiWorkflowFile(model, testsDir, emVersion) {
203
211
  const { start, end } = markerPair(CI_WORKFLOW_MARKER, "hash");
204
- return `${ciWorkflowHeader(model, emVersion)}${start}\n${ciManagedBody(model, testsDir)}\n${end}\n`;
212
+ return `${ciWorkflowHeader(model, emVersion)}${start}\n${ciManagedBody(model, testsDir, emVersion)}\n${end}\n`;
205
213
  }
206
214
  // ---- em-conform.yml (scheduled, advisory-only conformance cadence) ----
207
215
  /** The managed block only (no header/`on:`/`permissions:`/`jobs:` scaffolding) — what gets
208
216
  * written between the marker pair, both for a fresh file and to patch an existing marked one
209
217
  * in place. */
210
- export function conformManagedBody(model) {
218
+ export function conformManagedBody(model, emVersion) {
211
219
  const modelDir = dirname(model) === "." ? "." : dirname(model);
212
220
  return ` conform:
213
221
  runs-on: ubuntu-latest
@@ -222,7 +230,7 @@ export function conformManagedBody(model) {
222
230
 
223
231
  - name: Run conform phase
224
232
  run: |
225
- npm i -g @milehimikey/em@1 @anthropic-ai/claude-code
233
+ npm i -g @milehimikey/em@${emVersion} @anthropic-ai/claude-code
226
234
  em skill install --force
227
235
  claude -p "/event-modeling conform" \\
228
236
  --allowedTools "Bash(em:*),Bash(git:*),Read,Grep,Glob,Write,Edit"
@@ -268,7 +276,7 @@ jobs:
268
276
  }
269
277
  export function buildConformWorkflowFile(model, emVersion) {
270
278
  const { start, end } = markerPair(CONFORM_WORKFLOW_MARKER, "hash");
271
- return `${conformWorkflowHeader(model, emVersion)}${start}\n${conformManagedBody(model)}\n${end}\n`;
279
+ return `${conformWorkflowHeader(model, emVersion)}${start}\n${conformManagedBody(model, emVersion)}\n${end}\n`;
272
280
  }
273
281
  /**
274
282
  * Decide what to do with one generated file: create it if missing, patch the managed block if
@@ -1 +1 @@
1
- {"version":3,"file":"ciInit.js","sourceRoot":"","sources":["../../src/cli/ciInit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ciInit.js","sourceRoot":"","sources":["../../src/cli/ciInit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { SystemManifest } from "../system/manifest.js";
2
+ import { SystemDiagnostic, SystemExportDoc, SystemModelInput } from "../system/verify.js";
3
+ /** The oldest `em export` schema whose document carries what the verifier reads (`model.key`
4
+ * from MIL-193, `model.edges` from MIL-191 — both schema 1.10). */
5
+ export declare const MIN_EXPORT_SCHEMA: {
6
+ major: number;
7
+ minor: number;
8
+ };
9
+ export type LoadSystemResult = {
10
+ ok: true;
11
+ manifest: SystemManifest;
12
+ manifestText: string;
13
+ models: SystemModelInput[];
14
+ } | {
15
+ ok: false;
16
+ diagnostics: SystemDiagnostic[];
17
+ };
18
+ /** Read + parse the manifest at `manifestPath` and load every model it declares. `ok: false`
19
+ * means the system can't be verified at all (unreadable/invalid manifest, or a source that
20
+ * can't be read, parsed, or has compile errors) — the caller refuses, the same way `em export`
21
+ * refuses a model with errors, rather than verifying a partial system. */
22
+ export declare function loadSystem(manifestPath: string): LoadSystemResult;
23
+ type LoadedSource = {
24
+ sourceKind: "em" | "export";
25
+ doc: SystemExportDoc;
26
+ } | {
27
+ error: string;
28
+ };
29
+ /** Shape-check an `em export --json` document: `schemaVersion` >= 1.10 and the `model.key`/
30
+ * `model.slices`/`model.edges` fields present. Deliberately shallow — this is a guard against
31
+ * handing the verifier a file that isn't an export at all (or one from an older em), not a
32
+ * full schema validation; an export em itself wrote is trusted past this point. */
33
+ export declare function readExportDoc(text: string, file: string): LoadedSource;
34
+ export {};
@@ -0,0 +1,129 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // The filesystem half of `em system` (MIL-194): read the manifest, resolve each model's
3
+ // `source` relative to the manifest's directory, and turn every source — a `.em` file compiled
4
+ // in-process, or an `em export --json` document read as-is — into the ONE input shape the
5
+ // verifier (src/system/verify.ts) accepts: an export document. That is how "verification reads
6
+ // export JSON only" stays true while a co-located repo still gets to point at its `.em` files
7
+ // directly: a `.em` source is compiled with the same `compile()` + `buildExportDoc()` `em export`
8
+ // itself runs, never through a second model reader, so the verifier can't tell the two apart.
9
+ //
10
+ // Shared by the CLI action (src/cli.ts) and the MCP `system` tool (src/mcp/server.ts) so the two
11
+ // surfaces load a system identically — the parity requirement. Every failure is a returned
12
+ // diagnostic, never a throw or a process exit: the CLI prints and exits, MCP returns a tool error.
13
+ import { readFileSync } from "node:fs";
14
+ import { dirname, extname, isAbsolute, join } from "node:path";
15
+ import { compile } from "../pipeline.js";
16
+ import { ParseError } from "../parser/parser.js";
17
+ import { hasErrors } from "../model/validate.js";
18
+ import { buildExportDoc } from "../emit/json.js";
19
+ import { makeDiag } from "../model/rules.js";
20
+ import { parseManifest } from "../system/manifest.js";
21
+ /** The oldest `em export` schema whose document carries what the verifier reads (`model.key`
22
+ * from MIL-193, `model.edges` from MIL-191 — both schema 1.10). */
23
+ export const MIN_EXPORT_SCHEMA = { major: 1, minor: 10 };
24
+ /** Read + parse the manifest at `manifestPath` and load every model it declares. `ok: false`
25
+ * means the system can't be verified at all (unreadable/invalid manifest, or a source that
26
+ * can't be read, parsed, or has compile errors) — the caller refuses, the same way `em export`
27
+ * refuses a model with errors, rather than verifying a partial system. */
28
+ export function loadSystem(manifestPath) {
29
+ let manifestText;
30
+ try {
31
+ manifestText = readFileSync(manifestPath, "utf8");
32
+ }
33
+ catch {
34
+ return { ok: false, diagnostics: [{ file: manifestPath, ...makeDiag("system-manifest-invalid", { message: `cannot read ${manifestPath}` }) }] };
35
+ }
36
+ const parsed = parseManifest(manifestText);
37
+ if (!parsed.ok) {
38
+ return { ok: false, diagnostics: parsed.diagnostics.map((d) => ({ file: manifestPath, ...d })) };
39
+ }
40
+ const baseDir = dirname(manifestPath);
41
+ const diagnostics = [];
42
+ const models = [];
43
+ for (const entry of parsed.manifest.models) {
44
+ // Joined, not resolved: diagnostics and `--json` echo this path, and a document a CI job
45
+ // commits must not embed one machine's absolute checkout path — `em export`'s `source.path`
46
+ // keeps the same "as given" posture.
47
+ const file = isAbsolute(entry.source) ? entry.source : join(baseDir, entry.source);
48
+ const loaded = loadSource(file);
49
+ if ("error" in loaded) {
50
+ diagnostics.push({
51
+ file: manifestPath,
52
+ ...makeDiag("system-manifest-invalid", { message: `model "${entry.key}": ${loaded.error}`, line: entry.line }),
53
+ });
54
+ continue;
55
+ }
56
+ models.push({ key: entry.key, source: entry.source, sourceKind: loaded.sourceKind, owner: entry.owner, file, doc: loaded.doc });
57
+ }
58
+ if (diagnostics.length > 0)
59
+ return { ok: false, diagnostics };
60
+ return { ok: true, manifest: parsed.manifest, manifestText, models };
61
+ }
62
+ /** One source path to an export document. `.em` compiles (refusing on parse/validation
63
+ * errors, same gate as `em export`); anything else is read as an `em export --json` document
64
+ * and shape-checked for the fields the verifier needs. */
65
+ function loadSource(file) {
66
+ let text;
67
+ try {
68
+ text = readFileSync(file, "utf8");
69
+ }
70
+ catch {
71
+ return { error: `cannot read ${file}` };
72
+ }
73
+ if (extname(file).toLowerCase() === ".em") {
74
+ try {
75
+ const { model, refs, diagnostics } = compile(text);
76
+ if (hasErrors(diagnostics)) {
77
+ return { error: `${file} has validation errors — run \`em validate ${file}\` and fix them first` };
78
+ }
79
+ // The document's own `model.key` (MIL-193, schema 1.10) is the key the manifest must match —
80
+ // never recomputed here, so `em system` and `em export` can't disagree about it.
81
+ const { doc } = buildExportDoc(model, refs, diagnostics, text, file);
82
+ return { sourceKind: "em", doc };
83
+ }
84
+ catch (e) {
85
+ if (e instanceof ParseError)
86
+ return { error: `parse error in ${file} ${e.message}` };
87
+ throw e;
88
+ }
89
+ }
90
+ return readExportDoc(text, file);
91
+ }
92
+ /** Shape-check an `em export --json` document: `schemaVersion` >= 1.10 and the `model.key`/
93
+ * `model.slices`/`model.edges` fields present. Deliberately shallow — this is a guard against
94
+ * handing the verifier a file that isn't an export at all (or one from an older em), not a
95
+ * full schema validation; an export em itself wrote is trusted past this point. */
96
+ export function readExportDoc(text, file) {
97
+ let raw;
98
+ try {
99
+ raw = JSON.parse(text);
100
+ }
101
+ catch {
102
+ return { error: `${file} is not valid JSON (expected an \`em export --json\` document)` };
103
+ }
104
+ if (typeof raw !== "object" || raw === null || typeof raw.schemaVersion !== "string") {
105
+ return { error: `${file} is not an \`em export --json\` document (no schemaVersion)` };
106
+ }
107
+ const doc = raw;
108
+ const [majorStr, minorStr] = doc.schemaVersion.split(".");
109
+ const major = Number(majorStr);
110
+ const minor = Number(minorStr);
111
+ const tooOld = !Number.isInteger(major) || !Number.isInteger(minor) || major < MIN_EXPORT_SCHEMA.major || (major === MIN_EXPORT_SCHEMA.major && minor < MIN_EXPORT_SCHEMA.minor);
112
+ if (tooOld) {
113
+ return {
114
+ error: `${file} has export schemaVersion "${doc.schemaVersion}" — \`em system\` needs >= ${MIN_EXPORT_SCHEMA.major}.${MIN_EXPORT_SCHEMA.minor} ` +
115
+ `(model.key and model.edges); regenerate it with a current \`em export --json\``,
116
+ };
117
+ }
118
+ const model = doc.model;
119
+ if (typeof model !== "object" || model === null)
120
+ return { error: `${file}: export document has no \`model\`` };
121
+ if (typeof model.key !== "string")
122
+ return { error: `${file}: export document has no \`model.key\` — regenerate it with a current \`em export --json\`` };
123
+ if (!Array.isArray(model.slices))
124
+ return { error: `${file}: export document has no \`model.slices\`` };
125
+ if (!Array.isArray(model.edges))
126
+ return { error: `${file}: export document has no \`model.edges\` — regenerate it with a current \`em export --json\`` };
127
+ return { sourceKind: "export", doc: raw };
128
+ }
129
+ //# sourceMappingURL=systemInputs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemInputs.js","sourceRoot":"","sources":["../../src/cli/systemInputs.ts"],"names":[],"mappings":"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"}