@milehimikey/em 1.9.1 → 1.11.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 (125) hide show
  1. package/.claude/skills/event-modeling/SKILL.md +1 -1
  2. package/.claude/skills/event-modeling-conform/SKILL.md +5 -1
  3. package/.claude/skills/event-modeling-design/SKILL.md +31 -12
  4. package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
  5. package/.claude/skills/event-modeling-implement/SKILL.md +14 -3
  6. package/.claude/skills/event-modeling-implement/reference/implement.md +73 -6
  7. package/.claude/skills/event-modeling-review/SKILL.md +14 -3
  8. package/.claude/skills/event-modeling-shared/reference/em-dsl.md +110 -11
  9. package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +4 -1
  10. package/.claude/skills/event-modeling-shared/templates/constitution.md +111 -0
  11. package/.claude/skills/event-modeling-shared/templates/model-readme.md +2 -2
  12. package/.claude/skills/event-modeling-shared/templates/slice.md +4 -0
  13. package/README.md +8 -1
  14. package/dist/catalog/docJoin.d.ts +8 -0
  15. package/dist/catalog/docJoin.js +4 -0
  16. package/dist/catalog/docJoin.js.map +1 -1
  17. package/dist/catalog/sliceDoc.d.ts +8 -0
  18. package/dist/catalog/sliceDoc.js +2 -0
  19. package/dist/catalog/sliceDoc.js.map +1 -1
  20. package/dist/cli/ciInit.d.ts +10 -3
  21. package/dist/cli/ciInit.js +22 -14
  22. package/dist/cli/ciInit.js.map +1 -1
  23. package/dist/cli/ledgerCheck.d.ts +72 -0
  24. package/dist/cli/ledgerCheck.js +122 -1
  25. package/dist/cli/ledgerCheck.js.map +1 -1
  26. package/dist/cli/ratify.d.ts +37 -5
  27. package/dist/cli/ratify.js +106 -9
  28. package/dist/cli/ratify.js.map +1 -1
  29. package/dist/cli/reratify.js +14 -5
  30. package/dist/cli/reratify.js.map +1 -1
  31. package/dist/cli/review.d.ts +38 -0
  32. package/dist/cli/review.js +160 -0
  33. package/dist/cli/review.js.map +1 -0
  34. package/dist/cli/sliceIndex.d.ts +3 -0
  35. package/dist/cli/sliceIndex.js +5 -4
  36. package/dist/cli/sliceIndex.js.map +1 -1
  37. package/dist/cli/stateFile.d.ts +10 -0
  38. package/dist/cli/stateFile.js +14 -0
  39. package/dist/cli/stateFile.js.map +1 -1
  40. package/dist/cli/status.d.ts +44 -3
  41. package/dist/cli/status.js +75 -18
  42. package/dist/cli/status.js.map +1 -1
  43. package/dist/cli/systemInputs.d.ts +34 -0
  44. package/dist/cli/systemInputs.js +129 -0
  45. package/dist/cli/systemInputs.js.map +1 -0
  46. package/dist/cli.js +362 -23
  47. package/dist/cli.js.map +1 -1
  48. package/dist/emit/freshnessJson.d.ts +1 -1
  49. package/dist/emit/freshnessJson.js +5 -1
  50. package/dist/emit/freshnessJson.js.map +1 -1
  51. package/dist/emit/json.d.ts +37 -1
  52. package/dist/emit/json.js +67 -1
  53. package/dist/emit/json.js.map +1 -1
  54. package/dist/emit/ledgerJson.d.ts +1 -1
  55. package/dist/emit/ledgerJson.js +6 -1
  56. package/dist/emit/ledgerJson.js.map +1 -1
  57. package/dist/emit/queryJson.d.ts +6 -0
  58. package/dist/emit/queryJson.js +33 -0
  59. package/dist/emit/queryJson.js.map +1 -0
  60. package/dist/emit/statusJson.d.ts +1 -1
  61. package/dist/emit/statusJson.js +5 -1
  62. package/dist/emit/statusJson.js.map +1 -1
  63. package/dist/emit/systemJson.d.ts +8 -0
  64. package/dist/emit/systemJson.js +38 -0
  65. package/dist/emit/systemJson.js.map +1 -0
  66. package/dist/mcp/server.d.ts +1 -1
  67. package/dist/mcp/server.js +195 -9
  68. package/dist/mcp/server.js.map +1 -1
  69. package/dist/model/edges.d.ts +28 -1
  70. package/dist/model/edges.js +77 -15
  71. package/dist/model/edges.js.map +1 -1
  72. package/dist/model/model.d.ts +6 -0
  73. package/dist/model/model.js +2 -0
  74. package/dist/model/model.js.map +1 -1
  75. package/dist/model/qualifiedRef.d.ts +47 -0
  76. package/dist/model/qualifiedRef.js +100 -0
  77. package/dist/model/qualifiedRef.js.map +1 -0
  78. package/dist/model/queryIndex.d.ts +53 -0
  79. package/dist/model/queryIndex.js +114 -0
  80. package/dist/model/queryIndex.js.map +1 -0
  81. package/dist/model/rules.d.ts +88 -0
  82. package/dist/model/rules.js +101 -0
  83. package/dist/model/rules.js.map +1 -1
  84. package/dist/model/sliceDocIndex.d.ts +30 -0
  85. package/dist/model/sliceDocIndex.js +110 -0
  86. package/dist/model/sliceDocIndex.js.map +1 -0
  87. package/dist/model/validate.js +85 -11
  88. package/dist/model/validate.js.map +1 -1
  89. package/dist/parser/ast.d.ts +25 -0
  90. package/dist/parser/parser.d.ts +2 -0
  91. package/dist/parser/parser.js +104 -34
  92. package/dist/parser/parser.js.map +1 -1
  93. package/dist/query/format.d.ts +8 -0
  94. package/dist/query/format.js +80 -0
  95. package/dist/query/format.js.map +1 -0
  96. package/dist/query/pipeline.d.ts +17 -0
  97. package/dist/query/pipeline.js +38 -0
  98. package/dist/query/pipeline.js.map +1 -0
  99. package/dist/query/system.d.ts +60 -0
  100. package/dist/query/system.js +87 -0
  101. package/dist/query/system.js.map +1 -0
  102. package/dist/query/verbs.d.ts +100 -0
  103. package/dist/query/verbs.js +306 -0
  104. package/dist/query/verbs.js.map +1 -0
  105. package/dist/render/drawEdges.js +15 -4
  106. package/dist/render/drawEdges.js.map +1 -1
  107. package/dist/render/drawNotes.d.ts +13 -3
  108. package/dist/render/drawNotes.js +96 -20
  109. package/dist/render/drawNotes.js.map +1 -1
  110. package/dist/render/render.js +6 -5
  111. package/dist/render/render.js.map +1 -1
  112. package/dist/render/sliceDiagram.js +1 -0
  113. package/dist/render/sliceDiagram.js.map +1 -1
  114. package/dist/system/manifest.d.ts +45 -0
  115. package/dist/system/manifest.js +178 -0
  116. package/dist/system/manifest.js.map +1 -0
  117. package/dist/system/verify.d.ts +88 -0
  118. package/dist/system/verify.js +263 -0
  119. package/dist/system/verify.js.map +1 -0
  120. package/dist/templates.d.ts +14 -1
  121. package/dist/templates.js +134 -5
  122. package/dist/templates.js.map +1 -1
  123. package/dist/util/slug.js +16 -10
  124. package/dist/util/slug.js.map +1 -1
  125. package/package.json +10 -1
