@milehimikey/em 1.13.0 → 1.14.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 (239) hide show
  1. package/.claude/agents/em-critic.md +26 -0
  2. package/.claude/agents/em-implementer.md +34 -0
  3. package/.claude/agents/em-reviewer.md +31 -0
  4. package/.claude/agents/em-validator.md +27 -0
  5. package/.claude/skills/event-modeling/SKILL.md +52 -12
  6. package/.claude/skills/event-modeling-conform/SKILL.md +1 -1
  7. package/.claude/skills/event-modeling-conform/reference/conform.md +1 -1
  8. package/.claude/skills/event-modeling-design/SKILL.md +140 -18
  9. package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
  10. package/.claude/skills/event-modeling-engagement/SKILL.md +192 -0
  11. package/.claude/skills/event-modeling-engagement/reference/engagement.md +143 -0
  12. package/.claude/skills/event-modeling-implement/SKILL.md +7 -4
  13. package/.claude/skills/event-modeling-implement/reference/implement.md +51 -12
  14. package/.claude/skills/event-modeling-review/SKILL.md +1 -1
  15. package/.claude/skills/event-modeling-shared/reference/em-dsl.md +274 -188
  16. package/.claude/skills/event-modeling-shared/reference/operating-principles.md +61 -0
  17. package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +116 -4
  18. package/.claude/skills/event-modeling-shared/templates/constitution.md +18 -1
  19. package/.claude/skills/event-modeling-shared/templates/slice.md +64 -39
  20. package/.claude/skills/event-modeling-shared/templates/state.md +5 -1
  21. package/.claude-plugin/marketplace.json +14 -0
  22. package/README.md +25 -11
  23. package/dist/catalog/apiFirst.d.ts +28 -0
  24. package/dist/catalog/apiFirst.js +49 -0
  25. package/dist/catalog/apiFirst.js.map +1 -0
  26. package/dist/catalog/docJoin.d.ts +13 -0
  27. package/dist/catalog/docJoin.js +11 -0
  28. package/dist/catalog/docJoin.js.map +1 -1
  29. package/dist/catalog/docModelConsistencyValidate.js +44 -4
  30. package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
  31. package/dist/catalog/invariantsValidate.d.ts +4 -0
  32. package/dist/catalog/invariantsValidate.js +102 -0
  33. package/dist/catalog/invariantsValidate.js.map +1 -0
  34. package/dist/catalog/scenarios.d.ts +15 -0
  35. package/dist/catalog/scenarios.js +97 -0
  36. package/dist/catalog/scenarios.js.map +1 -0
  37. package/dist/catalog/sliceDoc.d.ts +8 -0
  38. package/dist/catalog/sliceDoc.js +9 -0
  39. package/dist/catalog/sliceDoc.js.map +1 -1
  40. package/dist/catalog/sliceReadyValidate.d.ts +31 -4
  41. package/dist/catalog/sliceReadyValidate.js +66 -8
  42. package/dist/catalog/sliceReadyValidate.js.map +1 -1
  43. package/dist/catalog/sliceSections.d.ts +55 -0
  44. package/dist/catalog/sliceSections.js +317 -0
  45. package/dist/catalog/sliceSections.js.map +1 -0
  46. package/dist/cli/agentsMd.js +7 -1
  47. package/dist/cli/agentsMd.js.map +1 -1
  48. package/dist/cli/api.d.ts +90 -0
  49. package/dist/cli/api.js +318 -0
  50. package/dist/cli/api.js.map +1 -0
  51. package/dist/cli/ciInit.d.ts +88 -3
  52. package/dist/cli/ciInit.js +507 -50
  53. package/dist/cli/ciInit.js.map +1 -1
  54. package/dist/cli/conformScope.d.ts +28 -0
  55. package/dist/cli/conformScope.js +67 -0
  56. package/dist/cli/conformScope.js.map +1 -1
  57. package/dist/cli/coverage.d.ts +25 -2
  58. package/dist/cli/coverage.js +86 -12
  59. package/dist/cli/coverage.js.map +1 -1
  60. package/dist/cli/engagement.d.ts +210 -0
  61. package/dist/cli/engagement.js +444 -0
  62. package/dist/cli/engagement.js.map +1 -0
  63. package/dist/cli/engagementFile.d.ts +86 -0
  64. package/dist/cli/engagementFile.js +255 -0
  65. package/dist/cli/engagementFile.js.map +1 -0
  66. package/dist/cli/metrics.d.ts +10 -0
  67. package/dist/cli/metrics.js +49 -1
  68. package/dist/cli/metrics.js.map +1 -1
  69. package/dist/cli/pluginPin.d.ts +55 -0
  70. package/dist/cli/pluginPin.js +188 -0
  71. package/dist/cli/pluginPin.js.map +1 -0
  72. package/dist/cli/ratify.d.ts +27 -2
  73. package/dist/cli/ratify.js +112 -13
  74. package/dist/cli/ratify.js.map +1 -1
  75. package/dist/cli/reratify.d.ts +11 -4
  76. package/dist/cli/reratify.js +89 -35
  77. package/dist/cli/reratify.js.map +1 -1
  78. package/dist/cli/scopeInputs.d.ts +48 -0
  79. package/dist/cli/scopeInputs.js +176 -0
  80. package/dist/cli/scopeInputs.js.map +1 -0
  81. package/dist/cli/skillCheck.d.ts +15 -1
  82. package/dist/cli/skillCheck.js +22 -1
  83. package/dist/cli/skillCheck.js.map +1 -1
  84. package/dist/cli/skillDirs.d.ts +5 -0
  85. package/dist/cli/skillDirs.js +13 -1
  86. package/dist/cli/skillDirs.js.map +1 -1
  87. package/dist/cli/skillSync.d.ts +4 -0
  88. package/dist/cli/skillSync.js +23 -0
  89. package/dist/cli/skillSync.js.map +1 -1
  90. package/dist/cli/sliceNew.d.ts +11 -7
  91. package/dist/cli/sliceNew.js +91 -18
  92. package/dist/cli/sliceNew.js.map +1 -1
  93. package/dist/cli/sliceSync.d.ts +50 -0
  94. package/dist/cli/sliceSync.js +170 -0
  95. package/dist/cli/sliceSync.js.map +1 -0
  96. package/dist/cli/status.d.ts +24 -1
  97. package/dist/cli/status.js +20 -1
  98. package/dist/cli/status.js.map +1 -1
  99. package/dist/cli/systemInputs.d.ts +53 -10
  100. package/dist/cli/systemInputs.js +186 -11
  101. package/dist/cli/systemInputs.js.map +1 -1
  102. package/dist/cli/upgrade.d.ts +30 -7
  103. package/dist/cli/upgrade.js +434 -50
  104. package/dist/cli/upgrade.js.map +1 -1
  105. package/dist/cli/usageLog.d.ts +4 -2
  106. package/dist/cli/usageLog.js +4 -2
  107. package/dist/cli/usageLog.js.map +1 -1
  108. package/dist/cli.js +631 -100
  109. package/dist/cli.js.map +1 -1
  110. package/dist/emit/api.d.ts +29 -0
  111. package/dist/emit/api.js +220 -0
  112. package/dist/emit/api.js.map +1 -0
  113. package/dist/emit/apiCheckJson.d.ts +3 -0
  114. package/dist/emit/apiCheckJson.js +21 -0
  115. package/dist/emit/apiCheckJson.js.map +1 -0
  116. package/dist/emit/codeownersJson.d.ts +3 -0
  117. package/dist/emit/codeownersJson.js +19 -0
  118. package/dist/emit/codeownersJson.js.map +1 -0
  119. package/dist/emit/coverageJson.d.ts +5 -2
  120. package/dist/emit/coverageJson.js +6 -2
  121. package/dist/emit/coverageJson.js.map +1 -1
  122. package/dist/emit/diffJson.d.ts +1 -1
  123. package/dist/emit/diffJson.js +8 -1
  124. package/dist/emit/diffJson.js.map +1 -1
  125. package/dist/emit/engagementJson.d.ts +8 -0
  126. package/dist/emit/engagementJson.js +46 -0
  127. package/dist/emit/engagementJson.js.map +1 -0
  128. package/dist/emit/glossaryJson.d.ts +1 -1
  129. package/dist/emit/glossaryJson.js +4 -1
  130. package/dist/emit/glossaryJson.js.map +1 -1
  131. package/dist/emit/json.d.ts +17 -1
  132. package/dist/emit/json.js +30 -1
  133. package/dist/emit/json.js.map +1 -1
  134. package/dist/emit/metricsJson.d.ts +1 -1
  135. package/dist/emit/metricsJson.js +4 -1
  136. package/dist/emit/metricsJson.js.map +1 -1
  137. package/dist/emit/queryJson.d.ts +1 -1
  138. package/dist/emit/queryJson.js +7 -1
  139. package/dist/emit/queryJson.js.map +1 -1
  140. package/dist/emit/scopeJson.d.ts +12 -0
  141. package/dist/emit/scopeJson.js +26 -0
  142. package/dist/emit/scopeJson.js.map +1 -0
  143. package/dist/emit/skillCheckJson.d.ts +3 -2
  144. package/dist/emit/skillCheckJson.js +10 -2
  145. package/dist/emit/skillCheckJson.js.map +1 -1
  146. package/dist/emit/statusJson.d.ts +1 -1
  147. package/dist/emit/statusJson.js +15 -1
  148. package/dist/emit/statusJson.js.map +1 -1
  149. package/dist/emit/systemJson.d.ts +15 -8
  150. package/dist/emit/systemJson.js +28 -13
  151. package/dist/emit/systemJson.js.map +1 -1
  152. package/dist/emit/upgradeJson.d.ts +1 -1
  153. package/dist/emit/upgradeJson.js +4 -1
  154. package/dist/emit/upgradeJson.js.map +1 -1
  155. package/dist/emit/validateJson.d.ts +3 -3
  156. package/dist/emit/validateJson.js +10 -4
  157. package/dist/emit/validateJson.js.map +1 -1
  158. package/dist/mcp/server.d.ts +1 -1
  159. package/dist/mcp/server.js +186 -37
  160. package/dist/mcp/server.js.map +1 -1
  161. package/dist/model/diff.d.ts +4 -1
  162. package/dist/model/diff.js +44 -8
  163. package/dist/model/diff.js.map +1 -1
  164. package/dist/model/glossary.d.ts +2 -0
  165. package/dist/model/glossary.js +1 -0
  166. package/dist/model/glossary.js.map +1 -1
  167. package/dist/model/model.d.ts +55 -2
  168. package/dist/model/model.js +57 -0
  169. package/dist/model/model.js.map +1 -1
  170. package/dist/model/qualifiedRef.d.ts +18 -0
  171. package/dist/model/qualifiedRef.js +26 -0
  172. package/dist/model/qualifiedRef.js.map +1 -1
  173. package/dist/model/queryIndex.d.ts +9 -1
  174. package/dist/model/queryIndex.js +18 -2
  175. package/dist/model/queryIndex.js.map +1 -1
  176. package/dist/model/rules.d.ts +143 -2
  177. package/dist/model/rules.js +162 -3
  178. package/dist/model/rules.js.map +1 -1
  179. package/dist/model/validate.d.ts +40 -0
  180. package/dist/model/validate.js +147 -1
  181. package/dist/model/validate.js.map +1 -1
  182. package/dist/parser/ast.d.ts +31 -3
  183. package/dist/parser/parser.js +148 -14
  184. package/dist/parser/parser.js.map +1 -1
  185. package/dist/query/format.js +1 -1
  186. package/dist/query/format.js.map +1 -1
  187. package/dist/query/verbs.d.ts +6 -0
  188. package/dist/query/verbs.js +6 -2
  189. package/dist/query/verbs.js.map +1 -1
  190. package/dist/system/adaptation.d.ts +14 -0
  191. package/dist/system/adaptation.js +49 -0
  192. package/dist/system/adaptation.js.map +1 -0
  193. package/dist/system/codeowners.d.ts +77 -0
  194. package/dist/system/codeowners.js +242 -0
  195. package/dist/system/codeowners.js.map +1 -0
  196. package/dist/system/manifest.d.ts +10 -5
  197. package/dist/system/manifest.js +54 -26
  198. package/dist/system/manifest.js.map +1 -1
  199. package/dist/system/migrateManifest.d.ts +28 -0
  200. package/dist/system/migrateManifest.js +155 -0
  201. package/dist/system/migrateManifest.js.map +1 -0
  202. package/dist/system/scope.d.ts +46 -0
  203. package/dist/system/scope.js +132 -0
  204. package/dist/system/scope.js.map +1 -0
  205. package/dist/system/verify.d.ts +50 -13
  206. package/dist/system/verify.js +179 -58
  207. package/dist/system/verify.js.map +1 -1
  208. package/dist/templates.d.ts +2 -2
  209. package/dist/templates.js +23 -2
  210. package/dist/templates.js.map +1 -1
  211. package/package.json +6 -3
  212. package/plugin/.claude-plugin/plugin.json +18 -0
  213. package/plugin/agents/em-critic.md +27 -0
  214. package/plugin/agents/em-implementer.md +35 -0
  215. package/plugin/agents/em-reviewer.md +32 -0
  216. package/plugin/agents/em-validator.md +28 -0
  217. package/plugin/shared/reference/em-dsl.md +866 -0
  218. package/plugin/shared/reference/methodology.md +329 -0
  219. package/plugin/shared/reference/operating-principles.md +222 -0
  220. package/plugin/shared/reference/slice-doc-schema.md +566 -0
  221. package/plugin/shared/templates/conformance-report.md +85 -0
  222. package/plugin/shared/templates/constitution.md +136 -0
  223. package/plugin/shared/templates/model-readme.md +46 -0
  224. package/plugin/shared/templates/slice.md +251 -0
  225. package/plugin/shared/templates/state.md +77 -0
  226. package/plugin/skills/conform/SKILL.md +93 -0
  227. package/plugin/skills/conform/reference/conform.md +428 -0
  228. package/plugin/skills/design/SKILL.md +297 -0
  229. package/plugin/skills/discover/SKILL.md +90 -0
  230. package/plugin/skills/discover/reference/extract.md +147 -0
  231. package/plugin/skills/engagement/SKILL.md +193 -0
  232. package/plugin/skills/engagement/reference/engagement.md +144 -0
  233. package/plugin/skills/event-modeling/SKILL.md +132 -0
  234. package/plugin/skills/implement/SKILL.md +61 -0
  235. package/plugin/skills/implement/reference/implement.md +439 -0
  236. package/plugin/skills/review/SKILL.md +74 -0
  237. package/dist/emit/typespec.d.ts +0 -26
  238. package/dist/emit/typespec.js +0 -356
  239. package/dist/emit/typespec.js.map +0 -1
