@milehimikey/em 1.8.0 → 1.9.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 (127) hide show
  1. package/.claude/skills/event-modeling/SKILL.md +58 -404
  2. package/.claude/skills/event-modeling-conform/SKILL.md +77 -0
  3. package/.claude/skills/{event-modeling → event-modeling-conform}/reference/conform.md +39 -13
  4. package/.claude/skills/event-modeling-design/SKILL.md +139 -0
  5. package/.claude/skills/event-modeling-discover/SKILL.md +89 -0
  6. package/.claude/skills/{event-modeling → event-modeling-discover}/reference/extract.md +3 -2
  7. package/.claude/skills/event-modeling-implement/SKILL.md +40 -0
  8. package/.claude/skills/{event-modeling → event-modeling-implement}/reference/implement.md +3 -2
  9. package/.claude/skills/event-modeling-review/SKILL.md +58 -0
  10. package/.claude/skills/{event-modeling → event-modeling-shared}/reference/em-dsl.md +128 -84
  11. package/.claude/skills/{event-modeling → event-modeling-shared}/reference/methodology.md +6 -5
  12. package/.claude/skills/event-modeling-shared/reference/operating-principles.md +147 -0
  13. package/.claude/skills/{event-modeling → event-modeling-shared}/templates/model-readme.md +2 -2
  14. package/.claude/skills/{event-modeling → event-modeling-shared}/templates/slice.md +51 -8
  15. package/README.md +24 -4
  16. package/dist/catalog/build.js +9 -0
  17. package/dist/catalog/build.js.map +1 -1
  18. package/dist/catalog/docJoin.d.ts +15 -0
  19. package/dist/catalog/docJoin.js +8 -0
  20. package/dist/catalog/docJoin.js.map +1 -1
  21. package/dist/catalog/modelCollisionValidate.d.ts +22 -0
  22. package/dist/catalog/modelCollisionValidate.js +67 -0
  23. package/dist/catalog/modelCollisionValidate.js.map +1 -0
  24. package/dist/catalog/orphanedSliceDocValidate.d.ts +11 -0
  25. package/dist/catalog/orphanedSliceDocValidate.js +98 -0
  26. package/dist/catalog/orphanedSliceDocValidate.js.map +1 -0
  27. package/dist/catalog/sliceDoc.d.ts +15 -0
  28. package/dist/catalog/sliceDoc.js +18 -0
  29. package/dist/catalog/sliceDoc.js.map +1 -1
  30. package/dist/cli/changelogBuild.d.ts +12 -0
  31. package/dist/cli/changelogBuild.js +89 -0
  32. package/dist/cli/changelogBuild.js.map +1 -0
  33. package/dist/cli/ciInit.d.ts +42 -0
  34. package/dist/cli/ciInit.js +298 -0
  35. package/dist/cli/ciInit.js.map +1 -0
  36. package/dist/cli/conformSupersede.d.ts +32 -0
  37. package/dist/cli/conformSupersede.js +102 -0
  38. package/dist/cli/conformSupersede.js.map +1 -0
  39. package/dist/cli/coverage.d.ts +17 -10
  40. package/dist/cli/coverage.js +61 -16
  41. package/dist/cli/coverage.js.map +1 -1
  42. package/dist/cli/frontmatterSurgery.d.ts +28 -0
  43. package/dist/cli/frontmatterSurgery.js +66 -0
  44. package/dist/cli/frontmatterSurgery.js.map +1 -0
  45. package/dist/cli/markImplemented.js +6 -45
  46. package/dist/cli/markImplemented.js.map +1 -1
  47. package/dist/cli/ratify.d.ts +41 -0
  48. package/dist/cli/ratify.js +151 -0
  49. package/dist/cli/ratify.js.map +1 -0
  50. package/dist/cli/reratify.d.ts +33 -0
  51. package/dist/cli/reratify.js +137 -0
  52. package/dist/cli/reratify.js.map +1 -0
  53. package/dist/cli/skillCheck.d.ts +6 -0
  54. package/dist/cli/skillCheck.js +46 -0
  55. package/dist/cli/skillCheck.js.map +1 -1
  56. package/dist/cli/skillDirs.d.ts +15 -0
  57. package/dist/cli/skillDirs.js +34 -0
  58. package/dist/cli/skillDirs.js.map +1 -0
  59. package/dist/cli/skillSync.d.ts +10 -0
  60. package/dist/cli/skillSync.js +15 -0
  61. package/dist/cli/skillSync.js.map +1 -1
  62. package/dist/cli/sliceIndex.d.ts +3 -0
  63. package/dist/cli/sliceIndex.js +6 -2
  64. package/dist/cli/sliceIndex.js.map +1 -1
  65. package/dist/cli/sliceLink.d.ts +52 -0
  66. package/dist/cli/sliceLink.js +152 -0
  67. package/dist/cli/sliceLink.js.map +1 -0
  68. package/dist/cli/status.d.ts +261 -0
  69. package/dist/cli/status.js +536 -0
  70. package/dist/cli/status.js.map +1 -0
  71. package/dist/cli/usageLog.d.ts +75 -0
  72. package/dist/cli/usageLog.js +193 -0
  73. package/dist/cli/usageLog.js.map +1 -0
  74. package/dist/cli.js +501 -130
  75. package/dist/cli.js.map +1 -1
  76. package/dist/emit/diffJson.d.ts +9 -1
  77. package/dist/emit/diffJson.js +44 -1
  78. package/dist/emit/diffJson.js.map +1 -1
  79. package/dist/emit/freshnessJson.d.ts +6 -0
  80. package/dist/emit/freshnessJson.js +24 -0
  81. package/dist/emit/freshnessJson.js.map +1 -0
  82. package/dist/emit/json.d.ts +67 -8
  83. package/dist/emit/json.js +19 -3
  84. package/dist/emit/json.js.map +1 -1
  85. package/dist/emit/statusJson.d.ts +7 -0
  86. package/dist/emit/statusJson.js +39 -0
  87. package/dist/emit/statusJson.js.map +1 -0
  88. package/dist/emit/typespec.d.ts +26 -0
  89. package/dist/emit/typespec.js +356 -0
  90. package/dist/emit/typespec.js.map +1 -0
  91. package/dist/emit/usageReportJson.d.ts +3 -0
  92. package/dist/emit/usageReportJson.js +23 -0
  93. package/dist/emit/usageReportJson.js.map +1 -0
  94. package/dist/mcp/server.d.ts +1 -1
  95. package/dist/mcp/server.js +301 -11
  96. package/dist/mcp/server.js.map +1 -1
  97. package/dist/model/rules.d.ts +13 -0
  98. package/dist/model/rules.js +20 -0
  99. package/dist/model/rules.js.map +1 -1
  100. package/dist/model/validate.js +9 -1
  101. package/dist/model/validate.js.map +1 -1
  102. package/dist/parser/ast.d.ts +6 -0
  103. package/dist/parser/parser.js +20 -6
  104. package/dist/parser/parser.js.map +1 -1
  105. package/dist/render/drawNotes.d.ts +11 -1
  106. package/dist/render/drawNotes.js +20 -2
  107. package/dist/render/drawNotes.js.map +1 -1
  108. package/dist/render/render.js +31 -6
  109. package/dist/render/render.js.map +1 -1
  110. package/dist/render/serve.js +4 -0
  111. package/dist/render/serve.js.map +1 -1
  112. package/dist/render/sliceOverlay.d.ts +7 -2
  113. package/dist/render/sliceOverlay.js +19 -7
  114. package/dist/render/sliceOverlay.js.map +1 -1
  115. package/dist/render/sliceStatus.d.ts +7 -3
  116. package/dist/render/sliceStatus.js +21 -14
  117. package/dist/render/sliceStatus.js.map +1 -1
  118. package/dist/render/viewerHtml.js +1 -1
  119. package/dist/render/viewerHtml.js.map +1 -1
  120. package/dist/templates.d.ts +2 -2
  121. package/dist/templates.js +5 -5
  122. package/dist/util/markers.d.ts +16 -4
  123. package/dist/util/markers.js +23 -10
  124. package/dist/util/markers.js.map +1 -1
  125. package/package.json +2 -1
  126. /package/.claude/skills/{event-modeling → event-modeling-shared}/templates/conformance-report.md +0 -0
  127. /package/.claude/skills/{event-modeling → event-modeling-shared}/templates/state.md +0 -0
