@milehimikey/em 1.12.0 → 1.13.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 (112) hide show
  1. package/.claude/skills/event-modeling/SKILL.md +5 -2
  2. package/.claude/skills/event-modeling-conform/SKILL.md +20 -9
  3. package/.claude/skills/event-modeling-conform/reference/conform.md +107 -10
  4. package/.claude/skills/event-modeling-design/SKILL.md +26 -4
  5. package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
  6. package/.claude/skills/event-modeling-implement/SKILL.md +7 -4
  7. package/.claude/skills/event-modeling-implement/reference/implement.md +26 -8
  8. package/.claude/skills/event-modeling-review/SKILL.md +5 -1
  9. package/.claude/skills/event-modeling-shared/reference/em-dsl.md +45 -6
  10. package/.claude/skills/event-modeling-shared/reference/operating-principles.md +13 -3
  11. package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +39 -0
  12. package/.claude/skills/event-modeling-shared/templates/conformance-report.md +8 -1
  13. package/.claude/skills/event-modeling-shared/templates/state.md +3 -0
  14. package/README.md +1 -0
  15. package/dist/catalog/docJoin.d.ts +9 -0
  16. package/dist/catalog/docJoin.js +6 -0
  17. package/dist/catalog/docJoin.js.map +1 -1
  18. package/dist/catalog/driftSignal.d.ts +11 -5
  19. package/dist/catalog/driftSignal.js +18 -4
  20. package/dist/catalog/driftSignal.js.map +1 -1
  21. package/dist/catalog/modelVersionValidate.d.ts +9 -0
  22. package/dist/catalog/modelVersionValidate.js +38 -0
  23. package/dist/catalog/modelVersionValidate.js.map +1 -0
  24. package/dist/catalog/sliceDoc.d.ts +12 -0
  25. package/dist/catalog/sliceDoc.js +15 -0
  26. package/dist/catalog/sliceDoc.js.map +1 -1
  27. package/dist/cli/ciInit.d.ts +24 -0
  28. package/dist/cli/ciInit.js +85 -15
  29. package/dist/cli/ciInit.js.map +1 -1
  30. package/dist/cli/conformScope.d.ts +1 -0
  31. package/dist/cli/conformScope.js +3 -1
  32. package/dist/cli/conformScope.js.map +1 -1
  33. package/dist/cli/conformSupersede.d.ts +24 -2
  34. package/dist/cli/conformSupersede.js +44 -3
  35. package/dist/cli/conformSupersede.js.map +1 -1
  36. package/dist/cli/coverage.d.ts +16 -2
  37. package/dist/cli/coverage.js +26 -4
  38. package/dist/cli/coverage.js.map +1 -1
  39. package/dist/cli/findings.d.ts +134 -0
  40. package/dist/cli/findings.js +355 -0
  41. package/dist/cli/findings.js.map +1 -0
  42. package/dist/cli/metrics.d.ts +93 -0
  43. package/dist/cli/metrics.js +331 -0
  44. package/dist/cli/metrics.js.map +1 -0
  45. package/dist/cli/modelVersion.d.ts +139 -0
  46. package/dist/cli/modelVersion.js +256 -0
  47. package/dist/cli/modelVersion.js.map +1 -0
  48. package/dist/cli/reratify.d.ts +24 -1
  49. package/dist/cli/reratify.js +73 -17
  50. package/dist/cli/reratify.js.map +1 -1
  51. package/dist/cli/skillCheck.js +2 -2
  52. package/dist/cli/skillCheck.js.map +1 -1
  53. package/dist/cli/sliceConform.d.ts +50 -0
  54. package/dist/cli/sliceConform.js +206 -0
  55. package/dist/cli/sliceConform.js.map +1 -0
  56. package/dist/cli/sliceIndex.d.ts +2 -0
  57. package/dist/cli/sliceIndex.js +15 -3
  58. package/dist/cli/sliceIndex.js.map +1 -1
  59. package/dist/cli/sliceNew.d.ts +12 -0
  60. package/dist/cli/sliceNew.js +23 -0
  61. package/dist/cli/sliceNew.js.map +1 -1
  62. package/dist/cli/sliceStubAll.d.ts +76 -0
  63. package/dist/cli/sliceStubAll.js +189 -0
  64. package/dist/cli/sliceStubAll.js.map +1 -0
  65. package/dist/cli/stateFile.d.ts +63 -7
  66. package/dist/cli/stateFile.js +179 -18
  67. package/dist/cli/stateFile.js.map +1 -1
  68. package/dist/cli/status.d.ts +79 -1
  69. package/dist/cli/status.js +134 -15
  70. package/dist/cli/status.js.map +1 -1
  71. package/dist/cli/upgrade.d.ts +132 -0
  72. package/dist/cli/upgrade.js +524 -0
  73. package/dist/cli/upgrade.js.map +1 -0
  74. package/dist/cli.js +609 -50
  75. package/dist/cli.js.map +1 -1
  76. package/dist/emit/coverageJson.d.ts +5 -2
  77. package/dist/emit/coverageJson.js +6 -2
  78. package/dist/emit/coverageJson.js.map +1 -1
  79. package/dist/emit/freshnessJson.d.ts +1 -1
  80. package/dist/emit/freshnessJson.js +3 -1
  81. package/dist/emit/freshnessJson.js.map +1 -1
  82. package/dist/emit/json.d.ts +11 -1
  83. package/dist/emit/json.js +35 -1
  84. package/dist/emit/json.js.map +1 -1
  85. package/dist/emit/metricsJson.d.ts +7 -0
  86. package/dist/emit/metricsJson.js +27 -0
  87. package/dist/emit/metricsJson.js.map +1 -0
  88. package/dist/emit/statusJson.d.ts +1 -1
  89. package/dist/emit/statusJson.js +17 -1
  90. package/dist/emit/statusJson.js.map +1 -1
  91. package/dist/emit/upgradeJson.d.ts +5 -0
  92. package/dist/emit/upgradeJson.js +29 -0
  93. package/dist/emit/upgradeJson.js.map +1 -0
  94. package/dist/emit/validateJson.d.ts +6 -2
  95. package/dist/emit/validateJson.js +12 -5
  96. package/dist/emit/validateJson.js.map +1 -1
  97. package/dist/mcp/server.d.ts +1 -1
  98. package/dist/mcp/server.js +137 -9
  99. package/dist/mcp/server.js.map +1 -1
  100. package/dist/model/rules.d.ts +7 -0
  101. package/dist/model/rules.js +12 -0
  102. package/dist/model/rules.js.map +1 -1
  103. package/dist/model/validate.d.ts +20 -0
  104. package/dist/model/validate.js +94 -45
  105. package/dist/model/validate.js.map +1 -1
  106. package/dist/templates.d.ts +2 -2
  107. package/dist/templates.js +7 -1
  108. package/dist/templates.js.map +1 -1
  109. package/dist/util/semver.d.ts +19 -0
  110. package/dist/util/semver.js +54 -0
  111. package/dist/util/semver.js.map +1 -0
  112. package/package.json +2 -2
