@milehimikey/em 1.16.1 → 1.18.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 (219) hide show
  1. package/.claude/skills/event-modeling/SKILL.md +1 -1
  2. package/.claude/skills/event-modeling-conform/SKILL.md +3 -2
  3. package/.claude/skills/event-modeling-conform/reference/conform.md +7 -0
  4. package/.claude/skills/event-modeling-design/SKILL.md +46 -5
  5. package/.claude/skills/event-modeling-discover/SKILL.md +43 -8
  6. package/.claude/skills/event-modeling-discover/reference/extract.md +6 -1
  7. package/.claude/skills/event-modeling-discover/reference/prd-rubric.md +102 -0
  8. package/.claude/skills/event-modeling-discover/reference/prd-spec-path.md +171 -0
  9. package/.claude/skills/event-modeling-engagement/SKILL.md +28 -6
  10. package/.claude/skills/event-modeling-engagement/reference/engagement.md +5 -4
  11. package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
  12. package/.claude/skills/event-modeling-implement/reference/implement.md +18 -8
  13. package/.claude/skills/event-modeling-review/SKILL.md +1 -1
  14. package/.claude/skills/event-modeling-shared/reference/em-dsl.md +107 -10
  15. package/.claude/skills/event-modeling-shared/reference/methodology.md +268 -0
  16. package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +122 -15
  17. package/.claude/skills/event-modeling-shared/templates/slice.md +11 -3
  18. package/.claude-plugin/marketplace.json +2 -2
  19. package/dist/catalog/docJoin.d.ts +13 -5
  20. package/dist/catalog/docJoin.js +6 -1
  21. package/dist/catalog/docJoin.js.map +1 -1
  22. package/dist/catalog/docModelConsistencyValidate.js +160 -0
  23. package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
  24. package/dist/catalog/invariantsValidate.d.ts +2 -0
  25. package/dist/catalog/invariantsValidate.js +67 -1
  26. package/dist/catalog/invariantsValidate.js.map +1 -1
  27. package/dist/catalog/scenarioQualityValidate.d.ts +4 -0
  28. package/dist/catalog/scenarioQualityValidate.js +148 -0
  29. package/dist/catalog/scenarioQualityValidate.js.map +1 -0
  30. package/dist/catalog/scenarios.d.ts +5 -0
  31. package/dist/catalog/scenarios.js +80 -0
  32. package/dist/catalog/scenarios.js.map +1 -1
  33. package/dist/catalog/signedBodyValidate.d.ts +7 -0
  34. package/dist/catalog/signedBodyValidate.js +29 -0
  35. package/dist/catalog/signedBodyValidate.js.map +1 -0
  36. package/dist/catalog/sliceDoc.d.ts +53 -7
  37. package/dist/catalog/sliceDoc.js +89 -10
  38. package/dist/catalog/sliceDoc.js.map +1 -1
  39. package/dist/catalog/sliceReadyValidate.d.ts +23 -2
  40. package/dist/catalog/sliceReadyValidate.js +54 -22
  41. package/dist/catalog/sliceReadyValidate.js.map +1 -1
  42. package/dist/catalog/sliceSections.d.ts +3 -2
  43. package/dist/catalog/sliceSections.js +99 -9
  44. package/dist/catalog/sliceSections.js.map +1 -1
  45. package/dist/cli/ciInit.d.ts +4 -11
  46. package/dist/cli/ciInit.js +24 -6
  47. package/dist/cli/ciInit.js.map +1 -1
  48. package/dist/cli/coverage.d.ts +9 -0
  49. package/dist/cli/coverage.js +18 -0
  50. package/dist/cli/coverage.js.map +1 -1
  51. package/dist/cli/defer.d.ts +60 -17
  52. package/dist/cli/defer.js +187 -86
  53. package/dist/cli/defer.js.map +1 -1
  54. package/dist/cli/engagement.d.ts +46 -0
  55. package/dist/cli/engagement.js +156 -1
  56. package/dist/cli/engagement.js.map +1 -1
  57. package/dist/cli/engagementFoundation.d.ts +47 -0
  58. package/dist/cli/engagementFoundation.js +164 -0
  59. package/dist/cli/engagementFoundation.js.map +1 -0
  60. package/dist/cli/frontmatterSurgery.d.ts +5 -0
  61. package/dist/cli/frontmatterSurgery.js +15 -0
  62. package/dist/cli/frontmatterSurgery.js.map +1 -1
  63. package/dist/cli/ledgerCheck.d.ts +5 -1
  64. package/dist/cli/ledgerCheck.js +50 -20
  65. package/dist/cli/ledgerCheck.js.map +1 -1
  66. package/dist/cli/markImplemented.d.ts +14 -10
  67. package/dist/cli/markImplemented.js +49 -1
  68. package/dist/cli/markImplemented.js.map +1 -1
  69. package/dist/cli/prdTriage.d.ts +109 -0
  70. package/dist/cli/prdTriage.js +378 -0
  71. package/dist/cli/prdTriage.js.map +1 -0
  72. package/dist/cli/ratify.d.ts +14 -2
  73. package/dist/cli/ratify.js +34 -6
  74. package/dist/cli/ratify.js.map +1 -1
  75. package/dist/cli/refsCheck.d.ts +78 -0
  76. package/dist/cli/refsCheck.js +153 -0
  77. package/dist/cli/refsCheck.js.map +1 -0
  78. package/dist/cli/render-inputs.d.ts +2 -0
  79. package/dist/cli/render-inputs.js +4 -0
  80. package/dist/cli/render-inputs.js.map +1 -1
  81. package/dist/cli/revise.d.ts +12 -3
  82. package/dist/cli/revise.js +43 -10
  83. package/dist/cli/revise.js.map +1 -1
  84. package/dist/cli/shape.d.ts +27 -0
  85. package/dist/cli/shape.js +77 -0
  86. package/dist/cli/shape.js.map +1 -0
  87. package/dist/cli/sliceConform.js +9 -0
  88. package/dist/cli/sliceConform.js.map +1 -1
  89. package/dist/cli/sliceIndex.d.ts +6 -1
  90. package/dist/cli/sliceIndex.js +28 -13
  91. package/dist/cli/sliceIndex.js.map +1 -1
  92. package/dist/cli/sliceNew.d.ts +4 -1
  93. package/dist/cli/sliceNew.js +26 -9
  94. package/dist/cli/sliceNew.js.map +1 -1
  95. package/dist/cli/status.d.ts +26 -5
  96. package/dist/cli/status.js +28 -6
  97. package/dist/cli/status.js.map +1 -1
  98. package/dist/cli/storylineSuggest.d.ts +26 -0
  99. package/dist/cli/storylineSuggest.js +252 -0
  100. package/dist/cli/storylineSuggest.js.map +1 -0
  101. package/dist/cli/upgrade.d.ts +15 -3
  102. package/dist/cli/upgrade.js +537 -8
  103. package/dist/cli/upgrade.js.map +1 -1
  104. package/dist/cli/upgradeReshape.d.ts +60 -0
  105. package/dist/cli/upgradeReshape.js +425 -0
  106. package/dist/cli/upgradeReshape.js.map +1 -0
  107. package/dist/cli.js +430 -57
  108. package/dist/cli.js.map +1 -1
  109. package/dist/emit/dot.d.ts +2 -0
  110. package/dist/emit/dot.js +44 -8
  111. package/dist/emit/dot.js.map +1 -1
  112. package/dist/emit/engagementJson.d.ts +4 -1
  113. package/dist/emit/engagementJson.js +27 -1
  114. package/dist/emit/engagementJson.js.map +1 -1
  115. package/dist/emit/json.d.ts +21 -1
  116. package/dist/emit/json.js +29 -2
  117. package/dist/emit/json.js.map +1 -1
  118. package/dist/emit/ledgerJson.d.ts +1 -1
  119. package/dist/emit/ledgerJson.js +6 -1
  120. package/dist/emit/ledgerJson.js.map +1 -1
  121. package/dist/emit/queryJson.d.ts +1 -1
  122. package/dist/emit/queryJson.js +3 -1
  123. package/dist/emit/queryJson.js.map +1 -1
  124. package/dist/emit/refsJson.d.ts +4 -0
  125. package/dist/emit/refsJson.js +19 -0
  126. package/dist/emit/refsJson.js.map +1 -0
  127. package/dist/emit/statusJson.d.ts +1 -1
  128. package/dist/emit/statusJson.js +6 -1
  129. package/dist/emit/statusJson.js.map +1 -1
  130. package/dist/emit/theme.d.ts +1 -0
  131. package/dist/emit/theme.js +13 -0
  132. package/dist/emit/theme.js.map +1 -1
  133. package/dist/emit/validateJson.d.ts +5 -2
  134. package/dist/emit/validateJson.js +41 -2
  135. package/dist/emit/validateJson.js.map +1 -1
  136. package/dist/layout/grid.d.ts +5 -1
  137. package/dist/layout/grid.js +93 -2
  138. package/dist/layout/grid.js.map +1 -1
  139. package/dist/mcp/server.js +79 -14
  140. package/dist/mcp/server.js.map +1 -1
  141. package/dist/model/edges.d.ts +7 -0
  142. package/dist/model/edges.js +33 -16
  143. package/dist/model/edges.js.map +1 -1
  144. package/dist/model/model.d.ts +33 -0
  145. package/dist/model/model.js +87 -3
  146. package/dist/model/model.js.map +1 -1
  147. package/dist/model/queryIndex.js +2 -2
  148. package/dist/model/queryIndex.js.map +1 -1
  149. package/dist/model/refs.js +8 -5
  150. package/dist/model/refs.js.map +1 -1
  151. package/dist/model/rules.d.ts +167 -1
  152. package/dist/model/rules.js +164 -3
  153. package/dist/model/rules.js.map +1 -1
  154. package/dist/model/shapeLint.d.ts +12 -0
  155. package/dist/model/shapeLint.js +170 -0
  156. package/dist/model/shapeLint.js.map +1 -0
  157. package/dist/model/storylines.d.ts +51 -0
  158. package/dist/model/storylines.js +188 -0
  159. package/dist/model/storylines.js.map +1 -0
  160. package/dist/model/validate.d.ts +6 -1
  161. package/dist/model/validate.js +317 -14
  162. package/dist/model/validate.js.map +1 -1
  163. package/dist/parser/againSugar.d.ts +30 -0
  164. package/dist/parser/againSugar.js +105 -0
  165. package/dist/parser/againSugar.js.map +1 -0
  166. package/dist/parser/ast.d.ts +33 -0
  167. package/dist/parser/lexer.d.ts +9 -1
  168. package/dist/parser/lexer.js +17 -2
  169. package/dist/parser/lexer.js.map +1 -1
  170. package/dist/parser/parser.js +284 -4
  171. package/dist/parser/parser.js.map +1 -1
  172. package/dist/query/format.js +1 -0
  173. package/dist/query/format.js.map +1 -1
  174. package/dist/query/verbs.d.ts +4 -0
  175. package/dist/query/verbs.js +30 -3
  176. package/dist/query/verbs.js.map +1 -1
  177. package/dist/render/drawEdges.js +100 -4
  178. package/dist/render/drawEdges.js.map +1 -1
  179. package/dist/render/render.js +20 -2
  180. package/dist/render/render.js.map +1 -1
  181. package/dist/render/sliceDiagram.js +5 -5
  182. package/dist/render/sliceDiagram.js.map +1 -1
  183. package/dist/render/storylineBands.d.ts +11 -0
  184. package/dist/render/storylineBands.js +80 -0
  185. package/dist/render/storylineBands.js.map +1 -0
  186. package/dist/render/storylineDiagram.d.ts +14 -0
  187. package/dist/render/storylineDiagram.js +142 -0
  188. package/dist/render/storylineDiagram.js.map +1 -0
  189. package/dist/roster/check.d.ts +32 -0
  190. package/dist/roster/check.js +92 -0
  191. package/dist/roster/check.js.map +1 -0
  192. package/dist/roster/context.d.ts +3 -0
  193. package/dist/roster/context.js +23 -0
  194. package/dist/roster/context.js.map +1 -0
  195. package/dist/roster/init.d.ts +15 -0
  196. package/dist/roster/init.js +52 -0
  197. package/dist/roster/init.js.map +1 -0
  198. package/dist/roster/roster.d.ts +79 -0
  199. package/dist/roster/roster.js +298 -0
  200. package/dist/roster/roster.js.map +1 -0
  201. package/package.json +1 -1
  202. package/plugin/.claude-plugin/plugin.json +2 -2
  203. package/plugin/shared/reference/em-dsl.md +107 -10
  204. package/plugin/shared/reference/methodology.md +268 -0
  205. package/plugin/shared/reference/slice-doc-schema.md +122 -15
  206. package/plugin/shared/templates/slice.md +11 -3
  207. package/plugin/skills/conform/SKILL.md +3 -2
  208. package/plugin/skills/conform/reference/conform.md +7 -0
  209. package/plugin/skills/design/SKILL.md +46 -5
  210. package/plugin/skills/discover/SKILL.md +43 -8
  211. package/plugin/skills/discover/reference/extract.md +6 -1
  212. package/plugin/skills/discover/reference/prd-rubric.md +103 -0
  213. package/plugin/skills/discover/reference/prd-spec-path.md +172 -0
  214. package/plugin/skills/engagement/SKILL.md +28 -6
  215. package/plugin/skills/engagement/reference/engagement.md +5 -4
  216. package/plugin/skills/event-modeling/SKILL.md +1 -1
  217. package/plugin/skills/implement/SKILL.md +1 -1
  218. package/plugin/skills/implement/reference/implement.md +18 -8
  219. package/plugin/skills/review/SKILL.md +1 -1