@@ -81,4 +81,27 @@ export function applySkillSyncBundle(bundlePlan, packagedRoot, vendoredRoot) {
81
81
  applySkillSync(plan, join(packagedRoot, dirName), join(vendoredRoot, dirName));
82
82
  }
83
83
  }
84
+ // ---- Agent files (MIL-269, R32) — `.claude/agents/` is shared with the consumer's own agents, so
85
+ // unlike planSkillSync these walk a FIXED list of file names and never report anything as
86
+ // `removed`: a file that is not on the list is not em's to list, touch or delete.
87
+ /** Pure: per listed file, `added` (absent in vendoredDir), `modified` (hash differs) or unchanged.
88
+ * A listed file missing from packagedDir is skipped. Never lists, reads or removes anything else
89
+ * in vendoredDir. Apply with `applySkillSync(plan, packagedDir, vendoredDir)`. */
90
+ export function planAgentSync(packagedDir, vendoredDir, fileNames) {
91
+ const changes = [];
92
+ let unchangedCount = 0;
93
+ for (const relPath of [...fileNames].sort()) {
94
+ const src = join(packagedDir, relPath);
95
+ if (!existsSync(src))
96
+ continue;
97
+ const dest = join(vendoredDir, relPath);
98
+ if (!existsSync(dest))
99
+ changes.push({ relPath, kind: "added" });
100
+ else if (sha256(src) !== sha256(dest))
101
+ changes.push({ relPath, kind: "modified" });
102
+ else
103
+ unchangedCount++;
104
+ }
105
+ return { changes, unchangedCount };
106
+ }
84
107
  //# sourceMappingURL=skillSync.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"skillSync.js","sourceRoot":"","sources":["../../src/cli/skillSync.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skillSync.js","sourceRoot":"","sources":["../../src/cli/skillSync.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { GeneratedRegion } from "../catalog/sliceSections.js";