@@ -68,6 +68,13 @@ export declare const RULES: {
68
68
  readonly usageCategory: "event field not provided by command";
69
69
  readonly docAnchor: "fields-completeness";
70
70
  };
71
+ readonly "derived-from-unresolved": {
72
+ readonly severity: "error";
73
+ readonly title: "`derived from` names an unknown event";
74
+ readonly fix: "Name one of the view's actual sources, or drop the traced event from `derived from`.";
75
+ readonly usageCategory: "derived from names unresolved event";
76
+ readonly docAnchor: "fields-completeness";
77
+ };
71
78
  readonly "reaction-from-unresolved": {
72
79
  readonly severity: "error";
73
80
  readonly title: "Unknown read-model source";
@@ -134,6 +141,18 @@ export declare const RULES: {
134
141
  readonly fix: "Restructure so the target comes later.";
135
142
  readonly usageCategory: "arrow points backward";
136
143
  };
144
+ readonly "loops-to-forward": {
145
+ readonly severity: "error";
146
+ readonly title: "`loops-to` target not earlier on the timeline";
147
+ readonly fix: "Point `loops-to` at an earlier view, or use `from` on a later `view … again` instance instead.";
148
+ readonly usageCategory: "loops-to points forward";
149
+ };
150
+ readonly "loops-to-unresolved": {
151
+ readonly severity: "error";
152
+ readonly title: "`loops-to` target unresolved";
153
+ readonly fix: "Name a view that exists, or declare it before this event.";
154
+ readonly usageCategory: "loops-to target unresolved";
155
+ };
137
156
  readonly "connection-legality/illegal-pair": {
138
157
  readonly severity: "error";
139
158
  readonly title: "Illegal connection";
@@ -323,12 +342,81 @@ export declare const RULES: {
323
342
  readonly fix: "Rename the type so its export ref is unique.";
324
343
  readonly usageCategory: "duplicate type ref";
325
344
  };
345
+ readonly "duplicate-model-key": {
346
+ readonly severity: "warning";
347
+ readonly title: "Duplicate model key";
348
+ readonly fix: "Give each model a unique `model \"Name\"` so its key (and every cross-model ref) is stable.";
349
+ readonly usageCategory: "duplicate model key";
350
+ };
326
351
  readonly "cross-model-slice-doc-collision": {
327
352
  readonly severity: "warning";
328
353
  readonly title: "Colliding slice doc path across models";
329
354
  readonly fix: "Give each model its own directory (see docs/cli.md, \"Multi-model projects\").";
330
355
  readonly usageCategory: "colliding slice doc path across models";
331
356
  };
357
+ readonly "system-manifest-invalid": {
358
+ readonly severity: "error";
359
+ readonly title: "Seam manifest invalid";
360
+ readonly fix: "Fix the manifest: required keys, `systemSchemaVersion: \"1.0\"`, a readable `source` per model, and only declared model keys in seam refs.";
361
+ readonly usageCategory: "seam manifest invalid";
362
+ readonly docAnchor: "seam-manifest";
363
+ };
364
+ readonly "system-model-key-mismatch": {
365
+ readonly severity: "error";
366
+ readonly title: "Manifest model key differs from the export's `model.key`";
367
+ readonly fix: "Rename the manifest's `models:` key to the computed key the message prints.";
368
+ readonly usageCategory: "seam manifest model key mismatch";
369
+ readonly docAnchor: "seam-manifest";
370
+ };
371
+ readonly "seam-endpoint-unresolved": {
372
+ readonly severity: "error";
373
+ readonly title: "Seam endpoint does not resolve";
374
+ 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.";
375
+ readonly usageCategory: "seam endpoint unresolved";
376
+ readonly docAnchor: "seam-manifest";
377
+ };
378
+ readonly "seam-source-not-public": {
379
+ readonly severity: "error";
380
+ readonly title: "Seam source is not `public`";
381
+ readonly fix: "Mark the event/view `public` in its model, or point the seam at the element that is.";
382
+ readonly usageCategory: "seam source not public";
383
+ readonly docAnchor: "seam-manifest";
384
+ };
385
+ readonly "seam-consumer-not-reaction": {
386
+ readonly severity: "error";
387
+ readonly title: "Seam consumer is not a reaction";
388
+ readonly fix: "Point `to` at a translation/automation element (or a slice containing exactly one).";
389
+ readonly usageCategory: "seam consumer not a reaction";
390
+ readonly docAnchor: "seam-manifest";
391
+ };
392
+ readonly "seam-duplicate": {
393
+ readonly severity: "warning";
394
+ readonly title: "Duplicate seam";
395
+ readonly fix: "Remove the repeated `from`/`to` pair.";
396
+ readonly usageCategory: "duplicate seam";
397
+ readonly docAnchor: "seam-manifest";
398
+ };
399
+ readonly "dangling-public-event": {
400
+ readonly severity: "warning";
401
+ readonly title: "Public event/view no seam consumes";
402
+ readonly fix: "Declare the seam that reads it, or drop `public` if nothing outside the model does.";
403
+ readonly usageCategory: "public event not consumed by any seam";
404
+ readonly docAnchor: "seam-manifest";
405
+ };
406
+ readonly "unbound-translation": {
407
+ readonly severity: "warning";
408
+ readonly title: "Externally-fed reaction no seam feeds";
409
+ readonly fix: "Declare the seam whose `to` is this reaction, or give it an in-model `from`.";
410
+ readonly usageCategory: "externally-fed reaction not bound by any seam";
411
+ readonly docAnchor: "seam-manifest";
412
+ };
413
+ readonly "undeclared-seam-candidate": {
414
+ readonly severity: "warning";
415
+ readonly title: "Looks connected across models, no seam declared";
416
+ readonly fix: "Declare the seam, or rename one side so the name match stops looking like a link.";
417
+ readonly usageCategory: "undeclared seam candidate";
418
+ readonly docAnchor: "seam-manifest";
419
+ };
332
420
  readonly "slice-ready-unknown-slice": {
333
421
  readonly severity: "error";
334
422
  readonly title: "Unknown --slice-ready key";
@@ -68,6 +68,13 @@ export const RULES = {
68
68
  usageCategory: "event field not provided by command",
69
69
  docAnchor: "fields-completeness",
70
70
  },
71
+ "derived-from-unresolved": {
72
+ severity: "error",
73
+ title: "`derived from` names an unknown event",
74
+ fix: "Name one of the view's actual sources, or drop the traced event from `derived from`.",
75
+ usageCategory: "derived from names unresolved event",
76
+ docAnchor: "fields-completeness",
77
+ },
71
78
  "reaction-from-unresolved": {
72
79
  severity: "error",
73
80
  title: "Unknown read-model source",
@@ -134,6 +141,18 @@ export const RULES = {
134
141
  fix: "Restructure so the target comes later.",
135
142
  usageCategory: "arrow points backward",
136
143
  },
144
+ "loops-to-forward": {
145
+ severity: "error",
146
+ title: "`loops-to` target not earlier on the timeline",
147
+ fix: "Point `loops-to` at an earlier view, or use `from` on a later `view … again` instance instead.",
148
+ usageCategory: "loops-to points forward",
149
+ },
150
+ "loops-to-unresolved": {
151
+ severity: "error",
152
+ title: "`loops-to` target unresolved",
153
+ fix: "Name a view that exists, or declare it before this event.",
154
+ usageCategory: "loops-to target unresolved",
155
+ },
137
156
  "connection-legality/illegal-pair": {
138
157
  severity: "error",
139
158
  title: "Illegal connection",
@@ -323,6 +342,17 @@ export const RULES = {
323
342
  fix: "Rename the type so its export ref is unique.",
324
343
  usageCategory: "duplicate type ref",
325
344
  },
345
+ // MIL-193: two models in one multi-model invocation whose model keys (kebab-slugged declared
346
+ // names, model/qualifiedRef.ts) collide — the later one takes a `~n` suffix, exactly as
347
+ // `duplicate-slice-name` handles a slice-key collision. Raised by computeModelKeys(), which
348
+ // only ever runs where more than one model is in play (`em query`, MIL-194's `em system`);
349
+ // a single-model compile can never see it.
350
+ "duplicate-model-key": {
351
+ severity: "warning",
352
+ title: "Duplicate model key",
353
+ fix: "Give each model a unique `model \"Name\"` so its key (and every cross-model ref) is stable.",
354
+ usageCategory: "duplicate model key",
355
+ },
326
356
  // MIL-160: two input models sharing a directory (so both resolve slice docs at
327
357
  // `<that-directory>/slices/<key>.md`) whose compiled slice keys overlap — nothing before this
328
358
  // caught it, since computeRefs() dedupes slice keys only within one model's own compile. Raised
@@ -336,6 +366,77 @@ export const RULES = {
336
366
  fix: "Give each model its own directory (see docs/cli.md, \"Multi-model projects\").",
337
367
  usageCategory: "colliding slice doc path across models",
338
368
  },
369
+ // MIL-194: the nine codes `em system <manifest>` raises while verifying a seam manifest
370
+ // (docs/cli.md "em system") against each model's export document — the cross-model half of
371
+ // "both ends of a flow": every `public` event/view needs a declared reader somewhere in the
372
+ // system, every externally-fed reaction needs a declared producer. Raised by
373
+ // src/system/verify.ts (pure, over export JSON only — never a compiled model) and
374
+ // src/system/manifest.ts (the manifest's own shape). Registered here, like
375
+ // `cross-model-slice-doc-collision`, so severity/title/fix generate into the same reference
376
+ // tables every other code does; none of them is ever raised by `em validate` itself.
377
+ "system-manifest-invalid": {
378
+ severity: "error",
379
+ title: "Seam manifest invalid",
380
+ fix: "Fix the manifest: required keys, `systemSchemaVersion: \"1.0\"`, a readable `source` per model, and only declared model keys in seam refs.",
381
+ usageCategory: "seam manifest invalid",
382
+ docAnchor: "seam-manifest",
383
+ },
384
+ "system-model-key-mismatch": {
385
+ severity: "error",
386
+ title: "Manifest model key differs from the export's `model.key`",
387
+ fix: "Rename the manifest's `models:` key to the computed key the message prints.",
388
+ usageCategory: "seam manifest model key mismatch",
389
+ docAnchor: "seam-manifest",
390
+ },
391
+ "seam-endpoint-unresolved": {
392
+ severity: "error",
393
+ title: "Seam endpoint does not resolve",
394
+ 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.",
395
+ usageCategory: "seam endpoint unresolved",
396
+ docAnchor: "seam-manifest",
397
+ },
398
+ "seam-source-not-public": {
399
+ severity: "error",
400
+ title: "Seam source is not `public`",
401
+ fix: "Mark the event/view `public` in its model, or point the seam at the element that is.",
402
+ usageCategory: "seam source not public",
403
+ docAnchor: "seam-manifest",
404
+ },
405
+ "seam-consumer-not-reaction": {
406
+ severity: "error",
407
+ title: "Seam consumer is not a reaction",
408
+ fix: "Point `to` at a translation/automation element (or a slice containing exactly one).",
409
+ usageCategory: "seam consumer not a reaction",
410
+ docAnchor: "seam-manifest",
411
+ },
412
+ "seam-duplicate": {
413
+ severity: "warning",
414
+ title: "Duplicate seam",
415
+ fix: "Remove the repeated `from`/`to` pair.",
416
+ usageCategory: "duplicate seam",
417
+ docAnchor: "seam-manifest",
418
+ },
419
+ "dangling-public-event": {
420
+ severity: "warning",
421
+ title: "Public event/view no seam consumes",
422
+ fix: "Declare the seam that reads it, or drop `public` if nothing outside the model does.",
423
+ usageCategory: "public event not consumed by any seam",
424
+ docAnchor: "seam-manifest",
425
+ },
426
+ "unbound-translation": {
427
+ severity: "warning",
428
+ title: "Externally-fed reaction no seam feeds",
429
+ fix: "Declare the seam whose `to` is this reaction, or give it an in-model `from`.",
430
+ usageCategory: "externally-fed reaction not bound by any seam",
431
+ docAnchor: "seam-manifest",
432
+ },
433
+ "undeclared-seam-candidate": {
434
+ severity: "warning",
435
+ title: "Looks connected across models, no seam declared",
436
+ fix: "Declare the seam, or rename one side so the name match stops looking like a link.",
437
+ usageCategory: "undeclared seam candidate",
438
+ docAnchor: "seam-manifest",
439
+ },
339
440
  "slice-ready-unknown-slice": {
340
441
  severity: "error",
341
442
  title: "Unknown --slice-ready key",
@@ -1 +1 @@
1
- {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/model/rules.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/model/rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { SliceDoc } from "../catalog/sliceDoc.js";
2
+ import { DriftSignalKind } from "../catalog/driftSignal.js";
3
+ import { Slice } from "./model.js";
4
+ /** Read + parse every `slices/*.md` file under `baseDir` exactly once, keyed by its filename
5
+ * stem (lowercased) — the same key `computeRefs()` assigns as a slice's export key. A missing
6
+ * `slices/` directory (routine — not every model has reached specify yet) returns an empty map,
7
+ * the same "nothing bound" state `readSliceDoc()` reports per-file via `null`. An individual
8
+ * file that fails to read (permissions, a broken symlink) is skipped rather than thrown —
9
+ * same silent-miss convention `readSliceDoc()` uses for a missing file. */
10
+ export declare function loadSliceDocsOnce(baseDir: string): Map<string, SliceDoc>;
11
+ /** A slice's query-facing doc join — deliberately narrower than `SliceDocExport`
12
+ * (`catalog/docJoin.ts`): only the facts `em query`'s verbs actually surface (declaring
13
+ * slice, doc path/status, drift, and the doc body for invariant-ID extraction), no lineage/
14
+ * ratification/owner fields. */
15
+ export interface SliceQueryDoc {
16
+ found: boolean;
17
+ path: string;
18
+ reason: "no-doc-bound" | "binding-missing-file" | "frontmatter-invalid" | null;
19
+ status: string | null;
20
+ implementedIn: string | null;
21
+ driftSignal: DriftSignalKind | null;
22
+ /** The doc's body text (post-frontmatter), for `extractInvariantIds()` — null whenever
23
+ * `found` is false or the frontmatter wasn't usable (nothing safe to scan). */
24
+ body: string | null;
25
+ }
26
+ /** Same resolution semantics as `docJoin.ts`'s resolveSliceDocJoin() — canonical `note` binding
27
+ * first, then a ratified MIL-121 cross-binding naming this slice in its `covers:` list — but
28
+ * reading from the in-memory map `loadSliceDocsOnce()` built once for the whole model, instead
29
+ * of one `readSliceDoc()` fs call per slice/candidate. */
30
+ export declare function joinSliceDocFast(slice: Slice, sliceKey: string, docsByKey: Map<string, SliceDoc>): SliceQueryDoc;
@@ -0,0 +1,110 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // A once-per-model slice-doc join for `em query` (MIL-168): the same canonical-then-
3
+ // MIL-121-cross-binding resolution `catalog/docJoin.ts`'s resolveSliceDocJoin() performs, but
4
+ // sourced from one `readdirSync(<baseDir>/slices/)` up front instead of one
5
+ // `existsSync`+`readFileSync` pair (`readSliceDoc.ts`) per slice/candidate. `em export`/`em
6
+ // status`/`em coverage` each call resolveSliceDocJoin() once per slice already and stay on that
7
+ // path unchanged (their per-slice cost is amortized across a single command run the same way);
8
+ // this module exists because `em query` builds one ModelIndex per compiled model and then
9
+ // answers many lookups against it, so paying the fs cost once, up front, per model — rather
10
+ // than once per slice scattered through the join — is the win at thousands-of-slices scale (see
11
+ // this ticket's report for the benchmark).
12
+ //
13
+ // Deliberately a read path, not a lint: unlike resolveSliceDocJoin(), this never raises a
14
+ // diagnostic for a missing-but-bound doc or invalid frontmatter — `em query` reports facts
15
+ // (`found`/`reason`), and leaves surfacing that as a warning to `em export`/`em status`, which
16
+ // already do.
17
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
18
+ import { join } from "node:path";
19
+ import { parseSliceDoc, hasUsableFrontmatter } from "../catalog/sliceDoc.js";
20
+ import { classifyImplementationDrift } from "../catalog/driftSignal.js";
21
+ import { NOTE_SLICE_PATH } from "../catalog/docJoin.js";
22
+ /** Matches a slice-doc filename (`slices/<key>.md`) — same kebab-slug grammar
23
+ * `catalog/sliceDoc.ts`'s SLICE_REF and `docJoin.ts`'s NOTE_SLICE_PATH use for the key itself. */
24
+ const SLICE_DOC_FILENAME_RE = /^([a-z0-9]+(?:-[a-z0-9]+)*)\.md$/i;
25
+ /** Read + parse every `slices/*.md` file under `baseDir` exactly once, keyed by its filename
26
+ * stem (lowercased) — the same key `computeRefs()` assigns as a slice's export key. A missing
27
+ * `slices/` directory (routine — not every model has reached specify yet) returns an empty map,
28
+ * the same "nothing bound" state `readSliceDoc()` reports per-file via `null`. An individual
29
+ * file that fails to read (permissions, a broken symlink) is skipped rather than thrown —
30
+ * same silent-miss convention `readSliceDoc()` uses for a missing file. */
31
+ export function loadSliceDocsOnce(baseDir) {
32
+ const docs = new Map();
33
+ let entries;
34
+ try {
35
+ entries = readdirSync(join(baseDir, "slices"));
36
+ }
37
+ catch {
38
+ return docs;
39
+ }
40
+ const names = new Set(entries);
41
+ for (const name of entries) {
42
+ const m = SLICE_DOC_FILENAME_RE.exec(name);
43
+ if (!m)
44
+ continue;
45
+ const key = m[1].toLowerCase();
46
+ // `readSliceDoc()` opens `slices/<key>.md` with the lowercased key verbatim, so a mixed-case
47
+ // filename is only a doc where the filesystem itself folds case. If the exact lowercase
48
+ // file is its own directory entry (a case-sensitive fs holding both), that entry is the
49
+ // one readSliceDoc() reads — skip this one, whatever order readdir listed them in.
50
+ // Otherwise probe once — only for the rare mixed-case entry — so query and export agree
51
+ // on every platform.
52
+ if (m[1] !== key) {
53
+ if (names.has(`${key}.md`))
54
+ continue;
55
+ if (!existsSync(join(baseDir, "slices", `${key}.md`)))
56
+ continue;
57
+ }
58
+ try {
59
+ docs.set(key, parseSliceDoc(readFileSync(join(baseDir, "slices", name), "utf8")));
60
+ }
61
+ catch {
62
+ // unreadable — treated as "no doc" for this key, same as a fs error inside readSliceDoc().
63
+ }
64
+ }
65
+ return docs;
66
+ }
67
+ /** Same resolution semantics as `docJoin.ts`'s resolveSliceDocJoin() — canonical `note` binding
68
+ * first, then a ratified MIL-121 cross-binding naming this slice in its `covers:` list — but
69
+ * reading from the in-memory map `loadSliceDocsOnce()` built once for the whole model, instead
70
+ * of one `readSliceDoc()` fs call per slice/candidate. */
71
+ export function joinSliceDocFast(slice, sliceKey, docsByKey) {
72
+ const path = `slices/${sliceKey}.md`;
73
+ const boundEls = slice.elements.filter((el) => el.note === path);
74
+ if (boundEls.length === 0) {
75
+ for (const el of slice.elements) {
76
+ if (!el.note)
77
+ continue;
78
+ const m = el.note.match(NOTE_SLICE_PATH);
79
+ if (!m)
80
+ continue;
81
+ const otherKey = m[1].toLowerCase();
82
+ if (otherKey === sliceKey)
83
+ continue;
84
+ const doc = docsByKey.get(otherKey);
85
+ if (!doc || !hasUsableFrontmatter(doc) || !doc.covers.includes(sliceKey))
86
+ continue;
87
+ return foundDoc(`slices/${otherKey}.md`, doc);
88
+ }
89
+ return { found: false, path, reason: "no-doc-bound", status: null, implementedIn: null, driftSignal: null, body: null };
90
+ }
91
+ const doc = docsByKey.get(sliceKey);
92
+ if (!doc)
93
+ return { found: false, path, reason: "binding-missing-file", status: null, implementedIn: null, driftSignal: null, body: null };
94
+ if (!hasUsableFrontmatter(doc)) {
95
+ return { found: true, path, reason: "frontmatter-invalid", status: null, implementedIn: null, driftSignal: null, body: null };
96
+ }
97
+ return foundDoc(path, doc);
98
+ }
99
+ function foundDoc(path, doc) {
100
+ return {
101
+ found: true,
102
+ path,
103
+ reason: null,
104
+ status: doc.status,
105
+ implementedIn: doc.implementedIn,
106
+ driftSignal: classifyImplementationDrift(doc),
107
+ body: doc.body,
108
+ };
109
+ }
110
+ //# sourceMappingURL=sliceDocIndex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sliceDocIndex.js","sourceRoot":"","sources":["../../src/model/sliceDocIndex.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  import { AUTOMATION_KINDS } from "../parser/ast.js";
4
4
  import { collectTags, normalizeName, resolveTypeRef } from "./model.js";
5
5
  import { pushDiag } from "./rules.js";
6
+ import { connectionKind, resolveLoopsToTarget } from "./edges.js";
6
7
  export function validate(model, grid, refs) {
7
8
  const diags = [];
8
9
  const refOf = (id) => refs.refById.get(id);
@@ -93,6 +94,9 @@ export function validate(model, grid, refs) {
93
94
  // `{ fields }`: the view, and *every* source event. A partially-declared
94
95
  // source set can't prove a gap (the fieldless event may well provide the
95
96
  // field), so it stays silent rather than warning on legitimate fields.
97
+ // A field marked `derived` (MIL-200) opts out of this check entirely — it's the
98
+ // model's own record that the field is computed from which events have landed, not
99
+ // copied from a single source event's payload.
96
100
  if (view.fields && view.fields.length > 0) {
97
101
  const fromNames = view.from ?? [];
98
102
  const sourceEvents = [];
@@ -111,6 +115,11 @@ export function validate(model, grid, refs) {
111
115
  }
112
116
  const eventList = fromNames.map((n) => `"${n}"`).join(", ");
113
117
  for (const f of view.fields) {
118
+ // `derived` (bare or traced, MIL-200) marks a field as computed from which events
119
+ // have landed rather than copied from a single source event's payload — exempt
120
+ // from this check entirely, same posture as `assigned` below for event fields.
121
+ if (f.derived)
122
+ continue;
114
123
  if (!fieldUnion.has(normalizeName(f.name))) {
115
124
  pushDiag(diags, "fields-completeness/view-field-no-source", {
116
125
  message: `view "${view.name}" field "${f.name}" has no source in ${eventList}`,
@@ -120,6 +129,28 @@ export function validate(model, grid, refs) {
120
129
  }
121
130
  }
122
131
  }
132
+ // `derived from "Event A", "Event B"` (view fields only, MIL-200): the traced form
133
+ // still checks something — every named event must resolve among the view's ACTUAL
134
+ // sources, its `from` names, or (for a `from`-less view) the events in its own slice.
135
+ // Independent of `sourcesDeclareFields` above: this checks event *names*, not field
136
+ // completeness, so it applies whether or not the sources declare `{ fields }`.
137
+ const actualSourceEvents = fromNames.length > 0 ? sourceEvents : events;
138
+ const actualSourceNames = new Set(actualSourceEvents.map((e) => normalizeName(e.name)));
139
+ for (const f of view.fields) {
140
+ for (const name of f.derivedFrom ?? []) {
141
+ if (!actualSourceNames.has(normalizeName(name))) {
142
+ const actualList = actualSourceEvents.length > 0
143
+ ? actualSourceEvents.map((e) => `"${e.name}"`).join(", ")
144
+ : "(none)";
145
+ pushDiag(diags, "derived-from-unresolved", {
146
+ message: `view "${view.name}" field "${f.name}" is derived from unknown event "${name}" — ` +
147
+ `its actual sources are ${actualList}`,
148
+ line: view.line,
149
+ refs: [refOf(view.id), ...actualSourceEvents.map((e) => refOf(e.id))],
150
+ });
151
+ }
152
+ }
153
+ }
123
154
  }
124
155
  }
125
156
  // Fields completeness: every event field in a slice should trace to a field on
@@ -193,6 +224,45 @@ export function validate(model, grid, refs) {
193
224
  }
194
225
  }
195
226
  }
227
+ // `loops-to "View"` (event only, MIL-199): a later fact re-feeding an earlier read model —
228
+ // the one loop-back device forward-only `from`/`arrow` can't express. The target must
229
+ // resolve to a `view` instance strictly EARLIER on the timeline; same-slice-or-later is
230
+ // what `from` on a later `view … again` instance is for.
231
+ for (const el of model.elements) {
232
+ if (el.kind !== "event")
233
+ continue;
234
+ for (const name of el.loopsTo ?? []) {
235
+ const bucket = model.byName.get(normalizeName(name));
236
+ const views = bucket?.filter((e) => e.kind === "view") ?? [];
237
+ if (views.length === 0) {
238
+ // Same courtesy as the reaction/view `from` checks above: a name that exists but as
239
+ // the wrong kind reads like a typo without saying so.
240
+ const other = bucket?.[0];
241
+ pushDiag(diags, "loops-to-unresolved", {
242
+ message: other
243
+ ? `event "${el.name}" loops-to "${name}", which is a ${other.kind}, not a read model — ` +
244
+ `\`loops-to\` names the view this event re-feeds`
245
+ : `event "${el.name}" loops-to unknown read model "${name}"`,
246
+ line: el.line,
247
+ refs: other ? [refOf(el.id), refOf(other.id)] : [refOf(el.id)],
248
+ });
249
+ continue;
250
+ }
251
+ const target = resolveLoopsToTarget(model, el, name);
252
+ if (!target) {
253
+ const nearest = views
254
+ .filter((v) => v.sliceIndex >= el.sliceIndex)
255
+ .sort((a, b) => a.sliceIndex - b.sliceIndex)[0];
256
+ pushDiag(diags, "loops-to-forward", {
257
+ message: `time flows left to right: event "${el.name}" (slice ${el.sliceIndex + 1}) loops-to ` +
258
+ `"${name}" (slice ${nearest.sliceIndex + 1}), which is not earlier on the timeline — ` +
259
+ `that's what \`from\` on a later \`view ${name} again\` instance is for`,
260
+ line: el.line,
261
+ refs: [refOf(el.id), refOf(nearest.id)],
262
+ });
263
+ }
264
+ }
265
+ }
196
266
  // A \`view X again\` instance needs an earlier declaration to continue.
197
267
  for (const el of model.elements) {
198
268
  if (el.kind === "view" && el.again && el.logicalId === el.id) {
@@ -396,6 +466,18 @@ export function validate(model, grid, refs) {
396
466
  if (from?.kind === "event" && to?.kind === "view")
397
467
  readEvents.add(normalizeName(from.name));
398
468
  }
469
+ // A resolved `loops-to "View"` (MIL-199) counts as consumption too — the event re-feeds an
470
+ // earlier read model instead of a new one, but it's still read by something. An unresolved
471
+ // or forward target (already flagged above by its own rule) does not credit the event here;
472
+ // it stays reported as unread on top of its loops-to diagnostic rather than silently passing.
473
+ for (const el of model.elements) {
474
+ if (el.kind !== "event")
475
+ continue;
476
+ for (const name of el.loopsTo ?? []) {
477
+ if (resolveLoopsToTarget(model, el, name))
478
+ readEvents.add(normalizeName(el.name));
479
+ }
480
+ }
399
481
  for (const el of model.elements) {
400
482
  if (el.kind !== "event")
401
483
  continue;
@@ -662,17 +744,9 @@ const isAuto = (k) => AUTOMATION_KINDS.has(k);
662
744
  /** The only kind pairs a connection may take, per the four patterns: information enters the
663
745
  * system through a command and leaves through a read model, and nothing skips a step. */
664
746
  function isLegalFlow(from, to) {
665
- if (from === "ui")
666
- return to === "command"; // State Change
667
- if (from === "command")
668
- return to === "event"; // State Change
669
- if (from === "event")
670
- return to === "view"; // State View
671
- if (from === "view")
672
- return to === "ui" || isAuto(to); // State View / Automation / Translation
673
- if (isAuto(from))
674
- return to === "command"; // reactions always go through a command
675
- return false;
747
+ // The six legal connections are a pure function of the endpoint kinds — edges.ts owns the
748
+ // table (the renderer, `em query`, and this rule all read the same one).
749
+ return connectionKind(from, to) !== undefined;
676
750
  }
677
751
  /** Why a given illegal pair is illegal, and what to put in the gap. */
678
752
  function flowGuidance(from, to) {