@@ -2,13 +2,14 @@ import { Diagnostic } from "../model/validate.js";
2
2
  import { NormalizedModel } from "../model/model.js";
3
3
  import { RefsResult } from "../model/refs.js";
4
4
  import { SliceReadyGates } from "../catalog/sliceReadyValidate.js";
5
+ import type { ShapeReport } from "../cli/shape.js";
5
6
  export declare const VALIDATE_SCHEMA_VERSION = "1.0";
6
7
  /** Build the plain `em validate <file> --json` document — the serialized diagnostics array
7
8
  * (stable `code`s, `refs`, line numbers, `usageCategory`) plus a pass/fail summary. Works on
8
9
  * a model with errors; `ok` mirrors `!hasErrors(diagnostics)`, the same predicate that gates
9
10
  * `em validate`'s exit code. */
10
11
  export declare function buildValidateJson(file: string, diagnostics: Diagnostic[]): string;
11
- export declare const VALIDATE_SLICE_READY_SCHEMA_VERSION = "1.2";
12
+ export declare const VALIDATE_SLICE_READY_SCHEMA_VERSION = "1.4";
12
13
  /** Build the `em validate <file> --slice-ready <key> --json` document — the machine verdict
13
14
  * replacing the two hand-parsed English sentences ("is ready-to-implement" /
14
15
  * "is NOT ready-to-implement") plus scraped warning prose. `gates` names each of the 5
@@ -20,7 +21,7 @@ export declare const VALIDATE_SLICE_READY_SCHEMA_VERSION = "1.2";
20
21
  * both-ends-of-a-flow diagnostic on one of its own elements); `diagnostics` carries that full
21
22
  * scoped list so a consumer sees exactly why, never just the 4 named gates. `continuationOf`
22
23
  * (MIL-208) is `null` for an ordinary slice or when `gates` is `null`. */