1
2
  /** `pattern`'s exact 4-value enum — docs/slice-doc-schema.md's "Canonical keys" table. */
2
3
  export declare const SLICE_PATTERNS: readonly ["state-change", "state-view", "automation", "translation"];
3
4
  export type SlicePattern = (typeof SLICE_PATTERNS)[number];
@@ -8,14 +9,17 @@ export declare function isSlicePattern(value: string): value is SlicePattern;
8
9
  * pass a pre-slugged key of their own, so the two can never drift apart. */
9
10
  export declare function sliceDocKey(displayName: string): string;
10
11
  /**
11
- * Build the full contents of a fresh `slices/<key>.md`. Frontmatter: exactly the 5 keys
12
- * required at `status: draft`, in the same order templates/slice.md's own frontmatter block
13
- * uses. Body: the `# Slice: <name>` heading and the diagram-image stub the skill's `slice`
14
- * phase step 3 fills the actual image in for (`em render ... --slice ... -o
15
- * slices/<key>.svg`) — every judgment section (Intent, Command, Scenarios, Open Questions,
16
- * ...) is deliberately left out, staying hand-authored per templates/slice.md.
12
+ * Build the full contents of a fresh `slices/<key>.md` (MIL-266: the whole template skeleton).
13
+ * Frontmatter: exactly the 5 keys required at `status: draft`, in the same order
14
+ * templates/slice.md's own frontmatter block uses. Body: the `# Slice: <name>` heading, the
15
+ * diagram-image stub, then every template section in template order (`## Delta` excepted — a
16
+ * version-1 doc has no delta yet). The GENERATED regions (command/event/view field tables, the
17
+ * Invariants list — catalog/sliceSections.ts) are filled from `regions`: the model's own regions
18
+ * when `em slice new --wire` compiled one, else the template's placeholder regions, which
19
+ * `em slice sync` fills once the doc is bound. Authored sections carry the template's
20
+ * placeholder bullets and stay hand-written.
17
21
  */