@@ -8,7 +8,9 @@ export declare const PHASES: readonly ["discover", "extract", "model", "slice",
8
8
  export type Phase = (typeof PHASES)[number];
9
9
  export declare function isPhase(value: string): value is Phase;
10
10
  /** The state file's mechanical fields, decoded to plain data. `lastConformance`/`lastReview`
11
- * are `null` for the template's `never` marker (never run yet). */
11
+ * are `null` for the template's `never` marker (never run yet). `modelVersion`/`certified`
12
+ * (MIL-218) are `null` for their own `none`/`never` markers, INCLUDING when the bullet is
13
+ * missing entirely from an older state file — see module header. */
12
14
  export interface ParsedState {
13
15
  modelPath: string;
14
16
  phase: string;
@@ -18,7 +20,20 @@ export interface ParsedState {
18
20
  date: string;
19
21
  revision: string;
20
22
  report: string;
23
+ partial: boolean;
21
24
  } | null;
25
+ modelVersion: number | null;
26
+ certified: {
27
+ version: number;
28
+ revision: string;
29
+ date: string;
30
+ } | null;
31
+ /** MIL-219: the `Em version:` bullet's value, or `null` for the `unknown` sentinel (including
32
+ * when the bullet is missing entirely from a state file predating this feature — same
33
+ * migration-tolerant treatment `modelVersion`/`certified` get). Never validated as a real
34
+ * semver here — this module only reads/writes the bullet text; `util/semver.ts` is where a
35
+ * caller that needs to compare it against the installed version goes. */
36
+ emVersion: string | null;
22
37
  lastReview: string | null;
23
38
  }
24
39
  export type ParseStateResult = {
@@ -50,10 +65,13 @@ export type LoadResult = {
50
65
  };
51
66
  /** The one fs read every `em state` subcommand goes through. */
52
67
  export declare function loadStateFile(dirOrFile: string): LoadResult;
53
- /** Parse the six mechanical bullets out of a state file's raw text. `ok: false` when the file
54
- * is missing one of the bullet lines entirely, or when `Last conformance:`/`Last stakeholder
55
- * review:` holds neither `never` nor its documented format — both are the file failing to be
56
- * the thing resume/conform scoping needs, so both are reported the same way. */
68
+ /** Parse the mechanical bullets out of a state file's raw text. `ok: false` when the file is
69
+ * missing one of the six REQUIRED bullet lines entirely, or when `Last conformance:`/`Last
70
+ * stakeholder review:` holds neither `never` nor its documented format — both are the file
71
+ * failing to be the thing resume/conform scoping needs, so both are reported the same way.
72
+ * MIL-218: `Model version:`/`Certified:` are migration-tolerant — see module header — so a
73
+ * missing bullet there is never added to `missing`; it parses as the `none`/`never` default
74
+ * instead, same as if the bullet were present and held that literal value. */
57
75
  export declare function parseState(text: string): ParseStateResult;
58
76
  /** A state file is shared by every `.em` file in its directory (`.event-modeling.md` has no
59
77
  * per-model namespacing), but its `Model file:` bullet names exactly ONE of them — so a
@@ -72,8 +90,46 @@ export declare function setPhase(text: string, phase: Phase, today: string, step
72
90
  /** `em state set-conformance`: rewrite `Last conformance:` in the EXACT format
73
91
  * reference/conform.md's "keep the format exact" instruction specifies — the next conform
74
92
  * run's scoping (reference/conform.md step 1) parses this line back out — plus `Last
75
- * updated:`. */
76
- export declare function setConformance(text: string, revision: string, report: string, today: string): PatchResult;
93
+ * updated:`. `partial` (MIL-214, `--partial`) appends a ` (partial)` suffix — the marker for a
94
+ * conformance sweep whose findings weren't ALL ruled on before the marker was recorded
95
+ * (`em state set-conformance`'s own refusal, cli.ts, is what `--partial` escapes) — parsed back
96
+ * out by `LAST_CONFORMANCE_RE`/`ParsedState.lastConformance.partial` above, and surfaced by
97
+ * every reader of `Last conformance:` (conform-scope.ts, status.ts, freshnessJson.ts). */
98
+ export declare function setConformance(text: string, revision: string, report: string, today: string, partial?: boolean): PatchResult;
99
+ /** MIL-219: rewrite `Em version:` (inserting it right after `Model file:` — the state file's
100
+ * very first bullet, module header — the first time a migrated file is touched) plus `Last
101
+ * updated:`. `version` is trusted to already be the em that's doing the writing — every caller
102
+ * passes its own `PKG_VERSION`/installed version, never a value read back from somewhere else.
103
+ * The one writer every OTHER `em state` mutator's output is piped through (cli.ts's
104
+ * `writeStateUpdate`) — see module header — so this is rarely called directly outside that
105
+ * wrapper and `em upgrade`'s own final commit (src/cli/upgrade.ts). */
106
+ export declare function setEmVersion(text: string, version: string, today: string): PatchResult;
107
+ /** `em model version bump` (MIL-218): rewrite `Model version:` (inserting it right after `Last
108
+ * conformance:` the first time a migrated file is touched — see module header) plus `Last
109
+ * updated:`. `version` is trusted to already be the freshly-bumped design version — the CLI
110
+ * layer computes it via `modelVersion.ts`'s `runModelVersionBump` before calling this. */
111
+ export declare function setModelVersion(text: string, version: number, today: string): PatchResult;
112
+ /** `em state set-conformance` (non-`--partial`, MIL-218 ruling D): rewrite `Certified:` plus
113
+ * `Last updated:`. Inserting it for the first time anchors on `Model version:` when that
114
+ * bullet is already present (the ordinary case — a model version must exist before it can be
115
+ * certified, `runCertifyModelVersion`'s own refusal), so the canonical bullet order (`Last
116
+ * conformance`, `Model version`, `Certified`, `Last stakeholder review`) holds regardless of
117
+ * which of the two migration inserts happens first; falls back to `Last conformance:` only
118
+ * for the edge case of a state file that somehow carries `Certified:` without `Model
119
+ * version:` yet. `version`/`revision`/`date` are trusted to already be the just-recorded
120
+ * certification — the CLI layer computes them via `modelVersion.ts`'s
121
+ * `runCertifyModelVersion` before calling this. */
122
+ export declare function setCertified(text: string, version: number, revision: string, date: string, today: string): PatchResult;
123
+ /** `em upgrade`'s `state-file` step (MIL-219): insert whichever of `Model version:`/`Certified:`
124
+ * are missing from `text` ENTIRELY, each at its own template default (`none`/`never` — same
125
+ * sentinels `parseState` already tolerates when a bullet is absent) — everything else, byte for
126
+ * byte, untouched. Deliberately excludes `Em version:`: that bullet gets its own dedicated
127
+ * final commit from `em upgrade --apply` (src/cli/upgrade.ts), regardless of whether this step
128
+ * ran at all, so folding it in here would double-write it across two commits on a first-ever
129
+ * upgrade. A no-op (both bullets already present) returns `text` unchanged — the caller decides
130
+ * whether "nothing changed" means "nothing to commit," same idempotency contract every other
131
+ * upgrade step holds. */
132
+ export declare function ensureOptionalBullets(text: string, today: string): PatchResult;
77
133
  /** `em state set-review`: rewrite `Last stakeholder review:` (per templates/state.md's format)
78
134
  * plus `Last updated:`. `date` is trusted to already look like `YYYY-MM-DD` — the CLI layer
79
135
  * validates before calling this. */
@@ -1,20 +1,44 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // Reads and writes the MECHANICAL fields of a model's resumable state file
3
3
  // (`.event-modeling.md`, see .claude/skills/event-modeling/templates/state.md): `Model file:`,
4
- // `Current phase:`, `Current step:`, `Last updated:`, `Last conformance:`, `Last stakeholder
5
- // review:`. This is the ONE parser for those bullets — `em changelog` (src/emit/changelog.ts,
6
- // parseDecisionsLog) parses a disjoint section of the same file (the `## Decisions log`) and
7
- // stays a separate function for that reason, but shares STATE_FILE_NAME with this module rather
8
- // than hard-coding the filename a second time.
4
+ // `Current phase:`, `Current step:`, `Last updated:`, `Last conformance:`, `Model version:`,
5
+ // `Certified:`, `Last stakeholder review:`. This is the ONE parser for those bullets — `em
6
+ // changelog` (src/emit/changelog.ts, parseDecisionsLog) parses a disjoint section of the same
7
+ // file (the `## Decisions log`) and stays a separate function for that reason, but shares
8
+ // STATE_FILE_NAME with this module rather than hard-coding the filename a second time.
9
9
  //
10
10
  // Deliberately narrow: judgment content (Session inputs, Participants, Decisions log, Usage
11
11
  // log, Open questions, Slice inventory) is agent-authored prose and out of scope here — this
12
- // module only ever touches the six mechanical bullets above, byte-for-byte leaving every other
12
+ // module only ever touches the mechanical bullets above, byte-for-byte leaving every other
13
13
  // line alone.
14
14
  //
15
- // Pure text in, text/data out (parseState, setPhase, setConformance, setReview); `loadStateFile`
16
- // is the one bit of fs I/O, kept here so both `em state` (src/cli.ts) and any future caller
17
- // share the same file-location convention instead of re-deriving it.
15
+ // MIL-218: `Model version:`/`Certified:` are a POINTER into the `model-versions/*.json`
16
+ // manifests (modelVersion.ts) — history lives there, not here. Both are MIGRATION-TOLERANT,
17
+ // unlike the other six bullets: a state file predating this feature parses as `modelVersion:
18
+ // null`/`certified: null` (the `none`/`never` markers) rather than failing outright — the
19
+ // existing "missing bullet is an error" behavior stays exactly as strict as before for every
20
+ // OTHER bullet. `setModelVersion`/`setCertified` insert the bullet (right after `Last
21
+ // conformance:`, the ruling's own placement) the first time a migrated file is touched, and
22
+ // update it in place afterward — the only two writers in this module that ever ADD a line
23
+ // rather than only ever replacing one that's already there.
24
+ //
25
+ // MIL-219: `Em version:` — which `em` last wrote this file — is a THIRD migration-tolerant
26
+ // bullet, same "absent parses as the sentinel, never an error" treatment (its sentinel is the
27
+ // literal `unknown`, not `none`/`never` — there's no meaningful zero value for "which em," just
28
+ // "we don't know"). Anchored right after `Model file:` (the state file's very first bullet)
29
+ // rather than beside the other two MIL-218 bullets — it's provenance about the TOOL, not about
30
+ // the model's own version history, so it reads first. Written by `em scaffold` (the installed
31
+ // em at scaffold time) and, per the MIL-219 ruling, by EVERY `em state` writer: cli.ts's shared
32
+ // `writeStateUpdate` helper stamps it on every successful write, since each of those write paths
33
+ // is already rewriting the file — see that function, not this module, for the actual stamping
34
+ // (this module only exposes the pure `setEmVersion` patch, same split every other bullet here
35
+ // holds). `em upgrade --apply` additionally writes it as its own dedicated final commit,
36
+ // regardless of whether any of its five mechanical steps applied — see src/cli/upgrade.ts.
37
+ //
38
+ // Pure text in, text/data out (parseState, setPhase, setConformance, setModelVersion,
39
+ // setCertified, setReview); `loadStateFile` is the one bit of fs I/O, kept here so both `em
40
+ // state` (src/cli.ts) and any future caller share the same file-location convention instead of
41
+ // re-deriving it.
18
42
  import { existsSync, readFileSync } from "node:fs";
19
43
  import { basename, join } from "node:path";
20
44
  /** Filename the skill scaffolds/reads at `<model-dir>/.event-modeling.md`. */
@@ -35,6 +59,14 @@ const LABELS = {
35
59
  lastConformance: "Last conformance",
36
60
  lastStakeholderReview: "Last stakeholder review",
37
61
  };
62
+ /** MIL-218/MIL-219: the three migration-tolerant bullets — see module header. Kept in a separate
63
+ * map from `LABELS` (rather than folded in) so `parseState`'s missing-bullet loop can treat them
64
+ * differently: absent is `none`/`never`/`unknown`, never a parse error. */
65
+ const OPTIONAL_LABELS = {
66
+ modelVersion: "Model version",
67
+ certified: "Certified",
68
+ emVersion: "Em version",
69
+ };
38
70
  function escapeForRegex(s) {
39
71
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
40
72
  }
@@ -63,12 +95,23 @@ export function loadStateFile(dirOrFile) {
63
95
  }
64
96
  return { ok: true, path, text: readFileSync(path, "utf8") };
65
97
  }
66
- const LAST_CONFORMANCE_RE = /^(\d{4}-\d{2}-\d{2}) @ (.+?) — report: (.+)$/;
98
+ // MIL-214: the `( (partial)`)?` tail is `--partial`'s marker — see `setConformance` below. The
99
+ // report capture stays non-greedy (`.+?`) so the optional suffix, not the report path, absorbs
100
+ // a trailing "(partial)" when present.
101
+ const LAST_CONFORMANCE_RE = /^(\d{4}-\d{2}-\d{2}) @ (.+?) — report: (.+?)( \(partial\))?$/;
67
102
  const LEADING_DATE_RE = /^(\d{4}-\d{2}-\d{2})\b/;
68
- /** Parse the six mechanical bullets out of a state file's raw text. `ok: false` when the file
69
- * is missing one of the bullet lines entirely, or when `Last conformance:`/`Last stakeholder
70
- * review:` holds neither `never` nor its documented format — both are the file failing to be
71
- * the thing resume/conform scoping needs, so both are reported the same way. */
103
+ // MIL-218: `Model version:` holds a bare positive integer or the literal `none`.
104
+ const MODEL_VERSION_RE = /^(\d+)$/;
105
+ // MIL-218: `Certified:` holds `v<N> @ <revision> (YYYY-MM-DD)` or the literal `never` — same
106
+ // `v<N>` prefix convention lineage refs use elsewhere in em (docs/dsl.md).
107
+ const CERTIFIED_RE = /^v(\d+) @ (.+) \((\d{4}-\d{2}-\d{2})\)$/;
108
+ /** Parse the mechanical bullets out of a state file's raw text. `ok: false` when the file is
109
+ * missing one of the six REQUIRED bullet lines entirely, or when `Last conformance:`/`Last
110
+ * stakeholder review:` holds neither `never` nor its documented format — both are the file
111
+ * failing to be the thing resume/conform scoping needs, so both are reported the same way.
112
+ * MIL-218: `Model version:`/`Certified:` are migration-tolerant — see module header — so a
113
+ * missing bullet there is never added to `missing`; it parses as the `none`/`never` default
114
+ * instead, same as if the bullet were present and held that literal value. */
72
115
  export function parseState(text) {
73
116
  const missing = [];
74
117
  const raw = {};
@@ -85,6 +128,11 @@ export function parseState(text) {
85
128
  message: `missing bullet line(s): ${missing.map((l) => `"- **${l}:**"`).join(", ")}`,
86
129
  };
87
130
  }
131
+ const optionalRaw = {};
132
+ for (const label of Object.values(OPTIONAL_LABELS)) {
133
+ const sentinel = label === OPTIONAL_LABELS.modelVersion ? "none" : label === OPTIONAL_LABELS.emVersion ? "unknown" : "never";
134
+ optionalRaw[label] = bulletValue(text, label) ?? sentinel;
135
+ }
88
136
  const modelPath = raw[LABELS.modelFile].replace(/^`|`$/g, "");
89
137
  const lastConformanceRaw = raw[LABELS.lastConformance];
90
138
  let lastConformance = null;
@@ -96,7 +144,7 @@ export function parseState(text) {
96
144
  message: `"- **Last conformance:**" doesn't match "YYYY-MM-DD @ <revision> — report: <path>" or "never": ${lastConformanceRaw}`,
97
145
  };
98
146
  }