23
- export declare function buildSliceReadyJson(file: string, sliceKey: string, gates: SliceReadyGates | null, diagnostics: Diagnostic[], ready: boolean, continuationOf: string | null): string;
24
+ export declare function buildSliceReadyJson(file: string, sliceKey: string, gates: SliceReadyGates | null, diagnostics: Diagnostic[], ready: boolean, continuationOf: string | null, reviewSkipped?: string | null, advisories?: Diagnostic[]): string;
24
25
  export declare const VALIDATE_LIST_SCHEMA_VERSION = "1.1";
25
26
  /** One `--list-issues`/`--list-divergences`/`--list-public` entry — the structured replacement
26
27
  * for the ` issue :12 slice "X" command "Y": text` eyeball format. `elementRef` is the same
@@ -55,3 +56,5 @@ export declare function collectMarkers(model: NormalizedModel, refs: RefsResult,
55
56
  * same errors-only list text mode still prints (`em validate` fails the run on genuine
56
57
  * errors regardless of which `--list-*` flag was passed). */
57
58
  export declare function buildValidateListJson(file: string, markers: MarkerEntry[], diagnostics: Diagnostic[]): string;
59
+ export declare const VALIDATE_SHAPE_SCHEMA_VERSION = "1.0";
60
+ export declare function buildShapeJson(file: string, report: ShapeReport, modelErrors: number): string;
@@ -55,7 +55,15 @@ export function buildValidateJson(file, diagnostics) {
55
55
  // - MIL-266: `slice-ready-structured-section-malformed` (error) can join the scoped diagnostics
56
56
  // — a doc whose generated regions or `### Scenario:` blocks don't parse. Diagnostic-only:
57
57
  // `gates` is unchanged.
58
- export const VALIDATE_SLICE_READY_SCHEMA_VERSION = "1.2";
58
+ // 1.3 (GH #260, 1.17.0): top-level `reviewSkipped: string | null` — the status `em slice ratify
59
+ // --skip-review` ratified from when that bypass is what let the ratification through; null for a
60
+ // reviewed ratification, a doc predating 1.17, an unusable doc, or an unknown slice. Informational
61
+ // (not a gate): a host decides whether an unreviewed ratification passes. Additive-only.
62
+ // 1.4 (GH #293, 1.18.0): top-level `advisories: Diagnostic[]` — diagnostics of advisory rules
63
+ // (RuleDef.advisory, e.g. the scenario-quality warnings) concerning this slice. They are listed
64
+ // but never gate `ready`; under `--strict` they are promoted into `diagnostics` as errors and
65
+ // `advisories` is empty. Additive-only.
66
+ export const VALIDATE_SLICE_READY_SCHEMA_VERSION = "1.4";
59
67
  /** Build the `em validate <file> --slice-ready <key> --json` document — the machine verdict
60
68
  * replacing the two hand-parsed English sentences ("is ready-to-implement" /
61
69
  * "is NOT ready-to-implement") plus scraped warning prose. `gates` names each of the 5
@@ -67,7 +75,7 @@ export const VALIDATE_SLICE_READY_SCHEMA_VERSION = "1.2";
67
75
  * both-ends-of-a-flow diagnostic on one of its own elements); `diagnostics` carries that full
68
76
  * scoped list so a consumer sees exactly why, never just the 4 named gates. `continuationOf`
69
77
  * (MIL-208) is `null` for an ordinary slice or when `gates` is `null`. */
70
- export function buildSliceReadyJson(file, sliceKey, gates, diagnostics, ready, continuationOf) {
78
+ export function buildSliceReadyJson(file, sliceKey, gates, diagnostics, ready, continuationOf, reviewSkipped = null, advisories = []) {
71
79
  const doc = {
72
80
  validateSliceReadySchemaVersion: VALIDATE_SLICE_READY_SCHEMA_VERSION,
73
81
  generator: { name: GENERATOR_NAME, version: GENERATOR_VERSION },
@@ -75,8 +83,10 @@ export function buildSliceReadyJson(file, sliceKey, gates, diagnostics, ready, c
75
83
  sliceKey,
76
84
  gates,
77
85
  continuationOf,
86
+ reviewSkipped,
78
87
  ready,
79
88
  diagnostics: diagnostics.map(serializeDiagnosticWithUsage),
89
+ advisories: advisories.map(serializeDiagnosticWithUsage),
80
90
  };
81
91
  return JSON.stringify(doc, null, 2);
82
92
  }
@@ -137,4 +147,33 @@ export function buildValidateListJson(file, markers, diagnostics) {
137
147
  };
138
148
  return JSON.stringify(doc, null, 2);
139
149
  }
150
+ // 1.0 (GH #282): initial shape — `em validate --shape --json`. `rules[]` carries every shape-family
151
+ // rule (zero-count ones too, so a consumer sees what was checked), each with its `findings` (the
152
+ // diagnostics that count: message, line, refs) and `waived` (excused by `--waive-file`, never
153
+ // counted). `summary.findings` / `summary.waived` total them; `clean` is `summary.findings === 0`.
154
+ // `staleWaivers` lists waive-file lines that excused nothing (stale key or unknown rule code).
155
+ // `modelErrors` is the count of error diagnostics elsewhere in the model (shape output is
156
+ // incomplete while it is non-zero). Advisory: the exit code is 0 whatever the content.
157
+ export const VALIDATE_SHAPE_SCHEMA_VERSION = "1.0";
158
+ export function buildShapeJson(file, report, modelErrors) {
159
+ const ser = (d) => ({ message: d.message, line: d.line ?? null, refs: d.refs ?? [] });
160
+ const doc = {
161
+ shapeSchemaVersion: VALIDATE_SHAPE_SCHEMA_VERSION,
162
+ generator: { name: GENERATOR_NAME, version: GENERATOR_VERSION },
163
+ file,
164
+ clean: report.findings === 0,
165
+ modelErrors,
166
+ summary: { findings: report.findings, waived: report.waived, rules: report.rules.length },
167
+ staleWaivers: report.staleWaivers,
168
+ rules: report.rules.map((r) => ({
169
+ code: r.code,
170
+ title: r.title,
171
+ docAnchor: r.docAnchor,
172
+ count: r.findings.length,
173
+ findings: r.findings.map(ser),
174
+ waived: r.waived.map(ser),
175
+ })),
176
+ };
177
+ return JSON.stringify(doc, null, 2);
178
+ }
140
179
  //# sourceMappingURL=validateJson.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validateJson.js","sourceRoot":"","sources":["../../src/emit/validateJson.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validateJson.js","sourceRoot":"","sources":["../../src/emit/validateJson.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { Element, NormalizedModel } from "../model/model.js";
2
- export type Band = "header" | "automation" | "ui" | "api" | "event";
2
+ export type Band = "storyline" | "header" | "automation" | "ui" | "api" | "event";
3
3
  export declare const HEADER_KEY = "__header";
4
+ export declare const STORYLINE_KEY = "__storyline";
4
5
  export interface GridRow {
5
6
  key: string;
6
7
  label: string;
@@ -26,6 +27,9 @@ export interface LayoutOptions {
26
27
  /** Keep the structural command/view rows even when empty. */
27
28
  keepEmptyLanes?: boolean;
28
29
  }
30
+ /** Every alternative of the given event's `event A | B @Ctx` line, in declaration order
31
+ * (just the event itself when it has no alternatives). The first one is the grid cell's element. */
32
+ export declare function alternativesOf(model: NormalizedModel, el: Element): Element[];
29
33
  export declare function placeholderId(row: number, col: number): string;
30
34
  export declare function headerCellId(col: number): string;
31
35
  /** Node id at a grid coordinate (header cell, element, or placeholder). */
@@ -2,6 +2,8 @@
2
2
  // Turns a normalized model into a rigid R x C grid.
3
3
  //
4
4
  // Rows (bands), top -> bottom:
5
+ // -. storyline (only when the model declares `storyline` blocks, GH #277: a labelled band
6
+ // per run of a storyline's columns, drawn in render/storylineBands.ts)
5
7
  // 0. header (slice names — one visible cell per column)
6
8
  // 1. automation (single row, only if the model uses automation elements)
7
9
  // 2. ui (one row per persona)
@@ -13,6 +15,14 @@
13
15
  // Every (row, col) without a real element becomes an invisible placeholder so
14
16
  // that rank chains and weighted column edges keep the grid perfectly aligned.
15
17
  export const HEADER_KEY = "__header";
18
+ export const STORYLINE_KEY = "__storyline";
19
+ /** Every alternative of the given event's `event A | B @Ctx` line, in declaration order
20
+ * (just the event itself when it has no alternatives). The first one is the grid cell's element. */
21
+ export function alternativesOf(model, el) {
22
+ if (el.alternativeGroup === undefined)
23
+ return [el];
24
+ return model.elements.filter((e) => e.alternativeGroup === el.alternativeGroup && e.sliceIndex === el.sliceIndex);
25
+ }
16
26
  export function placeholderId(row, col) {
17
27
  return `__ph_${row}_${col}`;
18
28
  }
@@ -26,6 +36,48 @@ export function nodeIdAt(grid, row, col) {
26
36
  const el = grid.cells[row][col];
27
37
  return el ? el.id : placeholderId(row, col);
28
38
  }
39
+ /** A `view … again` instance may share an api cell with other `again` instances (GH #287). */
40
+ function isStackable(el) {
41
+ return el.kind === "view" && el.again === true;
42
+ }
43
+ /** The deepest api-cell stack any column needs: the largest count of `again` views in one slice
44
+ * whose api cell holds nothing but `again` views. 1 when nothing stacks. */
45
+ function apiStackDepth(model) {
46
+ let depth = 1;
47
+ for (const slice of model.slices) {
48
+ const api = slice.elements.filter((e) => e.kind === "command" || e.kind === "view");
49
+ if (api.length > 1 && api.every(isStackable))
50
+ depth = Math.max(depth, api.length);
51
+ }
52
+ return depth;
53
+ }
54
+ /** Slice indexes that are continuation-shaped: every non-`ui` element is an `again` view (at
55
+ * least one). Only these slices stack their `ui` boxes (GH #287). */
56
+ function continuationSlices(model) {
57
+ const out = new Set();
58
+ for (const slice of model.slices) {
59
+ const nonUi = slice.elements.filter((e) => e.kind !== "ui");
60
+ if (nonUi.length > 0 && nonUi.every(isStackable))
61
+ out.add(slice.index);
62
+ }
63
+ return out;
64
+ }
65
+ /** Per persona, the deepest ui-cell stack any continuation column needs (screens of one persona
66
+ * stack like the views do in the api lane). */
67
+ function uiStackDepths(model, continuation) {
68
+ const depths = new Map();
69
+ for (const slice of model.slices) {
70
+ if (!continuation.has(slice.index))
71
+ continue;
72
+ const counts = new Map();
73
+ for (const e of slice.elements)
74
+ if (e.kind === "ui")
75
+ counts.set(e.persona, (counts.get(e.persona) ?? 0) + 1);
76
+ for (const [persona, n] of counts)
77
+ depths.set(persona, Math.max(depths.get(persona) ?? 1, n));
78
+ }
79
+ return depths;
80
+ }
29
81
  function rowKeyForElement(el) {
30
82
  switch (el.kind) {
31
83
  case "ui":
@@ -44,28 +96,67 @@ function rowKeyForElement(el) {
44
96
  }
45
97
  export function layout(model, opts = {}) {
46
98
  const rows = [];
99
+ if ((model.storylines ?? []).length > 0) {
100
+ rows.push({ key: STORYLINE_KEY, label: "Storyline", band: "storyline" });
101
+ }
47
102
  rows.push({ key: HEADER_KEY, label: "", band: "header" });
48
103
  if (model.hasAutomation) {
49
104
  rows.push({ key: "automation", label: "Automation", band: "automation" });
50
105
  }
106
+ const continuation = continuationSlices(model);
107
+ const uiDepths = uiStackDepths(model, continuation);
51
108
  for (const persona of model.personas) {
52
109
  rows.push({ key: `ui:${persona}`, label: persona, band: "ui" });
110
+ // GH #287: extra rows (`ui:<persona>:2`, …) for screens stacked in one continuation column.
111
+ for (let n = 2; n <= (uiDepths.get(persona) ?? 1); n++)
112
+ rows.push({ key: `ui:${persona}:${n}`, label: "", band: "ui" });
53
113
  }
54
114
  rows.push({ key: "api", label: "API", band: "api" });
55
115
  for (const context of model.contexts) {
56
116
  rows.push({ key: `event:${context}`, label: context, band: "event" });
57
117
  }
118
+ // GH #287: several `again` views of one continuation slice stack in its api cell, so the api
119
+ // lane grows by one extra row per additional stacked view (`api:2`, `api:3`, …) — only the
120
+ // columns that stack use them, every other cell there is an invisible spacer.
121
+ const stackDepth = apiStackDepth(model);
122
+ if (stackDepth > 1) {
123
+ const apiAt = rows.findIndex((r) => r.key === "api");
124
+ const extra = [];
125
+ for (let n = 2; n <= stackDepth; n++)
126
+ extra.push({ key: `api:${n}`, label: "", band: "api" });
127
+ rows.splice(apiAt + 1, 0, ...extra);
128
+ }
58
129
  const indexOf = new Map();
59
130
  rows.forEach((r, i) => indexOf.set(r.key, i));
60
131
  const cols = model.slices.length;
61
132
  const cells = rows.map(() => new Array(cols).fill(null));
62
133
  const collisions = [];
134
+ const stacked = new Map(); // col -> views already in its api cell
135
+ const uiStacked = new Map(); // `${persona}|${col}` -> screens already in that ui cell
63
136
  for (const el of model.elements) {
64
- const r = indexOf.get(rowKeyForElement(el));
137
+ let r = indexOf.get(rowKeyForElement(el));
65
138
  if (r === undefined)
66
139
  continue; // unreachable, rows cover all kinds
67
140
  const c = el.sliceIndex;
68
- if (cells[r][c]) {
141
+ // GH #287: `again` views stack in the api lane, and screens of one persona stack in its ui
142
+ // lane, inside a continuation column.
143
+ if (isStackable(el) && cells[r][c] && isStackable(cells[r][c])) {
144
+ const depth = (stacked.get(c) ?? 1) + 1;
145
+ stacked.set(c, depth);
146
+ r = indexOf.get(`api:${depth}`);
147
+ }
148
+ if (el.kind === "ui" && cells[r][c] && continuation.has(c)) {
149
+ const k = `${el.persona}|${c}`;
150
+ const depth = (uiStacked.get(k) ?? 1) + 1;
151
+ uiStacked.set(k, depth);
152
+ r = indexOf.get(`ui:${el.persona}:${depth}`);
153
+ }
154
+ const occupant = cells[r][c];
155
+ // GH #278: alternatives of one `event A | B @Ctx` line share their context's cell — the
156
+ // first is the cell's element, the rest are drawn inside its box (emit/dot.ts).
157
+ if (occupant && el.alternativeGroup !== undefined && occupant.alternativeGroup === el.alternativeGroup)
158
+ continue;
159
+ if (occupant) {
69
160
  collisions.push({ rowKey: rows[r].key, col: c, kept: cells[r][c], dropped: el });
70
161
  continue;
71
162
  }
@@ -1 +1 @@
1
- {"version":3,"file":"grid.js","sourceRoot":"","sources":["../../src/layout/grid.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"grid.js","sourceRoot":"","sources":["../../src/layout/grid.ts"],"names":[],"mappings":"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"}
@@ -30,10 +30,11 @@ import { ParseError } from "../parser/parser.js";
30
30
  import { hasErrors } from "../model/validate.js";
31
31
  import { diffModels } from "../model/diff.js";
32
32
  import { buildExport, buildSliceExport, GENERATOR_VERSION } from "../emit/json.js";
33
- import { buildValidateJson, buildSliceReadyJson, buildValidateListJson, collectMarkers } from "../emit/validateJson.js";
33
+ import { buildValidateJson, buildShapeJson, buildSliceReadyJson, buildValidateListJson, collectMarkers } from "../emit/validateJson.js";
34
34
  import { buildDiffJson } from "../emit/diffJson.js";
35
35
  import { runApiCheck } from "../cli/api.js";
36
36
  import { buildApiCheckJson } from "../emit/apiCheckJson.js";
37
+ import { buildShapeReport, readWaiveFile } from "../cli/shape.js";
37
38
  import { validateLineage } from "../catalog/lineageValidate.js";
38
39
  import { validateFrontmatterCoherence } from "../catalog/frontmatterCoherenceValidate.js";
39
40
  import { validateNoteBindings } from "../catalog/noteBindingValidate.js";
@@ -41,10 +42,12 @@ import { validateDocModelConsistency } from "../catalog/docModelConsistencyValid
41
42
  import { validateOrphanedSliceDocs } from "../catalog/orphanedSliceDocValidate.js";
42
43
  import { validateModelVersionStale } from "../catalog/modelVersionValidate.js";
43
44
  import { validateInvariants } from "../catalog/invariantsValidate.js";
45
+ import { loadRoster } from "../roster/roster.js";
44
46
  import { computeSliceReadiness } from "../catalog/sliceReadyValidate.js";
45
- import { engagementPlanFor, engagementStatusFor } from "../cli/engagement.js";
47
+ import { engagementMembersFor, engagementPlanFor, engagementStatusFor } from "../cli/engagement.js";
48
+ import { checkFoundation } from "../cli/engagementFoundation.js";
46
49
  import { readOpenEngagements } from "../cli/engagementFile.js";
47
- import { buildEngagementPlanJson, buildEngagementStatusJson } from "../emit/engagementJson.js";
50
+ import { buildEngagementFoundationJson, buildEngagementPlanJson, buildEngagementStatusJson } from "../emit/engagementJson.js";
48
51
  import { buildSliceSyncJson, runSliceSync } from "../cli/sliceSync.js";
49
52
  import { buildCoverageReport, resolveScopedSlices, resolveCoverageSliceKey } from "../cli/coverage.js";
50
53
  import { buildCoverageJson } from "../emit/coverageJson.js";
@@ -68,6 +71,7 @@ import { buildMetricsJson } from "../emit/metricsJson.js";
68
71
  import { runSystemScope } from "../cli/scopeInputs.js";
69
72
  import { buildScopeJson } from "../emit/scopeJson.js";
70
73
  import { checkFindingsFile, buildCheckFindingsJson } from "../cli/findings.js";
74
+ import { checkPrdTriage, buildCheckPrdTriageJson } from "../cli/prdTriage.js";
71
75
  import { compileForQuery } from "../query/pipeline.js";
72
76
  import { buildQuerySystem } from "../query/system.js";
73
77
  import { queryConsumers, queryProducers, queryDownstream, queryUpstream, querySlices, queryInvariant, queryField, queryPath, } from "../query/verbs.js";
@@ -212,12 +216,25 @@ export function createServer() {
212
216
  "`em validate <file> --json` prints: a pass/fail summary plus every diagnostic (code, " +
213
217
  "message, line, refs, usageCategory). Works even when the model has errors — this is " +
214
218
  "the tool to call first when you just need to know what's wrong, or to confirm a model " +
215
- "is clean before exporting it.",
216
- inputSchema: { file: fileParam },
217
- }, async ({ file }) => {
219
+ "is clean before exporting it. With `shape: true` (GH #282) it returns the " +
220
+ "`em validate <file> --shape --json` document instead: only the advisory shape-family " +
221
+ "lints, per-rule finding arrays with refs (`shapeSchemaVersion`), never a failure; " +
222
+ "`waiveFile` (a path, only with `shape`) baselines accepted slice keys.",
223
+ inputSchema: {
224
+ file: fileParam,
225
+ shape: z.boolean().default(false).describe("GH #282: return the shape-lint view (`em validate --shape --json`) instead of the full diagnostics"),
226
+ waiveFile: z.string().optional().describe("with `shape`: path of a waive file (one slice key per line, `#` comments) whose shape findings are listed as waived, not counted"),
227
+ },
228
+ }, async ({ file, shape, waiveFile }) => {
218
229
  const compiled = compileWithValidation(file);
219
230
  if ("error" in compiled)
220
231
  return errorResult(compiled.error);
232
+ if (waiveFile && !shape)
233
+ return errorResult("waiveFile applies only with shape: true");
234
+ if (shape) {
235
+ const report = buildShapeReport(compiled.allDiagnostics, waiveFile ? readWaiveFile(waiveFile) : []);
236
+ return textResult(buildShapeJson(file, report, compiled.allDiagnostics.filter((d) => d.severity === "error").length));
237
+ }
221
238
  return textResult(buildValidateJson(file, compiled.allDiagnostics));
222
239
  });
223
240
  server.registerTool("slice_ready", {
@@ -228,16 +245,27 @@ export function createServer() {
228
245
  "contract current for a public-touching slice), the " +
229
246
  "overall `ready` boolean, and the scoped diagnostics behind it. Call this before " +
230
247
  "implementing a slice — never infer readiness yourself from `export_slice`'s content.",
231
- inputSchema: { file: fileParam, sliceKey: sliceKeyParam },
232
- }, async ({ file, sliceKey }) => {
248
+ inputSchema: {
249
+ file: fileParam,
250
+ sliceKey: sliceKeyParam,
251
+ requireRatifiedHash: z
252
+ .boolean()
253
+ .default(false)
254
+ .describe("GH #256 strict mode (`em validate --slice-ready --require-ratified-hash`): a ready-to-implement doc with no `ratifiedHash:` is not ready"),
255
+ roster: z
256
+ .string()
257
+ .optional()
258
+ .describe("GH #259: path of the ratifier roster to check `ratifiedBy` against (`em validate --slice-ready --roster`); omitted = the nearest ratifiers.yaml above the model, none = unrestricted"),
259
+ },
260
+ }, async ({ file, sliceKey, requireRatifiedHash, roster }) => {
233
261
  const compiled = compileWithValidation(file);
234
262
  if ("error" in compiled)
235
263
  return errorResult(compiled.error);
236
264
  const { model, refs, allDiagnostics, source, diagnostics } = compiled;
237
265
  const baseDir = dirname(file);
238
266
  const contractInput = { file, source, diagnostics };
239
- const { scoped, ready, result } = computeSliceReadiness(model, refs, baseDir, sliceKey, contractInput, allDiagnostics);
240
- return textResult(buildSliceReadyJson(file, sliceKey, result?.gates ?? null, scoped, ready, result?.continuationOf ?? null));
267
+ const { scoped, advisories, ready, result } = computeSliceReadiness(model, refs, baseDir, sliceKey, contractInput, allDiagnostics, { requireRatifiedHash, rosterPath: roster });
268
+ return textResult(buildSliceReadyJson(file, sliceKey, result?.gates ?? null, scoped, ready, result?.continuationOf ?? null, result?.reviewSkipped ?? null, advisories));
241
269
  });
242
270
  server.registerTool("slice_sync", {
243
271
  title: "Check slice docs' generated regions against the model",
@@ -478,7 +506,7 @@ export function createServer() {
478
506
  const emVersion = compiledFiles
479
507
  .map(({ file }) => resolveEmVersionStatusEntry(file, GENERATOR_VERSION))
480
508
  .filter((e) => e !== null);
481
- const report = buildStatusReport(files, sliceFacts, openIssuesCount, invariants, conformance, statusDiagnostics, modelVersion, emVersion, statusSystemBlock(files[0]), readOpenEngagements(files));
509
+ const report = buildStatusReport(files, sliceFacts, openIssuesCount, invariants, conformance, statusDiagnostics, modelVersion, emVersion, statusSystemBlock(files[0]), readOpenEngagements(files), loadRoster(dirname(files[0])).state);
482
510
  return textResult(buildStatusJson(report));
483
511
  });
484
512
  server.registerTool("upgrade", {
@@ -769,6 +797,20 @@ export function createServer() {
769
797
  }, async ({ path }) => {
770
798
  return textResult(buildCheckFindingsJson(checkFindingsFile(path)));
771
799
  });
800
+ server.registerTool("discover_triage_check", {
801
+ title: "Check a PRD/spec discovery triage record",
802
+ description: "Return the same JSON document `em discover triage-check <path> --json` prints (GH #295): " +
803
+ "whether a discovery/prd-triage.json is valid (prdTriageSchemaVersion 1.0, the shipped " +
804
+ "rubric version, every statement/storyline quote appearing verbatim in the input " +
805
+ "document, every statement carrying a category and outcome, modeled/rewritten ones a " +
806
+ "group and storyline). `source` overrides the file's own `source` path.",
807
+ inputSchema: {
808
+ path: z.string().describe("path to a discovery/prd-triage.json file"),
809
+ source: z.string().optional().describe("the input PRD/spec to check quotes against (default: the file's own `source`)"),
810
+ },
811
+ }, async ({ path, source }) => {
812
+ return textResult(buildCheckPrdTriageJson(checkPrdTriage(path, { source })));
813
+ });
772
814
  server.registerTool("query", {
773
815
  title: "Deterministic graph queries over the compiled model",
774
816
  description: "Return the same JSON document `em query <verb> <files...> --json` prints (MIL-168): " +
@@ -797,13 +839,14 @@ export function createServer() {
797
839
  context: z.string().optional().describe("slices: match a slice with an event in this @Context"),
798
840
  persona: z.string().optional().describe("slices: match a slice with a ui in this @Persona"),
799
841
  tag: z.string().optional().describe("slices: match a slice with an event carrying this tag key"),
842
+ storyline: z.string().optional().describe("slices: match a slice declared in this `storyline` block"),
800
843
  id: z.string().optional().describe("invariant: the INV-* id to look up"),
801
844
  testsDir: z.string().optional().describe("invariant: directory to scan for test files citing this id"),
802
845
  name: z.string().optional().describe("field: the field's name"),
803
846
  from: z.string().optional().describe("path: the starting element's export ref or display name"),
804
847
  to: z.string().optional().describe("path: the ending element's export ref or display name"),
805
848
  },
806
- }, async ({ files, verb, event, of, depth, pattern, status, context, persona, tag, id, testsDir, name, from, to }) => {
849
+ }, async ({ files, verb, event, of, depth, pattern, status, context, persona, tag, storyline, id, testsDir, name, from, to }) => {
807
850
  if (testsDir !== undefined) {
808
851
  if (!existsSync(testsDir))
809
852
  return errorResult(`testsDir not found: ${testsDir}`);
@@ -848,7 +891,7 @@ export function createServer() {
848
891
  return textResult(buildQueryJson(verb, files, { of, depth: depth ?? null }, result.results));
849
892
  }
850
893
  case "slices": {
851
- const filters = { pattern, status, context, persona, tag };
894
+ const filters = { pattern, status, context, persona, tag, storyline };
852
895
  const result = querySlices(system, filters);
853
896
  if (!result.ok)
854
897
  return errorResult(result.error);
@@ -979,7 +1022,9 @@ export function createServer() {
979
1022
  "the engagement's slices in dependency levels over model.edges (loops-to excluded), each " +
980
1023
  "with its --slice-ready verdict, branch impl/<key>, base (always main — every slice PR " +
981
1024
  "targets main, MIL-280), and any computed hold (not-ready, " +
982
- "upstream-outside-engagement-unmerged); level widths vs the parallel ceiling. Read-only. " +
1025
+ "upstream-outside-engagement-unmerged); level widths vs the parallel ceiling; and `preflight` (GH #239, plus a `shape` kind per shape-family lint firing on the engagement's slices, GH #282 — answered by a `shape-accepted:` bullet in `.event-modeling.md`) — " +
1026
+ "the model-wide gaps the engagement's slices share (repeated-invariant, event-without-tag, shared-trigger, " +
1027
+ "doc-model-mismatch), to put to the human in ONE question round before fan-out. Read-only. " +
983
1028
  "Tool error when the engagement is missing or has a cycle.",
984
1029
  inputSchema: { file: fileParam, slug: slugParam },
985
1030
  }, async ({ file, slug }) => {
@@ -1009,6 +1054,26 @@ export function createServer() {
1009
1054
  return errorResult(`em engagement status: ${result.message}`);
1010
1055
  return textResult(buildEngagementStatusJson(result.status));
1011
1056
  });
1057
+ server.registerTool("engagement_foundation", {
1058
+ title: "Check the foundation PR is in the code for an engagement's events",
1059
+ description: "Return the same JSON document `em engagement foundation <file> <slug> --code <dir> --json` prints (GH #240): " +
1060
+ "for every event the engagement's slices emit or consume, whether a file under `code` carries an identifier " +
1061
+ "derived from its name (OrderPlaced / order_placed / ORDER_PLACED / order-placed) and, in those files, each " +
1062
+ "model field and tag field — per event `present` | `incomplete` (missingFields / missingTagFields named) | " +
1063
+ "`missing-event`, so the lead can tell \"foundation absent\" from \"foundation incomplete\" before fan-out. " +
1064
+ "A text scan, not a type check. Read-only.",
1065
+ inputSchema: { file: fileParam, slug: slugParam, code: z.string().describe("the target repository directory to scan") },
1066
+ }, async ({ file, slug, code }) => {
1067
+ if (!existsSync(code) || !statSync(code).isDirectory())
1068
+ return errorResult(`em engagement foundation: --code ${code} is not a directory`);
1069
+ const compiled = compileFile(file);
1070
+ if ("error" in compiled)
1071
+ return errorResult(compiled.error);
1072
+ const members = engagementMembersFor({ file, model: compiled.model, refs: compiled.refs, baseDir: dirname(file) }, slug);
1073
+ if (!members.ok)
1074
+ return errorResult(`em engagement foundation: ${members.message}`);
1075
+ return textResult(buildEngagementFoundationJson(file, slug, checkFoundation(compiled.model, members.members, members.idx, code)));
1076
+ });
1012
1077
  return server;
1013
1078
  }
1014
1079
  //# sourceMappingURL=server.js.map