18
- export declare function buildSliceDocContent(displayName: string, key: string, pattern: SlicePattern, swimlane: string): string;
22
+ export declare function buildSliceDocContent(displayName: string, key: string, pattern: SlicePattern, swimlane: string, regions?: GeneratedRegion[]): string;
19
23
  /**
20
24
  * Build the full contents of a fresh, near-free `slices/<key>.md` STUB (MIL-184: `em slice new
21
25
  * --stub` / `em slice stub-all`) — the same 5 frontmatter keys `buildSliceDocContent` writes
@@ -1,6 +1,7 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // `em slice new` (MIL-97 item 3): scaffolds a fresh slices/<key>.md doc's mechanical
3
- // frontmatter + heading — exactly the 5 keys docs/slice-doc-schema.md's required-vs-optional
3
+ // frontmatter + heading (MIL-266: plus the full template skeleton — see buildSliceDocContent;
4
+ // the paragraph below describes the frontmatter, which is unchanged) — exactly the 5 keys docs/slice-doc-schema.md's required-vs-optional
4
5
  // table requires at `status: draft` (schemaVersion/pattern/swimlane/status/version), nothing
5
6
  // else — no `implementedIn` (only required once a slice has ever reached `implemented`), no
6
7
  // lineage keys (`split-from`/`merged-from`/`superseded-by` only apply to a split/merge/rename
@@ -13,6 +14,7 @@
13
14
  // the printed `note` reminder, same split as sliceIndex.ts (buildSliceIndexTable vs
14
15
  // runSliceIndex/CLI wiring).
15
16
  import { kebabSlug } from "../util/slug.js";
17
+ import { INVARIANTS_ELABORATE_COMMENT, placeholderRegions, regionEndLine, regionStartLine, } from "../catalog/sliceSections.js";
16
18
  /** `pattern`'s exact 4-value enum — docs/slice-doc-schema.md's "Canonical keys" table. */
17
19
  export const SLICE_PATTERNS = ["state-change", "state-view", "automation", "translation"];
