@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,9 +1,21 @@
1
+ import { ElementKind } from "../parser/ast.js";
1
2
  import { Element, NormalizedModel } from "./model.js";
3
+ /** Where an edge came from: inferred from a slice's pattern shape, resolved from an explicit
4
+ * `from "Name"` clause, or declared by an `arrow`. First-wins on a duplicate (from, to) pair
5
+ * in exactly this order — an `arrow` restating an inferred connection is the same line. */
6
+ export type EdgeSource = "pattern" | "from" | "arrow";
2
7
  export interface SemanticEdge {
3
8
  from: string;
4
9
  to: string;
5
- color: string;
10
+ source: EdgeSource;
6
11
  }
12
+ /** The six legal connection types, named by their endpoint kinds. */
13
+ export type ConnectionKind = "ui->command" | "command->event" | "event->view" | "view->ui" | "view->reaction" | "reaction->command";
14
+ /** The legal connection type for an endpoint-kind pair, or undefined when no such connection
15
+ * is legal — the relationship is a pure function of the two kinds, so edges carry no `kind`
16
+ * of their own (validate.ts's illegal-pair rule and query's edge labels both derive from
17
+ * here). */
18
+ export declare function connectionKind(from: ElementKind, to: ElementKind): ConnectionKind | undefined;
7
19
  /** Infer pattern arrows from each slice plus cross-slice `from` sources. */
8
20
  export declare function semanticEdges(model: NormalizedModel): SemanticEdge[];
9
21
  /**
@@ -1,22 +1,48 @@
1
1
  // SPDX-License-Identifier: MIT
2
- // The semantic edges of a model: which arrows exist and their colour. This is
3
- // the single source of truth for the diagram's arrows, decoupled from how they
4
- // are drawn (the renderer turns these into SVG paths over the Graphviz grid).
2
+ // The semantic edges of a model: which connections exist, and where each came from. This is
3
+ // the single source of truth for the graph — the renderer draws exactly these (colouring each
4
+ // by its source element's kind at the call site, render/drawEdges.ts), `em query`'s ModelIndex
5
+ // traverses exactly these (model/queryIndex.ts), and `em export` serializes exactly these as
6
+ // `model.edges` (emit/json.ts, schema 1.10 / MIL-191). One derivation, three consumers: the guards below (the misplaced-ui rule, the
7
+ // same-slice-only event->view rule, the pair dedup) are judgment calls invisible in the data,
8
+ // so a second walk re-deriving them would drift — it did once already (the MIL-162 portal
9
+ // spike re-derived independently).
5
10
  import { AUTOMATION_KINDS } from "../parser/ast.js";
6
11
  import { normalizeName } from "./model.js";
7
- import { edgeColorFor } from "../emit/theme.js";
12
+ /** The legal connection type for an endpoint-kind pair, or undefined when no such connection
13
+ * is legal — the relationship is a pure function of the two kinds, so edges carry no `kind`
14
+ * of their own (validate.ts's illegal-pair rule and query's edge labels both derive from
15
+ * here). */
16
+ export function connectionKind(from, to) {
17
+ if (from === "ui")
18
+ return to === "command" ? "ui->command" : undefined; // State Change
19
+ if (from === "command")
20
+ return to === "event" ? "command->event" : undefined; // State Change
21
+ if (from === "event")
22
+ return to === "view" ? "event->view" : undefined; // State View
23
+ if (from === "view") {
24
+ if (to === "ui")
25
+ return "view->ui"; // State View
26
+ if (AUTOMATION_KINDS.has(to))
27
+ return "view->reaction"; // Automation / Translation
28
+ return undefined;
29
+ }
30
+ if (AUTOMATION_KINDS.has(from))
31
+ return to === "command" ? "reaction->command" : undefined; // reactions always go through a command
32
+ return undefined;
33
+ }
8
34
  /** Infer pattern arrows from each slice plus cross-slice `from` sources. */
