@milehimikey/em 1.13.1 → 1.14.1

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 (235) 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 +50 -11
  6. package/.claude/skills/event-modeling-conform/SKILL.md +1 -1
  7. package/.claude/skills/event-modeling-design/SKILL.md +127 -18
  8. package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
  9. package/.claude/skills/event-modeling-engagement/SKILL.md +192 -0
  10. package/.claude/skills/event-modeling-engagement/reference/engagement.md +143 -0
  11. package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
  12. package/.claude/skills/event-modeling-implement/reference/implement.md +38 -11
  13. package/.claude/skills/event-modeling-review/SKILL.md +2 -2
  14. package/.claude/skills/event-modeling-shared/reference/em-dsl.md +279 -189
  15. package/.claude/skills/event-modeling-shared/reference/operating-principles.md +61 -0
  16. package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +116 -5
  17. package/.claude/skills/event-modeling-shared/templates/constitution.md +18 -1
  18. package/.claude/skills/event-modeling-shared/templates/slice.md +64 -39
  19. package/.claude/skills/event-modeling-shared/templates/state.md +5 -1
  20. package/.claude-plugin/marketplace.json +14 -0
  21. package/README.md +25 -11
  22. package/dist/catalog/apiFirst.d.ts +28 -0
  23. package/dist/catalog/apiFirst.js +49 -0
  24. package/dist/catalog/apiFirst.js.map +1 -0
  25. package/dist/catalog/docJoin.d.ts +13 -0
  26. package/dist/catalog/docJoin.js +11 -0
  27. package/dist/catalog/docJoin.js.map +1 -1
  28. package/dist/catalog/docModelConsistencyValidate.js +44 -4
  29. package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
  30. package/dist/catalog/invariantsValidate.d.ts +4 -0
  31. package/dist/catalog/invariantsValidate.js +102 -0
  32. package/dist/catalog/invariantsValidate.js.map +1 -0
  33. package/dist/catalog/scenarios.d.ts +15 -0
  34. package/dist/catalog/scenarios.js +97 -0
  35. package/dist/catalog/scenarios.js.map +1 -0
  36. package/dist/catalog/sliceDoc.d.ts +8 -0
  37. package/dist/catalog/sliceDoc.js +9 -0
  38. package/dist/catalog/sliceDoc.js.map +1 -1
  39. package/dist/catalog/sliceReadyValidate.d.ts +31 -4
  40. package/dist/catalog/sliceReadyValidate.js +66 -8
  41. package/dist/catalog/sliceReadyValidate.js.map +1 -1
  42. package/dist/catalog/sliceSections.d.ts +55 -0
  43. package/dist/catalog/sliceSections.js +317 -0
  44. package/dist/catalog/sliceSections.js.map +1 -0
  45. package/dist/cli/agentsMd.js +7 -1
  46. package/dist/cli/agentsMd.js.map +1 -1
  47. package/dist/cli/api.d.ts +90 -0
  48. package/dist/cli/api.js +318 -0
  49. package/dist/cli/api.js.map +1 -0
  50. package/dist/cli/ciInit.d.ts +82 -21
  51. package/dist/cli/ciInit.js +468 -64
  52. package/dist/cli/ciInit.js.map +1 -1
  53. package/dist/cli/conformScope.d.ts +28 -0
  54. package/dist/cli/conformScope.js +67 -0
  55. package/dist/cli/conformScope.js.map +1 -1
  56. package/dist/cli/coverage.d.ts +9 -0
  57. package/dist/cli/coverage.js +60 -8
  58. package/dist/cli/coverage.js.map +1 -1
  59. package/dist/cli/defer.d.ts +55 -0
  60. package/dist/cli/defer.js +244 -0
  61. package/dist/cli/defer.js.map +1 -0
  62. package/dist/cli/engagement.d.ts +210 -0
  63. package/dist/cli/engagement.js +444 -0
  64. package/dist/cli/engagement.js.map +1 -0
  65. package/dist/cli/engagementFile.d.ts +86 -0
  66. package/dist/cli/engagementFile.js +255 -0
  67. package/dist/cli/engagementFile.js.map +1 -0
  68. package/dist/cli/metrics.d.ts +10 -0
  69. package/dist/cli/metrics.js +49 -1
  70. package/dist/cli/metrics.js.map +1 -1
  71. package/dist/cli/pluginPin.d.ts +55 -0
  72. package/dist/cli/pluginPin.js +188 -0
  73. package/dist/cli/pluginPin.js.map +1 -0
  74. package/dist/cli/ratify.d.ts +27 -2
  75. package/dist/cli/ratify.js +112 -13
  76. package/dist/cli/ratify.js.map +1 -1
  77. package/dist/cli/reratify.d.ts +4 -2
  78. package/dist/cli/reratify.js +41 -16
  79. package/dist/cli/reratify.js.map +1 -1
  80. package/dist/cli/scopeInputs.d.ts +48 -0
  81. package/dist/cli/scopeInputs.js +176 -0
  82. package/dist/cli/scopeInputs.js.map +1 -0
  83. package/dist/cli/skillCheck.d.ts +15 -1
  84. package/dist/cli/skillCheck.js +22 -1
  85. package/dist/cli/skillCheck.js.map +1 -1
  86. package/dist/cli/skillDirs.d.ts +5 -0
  87. package/dist/cli/skillDirs.js +13 -1
  88. package/dist/cli/skillDirs.js.map +1 -1
  89. package/dist/cli/skillSync.d.ts +4 -0
  90. package/dist/cli/skillSync.js +23 -0
  91. package/dist/cli/skillSync.js.map +1 -1
  92. package/dist/cli/sliceNew.d.ts +11 -7
  93. package/dist/cli/sliceNew.js +91 -18
  94. package/dist/cli/sliceNew.js.map +1 -1
  95. package/dist/cli/sliceSync.d.ts +50 -0
  96. package/dist/cli/sliceSync.js +170 -0
  97. package/dist/cli/sliceSync.js.map +1 -0
  98. package/dist/cli/status.d.ts +24 -1
  99. package/dist/cli/status.js +20 -1
  100. package/dist/cli/status.js.map +1 -1
  101. package/dist/cli/systemInputs.d.ts +53 -10
  102. package/dist/cli/systemInputs.js +186 -11
  103. package/dist/cli/systemInputs.js.map +1 -1
  104. package/dist/cli/upgrade.d.ts +16 -3
  105. package/dist/cli/upgrade.js +366 -30
  106. package/dist/cli/upgrade.js.map +1 -1
  107. package/dist/cli/usageLog.d.ts +4 -2
  108. package/dist/cli/usageLog.js +4 -2
  109. package/dist/cli/usageLog.js.map +1 -1
  110. package/dist/cli.js +599 -94
  111. package/dist/cli.js.map +1 -1
  112. package/dist/emit/api.d.ts +29 -0
  113. package/dist/emit/api.js +220 -0
  114. package/dist/emit/api.js.map +1 -0
  115. package/dist/emit/apiCheckJson.d.ts +3 -0
  116. package/dist/emit/apiCheckJson.js +21 -0
  117. package/dist/emit/apiCheckJson.js.map +1 -0
  118. package/dist/emit/codeownersJson.d.ts +3 -0
  119. package/dist/emit/codeownersJson.js +19 -0
  120. package/dist/emit/codeownersJson.js.map +1 -0
  121. package/dist/emit/diffJson.d.ts +1 -1
  122. package/dist/emit/diffJson.js +8 -1
  123. package/dist/emit/diffJson.js.map +1 -1
  124. package/dist/emit/engagementJson.d.ts +8 -0
  125. package/dist/emit/engagementJson.js +46 -0
  126. package/dist/emit/engagementJson.js.map +1 -0
  127. package/dist/emit/glossaryJson.d.ts +1 -1
  128. package/dist/emit/glossaryJson.js +4 -1
  129. package/dist/emit/glossaryJson.js.map +1 -1
  130. package/dist/emit/json.d.ts +17 -1
  131. package/dist/emit/json.js +30 -1
  132. package/dist/emit/json.js.map +1 -1
  133. package/dist/emit/metricsJson.d.ts +1 -1
  134. package/dist/emit/metricsJson.js +4 -1
  135. package/dist/emit/metricsJson.js.map +1 -1
  136. package/dist/emit/queryJson.d.ts +1 -1
  137. package/dist/emit/queryJson.js +7 -1
  138. package/dist/emit/queryJson.js.map +1 -1
  139. package/dist/emit/scopeJson.d.ts +12 -0
  140. package/dist/emit/scopeJson.js +26 -0
  141. package/dist/emit/scopeJson.js.map +1 -0
  142. package/dist/emit/skillCheckJson.d.ts +3 -2
  143. package/dist/emit/skillCheckJson.js +10 -2
  144. package/dist/emit/skillCheckJson.js.map +1 -1
  145. package/dist/emit/statusJson.d.ts +1 -1
  146. package/dist/emit/statusJson.js +15 -1
  147. package/dist/emit/statusJson.js.map +1 -1
  148. package/dist/emit/systemJson.d.ts +15 -8
  149. package/dist/emit/systemJson.js +28 -13
  150. package/dist/emit/systemJson.js.map +1 -1
  151. package/dist/emit/validateJson.d.ts +3 -3
  152. package/dist/emit/validateJson.js +10 -4
  153. package/dist/emit/validateJson.js.map +1 -1
  154. package/dist/mcp/server.d.ts +1 -1
  155. package/dist/mcp/server.js +163 -31
  156. package/dist/mcp/server.js.map +1 -1
  157. package/dist/model/diff.d.ts +4 -1
  158. package/dist/model/diff.js +44 -8
  159. package/dist/model/diff.js.map +1 -1
  160. package/dist/model/glossary.d.ts +2 -0
  161. package/dist/model/glossary.js +1 -0
  162. package/dist/model/glossary.js.map +1 -1
  163. package/dist/model/model.d.ts +55 -2
  164. package/dist/model/model.js +57 -0
  165. package/dist/model/model.js.map +1 -1
  166. package/dist/model/qualifiedRef.d.ts +18 -0
  167. package/dist/model/qualifiedRef.js +26 -0
  168. package/dist/model/qualifiedRef.js.map +1 -1
  169. package/dist/model/queryIndex.d.ts +9 -1
  170. package/dist/model/queryIndex.js +18 -2
  171. package/dist/model/queryIndex.js.map +1 -1
  172. package/dist/model/rules.d.ts +143 -2
  173. package/dist/model/rules.js +162 -3
  174. package/dist/model/rules.js.map +1 -1
  175. package/dist/model/validate.d.ts +40 -0
  176. package/dist/model/validate.js +147 -1
  177. package/dist/model/validate.js.map +1 -1
  178. package/dist/parser/ast.d.ts +31 -3
  179. package/dist/parser/parser.js +148 -14
  180. package/dist/parser/parser.js.map +1 -1
  181. package/dist/query/format.js +1 -1
  182. package/dist/query/format.js.map +1 -1
  183. package/dist/query/verbs.d.ts +6 -0
  184. package/dist/query/verbs.js +6 -2
  185. package/dist/query/verbs.js.map +1 -1
  186. package/dist/system/adaptation.d.ts +14 -0
  187. package/dist/system/adaptation.js +49 -0
  188. package/dist/system/adaptation.js.map +1 -0
  189. package/dist/system/codeowners.d.ts +77 -0
  190. package/dist/system/codeowners.js +242 -0
  191. package/dist/system/codeowners.js.map +1 -0
  192. package/dist/system/manifest.d.ts +10 -5
  193. package/dist/system/manifest.js +54 -26
  194. package/dist/system/manifest.js.map +1 -1
  195. package/dist/system/migrateManifest.d.ts +28 -0
  196. package/dist/system/migrateManifest.js +155 -0
  197. package/dist/system/migrateManifest.js.map +1 -0
  198. package/dist/system/scope.d.ts +46 -0
  199. package/dist/system/scope.js +132 -0
  200. package/dist/system/scope.js.map +1 -0
  201. package/dist/system/verify.d.ts +50 -13
  202. package/dist/system/verify.js +179 -58
  203. package/dist/system/verify.js.map +1 -1
  204. package/dist/templates.d.ts +2 -2
  205. package/dist/templates.js +23 -2
  206. package/dist/templates.js.map +1 -1
  207. package/package.json +5 -2
  208. package/plugin/.claude-plugin/plugin.json +18 -0
  209. package/plugin/agents/em-critic.md +27 -0
  210. package/plugin/agents/em-implementer.md +35 -0
  211. package/plugin/agents/em-reviewer.md +32 -0
  212. package/plugin/agents/em-validator.md +28 -0
  213. package/plugin/shared/reference/em-dsl.md +871 -0
  214. package/plugin/shared/reference/methodology.md +329 -0
  215. package/plugin/shared/reference/operating-principles.md +222 -0
  216. package/plugin/shared/reference/slice-doc-schema.md +574 -0
  217. package/plugin/shared/templates/conformance-report.md +85 -0
  218. package/plugin/shared/templates/constitution.md +136 -0
  219. package/plugin/shared/templates/model-readme.md +46 -0
  220. package/plugin/shared/templates/slice.md +251 -0
  221. package/plugin/shared/templates/state.md +77 -0
  222. package/plugin/skills/conform/SKILL.md +93 -0
  223. package/plugin/skills/conform/reference/conform.md +428 -0
  224. package/plugin/skills/design/SKILL.md +298 -0
  225. package/plugin/skills/discover/SKILL.md +90 -0
  226. package/plugin/skills/discover/reference/extract.md +147 -0
  227. package/plugin/skills/engagement/SKILL.md +193 -0
  228. package/plugin/skills/engagement/reference/engagement.md +144 -0
  229. package/plugin/skills/event-modeling/SKILL.md +132 -0
  230. package/plugin/skills/implement/SKILL.md +61 -0
  231. package/plugin/skills/implement/reference/implement.md +439 -0
  232. package/plugin/skills/review/SKILL.md +74 -0
  233. package/dist/emit/typespec.d.ts +0 -26
  234. package/dist/emit/typespec.js +0 -356
  235. package/dist/emit/typespec.js.map +0 -1