18
20
  export function isSlicePattern(value) {
@@ -31,24 +33,95 @@ export function sliceDocKey(displayName) {
31
33
  return kebabSlug(displayName);
32
34
  }
33
35
  /**
34
- * Build the full contents of a fresh `slices/<key>.md`. Frontmatter: exactly the 5 keys
35
- * required at `status: draft`, in the same order templates/slice.md's own frontmatter block
36
- * uses. Body: the `# Slice: <name>` heading and the diagram-image stub the skill's `slice`
37
- * phase step 3 fills the actual image in for (`em render ... --slice ... -o
38
- * slices/<key>.svg`) — every judgment section (Intent, Command, Scenarios, Open Questions,
39
- * ...) is deliberately left out, staying hand-authored per templates/slice.md.
36
+ * Build the full contents of a fresh `slices/<key>.md` (MIL-266: the whole template skeleton).
37
+ * Frontmatter: exactly the 5 keys required at `status: draft`, in the same order
38
+ * templates/slice.md's own frontmatter block uses. Body: the `# Slice: <name>` heading, the
39
+ * diagram-image stub, then every template section in template order (`## Delta` excepted — a
40
+ * version-1 doc has no delta yet). The GENERATED regions (command/event/view field tables, the
41
+ * Invariants list — catalog/sliceSections.ts) are filled from `regions`: the model's own regions
42
+ * when `em slice new --wire` compiled one, else the template's placeholder regions, which
43
+ * `em slice sync` fills once the doc is bound. Authored sections carry the template's
44
+ * placeholder bullets and stay hand-written.
40
45
  */
41
- export function buildSliceDocContent(displayName, key, pattern, swimlane) {
42
- return (`---\n` +
43
- `schemaVersion: ${SCHEMA_VERSION}\n` +
44
- `pattern: ${pattern}\n` +
45
- `swimlane: ${swimlane}\n` +
46
- `status: draft\n` +
47
- `version: 1\n` +
48
- `---\n` +
49
- `# Slice: ${displayName}\n` +
50
- `\n` +
51
- `![Diagram](./${key}.svg)\n`);
46
+ export function buildSliceDocContent(displayName, key, pattern, swimlane, regions = placeholderRegions()) {
47
+ const block = (kind) => {
48
+ const out = [];
49
+ for (const r of regions) {
50
+ if (r.kind !== kind)
51
+ continue;
52
+ out.push(regionStartLine(r.name), ...r.body, regionEndLine(r.name));
53
+ }
54
+ return out;
55
+ };
56
+ const lines = [
57
+ `---`,
58
+ `schemaVersion: ${SCHEMA_VERSION}`,
59
+ `pattern: ${pattern}`,
60
+ `swimlane: ${swimlane}`,
61
+ `status: draft`,
62
+ `version: 1`,
63
+ `---`,
64
+ `# Slice: ${displayName}`,
65
+ ``,
66
+ `![Diagram](./${key}.svg)`,
67
+ ``,
68
+ `## Intent`,
69
+ `{{Why this slice exists — the user or business goal it serves, in one or two sentences. Note the`,
70
+ `originating ticket/conversation link here if one exists.}}`,
71
+ ``,
72
+ `## Trigger & Actor`,
73
+ `{{Who or what initiates this slice and under what circumstances. For automations, the watched`,
74
+ `read model and the triggering condition. For translations, state the trigger form: externally`,
75
+ `triggered (the external system/source feeding us) or internally triggered (the read model whose`,
76
+ `state we react to). Either way, name the command this reaction triggers — reactions never record`,
77
+ `an event directly.}}`,
78
+ ``,
79
+ `## Command / Input`,
80
+ ...block("command"),
81
+ ``,
82
+ `## Trigger`,
83
+ "**Triggered by:** {{screen `X` @Persona | processor `Y`, also in this slice}}",
84
+ ``,
85
+ `## Event(s) Emitted`,
86
+ ...block("event"),
87
+ `**Read by:** {{which read model projects this event, and in which slice}}`,
88
+ ``,
89
+ `## Read Model / View`,
90
+ ...block("view"),
91
+ `- **Consumed by:** {{which UI screen (or API-caller persona), or reaction}}`,
92
+ `- **Freshness / consistency expectation:** {{real-time | eventual | on-demand}}`,
93
+ ``,
94
+ `## Invariants / Business Rules`,
95
+ ...block("invariants"),
96
+ INVARIANTS_ELABORATE_COMMENT,
97
+ ``,
98
+ `## Scenarios (Given / When / Then)`,
99
+ `### Scenario: Happy path`,
100
+ `- **Given:**`,
101
+ ` - {{starting state / prior events}}`,
102
+ `- **When:**`,
103
+ ` - {{command/trigger}}`,
104
+ `- **Then:**`,
105
+ ` - {{event(s) recorded}}`,
106
+ ` - {{resulting read-model change}}`,
107
+ ``,
108
+ `## Alternate & Error Flows`,
109
+ `- {{e.g. external call fails → retry policy / compensating event}}`,
110
+ `- {{idempotency: what happens if the command/event arrives twice?}}`,
111
+ ``,
112
+ `## Non-Functional Requirements`,
113
+ `- **Security / authz:** {{who may invoke this; role/permission checks — or "none"}}`,
114
+ `- **PII & compliance:** {{personal data touched, retention/consent constraints — or "none"}}`,
115
+ `- **Performance / SLA:** {{latency/throughput expectation — or "none"}}`,
116
+ ``,
117
+ `## Dependencies & Read Models Affected`,
118
+ `- **Upstream events this slice relies on:** {{...}}`,
119
+ `- **Downstream read models / slices affected:** {{...}}`,
120
+ ``,
121
+ `## Open Questions`,
122
+ `- [ ] {{question}}`,
123
+ ];
124
+ return lines.join("\n") + "\n";
52
125
  }
53
126
  /**
54
127
  * Build the full contents of a fresh, near-free `slices/<key>.md` STUB (MIL-184: `em slice new
@@ -1 +1 @@
1
- {"version":3,"file":"sliceNew.js","sourceRoot":"","sources":["../../src/cli/sliceNew.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,qFAAqF;AACrF,6FAA6F;AAC7F,6FAA6F;AAC7F,4FAA4F;AAC5F,8FAA8F;AAC9F,+FAA+F;AAC/F,8FAA8F;AAC9F,+FAA+F;AAC/F,6FAA6F;AAC7F,EAAE;AACF,8FAA8F;AAC9F,oFAAoF;AACpF,6BAA6B;AAE7B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,0FAA0F;AAC1F,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,CAAU,CAAC;AAGnG,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAQ,cAAoC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC;AAED;;;8BAG8B;AAC9B,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB;;;6EAG6E;AAC7E,MAAM,UAAU,WAAW,CAAC,WAAmB;IAC7C,OAAO,SAAS,CAAC,WAAW,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmB,EAAE,GAAW,EAAE,OAAqB,EAAE,QAAgB;IAC5G,OAAO,CACL,OAAO;QACP,kBAAkB,cAAc,IAAI;QACpC,YAAY,OAAO,IAAI;QACvB,aAAa,QAAQ,IAAI;QACzB,iBAAiB;QACjB,cAAc;QACd,OAAO;QACP,YAAY,WAAW,IAAI;QAC3B,IAAI;QACJ,gBAAgB,GAAG,SAAS,CAC7B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB,EAAE,OAAqB,EAAE,QAAgB;IAC9F,OAAO,CACL,OAAO;QACP,kBAAkB,cAAc,IAAI;QACpC,YAAY,OAAO,IAAI;QACvB,aAAa,QAAQ,IAAI;QACzB,iBAAiB;QACjB,cAAc;QACd,OAAO;QACP,YAAY,WAAW,IAAI;QAC3B,IAAI;QACJ,mEAAmE,CACpE,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"sliceNew.js","sourceRoot":"","sources":["../../src/cli/sliceNew.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { NormalizedModel } from "../model/model.js";
2
+ import { RefsResult } from "../model/refs.js";
3
+ import { GeneratedRegion } from "../catalog/sliceSections.js";
4
+ export declare const SLICE_SYNC_SCHEMA_VERSION = "1.0";
5
+ export type RegionSyncStatus = "ok" | "stale" | "synced" | "missing" | "orphan";
6
+ export type DocSyncStatus = "ok" | "stale" | "synced" | "no-regions" | "malformed";
7
+ export interface RegionSyncEntry {
8
+ name: string;
9
+ status: RegionSyncStatus;
10
+ }
11
+ export interface DocTextSync {
12
+ status: Exclude<DocSyncStatus, "synced">;
13
+ regions: RegionSyncEntry[];
14
+ /** Marker-balance problems (status `malformed`). */
15
+ problems: string[];
16
+ /** The doc text with every expected, present region regenerated — equal to the input when
17
+ * nothing is stale or the doc is malformed / has no regions. */
18
+ next: string;
19
+ }
20
+ /** Regenerate `raw`'s regions against `expected`. Pure. Statuses are check-mode (`stale`, never
21
+ * `synced`); the runner relabels after writing. */
22
+ export declare function syncDocText(raw: string, expected: GeneratedRegion[]): DocTextSync;
23
+ export interface DocSyncResult {
24
+ key: string;
25
+ path: string;
26
+ status: DocSyncStatus;
27
+ regions: RegionSyncEntry[];
28
+ problems: string[];
29
+ }
30
+ export type SliceSyncOutcome = {
31
+ ok: true;
32
+ docs: DocSyncResult[];
33
+ } | {
34
+ ok: false;
35
+ message: string;
36
+ };
37
+ /**
38
+ * Sync every bound doc of `model` (or only the doc `sliceKey` resolves to). `check` never
39
+ * writes. `baseDir` is the `.em` file's directory (doc paths are relative to it).
40
+ */
41
+ export declare function runSliceSync(model: NormalizedModel, refs: RefsResult, baseDir: string, sliceKey: string | undefined, check: boolean): SliceSyncOutcome;
42
+ /** `em slice sync … --json` (and the MCP `slice_sync` tool, check mode only). */
43
+ export declare function buildSliceSyncJson(file: string, docs: DocSyncResult[]): string;
44
+ /** The exit-1 condition shared by the CLI: a malformed doc always, a stale doc under --check. */
45
+ export declare function sliceSyncFailed(docs: DocSyncResult[], check: boolean): boolean;
46
+ /** Text-mode report: `{ out, err }` lines (status lines on stdout, notes and problems on stderr). */
47
+ export declare function formatSliceSync(docs: DocSyncResult[], check: boolean): {
48
+ out: string[];
49
+ err: string[];
50
+ };
@@ -0,0 +1,170 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // `em slice sync <model> [<key>] [--check] [--json]` (MIL-266): regenerate the GENERATED regions
3
+ // of existing slice docs in place from the model — the command/event/view field tables and the
4
+ // Invariants list catalog/sliceSections.ts defines — so a model edit never leaves a doc's tables
5
+ // quietly wrong. Authored bytes are never touched: only the text strictly between a region's two
6
+ // marker lines is replaced, edits are spliced in by offset (never parse-and-reserialize), and the
7
+ // doc's own line ending (LF or CRLF) is used for every generated line.
8
+ //
9
+ // Region set per doc: catalog/sliceSections.ts `buildSliceRegions` over every slice whose doc join
10
+ // (catalog/docJoin.ts `resolveSliceDocJoin` — the same binding `em export` uses) resolves to that
11
+ // doc: its own slice, plus any MIL-121 cross-covered slice or MIL-208 continuation.
12
+ // - a region the doc has and the model expects → regenerated (`ok` when already current,
13
+ // `stale` under --check, `synced` once rewritten);
14
+ // - a region the doc has and the model doesn't → `orphan`, left untouched, a `note:`;
15
+ // - a region the model expects and the doc lacks → `missing`, NOT inserted (that would be an
16
+ // edit outside the markers), a `note:`;
17
+ // - a doc with no `em-slice-*` marker at all → `no-regions`, skipped with a note (a 1.13
18
+ // doc stays exactly as written until someone adopts regions);
19
+ // - unbalanced markers → `malformed`, nothing in that doc is
20
+ // rewritten, exit 1.
21
+ // `--check` never writes; it exits 1 when any doc is stale (or malformed).
22
+ //
23
+ // Pure core (`syncDocText`) + fs-aware runner (`runSliceSync`); the CLI and the MCP `slice_sync`
24
+ // tool (check-only) share `buildSliceSyncJson`.
25
+ import { readFileSync, writeFileSync } from "node:fs";
26
+ import { join } from "node:path";
27
+ import { resolveSliceDocJoin } from "../catalog/docJoin.js";
28
+ import { buildSliceRegions, scanSliceRegions } from "../catalog/sliceSections.js";
29
+ import { GENERATOR_NAME, GENERATOR_VERSION } from "../emit/json.js";
30
+ // 1.0 (MIL-266): initial shape.
31
+ export const SLICE_SYNC_SCHEMA_VERSION = "1.0";
32
+ /** Regenerate `raw`'s regions against `expected`. Pure. Statuses are check-mode (`stale`, never
33
+ * `synced`); the runner relabels after writing. */
34
+ export function syncDocText(raw, expected) {
35
+ const scan = scanSliceRegions(raw);
36
+ if (scan.problems.length > 0)
37
+ return { status: "malformed", regions: [], problems: scan.problems, next: raw };
38
+ if (scan.regions.length === 0)
39
+ return { status: "no-regions", regions: [], problems: [], next: raw };
40
+ const eol = raw.includes("\r\n") ? "\r\n" : "\n";
41
+ const byName = new Map(expected.map((r) => [r.name, r]));
42
+ const present = new Set(scan.regions.map((r) => r.name));
43
+ const regions = [];
44
+ const edits = [];
45
+ for (const span of scan.regions) {
46
+ const want = byName.get(span.name);
47
+ if (!want) {
48
+ regions.push({ name: span.name, status: "orphan" });
49
+ continue;
50
+ }
51
+ const inner = eol + want.body.join(eol) + eol;
52
+ if (raw.slice(span.innerStart, span.innerEnd) === inner) {
53
+ regions.push({ name: span.name, status: "ok" });
54
+ }
55
+ else {
56
+ regions.push({ name: span.name, status: "stale" });
57
+ edits.push({ start: span.innerStart, end: span.innerEnd, text: inner });
58
+ }
59
+ }
60
+ for (const r of expected)
61
+ if (!present.has(r.name))
62
+ regions.push({ name: r.name, status: "missing" });
63
+ let next = raw;
64
+ for (const e of [...edits].sort((a, b) => b.start - a.start))
65
+ next = next.slice(0, e.start) + e.text + next.slice(e.end);
66
+ return { status: edits.length > 0 ? "stale" : "ok", regions, problems: [], next };
67
+ }
68
+ /**
69
+ * Sync every bound doc of `model` (or only the doc `sliceKey` resolves to). `check` never
70
+ * writes. `baseDir` is the `.em` file's directory (doc paths are relative to it).
71
+ */
72
+ export function runSliceSync(model, refs, baseDir, sliceKey, check) {
73
+ const groups = new Map();
74
+ const refOf = (id) => refs.refById.get(id);
75
+ model.slices.forEach((slice, i) => {
76
+ const { doc } = resolveSliceDocJoin(model, refs, slice, refs.sliceKeys[i], baseDir, refOf);
77
+ if (!doc.found || doc.reason !== null)
78
+ return;
79
+ const list = groups.get(doc.path);
80
+ if (list)
81
+ list.push(i);
82
+ else
83
+ groups.set(doc.path, [i]);
84
+ });
85
+ let only = null;
86
+ if (sliceKey !== undefined) {
87
+ const idx = refs.sliceKeys.indexOf(sliceKey);
88
+ if (idx === -1)
89
+ return { ok: false, message: `no slice with export key "${sliceKey}" in this model` };
90
+ const { doc } = resolveSliceDocJoin(model, refs, model.slices[idx], sliceKey, baseDir, refOf);
91
+ if (doc.reason === "no-doc-bound") {
92
+ return { ok: false, message: `slice "${sliceKey}" has no doc bound via \`note "slices/${sliceKey}.md"\` — nothing to sync` };
93
+ }
94
+ if (doc.reason === "binding-missing-file")
95
+ return { ok: false, message: `slice "${sliceKey}"'s bound doc ${doc.path} does not exist` };
96
+ if (doc.reason === "frontmatter-invalid") {
97
+ return { ok: false, message: `slice "${sliceKey}"'s doc ${doc.path} has unusable frontmatter — run em validate and fix it first` };
98
+ }
99
+ only = doc.path;
100
+ }
101
+ const docs = [];
102
+ for (const [path, indices] of groups) {
103
+ if (only !== null && path !== only)
104
+ continue;
105
+ const docKey = path.replace(/^slices\//, "").replace(/\.md$/, "");
106
+ const ownerIdx = indices.find((i) => refs.sliceKeys[i] === docKey) ?? Math.min(...indices);
107
+ const abs = join(baseDir, path);
108
+ const raw = readFileSync(abs, "utf8");
109
+ const result = syncDocText(raw, buildSliceRegions(model, indices));
110
+ let status = result.status;
111
+ let regions = result.regions;
112
+ if (!check && result.status === "stale") {
113
+ writeFileSync(abs, result.next);
114
+ status = "synced";
115
+ regions = regions.map((r) => (r.status === "stale" ? { name: r.name, status: "synced" } : r));
116
+ }
117
+ docs.push({ key: refs.sliceKeys[ownerIdx], path, status, regions, problems: result.problems });
118
+ }
119
+ return { ok: true, docs };
120
+ }
121
+ /** `em slice sync … --json` (and the MCP `slice_sync` tool, check mode only). */
122
+ export function buildSliceSyncJson(file, docs) {
123
+ return JSON.stringify({
124
+ sliceSyncSchemaVersion: SLICE_SYNC_SCHEMA_VERSION,
125
+ generator: { name: GENERATOR_NAME, version: GENERATOR_VERSION },
126
+ file,
127
+ docs: docs.map((d) => ({ key: d.key, path: d.path, status: d.status, regions: d.regions })),
128
+ }, null, 2);
129
+ }
130
+ /** The exit-1 condition shared by the CLI: a malformed doc always, a stale doc under --check. */
131
+ export function sliceSyncFailed(docs, check) {
132
+ return docs.some((d) => d.status === "malformed" || (check && d.status === "stale"));
133
+ }
134
+ /** Text-mode report: `{ out, err }` lines (status lines on stdout, notes and problems on stderr). */
135
+ export function formatSliceSync(docs, check) {
136
+ const out = [];
137
+ const err = [];
138
+ for (const d of docs) {
139
+ const changed = d.regions.filter((r) => r.status === "stale" || r.status === "synced").map((r) => r.name);
140
+ switch (d.status) {
141
+ case "ok":
142
+ out.push(`ok: ${d.path}`);
143
+ break;
144
+ case "stale":
145
+ out.push(`stale: ${d.path} (${changed.join(", ")})`);
146
+ break;
147
+ case "synced":
148
+ out.push(`synced: ${d.path} (${changed.join(", ")})`);
149
+ break;
150
+ case "no-regions":
151
+ if (check)
152
+ out.push(`no-regions: ${d.path}`);
153
+ else
154
+ err.push(`note: ${d.path} has no generated regions — re-create with em slice new --force to adopt them`);
155
+ break;
156
+ case "malformed":
157
+ err.push(`malformed: ${d.path} (${d.problems.join("; ")}) — nothing in it was rewritten`);
158
+ break;
159
+ }
160
+ for (const r of d.regions) {
161
+ if (r.status === "orphan")
162
+ err.push(`note: ${d.path}: region "${r.name}" matches nothing in the model — left untouched`);
163
+ if (r.status === "missing") {
164
+ err.push(`note: ${d.path}: the model expects region "${r.name}", which the doc lacks — add its marker pair, or re-create with em slice new --force`);
165
+ }
166
+ }
167
+ }
168
+ return { out, err };
169
+ }
170
+ //# sourceMappingURL=sliceSync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sliceSync.js","sourceRoot":"","sources":["../../src/cli/sliceSync.ts"],"names":[],"mappings":"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"}
@@ -54,6 +54,11 @@ export interface SliceStatusFact {
54
54
  * fact already counts that status/drift once) and tallies it in `StatusReport.continuations`
55
55
  * instead. */
56
56
  continuationOf: string | null;
57
+ /** MIL-238: the slice owns at least one `public` command/event/view (catalog/apiFirst.ts). */
58
+ publicTouching: boolean;
59
+ /** MIL-238: the bound doc records an API-first meaning confirmation — `meaningConfirmed: true`
60
+ * or a `contractChange:` reason. False when neither (or no doc). */
61
+ meaningConfirmationRecorded: boolean;
57
62
  }
58
63
  export interface SliceStatusFactsResult {
59
64
  facts: SliceStatusFact[];
@@ -342,11 +347,29 @@ export interface StatusReport {
342
347
  /** MIL-171: per-slice owner facts, one entry per slice across every input file — see
343
348
  * `StatusOwnerEntry`. */
344
349
  owners: StatusOwnerEntry[];
350
+ /** MIL-239 (R11): the nearest `system.yaml` above the first input file and how many of its
351
+ * `consumes` bindings failed the consumer-adaptation check; `null` when no manifest was found
352
+ * (or it could not be loaded). `manifest` is the path as reached from the first input. */
353
+ system: {
354
+ manifest: string;
355
+ consumerNotAdapted: number;
356
+ } | null;
357
+ /** MIL-238: count of public-touching slices (owning a `public` command/event/view) at
358
+ * `ready-to-implement` or `implemented` whose doc records neither `meaningConfirmed: true` nor
359
+ * a `contractChange:` — ratified before the API-first gate, or hand-edited. Continuations are
360
+ * skipped (the originating slice's own fact counts its doc once). */
361
+ publicSlicesUnconfirmed: number;
362
+ /** MIL-268: open engagements (`engagements/<slug>.md` with `status: open`) beside the input
363
+ * models — one scan per distinct model directory, slugs sorted. */
364
+ engagements: {
365
+ open: number;
366
+ slugs: string[];
367
+ };
345
368
  }
346
369
  /** Aggregate everything `em status` reports into one `StatusReport` — pure, no I/O. Callers
347
370
  * (the CLI action, the MCP tool) resolve every input first (compile each model, join every
348
371
  * slice's doc, scan the test tree once, resolve conformance) and hand the results here. */
349
- export declare function buildStatusReport(files: string[], sliceFacts: SliceStatusFact[], openIssuesCount: number, invariants: StatusInvariantTotals | null, conformance: ConformanceEntry[], diagnostics: StatusDiagnostic[], modelVersion?: ModelVersionStatusEntry[], emVersion?: EmVersionStatusEntry[]): StatusReport;
372
+ export declare function buildStatusReport(files: string[], sliceFacts: SliceStatusFact[], openIssuesCount: number, invariants: StatusInvariantTotals | null, conformance: ConformanceEntry[], diagnostics: StatusDiagnostic[], modelVersion?: ModelVersionStatusEntry[], emVersion?: EmVersionStatusEntry[], system?: StatusReport["system"], engagements?: StatusReport["engagements"]): StatusReport;
350
373
  /** Sum per-model `CoverageReport`s (see `./coverage.ts`) into one `StatusInvariantTotals` —
351
374
  * `em status` doesn't need the per-slice/per-ID detail `em coverage --json` carries, just the
352
375
  * totals, across however many models `--tests <dir>` was scanned against. */
@@ -31,6 +31,7 @@ import { changedPathsSince, buildConformScope } from "./conformScope.js";
31
31
  import { lookupFindingsBesideReport, unruledFindingsInScope } from "./findings.js";
32
32
  import { findCertifiedVersion, latestModelVersionNumber, modelVersionDrift } from "./modelVersion.js";
33
33
  import { isOlder } from "../util/semver.js";
34
+ import { slicePublicTouching } from "../catalog/apiFirst.js";
34
35
  /** The 4 canonical slice-doc lifecycle statuses (docs/slice-doc-schema.md) — the same enum
35
36
  * `em catalog`'s header coloring and `em render`'s status legend already recognize. */
36
37
  export const CANONICAL_STATUSES = ["draft", "reviewed", "ready-to-implement", "implemented"];
@@ -83,6 +84,8 @@ export function resolveSliceStatusFacts(file, model, refs, baseDir) {
83
84
  openQuestionsTotal,
84
85
  openQuestionsUnchecked,
85
86
  continuationOf: continuationOfKey,
87
+ publicTouching: slicePublicTouching(slice),
88
+ meaningConfirmationRecorded: doc.meaningConfirmed || doc.contractChange !== null,
86
89
  };
87
90
  });