@@ -0,0 +1,39 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Builds the `em status --json` document: a versioned envelope around `StatusReport` (see
3
+ // ../cli/status.ts). Follows `em coverage`/`em ledger`'s conventions (coverageJson.ts,
4
+ // ledgerJson.ts): a schema field versioned independently of both the npm package and every
5
+ // other command's own schema. This is also the EXACT document the MCP `status` tool returns
6
+ // (src/mcp/server.ts) — both callers build it by handing the same `StatusReport` to this one
7
+ // function, so there is exactly one schema for this surface (MCP parity, MIL-163).
8
+ import { serializeDiagnostic } from "../model/validate.js";
9
+ import { GENERATOR_NAME, GENERATOR_VERSION } from "./json.js";
10
+ // 1.0 (MIL-163): initial shape.
11
+ // 1.1 (MIL-164): each `conformance[]` entry gains `slicePRsBehindHead` (number | null) —
12
+ // candidate-slice count from the same conform-scope machinery, alongside `commitsBehindHead`.
13
+ // 1.2 (MIL-171): a new top-level `owners` array — one `{ file, key, owner }` entry per slice
14
+ // across every input file, `owner` verbatim from the doc's frontmatter `owner:` (null when
15
+ // absent or when no doc was found). See ../cli/status.ts's StatusOwnerEntry.
16
+ export const STATUS_SCHEMA_VERSION = "1.2";
17
+ /** Build the `em status <files...> --json` document. Pretty-printed (2-space), no trailing
18
+ * newline — the caller adds it, same convention as buildCoverageJson/buildLedgerJson. No
19
+ * timestamps or other non-deterministic fields: byte-identical for the same models/git state
20
+ * (MIL-163's "deterministic core" constraint). */
21
+ export function buildStatusJson(report) {
22
+ const doc = {
23
+ statusSchemaVersion: STATUS_SCHEMA_VERSION,
24
+ generator: { name: GENERATOR_NAME, version: GENERATOR_VERSION },
25
+ files: report.files,
26
+ slices: report.slices,
27
+ driftSignal: report.driftSignal,
28
+ invariants: report.invariants,
29
+ issues: report.issues,
30
+ conformance: report.conformance,
31
+ owners: report.owners,
32
+ // Doc-join diagnostics (binding-missing-file/frontmatter-invalid), tagged with the file
33
+ // each concerns — same serialized diagnostic shape em export/em diff use (severity, code,
34
+ // message, line, refs), plus `file` since this is a multi-model surface.
35
+ diagnostics: report.diagnostics.map((d) => ({ file: d.file, ...serializeDiagnostic(d) })),
36
+ };
37
+ return JSON.stringify(doc, null, 2);
38
+ }
39
+ //# sourceMappingURL=statusJson.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statusJson.js","sourceRoot":"","sources":["../../src/emit/statusJson.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,0FAA0F;AAC1F,uFAAuF;AACvF,2FAA2F;AAC3F,4FAA4F;AAC5F,6FAA6F;AAC7F,mFAAmF;AAGnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9D,gCAAgC;AAChC,yFAAyF;AACzF,8FAA8F;AAC9F,6FAA6F;AAC7F,2FAA2F;AAC3F,6EAA6E;AAC7E,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAE3C;;;mDAGmD;AACnD,MAAM,UAAU,eAAe,CAAC,MAAoB;IAClD,MAAM,GAAG,GAAG;QACV,mBAAmB,EAAE,qBAAqB;QAC1C,SAAS,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,iBAAiB,EAAE;QAC/D,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,wFAAwF;QACxF,0FAA0F;QAC1F,yEAAyE;QACzE,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;KAC1F,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { NormalizedModel } from "../model/model.js";
2
+ import { RefsResult } from "../model/refs.js";
3
+ import { Diagnostic } from "../model/validate.js";
4
+ export declare const TYPESPEC_SCHEMA_VERSION = "1.0";
5
+ export interface TypeSpecResult {
6
+ /** TypeSpec source text, no trailing newline. */
7
+ text: string;
8
+ /** Same diagnostics `buildExport` would raise for this model (doc-join warnings, ref
9
+ * collisions, etc.) — the caller decides how to print/gate these, same posture as
10
+ * `buildExport`'s own `diagnostics` field. */
11
+ diagnostics: Diagnostic[];
12
+ /** Human-readable notes about fields whose em type string had no scalar mapping and fell
13
+ * back to `unknown` — informational only, never blocking (POC's "best-effort inference with
14
+ * a warning" choice — see the type-mapping section below). Empty when every included
15
+ * field's type mapped cleanly, or declared no type at all (an untyped field isn't a mapping
16
+ * failure — see `mapFieldType`). */
17
+ unmappedTypes: string[];
18
+ }
19
+ export declare const SCALAR_TYPE_MAP: Readonly<Record<string, string>>;
20
+ /**
21
+ * Build the `em typespec <file>` document: TypeSpec source text for a model's contract
22
+ * surface. Mirrors `buildExport`'s parameter contract exactly (same four inputs, same
23
+ * "already-validated, error-free model" precondition — the caller, cli.ts, applies the same
24
+ * refuse-on-error gate `em export` uses before calling this).
25
+ */
26
+ export declare function buildTypeSpec(model: NormalizedModel, refs: RefsResult, diagnostics: Diagnostic[], source: string, path: string): TypeSpecResult;
@@ -0,0 +1,356 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // POC (MIL-159): generates a TypeSpec (https://typespec.io) contract surface — plain `model`/
3
+ // `interface`/`op` declarations, core scalars only, no imports — for a model's commands,
4
+ // public events, and public views. EXPERIMENTAL: see docs/cli.md's `em typespec` section for
5
+ // the scoping/type-mapping decisions this POC makes and what it deliberately leaves out.
6
+ //
7
+ // Reuses `buildExportDoc` (emit/json.ts) rather than re-deriving typeRef/tags/renamedFrom/
8
+ // assigned/public from the raw model a second time — same discipline `em export` itself
9
+ // follows: one resolution pass, one place field metadata is computed, every consumer reads
10
+ // the resolved shape. Deterministic and dependency-free: no LLM, no new runtime dependency —
11
+ // this emits TypeSpec *source text* directly rather than building an AST through
12
+ // `@typespec/compiler` (see test/typespec.test.ts for the optional, skip-if-absent
13
+ // compile-verification test that checks the text this module emits is actually valid
14
+ // TypeSpec, using `@typespec/compiler` as a devDependency only).
15
+ import { dedupe } from "../util/slug.js";
16
+ import { buildExportDoc } from "./json.js";
17
+ // 1.0 (MIL-159, POC): initial shape. Not part of the `em export` schema-versioning lineage —
18
+ // this is source text, not JSON, and the POC's own mapping/scoping decisions (see below) are
19
+ // expected to change if/when this graduates past POC, so it gets its own independent version.
20
+ export const TYPESPEC_SCHEMA_VERSION = "1.0";
21
+ // ---- Type mapping strategy ---------------------------------------------------------------
22
+ //
23
+ // em field types are free text with no semantic checking (docs/dsl.md, "Fields"). TypeSpec
24
+ // needs real scalar/model references, so this POC picks one explicit, documented strategy
25
+ // (per the ticket's "needs an explicit mapping strategy" — not assumed) rather than passing
26
+ // text through unchanged:
27
+ //
28
+ // 1. A field whose type names a declared `type` block (`FieldExport.typeRef`, already
29
+ // resolved by `buildExportDoc` — bare or `[]`-suffixed) references that type's generated
30
+ // `model` by name. This is the clean, low-risk case the ticket calls out — em already does
31
+ // all the resolution work.
32
+ // 2. Otherwise, the *bare* type name (after stripping a `[]` suffix or a `List<...>`/
33
+ // `Array<...>`/`Set<...>` generic wrapper) is looked up case-insensitively in
34
+ // SCALAR_TYPE_MAP below. A hit maps to that TypeSpec core scalar.
35
+ // 3. A field with no declared type at all (`type` was never written) maps to `unknown` —
36
+ // not a mapping failure, just an honest "this field's shape isn't declared here."
37
+ // 4. Anything else — a declared type string that's neither a known scalar nor a resolvable
38
+ // `type` reference (`Money`, a typo, a domain-specific string nobody's mapped) — also
39
+ // becomes `unknown`, but is recorded in `TypeSpecResult.unmappedTypes` so the gap is
40
+ // visible instead of silently swallowed. `List<X>` around an unresolved `X` (including a
41
+ // declared type referenced through the generic-wrapper spelling rather than `X[]` — see
42
+ // docs/dsl.md's Named types section on why only the bare/`[]` forms resolve) still maps to
43
+ // `unknown[]`, not `unknown`, so the arity survives even when the element type doesn't.
44
+ //
45
+ // This table is intentionally small and unopinionated (nothing domain-specific like `Money` ->
46
+ // a currency shape) — go/no-go note: a promoted, non-POC version would likely want this
47
+ // user-configurable (a mapping file) rather than hardcoded.
48
+ export const SCALAR_TYPE_MAP = Object.freeze({
49
+ string: "string",
50
+ str: "string",
51
+ text: "string",
52
+ uuid: "string",
53
+ guid: "string",
54
+ int: "int32",
55
+ integer: "int32",
56
+ int32: "int32",
57
+ int64: "int64",
58
+ long: "int64",
59
+ short: "int16",
60
+ int16: "int16",
61
+ byte: "int8",
62
+ int8: "int8",
63
+ uint: "uint32",
64
+ boolean: "boolean",
65
+ bool: "boolean",
66
+ float: "float32",
67
+ float32: "float32",
68
+ double: "float64",
69
+ float64: "float64",
70
+ decimal: "decimal",
71
+ money: "decimal",
72
+ currency: "decimal",
73
+ instant: "utcDateTime",
74
+ datetime: "utcDateTime",
75
+ timestamp: "utcDateTime",
76
+ utcdatetime: "utcDateTime",
77
+ date: "plainDate",
78
+ time: "plainTime",
79
+ duration: "duration",
80
+ url: "url",
81
+ uri: "url",
82
+ bytes: "bytes",
83
+ binary: "bytes",
84
+ object: "unknown",
85
+ any: "unknown",
86
+ void: "void",
87
+ });
88
+ function mapRawType(raw) {
89
+ let s = raw.trim();
90
+ let array = false;
91
+ const generic = s.match(/^(?:List|Array|Set)<(.+)>$/i);
92
+ if (generic) {
93
+ array = true;
94
+ s = generic[1].trim();
95
+ }
96
+ else if (s.endsWith("[]")) {
97
+ array = true;
98
+ s = s.slice(0, -2).trim();
99
+ }
100
+ const scalar = SCALAR_TYPE_MAP[s.toLowerCase()];
101
+ if (scalar)
102
+ return { tsType: array ? `${scalar}[]` : scalar, mapped: true };
103
+ return { tsType: array ? "unknown[]" : "unknown", mapped: false };
104
+ }
105
+ // ---- Identifier shaping -----------------------------------------------------------------
106
+ /** em element/type names are free text ("Place Order", "Order Placed"). TypeSpec model/
107
+ * operation names need a bare identifier — PascalCase, matching TypeSpec's own convention
108
+ * for `model`/`interface` names. */
109
+ function pascalCase(name) {
110
+ const words = name.match(/[A-Za-z0-9]+/g) ?? [];
111
+ const joined = words.map((w) => w[0].toUpperCase() + w.slice(1)).join("");
112
+ if (joined.length === 0)
113
+ return "Unnamed";
114
+ return /^[0-9]/.test(joined) ? `_${joined}` : joined;
115
+ }
116
+ function camelCase(pascal) {
117
+ return pascal.length > 0 ? pascal[0].toLowerCase() + pascal.slice(1) : pascal;
118
+ }
119
+ /** A field name that isn't a bare TypeSpec identifier (spaces, leading digit, ...) is quoted
120
+ * with backticks — the same escape TypeSpec itself uses for a non-identifier member name. em
121
+ * field names are conventionally already valid identifiers (see examples/*.em), so this is a
122
+ * defensive fallback, not the expected path. */
123
+ function fieldIdentifier(name) {
124
+ if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(name))
125
+ return name;
126
+ return "`" + name.replace(/\\/g, "\\\\").replace(/`/g, "\\`") + "`";
127
+ }
128
+ // ---- Doc-comment metadata -----------------------------------------------------------------
129
+ //
130
+ // `tag` (DCB), `renamed from`, and `assigned` are modeling/event-store concerns, not wire-
131
+ // contract shape — decided (per the ticket's open question) to carry them forward as plain
132
+ // `/** ... */` doc comments, never as decorators. A custom `@tag`/`@assigned`/`@renamedFrom`
133
+ // decorator would need its own TypeSpec extension library (`extern dec` + a JS implementation)
134
+ // to be anything but cosmetic, which is out of scope for a dependency-free POC; a doc comment
135
+ // keeps the information visible in the generated contract without inventing new TypeSpec
136
+ // vocabulary this POC can't back with real semantics.
137
+ function fieldDocComment(f) {
138
+ const notes = [];
139
+ if (f.tag)
140
+ notes.push("DCB identity tag");
141
+ if (f.renamedFrom && f.renamedFrom.length > 0) {
142
+ notes.push(`renamed from ${f.renamedFrom.map((n) => JSON.stringify(n)).join(", ")}`);
143
+ }
144
+ if (f.assigned)
145
+ notes.push("system-assigned — not supplied by the triggering command");
146
+ return notes.length > 0 ? notes.join("; ") : null;
147
+ }
148
+ function elementDocComment(el) {
149
+ const notes = [];
150
+ if (el.renamedFrom && el.renamedFrom.length > 0) {
151
+ notes.push(`renamed from ${el.renamedFrom.map((n) => JSON.stringify(n)).join(", ")}`);
152
+ }
153
+ if (el.tags) {
154
+ for (const t of el.tags) {
155
+ if (t.kind === "composite")
156
+ notes.push(`DCB composite tag \`${t.key}\` from ${(t.fields ?? []).join(", ")}`);
157
+ else if (t.kind === "external")
158
+ notes.push(`DCB external tag \`${t.key}\`: ${t.description}`);
159
+ // identity tags are already surfaced per-field (fieldDocComment) — not repeated here.
160
+ }
161
+ }
162
+ return notes.length > 0 ? notes.join("; ") : null;
163
+ }
164
+ function indent(lines, depth) {
165
+ const pad = " ".repeat(depth);
166
+ return lines.map((l) => (l.length > 0 ? pad + l : l));
167
+ }
168
+ /**
169
+ * Build the `em typespec <file>` document: TypeSpec source text for a model's contract
170
+ * surface. Mirrors `buildExport`'s parameter contract exactly (same four inputs, same
171
+ * "already-validated, error-free model" precondition — the caller, cli.ts, applies the same
172
+ * refuse-on-error gate `em export` uses before calling this).
173
+ */
174
+ export function buildTypeSpec(model, refs, diagnostics, source, path) {
175
+ const { doc, diagnostics: allDiagnostics } = buildExportDoc(model, refs, diagnostics, source, path);
176
+ const unmappedNotes = [];
177
+ const recordUnmapped = (refLabel, field, rawType) => {
178
+ unmappedNotes.push(`${refLabel} field "${field}": type "${rawType}" has no scalar mapping — emitted as \`unknown\``);
179
+ };
180
+ const typesByRef = new Map(doc.model.types.map((t) => [t.ref, t]));
181
+ // ---- Scoping (per the ticket's own decision points) --------------------------------
182
+ //
183
+ // Events/views: exactly `public` (docs/dsl.md's Integration surface — the flag this
184
+ // generator was built for). Commands have no `public` flag of their own (dsl.md), so this
185
+ // POC's decision is: a command is included when its own slice declares at least one public
186
+ // event or view — the request contract for a slice that's already promoted its outcome
187
+ // (or its read model) to the integration surface belongs on the same contract. A slice with
188
+ // no public event/view contributes nothing, including its commands.
189
+ const slicePublic = new Map();
190
+ for (const slice of doc.model.slices) {
191
+ slicePublic.set(slice.key, slice.elements.some((el) => (el.kind === "event" || el.kind === "view") && el.public === true));
192
+ }
193
+ const publicEvents = [];
194
+ const publicViews = [];
195
+ const scopedCommands = [];
196
+ // A repeated view instance (`view X again`) shares one logical identity (docs/dsl.md,
197
+ // "view … again") — only the first instance is emitted as a `model`; later instances are
198
+ // folded into it rather than re-declared under the same name (which TypeSpec would reject
199
+ // as a duplicate). Left out of this POC: merging the *new* fields a later public instance
200
+ // adds — see buildTypeSpec's module comment / the PR's "left out of POC" notes.
201
+ const seenViewNames = new Set();
202
+ for (const slice of doc.model.slices) {
203
+ for (const el of slice.elements) {
204
+ if (el.kind === "event" && el.public)
205
+ publicEvents.push(el);
206
+ else if (el.kind === "view" && el.public) {
207
+ const key = el.name.trim().toLowerCase();
208
+ if (!seenViewNames.has(key)) {
209
+ seenViewNames.add(key);
210
+ publicViews.push(el);
211
+ }
212
+ }
213
+ else if (el.kind === "command" && slicePublic.get(slice.key)) {
214
+ scopedCommands.push(el);
215
+ }
216
+ }
217
+ }
218
+ // ---- Named types: only those reachable from an included element's fields, transitively
219
+ // (never every declared type — a type nobody in the public/command surface references
220
+ // would be dead weight in a *contract* artifact, unlike `em export`'s full-model dump). ----
221
+ const reachableTypeRefs = new Set();
222
+ const walkFields = (fields) => {
223
+ if (!fields)
224
+ return;
225
+ for (const f of fields) {
226
+ if (f.typeRef && !reachableTypeRefs.has(f.typeRef.ref)) {
227
+ reachableTypeRefs.add(f.typeRef.ref);
228
+ const t = typesByRef.get(f.typeRef.ref);
229
+ if (t)
230
+ walkFields(t.fields);
231
+ }
232
+ }
233
+ };
234
+ for (const el of [...publicEvents, ...publicViews, ...scopedCommands])
235
+ walkFields(el.fields);
236
+ const usedNames = new Set();
237
+ const typeNameByRef = new Map();
238
+ const typeBlocks = [];
239
+ for (const t of doc.model.types) {
240
+ if (!reachableTypeRefs.has(t.ref))
241
+ continue;
242
+ const name = dedupe(pascalCase(t.name), usedNames, "_");
243
+ typeNameByRef.set(t.ref, name);
244
+ }
245
+ const resolveFieldType = (f, refLabel) => {
246
+ if (f.typeRef) {
247
+ const name = typeNameByRef.get(f.typeRef.ref) ?? pascalCase(f.typeRef.name);
248
+ return f.typeRef.array ? `${name}[]` : name;
249
+ }
250
+ if (f.type == null)
251
+ return "unknown";
252
+ const { tsType, mapped } = mapRawType(f.type);
253
+ if (!mapped)
254
+ recordUnmapped(refLabel, f.name, f.type);
255
+ return tsType;
256
+ };
257
+ const renderFieldLines = (fields, refLabel) => {
258
+ if (!fields || fields.length === 0)
259
+ return [];
260
+ const lines = [];
261
+ for (const f of fields) {
262
+ const fieldDoc = fieldDocComment(f);
263
+ if (fieldDoc)
264
+ lines.push(`/** ${fieldDoc} */`);
265
+ lines.push(`${fieldIdentifier(f.name)}: ${resolveFieldType(f, refLabel)};`);
266
+ }
267
+ return lines;
268
+ };
269
+ const renderModel = (name, fields, refLabel, docComment) => {
270
+ const lines = [];
271
+ if (docComment)
272
+ lines.push(`/** ${docComment} */`);
273
+ lines.push(`model ${name} {`);
274
+ lines.push(...indent(renderFieldLines(fields, refLabel), 1));
275
+ lines.push(`}`);
276
+ return lines.join("\n");
277
+ };
278
+ // Named types, in declaration order, filtered to what's reachable.
279
+ for (const t of doc.model.types) {
280
+ const name = typeNameByRef.get(t.ref);
281
+ if (!name)
282
+ continue;
283
+ typeBlocks.push(renderModel(name, t.fields, `types/${t.name}`));
284
+ }
285
+ // ---- Events (message payloads): plain `model` declarations, schema only ------------------
286
+ //
287
+ // Open question the ticket asks to research: how does TypeSpec represent an async/event
288
+ // contract, given core TypeSpec is HTTP/OpenAPI-shaped? This POC's answer is the option the
289
+ // ticket itself lists as viable without new tooling: a plain `model` for the payload shape,
290
+ // no protocol semantics attached. A promoted version could layer `@typespec/events` or an
291
+ // AsyncAPI emitter on top of these same models for channel/binding semantics — deliberately
292
+ // not attempted here (see "left out of POC", the PR description, and the go/no-go note in
293
+ // this module's header).
294
+ const eventNames = new Set(usedNames);
295
+ const eventBlocks = [];
296
+ for (const el of publicEvents) {
297
+ const name = dedupe(pascalCase(el.name), eventNames, "_");
298
+ eventBlocks.push(renderModel(name, el.fields, el.ref, elementDocComment(el)));
299
+ }
300
+ // ---- Views (read-model contracts): a `model` for the shape, plus a no-arg accessor `op` —
301
+ // covers both halves of the ticket's "Views -> TypeSpec models/operations". Deliberately no
302
+ // `@get`/`@route` (that's `@typespec/http` territory, a new dependency this POC doesn't
303
+ // need to prove the field-mapping question) — a bare, protocol-agnostic `op`. --------------
304
+ const viewNames = new Set(eventNames);
305
+ const viewBlocks = [];
306
+ const viewOps = [];
307
+ for (const el of publicViews) {
308
+ const name = dedupe(pascalCase(el.name), viewNames, "_");
309
+ viewBlocks.push(renderModel(name, el.fields, el.ref, elementDocComment(el)));
310
+ viewOps.push(`op get${name}(): ${name};`);
311
+ }
312
+ // ---- Commands (request contracts): an `op` per command, one parameter per field. ---------
313
+ const commandOpNames = new Set();
314
+ const commandOps = [];
315
+ for (const el of scopedCommands) {
316
+ const opName = dedupe(camelCase(pascalCase(el.name)), commandOpNames, "_");
317
+ const docComment = elementDocComment(el);
318
+ const params = (el.fields ?? []).map((f) => {
319
+ const fieldDoc = fieldDocComment(f);
320
+ const line = `${fieldIdentifier(f.name)}: ${resolveFieldType(f, el.ref)}`;
321
+ return fieldDoc ? `/** ${fieldDoc} */ ${line}` : line;
322
+ });
323
+ if (docComment)
324
+ commandOps.push(`/** ${docComment} */`);
325
+ commandOps.push(params.length > 0 ? `op ${opName}(${params.join(", ")}): void;` : `op ${opName}(): void;`);
326
+ }
327
+ // ---- Assemble ------------------------------------------------------------------------
328
+ const namespaceName = pascalCase(doc.model.name ?? "Model") || "Model";
329
+ const sections = [];
330
+ if (typeBlocks.length > 0)
331
+ sections.push(typeBlocks.join("\n\n"));
332
+ if (eventBlocks.length > 0)
333
+ sections.push(eventBlocks.join("\n\n"));
334
+ if (viewBlocks.length > 0) {
335
+ sections.push(viewBlocks.join("\n\n"));
336
+ sections.push(["interface Views {", ...indent(viewOps, 1), "}"].join("\n"));
337
+ }
338
+ if (commandOps.length > 0) {
339
+ sections.push(["interface Commands {", ...indent(commandOps, 1), "}"].join("\n"));
340
+ }
341
+ const header = [
342
+ `// GENERATED by \`em typespec\` (${TYPESPEC_SCHEMA_VERSION}) — EXPERIMENTAL / POC (MIL-159).`,
343
+ `// Source: ${doc.source.path} (sha256 ${doc.source.sha256})`,
344
+ `// Scope: \`public\` events/views (docs/dsl.md "Integration surface"), plus every command in`,
345
+ `// a slice that declares at least one of them. \`tag\`/\`renamed from\`/\`assigned\` are recorded`,
346
+ `// as doc comments only — see docs/cli.md's "em typespec" section for the full mapping.`,
347
+ `// Do not edit by hand — regenerate with \`em typespec ${doc.source.path}\`.`,
348
+ ];
349
+ const body = sections.length > 0 ? indent(sections.join("\n\n").split("\n"), 1) : [];
350
+ const namespaceLines = body.length > 0
351
+ ? [`namespace ${namespaceName} {`, ...body, `}`]
352
+ : [`namespace ${namespaceName} {}`];
353
+ const text = [...header, "", ...namespaceLines].join("\n");
354
+ return { text, diagnostics: allDiagnostics, unmappedTypes: unmappedNotes };
355
+ }
356
+ //# sourceMappingURL=typespec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typespec.js","sourceRoot":"","sources":["../../src/emit/typespec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { UsageReport } from "../cli/usageLog.js";
2
+ export declare const USAGE_REPORT_SCHEMA_VERSION = "1.0";
3
+ export declare function buildUsageReportJson(report: UsageReport): string;
@@ -0,0 +1,23 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Builds the `em usage-report --json` document: a versioned envelope around `UsageReport` (see
3
+ // ../cli/usageLog.ts). Follows every other command's convention (statusJson.ts/coverageJson.ts):
4
+ // a schema field versioned independently of both the npm package and every other command's own
5
+ // schema. Pretty-printed, no trailing newline, no timestamps — byte-identical for the same
6
+ // input files.
7
+ import { GENERATOR_NAME, GENERATOR_VERSION } from "./json.js";
8
+ // 1.0 (MIL-161): initial shape.
9
+ export const USAGE_REPORT_SCHEMA_VERSION = "1.0";
10
+ export function buildUsageReportJson(report) {
11
+ const doc = {
12
+ usageReportSchemaVersion: USAGE_REPORT_SCHEMA_VERSION,
13
+ generator: { name: GENERATOR_NAME, version: GENERATOR_VERSION },
14
+ root: report.root,
15
+ files: report.files,
16
+ sessions: report.sessions,
17
+ phaseCounts: report.phaseCounts,
18
+ categoryCounts: report.categoryCounts,
19
+ unparseableLines: report.unparseableLines,
20
+ };
21
+ return JSON.stringify(doc, null, 2);
22
+ }
23
+ //# sourceMappingURL=usageReportJson.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usageReportJson.js","sourceRoot":"","sources":["../../src/emit/usageReportJson.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,+FAA+F;AAC/F,iGAAiG;AACjG,+FAA+F;AAC/F,2FAA2F;AAC3F,eAAe;AAGf,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9D,gCAAgC;AAChC,MAAM,CAAC,MAAM,2BAA2B,GAAG,KAAK,CAAC;AAEjD,MAAM,UAAU,oBAAoB,CAAC,MAAmB;IACtD,MAAM,GAAG,GAAG;QACV,wBAAwB,EAAE,2BAA2B;QACrD,SAAS,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,iBAAiB,EAAE;QAC/D,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;KAC1C,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACtC,CAAC"}
@@ -4,7 +4,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
4
  * so `em --version`/`em export`'s `generator.version`/this server's version never drift apart. */
5
5
  export declare const SERVER_NAME = "em";
6
6
  export declare const SERVER_VERSION: string;
7
- /** Registers all seven MCP tools on a fresh McpServer instance and returns it, unconnected — the
7
+ /** Registers all thirteen MCP tools on a fresh McpServer instance and returns it, unconnected — the
8
8
  * caller (src/mcp/main.ts's stdio entry, or a test harness using an in-memory transport)
9
9
  * decides how to connect it. Building the server is a pure, side-effect-free function so tests
10
10
  * can exercise it directly with the SDK's in-memory transport, no child process required. */