9
35
  export function semanticEdges(model) {
10
36
  const edges = [];
11
37
  const seen = new Set();
12
- const add = (from, to, kind) => {
38
+ const add = (from, to, source) => {
13
39
  if (from === to)
14
40
  return;
15
41
  const key = `${from}>${to}`;
16
42
  if (seen.has(key))
17
43
  return;
18
44
  seen.add(key);
19
- edges.push({ from, to, color: edgeColorFor(kind) });
45
+ edges.push({ from, to, source });
20
46
  };
21
47
  for (const slice of model.slices) {
22
48
  const uis = slice.elements.filter((e) => e.kind === "ui");
@@ -31,25 +57,25 @@ export function semanticEdges(model) {
31
57
  if (command) {
32
58
  if (!auto)
33
59
  for (const ui of uis)
34
- add(ui.id, command.id, "ui");
60
+ add(ui.id, command.id, "pattern");
35
61
  for (const ev of events)
36
- add(command.id, ev.id, "command");
62
+ add(command.id, ev.id, "pattern");
37
63
  }
38
64
  // Automation/translation: it triggers the command in this same slice — the
39
65
  // reaction is to a command what a `ui` is in the State Change pattern. If it
40
66
  // also reads a read model that happens to share this slice, wire that too;
41
67
  // the far more common cross-slice case is handled by the `from` loop below.
42
68
  if (auto && command)
43
- add(auto.id, command.id, auto.kind);
69
+ add(auto.id, command.id, "pattern");
44
70
  if (auto && view)
45
- add(view.id, auto.id, "view");
71
+ add(view.id, auto.id, "pattern");
46
72
  // Output pattern: view -> UI (read model feeds the screen)
47
73
  if (view) {
48
74
  for (const ui of uis)
49
- add(view.id, ui.id, "view");
75
+ add(view.id, ui.id, "pattern");
50
76
  if ((view.from ?? []).length === 0) {
51
77
  for (const ev of events)
52
- add(ev.id, view.id, "event");
78
+ add(ev.id, view.id, "pattern");
53
79
  }
54
80
  }
55
81
  }
@@ -60,7 +86,7 @@ export function semanticEdges(model) {
60
86
  for (const name of el.from ?? []) {
61
87
  const src = resolveFromSource(model, el, name);
62
88
  if (src)
63
- add(src.id, el.id, src.kind);
89
+ add(src.id, el.id, "from");
64
90
  }
65
91
  }
66
92
  // Note: instances of the same logical read model (`view X again`) are deliberately NOT
@@ -69,11 +95,13 @@ export function semanticEdges(model) {
69
95
  // inbound event arrows are what show how the view changes over time. A view->view arrow
70
96
  // would be a modelling error — and, since commands and read models share the API lane,
71
97
  // it also renders as a flat line through any command box between the two instances,
72
- // reading as an illegal command->read-model connection.
98
+ // reading as an illegal command->read-model connection. (Traversal that needs to follow a
99
+ // read model across its instances — `em query`'s closures — does so via `logicalId`, as a
100
+ // query-engine rule, not as an edge.)
73
101
  // Explicit arrows from the DSL.
74
102
  for (const a of model.arrows) {
75
103
  if (a.fromId && a.toId)
76
- add(a.fromId, a.toId, model.byId.get(a.fromId)?.kind);
104
+ add(a.fromId, a.toId, "arrow");
77
105
  }
78
106
  return edges;
79
107
  }
@@ -1 +1 @@
1
- {"version":3,"file":"edges.js","sourceRoot":"","sources":["../../src/model/edges.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,8EAA8E;AAC9E,+EAA+E;AAC/E,8EAA8E;AAE9E,OAAO,EAAE,gBAAgB,EAAe,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAA4B,aAAa,EAAE,MAAM,YAAY,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAQhD,4EAA4E;AAC5E,MAAM,UAAU,aAAa,CAAC,KAAsB;IAClD,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAU,EAAE,IAA6B,EAAE,EAAE;QACtE,IAAI,IAAI,KAAK,EAAE;YAAE,OAAO;QACxB,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAEtE,sFAAsF;QACtF,yFAAyF;QACzF,yFAAyF;QACzF,2FAA2F;QAC3F,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,IAAI;gBAAE,KAAK,MAAM,EAAE,IAAI,GAAG;oBAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAC9D,KAAK,MAAM,EAAE,IAAI,MAAM;gBAAE,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAC7D,CAAC;QAED,2EAA2E;QAC3E,6EAA6E;QAC7E,2EAA2E;QAC3E,4EAA4E;QAC5E,IAAI,IAAI,IAAI,OAAO;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,IAAI,IAAI,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAEhD,2DAA2D;QAC3D,IAAI,IAAI,EAAE,CAAC;YACT,KAAK,MAAM,EAAE,IAAI,GAAG;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YAClD,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnC,KAAK,MAAM,EAAE,IAAI,MAAM;oBAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,mDAAmD;IACnD,yDAAyD;IACzD,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAChC,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;YACjC,MAAM,GAAG,GAAG,iBAAiB,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;YAC/C,IAAI,GAAG;gBAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,uFAAuF;IACvF,sFAAsF;IACtF,uFAAuF;IACvF,wFAAwF;IACxF,uFAAuF;IACvF,oFAAoF;IACpF,wDAAwD;IAExD,gCAAgC;IAChC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAC7B,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI;YAAE,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;IAChF,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAsB,EAAE,EAAW,EAAE,IAAY;IACjF,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;IACrD,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,OAAO,EAAE,CAAC,IAAI,KAAK,MAAM;QACvB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC;QACrD,CAAC,CAAC,qBAAqB,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACzG,CAAC;AAED,+FAA+F;AAC/F,SAAS,qBAAqB,CAAC,MAAiB,EAAE,UAAkB;IAClE,OAAO,MAAM;SACV,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,UAAU,IAAI,UAAU,CAAC;SAC9D,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC"}
1
+ {"version":3,"file":"edges.js","sourceRoot":"","sources":["../../src/model/edges.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,4FAA4F;AAC5F,8FAA8F;AAC9F,+FAA+F;AAC/F,6FAA6F;AAC7F,qIAAqI;AACrI,8FAA8F;AAC9F,0FAA0F;AAC1F,mCAAmC;AAEnC,OAAO,EAAE,gBAAgB,EAAe,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAA4B,aAAa,EAAE,MAAM,YAAY,CAAC;AAsBrE;;;aAGa;AACb,MAAM,UAAU,cAAc,CAAC,IAAiB,EAAE,EAAe;IAC/D,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,eAAe;IACvF,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,eAAe;IAC7F,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,aAAa;IACrF,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,IAAI,EAAE,KAAK,IAAI;YAAE,OAAO,UAAU,CAAC,CAAC,aAAa;QACjD,IAAI,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,gBAAgB,CAAC,CAAC,2BAA2B;QAClF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,wCAAwC;IACnI,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,aAAa,CAAC,KAAsB;IAClD,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAU,EAAE,MAAkB,EAAE,EAAE;QAC3D,IAAI,IAAI,KAAK,EAAE;YAAE,OAAO;QACxB,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAEtE,sFAAsF;QACtF,yFAAyF;QACzF,yFAAyF;QACzF,2FAA2F;QAC3F,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,IAAI;gBAAE,KAAK,MAAM,EAAE,IAAI,GAAG;oBAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;YACnE,KAAK,MAAM,EAAE,IAAI,MAAM;gBAAE,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAC7D,CAAC;QAED,2EAA2E;QAC3E,6EAA6E;QAC7E,2EAA2E;QAC3E,4EAA4E;QAC5E,IAAI,IAAI,IAAI,OAAO;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QACzD,IAAI,IAAI,IAAI,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAEnD,2DAA2D;QAC3D,IAAI,IAAI,EAAE,CAAC;YACT,KAAK,MAAM,EAAE,IAAI,GAAG;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;YACrD,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnC,KAAK,MAAM,EAAE,IAAI,MAAM;oBAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,mDAAmD;IACnD,yDAAyD;IACzD,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAChC,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;YACjC,MAAM,GAAG,GAAG,iBAAiB,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;YAC/C,IAAI,GAAG;gBAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,uFAAuF;IACvF,sFAAsF;IACtF,uFAAuF;IACvF,wFAAwF;IACxF,uFAAuF;IACvF,oFAAoF;IACpF,0FAA0F;IAC1F,0FAA0F;IAC1F,sCAAsC;IAEtC,gCAAgC;IAChC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAC7B,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI;YAAE,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAsB,EAAE,EAAW,EAAE,IAAY;IACjF,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;IACrD,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,OAAO,EAAE,CAAC,IAAI,KAAK,MAAM;QACvB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC;QACrD,CAAC,CAAC,qBAAqB,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;AACzG,CAAC;AAED,+FAA+F;AAC/F,SAAS,qBAAqB,CAAC,MAAiB,EAAE,UAAkB;IAClE,OAAO,MAAM;SACV,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,UAAU,IAAI,UAAU,CAAC;SAC9D,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC"}
@@ -89,6 +89,8 @@ export interface ResolvedArrow {
89
89
  }
90
90
  export interface NormalizedModel {
91
91
  name: string;
92
+ /** Whether `name` came from a `model "Name"` declaration (see `ModelNode.nameDeclared`). */
93
+ nameDeclared: boolean;
92
94
  personas: string[];
93
95
  contexts: string[];
94
96
  hasAutomation: boolean;
@@ -136,6 +136,7 @@ export function normalize(ast) {
136
136
  }));
137
137
  return {
138
138
  name: ast.name,
139
+ nameDeclared: ast.nameDeclared,
139
140
  personas,
140
141
  contexts,
141
142
  hasAutomation,
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/model/model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/model/model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { NormalizedModel } from "./model.js";
2
+ import type { Diagnostic } from "./validate.js";
3
+ /** The model-key shape: a kebab slug (`kebabSlug()`'s output) with an optional `~n` collision
4
+ * suffix. Anchored; the single definition `parseQualifiedRef`/`isQualifiedRef` split on. */
5
+ export declare const MODEL_KEY_RE: RegExp;
6
+ /**
7
+ * A model's own key: `kebabSlug(model.name)` when the name was declared (`model "Name"`);
8
+ * otherwise the kebab-slugged basename of `fallbackFile` (extension stripped) when one is
9
+ * given; otherwise the slug of the parser's default title. Never deduped — collisions are a
10
+ * multi-model concern, see `computeModelKeys()`.
11
+ */
12
+ export declare function computeModelKey(model: NormalizedModel, fallbackFile?: string): string;
13
+ export interface ModelKeysResult {
14
+ /** One key per entry, same order/index as the input. */
15
+ keys: string[];
16
+ /** `duplicate-model-key` warnings, one per entry that had to take a `~n` suffix. */
17
+ diagnostics: Diagnostic[];
18
+ }
19
+ /**
20
+ * Keys for every model of one multi-model invocation: `computeModelKey()` each, then dedupe
21
+ * with `~2`, `~3`, … in input order (the first entry to claim a key keeps it bare) and warn
22
+ * on every collision. Order-stable: a consumer that always lists its files the same way gets
23
+ * the same keys back.
24
+ */
25
+ export declare function computeModelKeys(entries: Array<{
26
+ model: NormalizedModel;
27
+ file: string;
28
+ }>): ModelKeysResult;
29
+ /** `<modelKey>:<ref>` — the one place the qualifier separator is spelled. `ref` is an
30
+ * element ref, a bare slice key, or a type ref, unchanged. */
31
+ export declare function formatQualifiedRef(modelKey: string, ref: string): string;
32
+ export interface ParsedQualifiedRef {
33
+ /** The qualifier, or `null` when `input` carried none (or its prefix isn't a model-key shape). */
34
+ modelKey: string | null;
35
+ /** The model-unqualified remainder — `input` itself when unqualified. */
36
+ ref: string;
37
+ }
38
+ /**
39
+ * Split `<modelKey>:<ref>` on the FIRST colon, but only when the prefix has the model-key
40
+ * shape (`MODEL_KEY_RE`); anything else is returned intact as an unqualified ref — a display
41
+ * name ("Order: Paid") may legitimately contain a colon, and callers resolving names must not
42
+ * lose it. Shape-only: whether the key names a model this caller actually has is its own
43
+ * question (`em query`'s `resolveElement` checks that and reports an unknown prefix).
44
+ */
45
+ export declare function parseQualifiedRef(input: string): ParsedQualifiedRef;
46
+ /** True when `parseQualifiedRef(input)` would find a model-key-shaped qualifier. */
47
+ export declare function isQualifiedRef(input: string): boolean;
@@ -0,0 +1,100 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Model-qualified addressing (MIL-193): the ONE grammar for naming a slice, element, or type
3
+ // that lives in another model. Export refs (`<sliceKey>/<kind>.<slug>`, `computeRefs()`) are
4
+ // deliberately model-unqualified and stay valid everywhere they are today; any artifact that
5
+ // crosses a model boundary — `em query`'s multi-model output, `em export`'s own `model.key`,
6
+ // MIL-194's seam manifest, em-portal deep links, em-tracker-bridge — prefixes them with a
7
+ // `modelKey` using exactly this module, so the "one addressing scheme" constraint (MIL-162)
8
+ // can't die by each consumer inventing its own qualifier.
9
+ //
10
+ // <modelKey>:<sliceKey>/<kind>.<slug> element
11
+ // <modelKey>:<sliceKey> slice
12
+ // <modelKey>:types/<slug> type
13
+ //
14
+ // `modelKey` is the kebab-slug of the DECLARED model name (`model "Name"`) — the same
15
+ // `kebabSlug()` every other export identity derives from — never a path: it survives file
16
+ // moves and renames, and a single-model `em export` can carry it with no system context. A
17
+ // file that declares no name falls back to its kebab-slugged basename (extension stripped);
18
+ // two models in one multi-model invocation that mint the same key are deduped `~2`, `~3`, …
19
+ // in file-list order (first wins the bare key) with a `duplicate-model-key` warning naming
20
+ // both files — the same posture as `computeRefs()`'s `duplicate-slice-name`.
21
+ //
22
+ // Lives in model/ for the same layering reason as refs.ts: a pure function of NormalizedModel
23
+ // (no fs, no JSON shape), consumed by emit/, query/, and — via the package's `./refs` subpath
24
+ // export — by external packages, which must never grow a second parser for this grammar.
25
+ import { pushDiag } from "./rules.js";
26
+ import { dedupe, kebabSlug } from "../util/slug.js";
27
+ /** The model-key shape: a kebab slug (`kebabSlug()`'s output) with an optional `~n` collision
28
+ * suffix. Anchored; the single definition `parseQualifiedRef`/`isQualifiedRef` split on. */
29
+ export const MODEL_KEY_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*(?:~\d+)?$/;
30
+ /** Strip a path to its kebab-slugged basename, extension removed — the no-declared-name
31
+ * fallback. Pure string work (no fs, and both `/` and `\` separators) so the module stays
32
+ * usable from a browser bundle. */
33
+ function fileBasenameKey(file) {
34
+ const base = file.split(/[\\/]/).pop() ?? file;
35
+ const dot = base.lastIndexOf(".");
36
+ return kebabSlug(dot > 0 ? base.slice(0, dot) : base);
37
+ }
38
+ /**
39
+ * A model's own key: `kebabSlug(model.name)` when the name was declared (`model "Name"`);
40
+ * otherwise the kebab-slugged basename of `fallbackFile` (extension stripped) when one is
41
+ * given; otherwise the slug of the parser's default title. Never deduped — collisions are a
42
+ * multi-model concern, see `computeModelKeys()`.
43
+ */
44
+ export function computeModelKey(model, fallbackFile) {
45
+ if (!model.nameDeclared && fallbackFile)
46
+ return fileBasenameKey(fallbackFile);
47
+ return kebabSlug(model.name);
48
+ }
49
+ /**
50
+ * Keys for every model of one multi-model invocation: `computeModelKey()` each, then dedupe
51
+ * with `~2`, `~3`, … in input order (the first entry to claim a key keeps it bare) and warn
52
+ * on every collision. Order-stable: a consumer that always lists its files the same way gets
53
+ * the same keys back.
54
+ */
55
+ export function computeModelKeys(entries) {
56
+ const diagnostics = [];
57
+ const used = new Set();
58
+ const firstFileByKey = new Map();
59
+ const keys = entries.map(({ model, file }) => {
60
+ const base = computeModelKey(model, file);
61
+ const key = dedupe(base, used, "~");
62
+ if (key === base) {
63
+ firstFileByKey.set(base, file);
64
+ }
65
+ else {
66
+ pushDiag(diagnostics, "duplicate-model-key", {
67
+ message: `duplicate model key "${base}" (${firstFileByKey.get(base)} and ${file} both derive it); give each model a unique \`model "Name"\` so cross-model refs stay stable — ${file} is addressed as "${key}" in this run`,
68
+ refs: [key, base],
69
+ });
70
+ }
71
+ return key;
72
+ });
73
+ return { keys, diagnostics };
74
+ }
75
+ /** `<modelKey>:<ref>` — the one place the qualifier separator is spelled. `ref` is an
76
+ * element ref, a bare slice key, or a type ref, unchanged. */
77
+ export function formatQualifiedRef(modelKey, ref) {
78
+ return `${modelKey}:${ref}`;
79
+ }
80
+ /**
81
+ * Split `<modelKey>:<ref>` on the FIRST colon, but only when the prefix has the model-key
82
+ * shape (`MODEL_KEY_RE`); anything else is returned intact as an unqualified ref — a display
83
+ * name ("Order: Paid") may legitimately contain a colon, and callers resolving names must not
84
+ * lose it. Shape-only: whether the key names a model this caller actually has is its own
85
+ * question (`em query`'s `resolveElement` checks that and reports an unknown prefix).
86
+ */
87
+ export function parseQualifiedRef(input) {
88
+ const colon = input.indexOf(":");
89
+ if (colon <= 0)
90
+ return { modelKey: null, ref: input };
91
+ const prefix = input.slice(0, colon);
92
+ if (!MODEL_KEY_RE.test(prefix))
93
+ return { modelKey: null, ref: input };
94
+ return { modelKey: prefix, ref: input.slice(colon + 1) };
95
+ }
96
+ /** True when `parseQualifiedRef(input)` would find a model-key-shaped qualifier. */
97
+ export function isQualifiedRef(input) {
98
+ return parseQualifiedRef(input).modelKey !== null;
99
+ }
100
+ //# sourceMappingURL=qualifiedRef.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qualifiedRef.js","sourceRoot":"","sources":["../../src/model/qualifiedRef.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { Element, NormalizedModel } from "./model.js";
2
+ import { RefsResult } from "./refs.js";
3
+ import { ConnectionKind } from "./edges.js";
4
+ import { SliceQueryDoc } from "./sliceDocIndex.js";
5
+ /** What a query result arrived by: one of the six legal connections, `view-instance` (the
6
+ * zero-cost hop between two timeline instances of one read model — not an edge), or `other`
7
+ * for an edge whose endpoint kinds form no legal connection (only reachable through a `from`
8
+ * clause resolving to a non-event; an explicit `arrow` between such a pair is a compile error
9
+ * query refuses on). */
10
+ export type QueryEdgeKind = ConnectionKind | "view-instance" | "other";
11
+ export interface IndexEdge {
12
+ ref: string;
13
+ kind: QueryEdgeKind;
14
+ }
15
+ export interface SliceIndexFact {
16
+ key: string;
17
+ name: string;
18
+ index: number;
19
+ line: number;
20
+ doc: SliceQueryDoc;
21
+ }
22
+ export interface InvariantIndexEntry {
23
+ id: string;
24
+ sliceKey: string;
25
+ }
26
+ export interface ModelIndex {
27
+ model: NormalizedModel;
28
+ refs: RefsResult;
29
+ baseDir: string;
30
+ /** Export ref -> Element, in `model.elements` order (== document order: slice, then
31
+ * within-slice declaration order) — the same order every query verb sorts its results by,
32
+ * for free, via Map iteration order. */
33
+ byRef: Map<string, Element>;
34
+ out: Map<string, IndexEdge[]>;
35
+ in: Map<string, IndexEdge[]>;
36
+ /** Ref of a repeated read model instance -> refs of its OTHER instances (same `logicalId`),
37
+ * in document order. Only populated for views declared more than once; a single-instance
38
+ * element has no entry. */
39
+ instances: Map<string, string[]>;
40
+ /** Slice export key -> its doc-join facts, in `model.slices` order. */
41
+ sliceFacts: Map<string, SliceIndexFact>;
42
+ /** INV-* id -> the slice that declares it. A doc is scanned once per slice it resolves for
43
+ * (its own canonical slice, plus every slice it ratifies via MIL-121 `covers:`), so the
44
+ * CANONICAL binding (`doc.path === slices/<thisSliceKey>.md`) always owns the id, whatever
45
+ * the slices' document order; a cross-bound slice claims an id only when no canonical slice
46
+ * for that doc exists in the model. Two canonical docs declaring the same id is first-wins
47
+ * in slice order — a bug in the model, not something query silently resolves further. */
48
+ invariants: Map<string, InvariantIndexEntry>;
49
+ }
50
+ export declare function buildModelIndex(model: NormalizedModel, refs: RefsResult, baseDir: string): ModelIndex;
@@ -0,0 +1,111 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // `ModelIndex` (MIL-168): the one graph index `em query`'s verbs all reduce to a map hit or a
3
+ // BFS over — built once per compiled model (see ../query/pipeline.ts's sub-pipeline) and shared
4
+ // by the CLI and the MCP `query` tool (both call `buildModelIndex()`, never a second traversal
5
+ // implementation — MCP parity, docs/mcp.md).
6
+ //
7
+ // - `byRef`: the inverse of `RefsResult.refById` — the compiled model has never had this
8
+ // before (`NormalizedModel.byName` is the only lookup table, keyed by display name, not ref).
9
+ // - `out`/`in`: adjacency over `semanticEdges()` (model/edges.ts — the SAME edge list the
10
+ // renderer draws, so query and diagram can't disagree on what connects), keyed by export ref
11
+ // so query never has to re-resolve an internal Element.id. Each edge is labeled with its
12
+ // connection kind, a pure function of the endpoint kinds (`connectionKind()`).
13
+ // - `instances`: repeated read-model instances (`view X again`) grouped by `logicalId` — never
14
+ // edges (see edges.ts's note on why instances don't connect), but the thing closures/paths
15
+ // follow so "what's downstream of this event" reaches every later timeline instance of a
16
+ // read model it feeds, not just the first (MIL-191's design note: a query-engine rule).
17
+ // - `sliceFacts`: the doc join done once via `sliceDocIndex.ts`'s single `readdirSync`.
18
+ // - `invariants`: INV-* id -> declaring slice, extracted from EVERY found slice doc's body
19
+ // regardless of its status — reuses `cli/coverage.ts`'s extraction (never re-derives the
20
+ // ownership-heading / structural-line rules a second time), but NOT coverage's in-scope
21
+ // status gate: that gate decides which invariants must be cited by tests, whereas a lookup
22
+ // ("which slice declares INV-X?") has to find a draft doc's invariant too, and reports the
23
+ // doc's status alongside it. Test citations are NOT precomputed here (a query run only ever
24
+ // asks about one ID at a time — see `em query invariant`) — the CLI/MCP layer calls
25
+ // `scanTestCitations()` (also coverage.ts) directly when `--tests` is given.
26
+ import { semanticEdges, connectionKind } from "./edges.js";
27
+ import { loadSliceDocsOnce, joinSliceDocFast } from "./sliceDocIndex.js";
28
+ import { extractInvariantIds } from "../cli/coverage.js";
29
+ function pushEdge(map, key, edge) {
30
+ const bucket = map.get(key);
31
+ if (bucket)
32
+ bucket.push(edge);
33
+ else
34
+ map.set(key, [edge]);
35
+ }
36
+ export function buildModelIndex(model, refs, baseDir) {
37
+ const byRef = new Map();
38
+ for (const el of model.elements) {
39
+ const ref = refs.refById.get(el.id);
40
+ if (ref)
41
+ byRef.set(ref, el);
42
+ }
43
+ const out = new Map();
44
+ const inMap = new Map();
45
+ for (const e of semanticEdges(model)) {
46
+ const fromRef = refs.refById.get(e.from);
47
+ const toRef = refs.refById.get(e.to);
48
+ const fromEl = model.byId.get(e.from);
49
+ const toEl = model.byId.get(e.to);
50
+ if (!fromRef || !toRef || !fromEl || !toEl)
51
+ continue;
52
+ const kind = connectionKind(fromEl.kind, toEl.kind) ?? "other";
53
+ pushEdge(out, fromRef, { ref: toRef, kind });
54
+ pushEdge(inMap, toRef, { ref: fromRef, kind });
55
+ }
56
+ const byLogical = new Map();
57
+ for (const el of model.elements) {
58
+ if (el.kind !== "view")
59
+ continue;
60
+ const ref = refs.refById.get(el.id);
61
+ if (!ref)
62
+ continue;
63
+ const bucket = byLogical.get(el.logicalId);
64
+ if (bucket)
65
+ bucket.push(ref);
66
+ else
67
+ byLogical.set(el.logicalId, [ref]);
68
+ }
69
+ const instances = new Map();
70
+ for (const group of byLogical.values()) {
71
+ if (group.length < 2)
72
+ continue;
73
+ for (const ref of group)
74
+ instances.set(ref, group.filter((r) => r !== ref));
75
+ }
76
+ const docsByKey = loadSliceDocsOnce(baseDir);
77
+ const sliceFacts = new Map();
78
+ model.slices.forEach((slice, i) => {
79
+ const key = refs.sliceKeys[i];
80
+ const doc = joinSliceDocFast(slice, key, docsByKey);
81
+ sliceFacts.set(key, { key, name: slice.name, index: i, line: slice.line, doc });
82
+ });
83
+ // Two passes, canonical bindings first, so a doc's own slice owns its invariants no matter
84
+ // where a slice it also `covers:` sits in document order (see the `invariants` field doc).
85
+ // A doc that resolves for several slices (its own plus every one it `covers:`) is scanned
86
+ // once, keyed by path — the ids are a property of the doc, not of the slice asking.
87
+ const invariants = new Map();
88
+ const idsByDocPath = new Map();
89
+ const idsOf = (doc) => {
90
+ let ids = idsByDocPath.get(doc.path);
91
+ if (!ids) {
92
+ ids = extractInvariantIds(doc.body);
93
+ idsByDocPath.set(doc.path, ids);
94
+ }
95
+ return ids;
96
+ };
97
+ const claim = (canonical) => {
98
+ for (const { key, doc } of sliceFacts.values()) {
99
+ if (doc.body === null || (doc.path === `slices/${key}.md`) !== canonical)
100
+ continue;
101
+ for (const id of idsOf(doc)) {
102
+ if (!invariants.has(id))
103
+ invariants.set(id, { id, sliceKey: key });
104
+ }
105
+ }
106
+ };
107
+ claim(true);
108
+ claim(false);
109
+ return { model, refs, baseDir, byRef, out, in: inMap, instances, sliceFacts, invariants };
110
+ }
111
+ //# sourceMappingURL=queryIndex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryIndex.js","sourceRoot":"","sources":["../../src/model/queryIndex.ts"],"names":[],"mappings":"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"}
@@ -323,12 +323,81 @@ export declare const RULES: {
323
323
  readonly fix: "Rename the type so its export ref is unique.";
324
324
  readonly usageCategory: "duplicate type ref";
325
325
  };
326
+ readonly "duplicate-model-key": {
327
+ readonly severity: "warning";
328
+ readonly title: "Duplicate model key";
329
+ readonly fix: "Give each model a unique `model \"Name\"` so its key (and every cross-model ref) is stable.";
330
+ readonly usageCategory: "duplicate model key";
331
+ };
326
332
  readonly "cross-model-slice-doc-collision": {
327
333
  readonly severity: "warning";
328
334
  readonly title: "Colliding slice doc path across models";
329
335
  readonly fix: "Give each model its own directory (see docs/cli.md, \"Multi-model projects\").";
330
336
  readonly usageCategory: "colliding slice doc path across models";
331
337
  };
338
+ readonly "system-manifest-invalid": {
339
+ readonly severity: "error";
340
+ readonly title: "Seam manifest invalid";
341
+ readonly fix: "Fix the manifest: required keys, `systemSchemaVersion: \"1.0\"`, a readable `source` per model, and only declared model keys in seam refs.";
342
+ readonly usageCategory: "seam manifest invalid";
343
+ readonly docAnchor: "seam-manifest";
344
+ };
345
+ readonly "system-model-key-mismatch": {
346
+ readonly severity: "error";
347
+ readonly title: "Manifest model key differs from the export's `model.key`";
348
+ readonly fix: "Rename the manifest's `models:` key to the computed key the message prints.";
349
+ readonly usageCategory: "seam manifest model key mismatch";
350
+ readonly docAnchor: "seam-manifest";
351
+ };
352
+ readonly "seam-endpoint-unresolved": {
353
+ readonly severity: "error";
354
+ readonly title: "Seam endpoint does not resolve";
355
+ readonly fix: "Fix the ref to an element the named model actually exports (`em export` lists every ref), or re-declare the seam after a rename.";
356
+ readonly usageCategory: "seam endpoint unresolved";
357
+ readonly docAnchor: "seam-manifest";
358
+ };
359
+ readonly "seam-source-not-public": {
360
+ readonly severity: "error";
361
+ readonly title: "Seam source is not `public`";
362
+ readonly fix: "Mark the event/view `public` in its model, or point the seam at the element that is.";
363
+ readonly usageCategory: "seam source not public";
364
+ readonly docAnchor: "seam-manifest";
365
+ };
366
+ readonly "seam-consumer-not-reaction": {
367
+ readonly severity: "error";
368
+ readonly title: "Seam consumer is not a reaction";
369
+ readonly fix: "Point `to` at a translation/automation element (or a slice containing exactly one).";
370
+ readonly usageCategory: "seam consumer not a reaction";
371
+ readonly docAnchor: "seam-manifest";
372
+ };
373
+ readonly "seam-duplicate": {
374
+ readonly severity: "warning";
375
+ readonly title: "Duplicate seam";
376
+ readonly fix: "Remove the repeated `from`/`to` pair.";
377
+ readonly usageCategory: "duplicate seam";
378
+ readonly docAnchor: "seam-manifest";
379
+ };
380
+ readonly "dangling-public-event": {
381
+ readonly severity: "warning";
382
+ readonly title: "Public event/view no seam consumes";
383
+ readonly fix: "Declare the seam that reads it, or drop `public` if nothing outside the model does.";
384
+ readonly usageCategory: "public event not consumed by any seam";
385
+ readonly docAnchor: "seam-manifest";
386
+ };
387
+ readonly "unbound-translation": {
388
+ readonly severity: "warning";
389
+ readonly title: "Externally-fed reaction no seam feeds";
390
+ readonly fix: "Declare the seam whose `to` is this reaction, or give it an in-model `from`.";
391
+ readonly usageCategory: "externally-fed reaction not bound by any seam";
392
+ readonly docAnchor: "seam-manifest";
393
+ };
394
+ readonly "undeclared-seam-candidate": {
395
+ readonly severity: "warning";
396
+ readonly title: "Looks connected across models, no seam declared";
397
+ readonly fix: "Declare the seam, or rename one side so the name match stops looking like a link.";
398
+ readonly usageCategory: "undeclared seam candidate";
399
+ readonly docAnchor: "seam-manifest";
400
+ };
332
401
  readonly "slice-ready-unknown-slice": {
333
402
  readonly severity: "error";
334
403
  readonly title: "Unknown --slice-ready key";