@@ -0,0 +1,155 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Plans the `system.yaml` 1.0 -> 2.0 migration (MIL-235, ruling R3) — the pure half of `em
3
+ // upgrade`'s `system-manifest` step (src/cli/upgrade.ts owns detection, fs, compile and the one
4
+ // commit). Three rewrites, planned together so the step either writes all of them or none:
5
+ //
6
+ // 1. every legacy seam `{from, to}` becomes a `consumes <fromModel>:<kind>.<slug>` clause
7
+ // appended to the consuming translation's own line in its `.em` file (a bare-slice `to` —
8
+ // `<model>:<slice>` — resolves to that slice's single reaction, same rule `em system` used);
9
+ // 2. every model's manifest `owner:` becomes `owner "<text>"` on that model's `model "Name"`
10
+ // header line (quoted free text as written; a header that already names owners wins);
11
+ // 3. the manifest itself is rewritten to 2.0 — `systemSchemaVersion: "2.0"`, `seams:` and every
12
+ // `owner:` removed — through the YAML document API so comments and quoting survive.
13
+ //
14
+ // Like the verifier, this reads EXPORT DOCUMENTS (refs + element lines) for resolution, never a
15
+ // NormalizedModel; the only model text it touches is source-text surgery on the exact lines the
16
+ // export points at. Anything it cannot migrate mechanically — a seam whose consumer is not a
17
+ // translation (`consumes` is translation-only), a member sourced from an export `.json` (no
18
+ // `.em` text to edit), an unresolvable ref — is a refusal with a message, never a partial plan.
19
+ import { parseDocument, isMap } from "yaml";
20
+ import { indexOfUnquoted, stripComment } from "../parser/lexer.js";
21
+ import { AUTOMATION_KINDS } from "../parser/ast.js";
22
+ import { formatContractRef, parseContractRef, parseQualifiedRef } from "../model/qualifiedRef.js";
23
+ import { SYSTEM_MANIFEST_SCHEMA_VERSION } from "./manifest.js";
24
+ /** Plan the whole migration. `manifest` must be a parsed 1.0 manifest; `members` one entry per
25
+ * manifest model, same order. */
26
+ export function planManifestMigration(manifestText, manifest, members) {
27
+ const byKey = new Map(members.map((m) => [m.key, m]));
28
+ // file -> (1-based line -> refs to append), insertion-ordered for stable output.
29
+ const consumesAt = new Map();
30
+ // file -> (1-based line -> `# …` comment lines carrying each seam's `description`, which has
31
+ // no home in the DSL — kept as a comment above the translation rather than silently dropped).
32
+ const notesAt = new Map();
33
+ const summary = [];
34
+ for (const [i, seam] of manifest.seams.entries()) {
35
+ const where = `seams[${i}] (${seam.from} -> ${seam.to})`;
36
+ // --- producer: `<model>:<slice>/<kind>.<slug>` -> `<model>:<kind>.<slug>`
37
+ const from = parseQualifiedRef(seam.from);
38
+ const fromTail = from.ref.includes("/") ? from.ref.slice(from.ref.indexOf("/") + 1) : "";
39
+ const contract = from.modelKey === null ? null : parseContractRef(`${from.modelKey}:${fromTail}`);
40
+ if (!contract) {
41
+ return { ok: false, message: `${where}: \`from\` is not a <modelKey>:<sliceKey>/<event|view>.<slug> ref — fix or drop the seam, then re-run` };
42
+ }
43
+ const ref = formatContractRef(contract.modelKey, contract.kind, contract.slug);
44
+ // --- consumer: an element ref, or a bare slice with exactly one reaction
45
+ const to = parseQualifiedRef(seam.to);
46
+ const consumer = to.modelKey === null ? undefined : byKey.get(to.modelKey);
47
+ if (!consumer) {
48
+ return { ok: false, message: `${where}: \`to\` names no model of this manifest — fix or drop the seam, then re-run` };
49
+ }
50
+ let element;
51
+ if (to.ref.includes("/")) {
52
+ for (const s of consumer.doc.model.slices)
53
+ element ??= s.elements.find((e) => e.ref === to.ref);
54
+ }
55
+ else {
56
+ const slice = consumer.doc.model.slices.find((s) => s.key === to.ref);
57
+ const reactions = slice ? slice.elements.filter((e) => AUTOMATION_KINDS.has(e.kind)) : [];
58
+ if (reactions.length === 1)
59
+ element = reactions[0];
60
+ }
61
+ if (!element) {
62
+ return { ok: false, message: `${where}: \`to\` does not resolve to one reaction in model "${consumer.key}" — fix or drop the seam, then re-run` };
63
+ }
64
+ if (element.kind !== "translation") {
65
+ return {
66
+ ok: false,
67
+ message: `${where}: the consumer is ${element.kind} "${element.name}", but \`consumes\` is only valid on translation — ` +
68
+ "make it a translation (it crosses a model boundary) or drop the seam, then re-run",
69
+ };
70
+ }
71
+ if (consumer.text === null) {
72
+ return { ok: false, message: `${where}: model "${consumer.key}" is sourced from an export document, not a .em file — add \`consumes ${ref}\` to its translation by hand` };
73
+ }
74
+ if ((element.consumes ?? []).includes(ref))
75
+ continue; // already declared model-side
76
+ const lines = consumesAt.get(consumer.file) ?? new Map();
77
+ consumesAt.set(consumer.file, lines);
78
+ const refs = lines.get(element.line) ?? [];
79
+ if (!refs.includes(ref))
80
+ refs.push(ref);
81
+ lines.set(element.line, refs);
82
+ if (seam.description !== null && seam.description.trim() !== "") {
83
+ const notes = notesAt.get(consumer.file) ?? new Map();
84
+ notesAt.set(consumer.file, notes);
85
+ notes.set(element.line, [...(notes.get(element.line) ?? []), `${ref} — ${seam.description.trim().replace(/\s+/g, " ")}`]);
86
+ }
87
+ }
88
+ const files = [];
89
+ for (const member of members) {
90
+ const entry = manifest.models.find((m) => m.key === member.key);
91
+ const owner = entry?.owner ?? null;
92
+ const headerOwners = Array.isArray(member.doc.model.owner) ? member.doc.model.owner : [];
93
+ const writeOwner = owner !== null && headerOwners.length === 0;
94
+ const lineEdits = consumesAt.get(member.file);
95
+ if (!writeOwner && !lineEdits)
96
+ continue;
97
+ if (member.text === null) {
98
+ return { ok: false, message: `model "${member.key}" is sourced from an export document, not a .em file — move its \`owner:\` onto the model header by hand` };
99
+ }
100
+ const eol = member.text.includes("\r\n") ? "\r\n" : "\n";
101
+ const lines = member.text.split(/\r?\n/);
102
+ if (writeOwner) {
103
+ const at = lines.findIndex((l) => /^model(\s|$)/.test(stripComment(l).trim()));
104
+ if (at < 0) {
105
+ return { ok: false, message: `model "${member.key}" (${member.file}) has no \`model "Name"\` header line to carry \`owner "${owner}"\` — add one, then re-run` };
106
+ }
107
+ lines[at] = appendClause(lines[at], `owner ${quote(owner)}`, false);
108
+ summary.push(`${member.file}: owner ${quote(owner)}`);
109
+ }
110
+ for (const [line, refs] of lineEdits ?? []) {
111
+ lines[line - 1] = appendClause(lines[line - 1], `consumes ${refs.join(", ")}`, true);
112
+ summary.push(`${member.file}:${line}: consumes ${refs.join(", ")}`);
113
+ }
114
+ // Description comments last, bottom-up, so earlier insertions never shift a later line.
115
+ const notes = [...(notesAt.get(member.file) ?? new Map()).entries()].sort((a, b) => b[0] - a[0]);
116
+ for (const [line, texts] of notes) {
117
+ const indent = /^\s*/.exec(lines[line - 1])[0];
118
+ lines.splice(line - 1, 0, ...texts.map((t) => `${indent}# ${t}`));
119
+ }
120
+ files.push({ file: member.file, text: lines.join(eol) });
121
+ }
122
+ // --- the manifest itself: same document, 2.0 keys only (comments/quoting preserved).
123
+ const doc = parseDocument(manifestText);
124
+ doc.set("systemSchemaVersion", SYSTEM_MANIFEST_SCHEMA_VERSION);
125
+ doc.delete("seams");
126
+ const models = doc.get("models", true);
127
+ if (isMap(models)) {
128
+ for (const pair of models.items)
129
+ if (isMap(pair.value))
130
+ pair.value.delete("owner");
131
+ }
132
+ let rewritten = String(doc);
133
+ if (!manifestText.endsWith("\n"))
134
+ rewritten = rewritten.replace(/\n$/, "");
135
+ summary.push(`system.yaml: systemSchemaVersion "${SYSTEM_MANIFEST_SCHEMA_VERSION}" (seams/owner removed)`);
136
+ return { ok: true, manifestText: rewritten, files, summary };
137
+ }
138
+ /** A `"…"` literal the `.em` lexer decodes back to `text` (`\"` and `\\` escapes). */
139
+ function quote(text) {
140
+ return `"${text.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
141
+ }
142
+ /** Append `clause` to one `.em` source line's code — before a trailing `# comment`, and (when
143
+ * `beforeBlock`) before an element's `{ … }` field-block opener, since clauses on the header
144
+ * side of the brace are the canonical position. Indentation and the comment are kept. */
145
+ function appendClause(raw, clause, beforeBlock) {
146
+ const code = stripComment(raw);
147
+ const comment = raw.slice(code.length);
148
+ const brace = beforeBlock ? indexOfUnquoted(code, "{") : -1;
149
+ if (brace >= 0) {
150
+ return `${code.slice(0, brace).trimEnd()} ${clause} ${code.slice(brace)}${comment}`;
151
+ }
152
+ const trimmed = code.trimEnd();
153
+ return `${trimmed} ${clause}${comment ? ` ${comment.trimStart()}` : code.slice(trimmed.length)}`;
154
+ }
155
+ //# sourceMappingURL=migrateManifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrateManifest.js","sourceRoot":"","sources":["../../src/system/migrateManifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { ApiCheckChange } from "../cli/api.js";
2
+ import type { SystemDiagnostic } from "./verify.js";
3
+ export interface ScopeModel {
4
+ key: string;
5
+ /** Repo-root-relative model file, `/`-separated. */
6
+ file: string;
7
+ /** Repo-root-relative model directory (`dirname(file)`; "" when the model sits at the repo root). */
8
+ dir: string;
9
+ /** Repo-root-relative contract file: `<dir>/contracts/<key>.tsp` (briefing R6). */
10
+ contract: string;
11
+ /** Repo-root-relative code roots the model's state file declares (`Code roots:` bullet); [] when none. */
12
+ codeRoots: string[];
13
+ /** Structural public-surface changes base -> HEAD (`diffSurfaces`). `null` = not evaluated: the
14
+ * model file is unchanged or exempt in this change set. A model absent at base reports every
15
+ * public element as additive "added". */
16
+ surfaceChanges: ApiCheckChange[] | null;
17
+ /** `<modelKey>:<kind>.<slug>` refs this model's translations consume, at HEAD and at base. */
18
+ headConsumes: string[];
19
+ baseConsumes: string[];
20
+ }
21
+ export interface ScopeInput {
22
+ models: ScopeModel[];
23
+ /** Repo-relative changed paths AFTER the `Em-Upgrade:` exemption: both sides of a rename. */
24
+ changed: string[];
25
+ }
26
+ export interface ScopeTouched {
27
+ key: string;
28
+ dir: string;
29
+ /** Changed paths under this model's dir (longest-prefix match), sorted. */
30
+ paths: string[];
31
+ }
32
+ export interface ScopeReport {
33
+ /** Models whose design dir has >= 1 changed path, sorted by key. */
34
+ touched: ScopeTouched[];
35
+ /** Changed paths under no model dir (ignored), sorted. */
36
+ unmapped: string[];
37
+ diagnostics: SystemDiagnostic[];
38
+ /** Number of `seam-crossing` errors. */
39
+ crossings: number;
40
+ }
41
+ /** Longest-prefix model for a path (briefing R6); `null` outside every model dir. */
42
+ export declare function modelForPath(models: Pick<ScopeModel, "key" | "dir">[], path: string): string | null;
43
+ /** `Code roots:` bullet from a model's `.event-modeling.md`: `- **Code roots:** a, b` (comma
44
+ * separated, repo-root-relative). `[]` when absent or `none`. */
45
+ export declare function parseCodeRoots(stateText: string): string[];
46
+ export declare function evaluateScope(input: ScopeInput): ScopeReport;
@@ -0,0 +1,132 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // `em system scope` (MIL-240): the pure half. Given each model's directory, its contract file,
3
+ // the structural public-surface changes between the base revision and HEAD, and both sides'
4
+ // `consumes` bindings, plus the change set's repo-relative paths, return the findings:
5
+ //
6
+ // seam-crossing (error) a producer's public surface or contract file changed AND a
7
+ // model that consumes it changed its design dir, in ONE change set
8
+ // seam-crossing-greenfield (warn) the only "surface changes" are elements no consumer was bound
9
+ // to at the base revision (new public surface) - not a crossing
10
+ // multi-model-change-set (warn) the change set touches >= 2 model dirs and crosses no contract
11
+ // code-spans-seam (warn) advisory: code under two seam-joined models' declared code roots
12
+ //
13
+ // There is NO override: review on the contract file (CODEOWNERS, MIL-234) is the override.
14
+ //
15
+ // Pure: no git, no fs, no compile. `src/cli/scopeInputs.ts` gathers the inputs; the same function
16
+ // runs per commit for `em metrics`' `seamCrossings`.
17
+ import { makeDiag } from "../model/rules.js";
18
+ import { parseContractRef } from "../model/qualifiedRef.js";
19
+ const isUnder = (path, dir) => dir === "" || path === dir || path.startsWith(dir + "/");
20
+ /** Longest-prefix model for a path (briefing R6); `null` outside every model dir. */
21
+ export function modelForPath(models, path) {
22
+ let best = null;
23
+ for (const m of models) {
24
+ if (!isUnder(path, m.dir))
25
+ continue;
26
+ if (best === null || m.dir.length > best.len)
27
+ best = { key: m.key, len: m.dir.length };
28
+ }
29
+ return best === null ? null : best.key;
30
+ }
31
+ /** `Code roots:` bullet from a model's `.event-modeling.md`: `- **Code roots:** a, b` (comma
32
+ * separated, repo-root-relative). `[]` when absent or `none`. */
33
+ export function parseCodeRoots(stateText) {
34
+ const m = /^-\s+\*\*Code roots:\*\*\s*(.*)$/m.exec(stateText);
35
+ if (!m)
36
+ return [];
37
+ return m[1]
38
+ .split(",")
39
+ .map((s) => s.trim().replace(/^`|`$/g, "").replace(/^\.\//, "").replace(/\/+$/, ""))
40
+ .filter((s) => s !== "" && s.toLowerCase() !== "none");
41
+ }
42
+ function consumedModels(m) {
43
+ const out = new Set();
44
+ for (const ref of [...m.headConsumes, ...m.baseConsumes]) {
45
+ const p = parseContractRef(ref);
46
+ if (p)
47
+ out.add(p.modelKey);
48
+ }
49
+ return out;
50
+ }
51
+ function diag(file, code, message, refs) {
52
+ return { file, ...makeDiag(code, { message, refs }) };
53
+ }
54
+ const sorted = (xs) => [...new Set(xs)].sort();
55
+ export function evaluateScope(input) {
56
+ const models = [...input.models].sort((a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0));
57
+ const byModel = new Map();
58
+ const unmapped = [];
59
+ for (const p of [...input.changed].sort()) {
60
+ const key = modelForPath(models, p);
61
+ if (key === null)
62
+ unmapped.push(p);
63
+ else
64
+ byModel.set(key, [...(byModel.get(key) ?? []), p]);
65
+ }
66
+ const touched = models
67
+ .filter((m) => byModel.has(m.key))
68
+ .map((m) => ({ key: m.key, dir: m.dir, paths: byModel.get(m.key) }));
69
+ const changedSet = new Set(input.changed);
70
+ // Consumers per producer, from either side of the change (a removed `consumes` still counts).
71
+ const consumes = new Map(models.map((m) => [m.key, consumedModels(m)]));
72
+ const boundAtBase = new Set(models.flatMap((m) => m.baseConsumes));
73
+ const diagnostics = [];
74
+ let crossings = 0;
75
+ for (const producer of models) {
76
+ const surface = producer.surfaceChanges ?? [];
77
+ const contractChanged = changedSet.has(producer.contract);
78
+ if (surface.length === 0 && !contractChanged)
79
+ continue;
80
+ // New public surface nothing was bound to at base is greenfield (not a crossing).
81
+ const isGreenfield = (c) => c.field === null && (c.what === "added" || c.what === "marked public") && !boundAtBase.has(`${producer.key}:${c.element}`);
82
+ const greenfield = surface.filter(isGreenfield);
83
+ const binding = surface.filter((c) => !isGreenfield(c));
84
+ // A changed contract file is explained by greenfield-only surface changes (it was regenerated);
85
+ // it is a trigger of its own only when nothing in the surface accounts for it.
86
+ const contractTrigger = contractChanged && surface.length === 0;
87
+ const triggered = binding.length > 0 || contractTrigger;
88
+ const consumers = models.filter((c) => c.key !== producer.key && (consumes.get(c.key)?.has(producer.key) ?? false) && byModel.has(c.key));
89
+ if (!triggered) {
90
+ if (greenfield.length > 0 && consumers.length > 0) {
91
+ const els = sorted(greenfield.map((c) => c.element));
92
+ diagnostics.push(diag(producer.file, "seam-crossing-greenfield", `${producer.key}: ${els.join(", ")} ${els.length === 1 ? "is" : "are"} new public surface with no consumer bound at the base revision, ` +
93
+ `changed together with ${consumers.map((c) => c.key).join(", ")} - not a crossing (greenfield); later changes to ${els.length === 1 ? "it" : "them"} are`, [...els.map((e) => `${producer.key}:${e}`), ...consumers.map((c) => c.key)]));
94
+ }
95
+ continue;
96
+ }
97
+ const what = sorted(binding.map((c) => `${c.element}${c.field !== null ? ` field "${c.field}"` : ""} ${c.what}`));
98
+ if (contractTrigger)
99
+ what.push(`contract file ${producer.contract} changed`);
100
+ const elementRefs = sorted(binding.map((c) => `${producer.key}:${c.element}`));
101
+ if (contractTrigger)
102
+ elementRefs.push(`${producer.key}:contract`);
103
+ for (const consumer of consumers) {
104
+ crossings++;
105
+ const paths = byModel.get(consumer.key);
106
+ diagnostics.push(diag(producer.file, "seam-crossing", `change set alters ${producer.key}'s public surface (${what.join("; ")}) and ${consumer.key}, which consumes it ` +
107
+ `(changed: ${paths.join(", ")}) - land the contract change and the consumer's adaptation in separate change sets; ` +
108
+ `review on ${producer.contract} is the only override`, [...elementRefs, consumer.key]));
109
+ }
110
+ }
111
+ if (crossings === 0 && touched.length >= 2) {
112
+ const keys = touched.map((t) => t.key);
113
+ diagnostics.push(diag(".", "multi-model-change-set", `change set touches ${keys.length} models (${keys.join(", ")}) but crosses no contract - consider one change set per model`, keys));
114
+ }
115
+ // Advisory code-side check: changed code under two seam-joined models' declared code roots.
116
+ const underRoots = (m) => sorted(input.changed.filter((p) => m.codeRoots.some((r) => isUnder(p, r))));
117
+ for (let i = 0; i < models.length; i++) {
118
+ for (let j = i + 1; j < models.length; j++) {
119
+ const a = models[i];
120
+ const b = models[j];
121
+ if (!(consumes.get(a.key)?.has(b.key) || consumes.get(b.key)?.has(a.key)))
122
+ continue;
123
+ const pa = underRoots(a);
124
+ const pb = underRoots(b);
125
+ if (pa.length === 0 || pb.length === 0)
126
+ continue;
127
+ diagnostics.push(diag(a.file, "code-spans-seam", `code change spans the seam between ${a.key} (${pa.join(", ")}) and ${b.key} (${pb.join(", ")}) - one code module per model, changed in separate change sets`, [a.key, b.key]));
128
+ }
129
+ }
130
+ return { touched, unmapped, diagnostics, crossings };
131
+ }
132
+ //# sourceMappingURL=scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/system/scope.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { ElementKind } from "../parser/ast.js";
2
2
  import type { Diagnostic } from "../model/validate.js";
3
- import type { SystemManifest } from "./manifest.js";
3
+ import { AdaptationField } from "./adaptation.js";
4
+ import { SystemManifest } from "./manifest.js";
4
5
  /** The subset of one `em export --json` document `verifySystem` reads. */
5
6
  export interface SystemExportElement {
6
7
  ref: string;
@@ -8,6 +9,12 @@ export interface SystemExportElement {
8
9
  name: string;
9
10
  line: number;
10
11
  public: boolean;
12
+ /** Export schema >= 1.15 (MIL-235): a translation's contract refs. Absent on older exports —
13
+ * read as none. */
14
+ consumes?: string[] | null;
15
+ /** The element's declared fields (MIL-239 reads them for the consumer-adaptation check).
16
+ * Absent on an export that carries none; read as no fields. */
17
+ fields?: AdaptationField[] | null;
11
18
  }
12
19
  export interface SystemExportSlice {
13
20
  key: string;
@@ -19,6 +26,8 @@ export interface SystemExportDoc {
19
26
  model: {
20
27
  key: string;
21
28
  name: string | null;
29
+ /** Export schema >= 1.15 (MIL-235): the header's `owner` entries. Absent on older exports. */
30
+ owner?: string[];
22
31
  slices: SystemExportSlice[];
23
32
  edges: {
24
33
  from: string;
@@ -27,17 +36,27 @@ export interface SystemExportDoc {
27
36
  };
28
37
  }
29
38
  export type SystemSourceKind = "em" | "export";
30
- /** One model, loaded by the caller: the manifest's entry plus its export document and the
31
- * path diagnostics about it should point at (the `.em` file, or the export `.json`). */
39
+ /** One model, loaded by the caller: its key (the manifest's, or the computed one in discovery
40
+ * mode), its export document, and the path diagnostics about it should point at (the `.em`
41
+ * file, or the export `.json`). */
32
42
  export interface SystemModelInput {
33
43
  key: string;
34
44
  source: string;
35
45
  sourceKind: SystemSourceKind;
36
- owner: string | null;
46
+ /** The model header's `owner` entries (export `model.owner`); a legacy 1.0 manifest's
47
+ * `owner:` fills in when the header names none. `[]` when neither does. */
48
+ owner: string[];
37
49
  /** Path diagnostics about this model's elements point at — resolved, as the CLI prints it. */
38
50
  file: string;
39
51
  doc: SystemExportDoc;
40
52
  }
53
+ /** How a discovered system (no manifest, MIL-235 R4) was found: the repo root (or start
54
+ * directory) as reached from the path the caller gave — never absolutized, same "as given"
55
+ * posture as a manifest path — and every discovered `.em` file relative to it, sorted. */
56
+ export interface SystemDiscovery {
57
+ root: string;
58
+ files: string[];
59
+ }
41
60
  /** A diagnostic plus the file it concerns — `em status --json`'s multi-model convention. */
42
61
  export interface SystemDiagnostic extends Diagnostic {
43
62
  file: string;
@@ -47,29 +66,32 @@ export interface SystemModelReport {
47
66
  name: string | null;
48
67
  source: string;
49
68
  sourceKind: SystemSourceKind;
50
- owner: string | null;
69
+ owner: string[];
51
70
  /** Unqualified (`<sliceKey>/<kind>.<slug>`) refs of every `public` element, export order. */
52
71
  publicSurface: string[];
53
72
  }
54
73
  export interface SystemSeamReport {
55
- /** Resolved, element-level qualified ref when the endpoint resolved; else the ref as written. */
74
+ /** Resolved, element-level qualified ref of the producing element when it resolved; else the
75
+ * ref as written (a `consumes` contract ref, or a legacy manifest `from`). */
56
76
  from: string;
77
+ /** Qualified ref of the consuming reaction (resolved), else the legacy manifest `to` as written. */
57
78
  to: string;
58
79
  fromSlice: string | null;
59
80
  toSlice: string | null;
81
+ /** Legacy 1.0 manifest seams only — `null` for a `consumes` binding. */
60
82
  description: string | null;
61
83
  status: "verified" | "error";
62
- /** Codes of every diagnostic raised on this seam (errors and warnings), in raise order. */
84
+ /** Codes of every diagnostic raised on this binding (errors and warnings), in raise order. */
63
85
  diagnostics: string[];
64
86
  }
65
87
  export interface ContextMap {
66
88
  nodes: {
67
89
  key: string;
68
90
  name: string | null;
69
- owner: string | null;
91
+ owner: string[];
70
92
  }[];
71
- /** One edge per ordered model pair with at least one declared seam (verified or not), sorted
72
- * by (from, to); `seams` counts the declarations. */
93
+ /** One edge per ordered (producer, consumer) model pair with at least one binding (verified or
94
+ * not), sorted by (from, to); `seams` counts the bindings. */
73
95
  edges: {
74
96
  from: string;
75
97
  to: string;
@@ -81,8 +103,23 @@ export interface SystemReport {
81
103
  models: SystemModelReport[];
82
104
  seams: SystemSeamReport[];
83
105
  contextMap: ContextMap;
106
+ /** MIL-239: `checked` = resolved `consumes` bindings whose consumer declares fields (so there
107
+ * was something to compare); `notAdapted` = how many of them raised `consumer-not-adapted`. */
108
+ consumerAdaptation: {
109
+ checked: number;
110
+ notAdapted: number;
111
+ };
84
112
  diagnostics: SystemDiagnostic[];
85
113
  }
86
- /** Verify `manifest` against the loaded `models` (one per manifest entry, same order).
87
- * `manifestFile` is the path manifest-level diagnostics point at. */
88
- export declare function verifySystem(manifest: SystemManifest, models: SystemModelInput[], manifestFile: string): SystemReport;
114
+ /** Caller-supplied, impure inputs `verifySystem` cannot compute itself. */
115
+ export interface VerifySystemOptions {
116
+ /** The short sha of the last commit that changed the producer model's source, or `null` when
117
+ * unknown (no git, no history, export-document source). Named in `consumer-not-adapted`. */
118
+ producerCommit?: (model: SystemModelInput) => string | null;
119
+ }
120
+ /** Verify a system: `models` (manifest order, or discovery order) plus, when the system came
121
+ * from a manifest, that `manifest` and the path manifest-level diagnostics point at. `manifest`
122
+ * is `null` in discovery mode (R4: no manifest found/given) — there is then no name, no
123
+ * manifest-key check, and no legacy seams. `preDiagnostics` (e.g. discovery's own
124
+ * `duplicate-model-key` warnings) lead the report's diagnostics unchanged. */
125
+ export declare function verifySystem(manifest: SystemManifest | null, models: SystemModelInput[], manifestFile: string | null, preDiagnostics?: SystemDiagnostic[], options?: VerifySystemOptions): SystemReport;