99
- lastConformance = { date: m[1], revision: m[2], report: m[3] };
147
+ lastConformance = { date: m[1], revision: m[2], report: m[3], partial: m[4] !== undefined };
100
148
  }
101
149
  const lastReviewRaw = raw[LABELS.lastStakeholderReview];
102
150
  let lastReview = null;
@@ -110,6 +158,32 @@ export function parseState(text) {
110
158
  }
111
159
  lastReview = m[1];
112
160
  }
161
+ const modelVersionRaw = optionalRaw[OPTIONAL_LABELS.modelVersion];
162
+ let modelVersion = null;
163
+ if (modelVersionRaw !== "none") {
164
+ const m = MODEL_VERSION_RE.exec(modelVersionRaw);
165
+ if (!m) {
166
+ return {
167
+ ok: false,
168
+ message: `"- **Model version:**" doesn't match a bare integer or "none": ${modelVersionRaw}`,
169
+ };
170
+ }
171
+ modelVersion = Number(m[1]);
172
+ }
173
+ const certifiedRaw = optionalRaw[OPTIONAL_LABELS.certified];
174
+ let certified = null;
175
+ if (certifiedRaw !== "never") {
176
+ const m = CERTIFIED_RE.exec(certifiedRaw);
177
+ if (!m) {
178
+ return {
179
+ ok: false,
180
+ message: `"- **Certified:**" doesn't match "v<N> @ <revision> (YYYY-MM-DD)" or "never": ${certifiedRaw}`,
181
+ };
182
+ }
183
+ certified = { version: Number(m[1]), revision: m[2], date: m[3] };
184
+ }
185
+ const emVersionRaw = optionalRaw[OPTIONAL_LABELS.emVersion];
186
+ const emVersion = emVersionRaw === "unknown" ? null : emVersionRaw;
113
187
  return {
114
188
  ok: true,
115
189
  state: {
@@ -118,6 +192,9 @@ export function parseState(text) {
118
192
  step: raw[LABELS.currentStep],
119
193
  lastUpdated: raw[LABELS.lastUpdated],
120
194
  lastConformance,
195
+ modelVersion,
196
+ certified,
197
+ emVersion,
121
198
  lastReview,
122
199
  },
123
200
  };
@@ -159,6 +236,26 @@ function applyBulletUpdates(text, updates) {
159
236
  }
160
237
  return { ok: true, text: result };
161
238
  }