88
91
  return { facts, diagnostics };
@@ -307,7 +310,7 @@ export function resolveEmVersionStatusEntry(file, installedVersion) {
307
310
  /** Aggregate everything `em status` reports into one `StatusReport` — pure, no I/O. Callers
308
311
  * (the CLI action, the MCP tool) resolve every input first (compile each model, join every
309
312
  * slice's doc, scan the test tree once, resolve conformance) and hand the results here. */
310
- export function buildStatusReport(files, sliceFacts, openIssuesCount, invariants, conformance, diagnostics, modelVersion = [], emVersion = []) {
313
+ export function buildStatusReport(files, sliceFacts, openIssuesCount, invariants, conformance, diagnostics, modelVersion = [], emVersion = [], system = null, engagements = { open: 0, slugs: [] }) {
311
314
  const byStatus = { draft: 0, reviewed: 0, readyToImplement: 0, implemented: 0, noDoc: 0, frontmatterInvalid: 0, unknown: 0 };
312
315
  const drift = {
313
316
  inSync: 0,
@@ -327,6 +330,7 @@ export function buildStatusReport(files, sliceFacts, openIssuesCount, invariants
327
330
  // relative path string without actually being the same file).
328
331
  const countedDocPaths = new Set();
329
332
  let continuations = 0;
333
+ let publicSlicesUnconfirmed = 0;
330
334
  for (const f of sliceFacts) {
331
335
  // MIL-208: a continuation slice has no status/drift of its own — the originating slice's
332
336
  // own fact (elsewhere in `sliceFacts`) already counts that status/drift once. Tally it
@@ -382,6 +386,11 @@ export function buildStatusReport(files, sliceFacts, openIssuesCount, invariants
382
386
  drift.notApplicable++;
383
387
  break;
384
388
  }
389
+ if (f.publicTouching &&
390
+ (f.bucket === "ready-to-implement" || f.bucket === "implemented") &&
391
+ !f.meaningConfirmationRecorded) {
392
+ publicSlicesUnconfirmed++;
393
+ }
385
394
  const alreadyCounted = f.docPath !== null && countedDocPaths.has(f.docPath);
386
395
  if (f.docPath !== null)
387
396
  countedDocPaths.add(f.docPath);
@@ -402,6 +411,9 @@ export function buildStatusReport(files, sliceFacts, openIssuesCount, invariants
402
411
  emVersion,
403
412
  diagnostics,
404
413
  owners: sliceFacts.map((f) => ({ file: f.file, key: f.key, owner: f.owner })),
414
+ system,
415
+ publicSlicesUnconfirmed,
416
+ engagements,
405
417
  };
406
418
  }
407
419
  /** Sum per-model `CoverageReport`s (see `./coverage.ts`) into one `StatusInvariantTotals` —
@@ -535,6 +547,9 @@ export function formatStatusDetail(report) {
535
547
  : "invariants: not checked — pass --tests <dir> to enable");
536
548
  lines.push(`issues: ${pluralize(report.issues.openIssues, "open issue")}, ` +
537
549
  `${report.issues.openQuestionsUnchecked}/${report.issues.openQuestionsTotal} open question(s) unchecked`);
550
+ // MIL-238: the API-first gate's backlog — ratified/shipped public-touching slices with no
551
+ // recorded meaning confirmation.
552
+ lines.push(`public-touching slices without a meaning confirmation: ${report.publicSlicesUnconfirmed}`);
538
553
  const multi = report.conformance.length > 1;
539
554
  for (const entry of report.conformance) {
540
555
  const label = multi ? `conformance (${entry.file}): ` : "conformance: ";
@@ -560,6 +575,10 @@ export function formatStatusDetail(report) {
560
575
  const label = multiEmVersion ? `em version (${entry.file}): ` : "em version: ";
561
576
  lines.push(`${label}${formatEmVersionPart(entry)}`);
562
577
  }
578
+ // MIL-268: the open engagements line (always present; slugs only when there are any).
579
+ lines.push(`open engagements: ${report.engagements.open}${report.engagements.open > 0 ? ` (${report.engagements.slugs.join(", ")})` : ""}`);
580
+ if (report.system)
581
+ lines.push(`consumer adaptation: ${report.system.consumerNotAdapted} not adapted (${report.system.manifest})`);
563
582
  if (report.diagnostics.length > 0) {
564
583
  lines.push(`doc issues: ${pluralize(report.diagnostics.length, "warning")} — see diagnostics (${report.diagnostics.map((d) => d.code).join(", ")})`);
565
584
  }