239
+ /** MIL-218: update `label`'s bullet if present, else INSERT it right after `afterLabel`'s own
240
+ * bullet line — the one-time migration act for a state file predating `Model version:`/
241
+ * `Certified:` (module header). Matches the line-ending style already in use right after
242
+ * `afterLabel`'s line (CRLF if that's what follows, else LF) so a migrated file doesn't end up
243
+ * with mixed endings. `afterLabel` is trusted to already exist (`setModelVersion`/
244
+ * `setCertified` only ever anchor on `Last conformance:`, one of the six REQUIRED bullets
245
+ * `loadStateFile`'s caller has already confirmed is present via a successful `parseState`). */
246
+ function insertOrUpdateBullet(text, label, value, afterLabel) {
247
+ const re = bulletLineRegex(label);
248
+ if (re.test(text)) {
249
+ return text.replace(re, () => `- **${label}:** ${value}`);
250
+ }
251
+ const afterRe = bulletLineRegex(afterLabel);
252
+ const m = afterRe.exec(text);
253
+ if (!m)
254
+ return text; // afterLabel missing — shouldn't happen on a real caller's already-parsed text
255
+ const insertPos = m.index + m[0].length;
256
+ const eol = text.slice(insertPos, insertPos + 2) === "\r\n" ? "\r\n" : "\n";
257
+ return `${text.slice(0, insertPos)}${eol}- **${label}:** ${value}${text.slice(insertPos)}`;
258
+ }
162
259
  /** `em state set-phase`: rewrite `Current phase:` (and `Current step:` when `step` is given)
163
260
  * plus `Last updated:`. `phase` is trusted to already be a validated `Phase` — the CLI layer
164
261
  * checks against `PHASES` before calling this so the enum has exactly one home. */
@@ -172,14 +269,78 @@ export function setPhase(text, phase, today, step) {
172
269
  /** `em state set-conformance`: rewrite `Last conformance:` in the EXACT format
173
270
  * reference/conform.md's "keep the format exact" instruction specifies — the next conform
174
271
  * run's scoping (reference/conform.md step 1) parses this line back out — plus `Last
175
- * updated:`. */
176
- export function setConformance(text, revision, report, today) {
177
- const value = `${today} @ ${revision} — report: ${report}`;
272
+ * updated:`. `partial` (MIL-214, `--partial`) appends a ` (partial)` suffix — the marker for a
273
+ * conformance sweep whose findings weren't ALL ruled on before the marker was recorded
274
+ * (`em state set-conformance`'s own refusal, cli.ts, is what `--partial` escapes) — parsed back
275
+ * out by `LAST_CONFORMANCE_RE`/`ParsedState.lastConformance.partial` above, and surfaced by
276
+ * every reader of `Last conformance:` (conform-scope.ts, status.ts, freshnessJson.ts). */
277
+ export function setConformance(text, revision, report, today, partial = false) {
278
+ const value = `${today} @ ${revision} — report: ${report}${partial ? " (partial)" : ""}`;
178
279
  return applyBulletUpdates(text, [
179
280
  { label: LABELS.lastConformance, value },
180
281
  { label: LABELS.lastUpdated, value: today },
181
282
  ]);
182
283
  }
284
+ /** MIL-219: rewrite `Em version:` (inserting it right after `Model file:` — the state file's
285
+ * very first bullet, module header — the first time a migrated file is touched) plus `Last
286
+ * updated:`. `version` is trusted to already be the em that's doing the writing — every caller
287
+ * passes its own `PKG_VERSION`/installed version, never a value read back from somewhere else.
288
+ * The one writer every OTHER `em state` mutator's output is piped through (cli.ts's
289
+ * `writeStateUpdate`) — see module header — so this is rarely called directly outside that
290
+ * wrapper and `em upgrade`'s own final commit (src/cli/upgrade.ts). */
291
+ export function setEmVersion(text, version, today) {
292
+ const withVersion = insertOrUpdateBullet(text, OPTIONAL_LABELS.emVersion, version, LABELS.modelFile);
293
+ return applyBulletUpdates(withVersion, [{ label: LABELS.lastUpdated, value: today }]);
294
+ }
295
+ /** `em model version bump` (MIL-218): rewrite `Model version:` (inserting it right after `Last
296
+ * conformance:` the first time a migrated file is touched — see module header) plus `Last
297
+ * updated:`. `version` is trusted to already be the freshly-bumped design version — the CLI
298
+ * layer computes it via `modelVersion.ts`'s `runModelVersionBump` before calling this. */
299
+ export function setModelVersion(text, version, today) {
300
+ const withVersion = insertOrUpdateBullet(text, OPTIONAL_LABELS.modelVersion, String(version), LABELS.lastConformance);
301
+ return applyBulletUpdates(withVersion, [{ label: LABELS.lastUpdated, value: today }]);
302
+ }
303
+ /** `em state set-conformance` (non-`--partial`, MIL-218 ruling D): rewrite `Certified:` plus
304
+ * `Last updated:`. Inserting it for the first time anchors on `Model version:` when that
305
+ * bullet is already present (the ordinary case — a model version must exist before it can be
306
+ * certified, `runCertifyModelVersion`'s own refusal), so the canonical bullet order (`Last
307
+ * conformance`, `Model version`, `Certified`, `Last stakeholder review`) holds regardless of
308
+ * which of the two migration inserts happens first; falls back to `Last conformance:` only
309
+ * for the edge case of a state file that somehow carries `Certified:` without `Model
310
+ * version:` yet. `version`/`revision`/`date` are trusted to already be the just-recorded
311
+ * certification — the CLI layer computes them via `modelVersion.ts`'s
312
+ * `runCertifyModelVersion` before calling this. */
313
+ export function setCertified(text, version, revision, date, today) {
314
+ const value = `v${version} @ ${revision} (${date})`;
315
+ const anchor = bulletLineRegex(OPTIONAL_LABELS.modelVersion).test(text) ? OPTIONAL_LABELS.modelVersion : LABELS.lastConformance;
316
+ const withCertified = insertOrUpdateBullet(text, OPTIONAL_LABELS.certified, value, anchor);
317
+ return applyBulletUpdates(withCertified, [{ label: LABELS.lastUpdated, value: today }]);
318
+ }
319
+ /** `em upgrade`'s `state-file` step (MIL-219): insert whichever of `Model version:`/`Certified:`
320
+ * are missing from `text` ENTIRELY, each at its own template default (`none`/`never` — same
321
+ * sentinels `parseState` already tolerates when a bullet is absent) — everything else, byte for
322
+ * byte, untouched. Deliberately excludes `Em version:`: that bullet gets its own dedicated
323
+ * final commit from `em upgrade --apply` (src/cli/upgrade.ts), regardless of whether this step
324
+ * ran at all, so folding it in here would double-write it across two commits on a first-ever
325
+ * upgrade. A no-op (both bullets already present) returns `text` unchanged — the caller decides
326
+ * whether "nothing changed" means "nothing to commit," same idempotency contract every other
327
+ * upgrade step holds. */
328
+ export function ensureOptionalBullets(text, today) {
329
+ let result = text;
330
+ let changed = false;
331
+ if (!bulletLineRegex(OPTIONAL_LABELS.modelVersion).test(result)) {
332
+ result = insertOrUpdateBullet(result, OPTIONAL_LABELS.modelVersion, "none", LABELS.lastConformance);
333
+ changed = true;
334
+ }
335
+ if (!bulletLineRegex(OPTIONAL_LABELS.certified).test(result)) {
336
+ const anchor = bulletLineRegex(OPTIONAL_LABELS.modelVersion).test(result) ? OPTIONAL_LABELS.modelVersion : LABELS.lastConformance;
337
+ result = insertOrUpdateBullet(result, OPTIONAL_LABELS.certified, "never", anchor);
338
+ changed = true;
339
+ }
340
+ if (!changed)
341
+ return { ok: true, text };
342
+ return applyBulletUpdates(result, [{ label: LABELS.lastUpdated, value: today }]);
343
+ }
183
344
  /** `em state set-review`: rewrite `Last stakeholder review:` (per templates/state.md's format)
184
345
  * plus `Last updated:`. `date` is trusted to already look like `YYYY-MM-DD` — the CLI layer
185
346
  * validates before calling this. */
@@ -1 +1 @@
1
- {"version":3,"file":"stateFile.js","sourceRoot":"","sources":["../../src/cli/stateFile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stateFile.js","sourceRoot":"","sources":["../../src/cli/stateFile.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ import { Diagnostic } from "../model/validate.js";
6
6
  import { CoverageReport } from "./coverage.js";
7
7
  import { GitRunner } from "./diff-inputs.js";
8
8
  import { SliceDocFacts } from "./conformScope.js";
9
+ import { ModelVersionSliceChange } from "./modelVersion.js";
9
10
  /** The 4 canonical slice-doc lifecycle statuses (docs/slice-doc-schema.md) — the same enum
10
11
  * `em catalog`'s header coloring and `em render`'s status legend already recognize. */
11
12
  export declare const CANONICAL_STATUSES: readonly ["draft", "reviewed", "ready-to-implement", "implemented"];
@@ -81,7 +82,16 @@ export interface ConformanceEntry {
81
82
  lastConformance: {
82
83
  date: string;
83
84
  revision: string;
85
+ partial: boolean;
84
86
  } | null;
87
+ /** MIL-214: unruled (`locus: null`) conformance findings in scope (every `implemented` slice;
88
+ * a `slice: null` finding counts as in scope for all of them) from the findings JSON beside
89
+ * `lastConformance`'s report — the same file `em state set-conformance`'s refusal/`--partial`
90
+ * gate reads (cli/findings.ts's `unruledFindingsInScope`). Null when there's no
91
+ * `lastConformance` to look beside, or no findings JSON exists there (a report written before
92
+ * MIL-214 — the documented migration path, same non-fatal "nothing to report" `null` every
93
+ * other opt-in count in this document uses). */
94
+ unruledFindings: number | null;
85
95
  /** The repo `commitsBehindHead` was computed in — `--repo` when given, else the model's own
86
96
  * directory (works out of the box for a single-repo project; conform-scope's `--repo`
87
97
  * convention still applies for a model whose implementation lives in a different repo). */
@@ -190,6 +200,50 @@ export declare function resolveSlicePRsBehindHead(repo: string, revision: string
190
200
  * rather than silently misattributed.
191
201
  */
192
202
  export declare function resolveConformanceEntry(file: string, repoOverride: string | undefined, sliceDocFacts: SliceDocFacts[], runGit?: GitRunner): ConformanceEntry;
203
+ /** One model's design/certified version facts (`em model version bump`/`em state
204
+ * set-conformance`'s certify step, modelVersion.ts) — the state-of-the-system rollup's own
205
+ * window onto the same `model-versions/*.json` manifests `em model version show` reads
206
+ * directly. `certified` names the most recently CERTIFIED design version, which need not be
207
+ * `design` itself (a later bump can outrun certification — `findCertifiedVersion`'s own
208
+ * "newest certified wins, not necessarily newest bumped" contract). `drifted`/`changes` are
209
+ * `modelVersionDrift`'s own predicate, verbatim — the same one `em validate`'s
210
+ * `model-version-stale` warning and the `em slice ratify`/`reratify` advisory read, never
211
+ * re-derived a third way. */
212
+ export interface ModelVersionStatusEntry {
213
+ file: string;
214
+ design: number | null;
215
+ certified: {
216
+ version: number;
217
+ at: string;
218
+ on: string;
219
+ } | null;
220
+ drifted: boolean;
221
+ changes: {
222
+ hashChanged: boolean;
223
+ slices: ModelVersionSliceChange[];
224
+ };
225
+ }
226
+ /** Resolve one input model's `ModelVersionStatusEntry`. `source` is that model's own `.em` text
227
+ * (for the modelHash comparison inside `modelVersionDrift`) — the caller's `compileFile(file)`
228
+ * result already carries it, never re-read here. */
229
+ export declare function resolveModelVersionStatusEntry(file: string, model: NormalizedModel, refs: RefsResult, source: string): ModelVersionStatusEntry;
230
+ /** One model directory's recorded-vs-installed `em` fact — the state file's `Em version:`
231
+ * bullet against the em actually running `em status`. `recorded: null` covers both "no state
232
+ * file bullet yet" (a repo predating MIL-219) and the file's own `unknown` sentinel — same
233
+ * "null means no evidence" reading `stateFile.ts`'s `ParsedState.emVersion` already holds.
234
+ * `behind` is `util/semver.ts`'s `isOlder` verbatim — `false` (never a crash) when `recorded`
235
+ * is null or unparseable, since "can't prove it's behind" reads the same as "not behind" for a
236
+ * warn-only advisory (`em upgrade` is the actual authority on whether a repo needs work). */
237
+ export interface EmVersionStatusEntry {
238
+ file: string;
239
+ recorded: string | null;
240
+ installed: string;
241
+ behind: boolean;
242
+ }
243
+ /** Resolve one input model's `EmVersionStatusEntry` — `null` when its state file is missing or
244
+ * fails to parse at all (same non-fatal "nothing to report" treatment `resolveConformanceEntry`
245
+ * gives a missing state file, rather than surfacing a second copy of that error here). */
246
+ export declare function resolveEmVersionStatusEntry(file: string, installedVersion: string): EmVersionStatusEntry | null;
193
247
  export interface StatusSliceCounts {
194
248
  total: number;
195
249
  byStatus: {
@@ -211,6 +265,11 @@ export interface StatusDriftCounts {
211
265
  neverImplemented: number;
212
266
  unpropagatedDelta: number;
213
267
  implementedWithoutLink: number;
268
+ /** MIL-214: status: implemented, implementedIn set, but `conformedVersion` is absent or
269
+ * doesn't match the current `version` — nobody has certified THIS version yet. Expected
270
+ * post-ship default (`em validate` never warns on it), same treatment `unpropagatedDelta`
271
+ * gets — see catalog/driftSignal.ts's `uncertified`. */
272
+ uncertified: number;
214
273
  /** Slices with no doc bound at all (or a binding naming a missing file) — driftSignal is null
215
274
  * because there's nothing to classify. Distinct from `frontmatterInvalid` below: THIS bucket
216
275
  * is `resolveSliceDocJoin`'s `found: false`, in either dimension. */
@@ -266,6 +325,15 @@ export interface StatusReport {
266
325
  invariants: StatusInvariantTotals | null;
267
326
  issues: StatusIssueTotals;
268
327
  conformance: ConformanceEntry[];
328
+ /** MIL-218: one entry per input file — design/certified version, and whether the vector has
329
+ * drifted since the design version was bumped. Named `modelVersion` (singular), valued as an
330
+ * array — same per-file breakdown shape `conformance`/`owners` already hold. */
331
+ modelVersion: ModelVersionStatusEntry[];
332
+ /** MIL-219: one entry per input file whose state file resolved — recorded `Em version:` vs.
333
+ * the em actually running, and whether it's behind. Same per-file array shape `modelVersion`
334
+ * holds (not a single flat object) — a repo's several models can share directories with
335
+ * DIFFERENT state files, so "one recorded fact" isn't well-defined at the report level. */
336
+ emVersion: EmVersionStatusEntry[];
269
337
  /** Doc-join diagnostics (`binding-missing-file`/`frontmatter-invalid` warnings) collected
270
338
  * while resolving every slice's doc, across every input file — carried here rather than
271
339
  * discarded, so a state-of-the-system report doesn't hide a broken doc reference just
@@ -278,7 +346,7 @@ export interface StatusReport {
278
346
  /** Aggregate everything `em status` reports into one `StatusReport` — pure, no I/O. Callers
279
347
  * (the CLI action, the MCP tool) resolve every input first (compile each model, join every
280
348
  * slice's doc, scan the test tree once, resolve conformance) and hand the results here. */
281
- export declare function buildStatusReport(files: string[], sliceFacts: SliceStatusFact[], openIssuesCount: number, invariants: StatusInvariantTotals | null, conformance: ConformanceEntry[], diagnostics: StatusDiagnostic[]): StatusReport;
349
+ export declare function buildStatusReport(files: string[], sliceFacts: SliceStatusFact[], openIssuesCount: number, invariants: StatusInvariantTotals | null, conformance: ConformanceEntry[], diagnostics: StatusDiagnostic[], modelVersion?: ModelVersionStatusEntry[], emVersion?: EmVersionStatusEntry[]): StatusReport;
282
350
  /** Sum per-model `CoverageReport`s (see `./coverage.ts`) into one `StatusInvariantTotals` —
283
351
  * `em status` doesn't need the per-slice/per-ID detail `em coverage --json` carries, just the
284
352
  * totals, across however many models `--tests <dir>` was scanned against. */
@@ -290,6 +358,16 @@ export declare function formatConformancePart(entry: ConformanceEntry): string;
290
358
  * the path the entry already resolved (relative to that model's own directory). Shared by the
291
359
  * text and markdown reports so the two can't drift. Existence only; never a content judgment. */
292
360
  export declare function formatConstitutionPart(entry: ConformanceEntry): string;
361
+ /** MIL-218: the per-model model-version clause — design version, most recently certified
362
+ * version (if any), and whether the vector has drifted since the design version was bumped.
363
+ * `"never bumped"` when `entry.design` is `null` — the routine state for a model that hasn't
364
+ * opted into `em model version bump` yet. */
365
+ export declare function formatModelVersionPart(entry: ModelVersionStatusEntry): string;
366
+ /** MIL-219: `"recorded 1.10.0, installed 1.13.0 — behind, run \`em upgrade\`"`, or `"recorded
367
+ * unknown, installed 1.13.0"` when the state file predates the `Em version:` bullet — never
368
+ * claims "behind" without a recorded value to compare (same conservative reading
369
+ * `resolveEmVersionStatusEntry`'s own `isOlder` call holds). */
370
+ export declare function formatEmVersionPart(entry: EmVersionStatusEntry): string;
293
371
  /** The one-line rollup: `"8/8 implemented · 20/20 invariants covered · 0 open issues · last
294
372
  * conformed <rev>, N commits behind HEAD"` (MIL-163's acceptance line). For multiple input
295
373
  * models, the conformance clause reports the FIRST file's entry — a single-file invocation is