@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
@@ -0,0 +1,256 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // `em model version` (MIL-218, from the MIL-214 discussion): the model-level counterpart to
3
+ // `em slice conform`'s per-slice certification. Slices carry their own `version:` and drift
4
+ // apart over time; nothing before this named "the model" as a whole. Two facts, kept separate:
5
+ //
6
+ // - **Design version** — an explicit, human-bumped integer (`em model version bump --by <name>
7
+ // [--on <date>]`), same identity discipline as `em slice ratify`. Bumps when structure
8
+ // changes (slice added/removed, seam change) or a batch of slice deltas is ratified
9
+ // together.
10
+ // - **Certified version** — "design version N was certified at revision R on date D", written
11
+ // by a full (non-`--partial`) `em state set-conformance` (MIL-214) into the CURRENT design
12
+ // version's manifest. A partial marker never certifies.
13
+ //
14
+ // Sidecar manifest, not the state file: `model-versions/v<N>.json`, sibling of `slices/` and
15
+ // `conformance/` — history, not progress, which is why it's not in `.event-modeling.md` (that
16
+ // file only ever carries a POINTER: the `Model version:`/`Certified:` bullets, stateFile.ts).
17
+ // Deterministic serialization through ONE writer (`serializeModelVersionDoc`), same discipline
18
+ // `serializeFindingsDoc` (findings.ts) holds — keys in a fixed order, 2-space, trailing newline,
19
+ // never a bare `JSON.stringify`.
20
+ //
21
+ // `modelHash` is the sha256 of the `.em` file's own bytes, after normalizing line endings to
22
+ // `\n` first — so a checkout with different line-ending settings (CRLF vs LF) never reads as a
23
+ // content change on its own; only real edits move the hash.
24
+ //
25
+ // `slices` covers every non-continuation slice (MIL-208's "an `again` view instance is a
26
+ // continuation of its originating slice, never a slice with its own doc/version to vector") —
27
+ // export key -> that slice's doc `version:` (or `null` when the slice has no usable doc yet).
28
+ //
29
+ // `modelVersionDrift` is the one shared predicate every warn-only surface (`em status`, `em
30
+ // validate`'s `model-version-stale`, `em slice ratify`/`reratify`'s advisory) reads — never
31
+ // re-derived three different ways. It never refuses anything itself; every caller decides how
32
+ // (or whether) to surface what it found.
33
+ import { createHash } from "node:crypto";
34
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
35
+ import { join } from "node:path";
36
+ import { resolveSliceDocJoin } from "../catalog/docJoin.js";
37
+ export const MODEL_VERSION_SCHEMA_VERSION = "1.0";
38
+ /** sha256 of `source`'s bytes, after normalizing every line ending to `\n` first — so a
39
+ * CRLF-vs-LF checkout difference never reads as a content change on its own. */
40
+ export function computeModelHash(source) {
41
+ const normalized = source.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
42
+ return createHash("sha256").update(normalized, "utf8").digest("hex");
43
+ }
44
+ /** Serialize a `ModelVersionManifest` deterministically — see module header. The ONE write path
45
+ * every producer of this file's bytes must go through, same discipline
46
+ * `findings.ts`'s `serializeFindingsDoc` holds. */
47
+ export function serializeModelVersionDoc(doc) {
48
+ const sortedSlices = {};
49
+ for (const key of Object.keys(doc.slices).sort())
50
+ sortedSlices[key] = doc.slices[key];
51
+ const canonical = {
52
+ bumpedBy: doc.bumpedBy,
53
+ bumpedOn: doc.bumpedOn,
54
+ certified: doc.certified
55
+ ? { at: doc.certified.at, findings: doc.certified.findings, on: doc.certified.on, report: doc.certified.report }
56
+ : null,
57
+ emVersion: doc.emVersion,
58
+ model: doc.model,
59
+ modelHash: doc.modelHash,
60
+ modelVersionSchemaVersion: doc.modelVersionSchemaVersion,
61
+ slices: sortedSlices,
62
+ version: doc.version,
63
+ };
64
+ return `${JSON.stringify(canonical, null, 2)}\n`;
65
+ }
66
+ /** `<baseDir>/model-versions` — sibling of `slices/`/`conformance/`. `baseDir` is the `.em`
67
+ * file's directory, same convention every doc/note/manifest path in `em` uses. */
68
+ export function modelVersionsDir(baseDir) {
69
+ return join(baseDir, "model-versions");
70
+ }
71
+ export function modelVersionManifestPath(baseDir, version) {
72
+ return join(modelVersionsDir(baseDir), `v${version}.json`);
73
+ }
74
+ const MANIFEST_NAME_RE = /^v(\d+)\.json$/;
75
+ /** Every design version this model directory has ever bumped to, ascending. `[]` when
76
+ * `model-versions/` doesn't exist at all — the routine state for a model that has never
77
+ * bumped. Malformed/non-matching filenames in the directory are silently ignored (this is a
78
+ * discovery scan, not a validator). */
79
+ export function listModelVersionNumbers(baseDir) {
80
+ let entries;
81
+ try {
82
+ entries = readdirSync(modelVersionsDir(baseDir));
83
+ }
84
+ catch {
85
+ return [];
86
+ }
87
+ const nums = new Set();
88
+ for (const name of entries) {
89
+ const m = MANIFEST_NAME_RE.exec(name);
90
+ if (m)
91
+ nums.add(Number(m[1]));
92
+ }
93
+ return [...nums].sort((a, b) => a - b);
94
+ }
95
+ /** The highest bumped design version, or `null` when this model directory has never bumped. */
96
+ export function latestModelVersionNumber(baseDir) {
97
+ const nums = listModelVersionNumbers(baseDir);
98
+ return nums.length > 0 ? nums[nums.length - 1] : null;
99
+ }
100
+ /** Read+parse one design version's manifest. `null` when it doesn't exist at all (not an
101
+ * error — the routine "never bumped to this version" state); `{ ok: false }` when the file
102
+ * exists but isn't readable/valid JSON (a genuine problem, reported rather than silently
103
+ * swallowed). No shape validation beyond "is it JSON" — this file is written by exactly one
104
+ * writer (`serializeModelVersionDoc`) in this codebase. */
105
+ export function readModelVersionManifest(baseDir, version) {
106
+ const path = modelVersionManifestPath(baseDir, version);
107
+ if (!existsSync(path))
108
+ return null;
109
+ let raw;
110
+ try {
111
+ raw = readFileSync(path, "utf8");
112
+ }
113
+ catch (e) {
114
+ return { ok: false, message: `could not read ${path}: ${e.message}` };
115
+ }
116
+ try {
117
+ return { ok: true, manifest: JSON.parse(raw) };
118
+ }
119
+ catch {
120
+ return { ok: false, message: `${path} is not valid JSON` };
121
+ }
122
+ }
123
+ /** The current slices vector: every non-continuation slice's export key -> its doc's `version:`
124
+ * (or `null` when the slice has no usable doc yet). MIL-208: a continuation slice (an
125
+ * `again`-view-only slice with no legacy doc of its own) is excluded — its originating slice's
126
+ * own entry already covers it, same exclusion `conformScope.ts`'s `resolveSliceDocFacts` makes.
127
+ * `baseDir` is the `.em` file's directory, same doc-resolution convention every other doc-aware
128
+ * command uses. */
129
+ export function computeSlicesVector(model, refs, baseDir) {
130
+ const vector = {};
131
+ model.slices.forEach((slice, i) => {
132
+ const key = refs.sliceKeys[i];
133
+ const { doc, continuationOf: continuationOfKey } = resolveSliceDocJoin(model, refs, slice, key, baseDir, (id) => refs.refById.get(id));
134
+ if (continuationOfKey !== null)
135
+ return;
136
+ vector[key] = doc.version;
137
+ });
138
+ return vector;
139
+ }
140
+ /**
141
+ * `em model version bump`: write `model-versions/v<N+1>.json` (N+1 = highest existing + 1, or
142
+ * 1 for the first-ever bump). Refuses when `by` is empty, and when nothing has changed since
143
+ * the latest existing manifest (same `modelHash` AND same slices vector) unless `force` — a
144
+ * no-op bump is the one case `--force` is right for (the caller wants a new version stamped
145
+ * even though nothing moved). Pure computation + one fs write; the caller is responsible for
146
+ * the state-file-missing precondition (a model-version bump without a resumable state file to
147
+ * point the `Model version:` bullet at makes no sense — `em model version bump`'s CLI action
148
+ * checks that first, before this function is ever called) and for rewriting the state file's
149
+ * own `Model version:` bullet afterward (`stateFile.ts`'s `setModelVersion`).
150
+ */
151
+ export function runModelVersionBump(baseDir, modelFileName, model, refs, source, by, on, emVersion, force) {
152
+ const trimmedBy = by.trim();
153
+ if (!trimmedBy)
154
+ return { ok: false, message: "a bumper name is required (--by)" };
155
+ const modelHash = computeModelHash(source);
156
+ const slices = computeSlicesVector(model, refs, baseDir);
157
+ const current = latestModelVersionNumber(baseDir);
158
+ if (current !== null && !force) {
159
+ const read = readModelVersionManifest(baseDir, current);
160
+ if (read && read.ok) {
161
+ const sameHash = read.manifest.modelHash === modelHash;
162
+ const sameSlices = JSON.stringify(Object.keys(read.manifest.slices).sort()) === JSON.stringify(Object.keys(slices).sort()) &&
163
+ Object.keys(slices).every((k) => (read.manifest.slices[k] ?? null) === (slices[k] ?? null));
164
+ if (sameHash && sameSlices) {
165
+ return {
166
+ ok: false,
167
+ message: `nothing has changed since v${current} (same model content and slice versions) — pass --force to bump anyway`,
168
+ };
169
+ }
170
+ }
171
+ }
172
+ const newVersion = (current ?? 0) + 1;
173
+ const manifest = {
174
+ modelVersionSchemaVersion: MODEL_VERSION_SCHEMA_VERSION,
175
+ model: modelFileName,
176
+ version: newVersion,
177
+ bumpedBy: trimmedBy,
178
+ bumpedOn: on,
179
+ emVersion,
180
+ modelHash,
181
+ slices,
182
+ certified: null,
183
+ };
184
+ mkdirSync(modelVersionsDir(baseDir), { recursive: true });
185
+ const path = modelVersionManifestPath(baseDir, newVersion);
186
+ writeFileSync(path, serializeModelVersionDoc(manifest), "utf8");
187
+ return { ok: true, version: newVersion, path };
188
+ }
189
+ export function modelVersionDrift(baseDir, model, refs, source) {
190
+ const current = latestModelVersionNumber(baseDir);
191
+ if (current === null)
192
+ return { current: null, hashChanged: false, slicesChanged: [] };
193
+ const read = readModelVersionManifest(baseDir, current);
194
+ if (!read || !read.ok)
195
+ return { current, hashChanged: false, slicesChanged: [] };
196
+ const hashChanged = read.manifest.modelHash !== computeModelHash(source);
197
+ const currentVector = computeSlicesVector(model, refs, baseDir);
198
+ const keys = new Set([...Object.keys(read.manifest.slices), ...Object.keys(currentVector)]);
199
+ const slicesChanged = [];
200
+ for (const key of [...keys].sort()) {
201
+ const from = read.manifest.slices[key] ?? null;
202
+ const to = currentVector[key] ?? null;
203
+ if (from !== to)
204
+ slicesChanged.push({ key, from, to });
205
+ }
206
+ return { current, hashChanged, slicesChanged };
207
+ }
208
+ /** The most recently bumped design version that has ever been certified — walking every
209
+ * manifest newest-first, since a later bump doesn't clear an earlier version's own
210
+ * `certified` stamp (only the CURRENT design version's manifest is ever written to by `em
211
+ * state set-conformance`; older manifests keep whatever certification they already carried).
212
+ * `null` when no manifest has ever been certified. Malformed manifests are skipped (best
213
+ * effort, same posture `findings.ts`'s `listAllFindingsFiles` takes toward a broken file it
214
+ * isn't itself the loud diagnostic for). */
215
+ export function findCertifiedVersion(baseDir) {
216
+ const nums = listModelVersionNumbers(baseDir).sort((a, b) => b - a);
217
+ for (const v of nums) {
218
+ const read = readModelVersionManifest(baseDir, v);
219
+ if (read && read.ok && read.manifest.certified)
220
+ return { version: v, certified: read.manifest.certified };
221
+ }
222
+ return null;
223
+ }
224
+ /**
225
+ * `em state set-conformance` (non-`--partial`, MIL-218 ruling D): write `certified: { at, on,
226
+ * report, findings }` into the CURRENT design version's manifest. Refuses when no manifest
227
+ * exists yet ("bump a model version first") and when the vector has drifted since that
228
+ * manifest was bumped (`modelVersionDrift`, computed here — the question is exactly "has THIS
229
+ * model changed since v<N> was bumped", the same predicate every other warn-only surface
230
+ * reads): the certification would otherwise name a version that isn't what was actually
231
+ * checked. Idempotent on an identical `certified` value; a DIFFERENT one simply overwrites —
232
+ * re-certifying at a later revision is legal and common (MIL-214's own `em slice conform` holds
233
+ * the same "overwrite, no --force" posture for exactly this reason).
234
+ */
235
+ export function runCertifyModelVersion(baseDir, model, refs, source, at, on, report, findings) {
236
+ const current = latestModelVersionNumber(baseDir);
237
+ if (current === null) {
238
+ return { ok: false, message: "no model-versions/ manifest exists yet — bump a model version first (`em model version bump`)" };
239
+ }
240
+ const drift = modelVersionDrift(baseDir, model, refs, source);
241
+ if (drift.hashChanged || drift.slicesChanged.length > 0) {
242
+ return {
243
+ ok: false,
244
+ message: `the model has drifted since v${current} was bumped — bump a new model version first (\`em model version bump\`) before certifying`,
245
+ };
246
+ }
247
+ const read = readModelVersionManifest(baseDir, current);
248
+ if (!read || !read.ok) {
249
+ return { ok: false, message: (read && "message" in read && read.message) || `model-versions/v${current}.json is missing or unreadable` };
250
+ }
251
+ const manifest = { ...read.manifest, certified: { at, on, report, findings } };
252
+ const path = modelVersionManifestPath(baseDir, current);
253
+ writeFileSync(path, serializeModelVersionDoc(manifest), "utf8");
254
+ return { ok: true, version: current, path };
255
+ }
256
+ //# sourceMappingURL=modelVersion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelVersion.js","sourceRoot":"","sources":["../../src/cli/modelVersion.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,4FAA4F;AAC5F,4FAA4F;AAC5F,+FAA+F;AAC/F,EAAE;AACF,gGAAgG;AAChG,0FAA0F;AAC1F,uFAAuF;AACvF,eAAe;AACf,+FAA+F;AAC/F,8FAA8F;AAC9F,2DAA2D;AAC3D,EAAE;AACF,6FAA6F;AAC7F,8FAA8F;AAC9F,8FAA8F;AAC9F,+FAA+F;AAC/F,iGAAiG;AACjG,iCAAiC;AACjC,EAAE;AACF,6FAA6F;AAC7F,+FAA+F;AAC/F,4DAA4D;AAC5D,EAAE;AACF,yFAAyF;AACzF,8FAA8F;AAC9F,8FAA8F;AAC9F,EAAE;AACF,4FAA4F;AAC5F,4FAA4F;AAC5F,8FAA8F;AAC9F,yCAAyC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,CAAC,MAAM,4BAA4B,GAAG,KAAK,CAAC;AAgClD;iFACiF;AACjF,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACtE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACvE,CAAC;AAED;;oDAEoD;AACpD,MAAM,UAAU,wBAAwB,CAAC,GAAyB;IAChE,MAAM,YAAY,GAAkC,EAAE,CAAC;IACvD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;QAAE,YAAY,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACtF,MAAM,SAAS,GAAG;QAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,SAAS,EAAE,GAAG,CAAC,SAAS;YACtB,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE;YAChH,CAAC,CAAC,IAAI;QACR,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,yBAAyB,EAAE,GAAG,CAAC,yBAAyB;QACxD,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,GAAG,CAAC,OAAO;KACrB,CAAC;IACF,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AACnD,CAAC;AAED;mFACmF;AACnF,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,OAAe,EAAE,OAAe;IACvE,OAAO,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,IAAI,OAAO,OAAO,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAE1C;;;wCAGwC;AACxC,MAAM,UAAU,uBAAuB,CAAC,OAAe;IACrD,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC;YAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,wBAAwB,CAAC,OAAe;IACtD,MAAM,IAAI,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC;AAID;;;;4DAI4D;AAC5D,MAAM,UAAU,wBAAwB,CAAC,OAAe,EAAE,OAAe;IACvE,MAAM,IAAI,GAAG,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,IAAI,KAAM,CAAW,CAAC,OAAO,EAAE,EAAE,CAAC;IACnF,CAAC;IACD,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,EAAE,CAAC;IACzE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7D,CAAC;AACH,CAAC;AAED;;;;;oBAKoB;AACpB,MAAM,UAAU,mBAAmB,CAAC,KAAsB,EAAE,IAAgB,EAAE,OAAe;IAC3F,MAAM,MAAM,GAAkC,EAAE,CAAC;IACjD,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,iBAAiB,EAAE,GAAG,mBAAmB,CACpE,KAAK,EACL,IAAI,EACJ,KAAK,EACL,GAAG,EACH,OAAO,EACP,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAE,CAC9B,CAAC;QACF,IAAI,iBAAiB,KAAK,IAAI;YAAE,OAAO;QACvC,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC;IAC5B,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAMD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,aAAqB,EACrB,KAAsB,EACtB,IAAgB,EAChB,MAAc,EACd,EAAU,EACV,EAAU,EACV,SAAiB,EACjB,KAAc;IAEd,MAAM,SAAS,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,kCAAkC,EAAE,CAAC;IAElF,MAAM,SAAS,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAElD,IAAI,OAAO,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxD,IAAI,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,SAAS,CAAC;YACvD,MAAM,UAAU,GACd,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;gBACvG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;YAC9F,IAAI,QAAQ,IAAI,UAAU,EAAE,CAAC;gBAC3B,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,OAAO,EAAE,8BAA8B,OAAO,wEAAwE;iBACvH,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAyB;QACrC,yBAAyB,EAAE,4BAA4B;QACvD,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,UAAU;QACnB,QAAQ,EAAE,SAAS;QACnB,QAAQ,EAAE,EAAE;QACZ,SAAS;QACT,SAAS;QACT,MAAM;QACN,SAAS,EAAE,IAAI;KAChB,CAAC;IACF,SAAS,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,wBAAwB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC3D,aAAa,CAAC,IAAI,EAAE,wBAAwB,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;IAChE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AACjD,CAAC;AAsBD,MAAM,UAAU,iBAAiB,CAC/B,OAAe,EACf,KAAsB,EACtB,IAAgB,EAChB,MAAc;IAEd,MAAM,OAAO,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAClD,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC;IACtF,MAAM,IAAI,GAAG,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxD,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC;IAEjF,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzE,MAAM,aAAa,GAAG,mBAAmB,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAC5F,MAAM,aAAa,GAA8B,EAAE,CAAC;IACpD,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;QAC/C,MAAM,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;QACtC,IAAI,IAAI,KAAK,EAAE;YAAE,aAAa,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;AACjD,CAAC;AAED;;;;;;6CAM6C;AAC7C,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,MAAM,IAAI,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,wBAAwB,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAClD,IAAI,IAAI,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;IAC5G,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAMD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAe,EACf,KAAsB,EACtB,IAAgB,EAChB,MAAc,EACd,EAAU,EACV,EAAU,EACV,MAAc,EACd,QAAuB;IAEvB,MAAM,OAAO,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAClD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,+FAA+F,EAAE,CAAC;IACjI,CAAC;IACD,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9D,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,gCAAgC,OAAO,4FAA4F;SAC7I,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxD,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,mBAAmB,OAAO,gCAAgC,EAAE,CAAC;IAC3I,CAAC;IACD,MAAM,QAAQ,GAAyB,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC;IACrG,MAAM,IAAI,GAAG,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxD,aAAa,CAAC,IAAI,EAAE,wBAAwB,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;IAChE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC9C,CAAC"}
@@ -4,22 +4,45 @@ export type ApplyReratifyResult = {
4
4
  ok: true;
5
5
  content: string;
6
6
  newVersion: number;
7
+ kind: ReratifyKind;
7
8
  } | {
8
9
  ok: false;
9
10
  message: string;
10
11
  };
12
+ /** MIL-258: `shipped` = the doc was `status: implemented` (status flips back); `unshipped` = a
13
+ * ratified `ready-to-implement` doc that never shipped (status untouched). */
14
+ export type ReratifyKind = "shipped" | "unshipped";
11
15
  /**
12
16
  * Pure text transform: bumps `version:` by 1 and flips `status:` to `ready-to-implement` in
13
17
  * `raw`'s frontmatter block, clearing any `ratifiedBy:`/`ratifiedOn:` lines found (see module
14
- * header). Refuses (`ok: false`) unless the doc's CURRENT `status:` is exactly `implemented` —
18
+ * header). Refuses (`ok: false`) unless the doc's CURRENT `status:` is `implemented`, or
19
+ * `ready-to-implement` with `ratifiedBy:` set (MIL-258, `kind: "unshipped"`, status left alone) —
15
20
  * see module header for why this precondition (not idempotent-no-op) is the right refusal
16
21
  * shape here. No fs access — the caller reads/writes; see `runReratify` below.
17
22
  */
18
23
  export declare function applyReratifyFrontmatter(raw: string): ApplyReratifyResult;
24
+ /** MIL-214: the certification-aware advisory `runReratify` computes about the version being
25
+ * superseded — never gates the bump, see module header. */
26
+ export interface ReratifyAdvisory {
27
+ /** True when the CURRENT (pre-bump) version has no matching `conformedVersion` — either never
28
+ * certified at all, or certified against a different version. */
29
+ neverCertified: boolean;
30
+ /** Count of unruled (`locus: null`) conformance findings in scope for this slice, across every
31
+ * `conformance/*-findings.json` beside the model — not scoped to one revision, since a
32
+ * reratify has no `--at` of its own to anchor on. */
33
+ unruledFindingsCount: number;
34
+ }
35
+ /** Pure: the two facts `runReratify`'s advisory reports, from the doc's own pre-bump
36
+ * `version`/`conformedVersion` plus a scan of every findings file beside the model — see
37
+ * `ReratifyAdvisory`. No refusal here or anywhere downstream; this is data for the CLI layer to
38
+ * print as `warn:` lines. */
39
+ export declare function reratifyAdvisory(baseDir: string, sliceKey: string, currentVersion: number | null, conformedVersion: number | null): ReratifyAdvisory;
19
40
  export type RunReratifyResult = {
20
41
  ok: true;
21
42
  path: string;
22
43
  newVersion: number;
44
+ kind: ReratifyKind;
45
+ advisory: ReratifyAdvisory | null;
23
46
  } | {
24
47
  ok: false;
25
48
  message: string;
@@ -10,15 +10,25 @@
10
10
  // version: <current + 1>
11
11
  // status: ready-to-implement
12
12
  //
13
- // Only applies to a doc currently `status: implemented` — the precondition
13
+ // MIL-258: that is the SHIPPED path. A second path covers a doc at `status: ready-to-implement`
14
+ // that still carries `ratifiedBy:` — a ratified version that has not shipped (the most common
15
+ // change during delivery: an implementer hits a gap, a human answers it, the doc changes before
16
+ // the build resumes). It bumps `version:` and clears the same four sign-off fields but leaves
17
+ // `status:` (and any `implementedIn:`) alone, since there is nothing to flip back. A
18
+ // `ready-to-implement` doc with NO `ratifiedBy:` still refuses: that is the exact state a
19
+ // reratify leaves a doc in, so refusing keeps the double-bump guard — the doc is awaiting
20
+ // `em slice ratify --by`, not another bump. `draft`/`reviewed` docs are not ratified and refuse
21
+ // too; they can simply be edited.
22
+ //
23
+ // Shipped path precondition (original, MIL-161) — a doc currently `status: implemented`, the precondition
14
24
  // docs/slice-doc-schema.md#status-under-re-ratification describes ("a new version is ratified
15
25
  // for a slice whose previous version already shipped"). Refuses (never guesses) otherwise: a
16
26
  // `draft`/`reviewed` doc hasn't shipped yet, so there's no prior version to bump FROM, and a
17
- // doc already `ready-to-implement` means either first-time authoring (never touch this doc with
18
- // reratify at all — `em slice new` is what scaffolds those) or a reratify that already ran (a
19
- // second bump would silently double-increment `version`, which this command deliberately never
20
- // does — bumping isn't naturally idempotent the way ratify/mark-implemented's absolute-value
21
- // writes are).
27
+ // doc already `ready-to-implement` WITHOUT `ratifiedBy:` means either first-time authoring (never
28
+ // touch this doc with reratify at all — `em slice new` is what scaffolds those) or a reratify
29
+ // that already ran (a second bump would silently double-increment `version`, which this command
30
+ // deliberately never does — bumping isn't naturally idempotent the way ratify/mark-implemented's
31
+ // absolute-value writes are).
22
32
  //
23
33
  // Also clears `ratifiedBy:`/`ratifiedOn:` if either is present: those fields record who signed
24
34
  // off the PRIOR version (`em slice ratify`, MIL-165) and describing the brand-new, not-yet-
@@ -39,11 +49,20 @@
39
49
  // (best-effort) the file's own line-ending style — is copied through verbatim. The `## Delta`
40
50
  // section (docs/slice-doc-schema.md#delta-section-grammar-and-lifecycle) recording WHAT changed
41
51
  // stays entirely hand-authored — this command only ever touches the two lifecycle fields above.
52
+ //
53
+ // MIL-214: `reratifyAdvisory` below is the certification-aware counterpart to MIL-198's
54
+ // upstream-timeline advisory (ratify.ts's `upstreamUnratifiedSlices`) — same shape, same
55
+ // never-refuses stance. Bumping a version whose CURRENT one was never certified (or still has
56
+ // unruled conformance findings) isn't wrong — the team may have good reason to move on before a
57
+ // conform sweep ever ran — so this is advisory only, printed by the CLI layer, never gating the
58
+ // bump itself. MIL-258: the advisory is about superseding a SHIPPED version, so the unshipped
59
+ // path skips it entirely (`advisory: null`) — an unshipped version has no certification to lack.
42
60
  import { readFileSync, writeFileSync } from "node:fs";
43
61
  import { join } from "node:path";
44
62
  import { continuationOf } from "../model/continuation.js";
45
63
  import { resolveSliceDocJoin } from "../catalog/docJoin.js";
46
64
  import { fieldLineRegex, fieldLineWithEolRegex, locateFrontmatterInner, normalizeFieldValue } from "./frontmatterSurgery.js";
65
+ import { listAllFindingsFiles, unruledFindingsInScope } from "./findings.js";
47
66
  /** The status a doc must already be in for `reratify` to apply — mirrors `RATIFIED_STATUS` in
48
67
  * ratify.ts (the status this command flips TO), named separately since it's the precondition
49
68
  * here, not the target. */
@@ -52,7 +71,8 @@ const TARGET_STATUS = "ready-to-implement";
52
71
  /**
53
72
  * Pure text transform: bumps `version:` by 1 and flips `status:` to `ready-to-implement` in
54
73
  * `raw`'s frontmatter block, clearing any `ratifiedBy:`/`ratifiedOn:` lines found (see module
55
- * header). Refuses (`ok: false`) unless the doc's CURRENT `status:` is exactly `implemented` —
74
+ * header). Refuses (`ok: false`) unless the doc's CURRENT `status:` is `implemented`, or
75
+ * `ready-to-implement` with `ratifiedBy:` set (MIL-258, `kind: "unshipped"`, status left alone) —
56
76
  * see module header for why this precondition (not idempotent-no-op) is the right refusal
57
77
  * shape here. No fs access — the caller reads/writes; see `runReratify` below.
58
78
  */
@@ -65,14 +85,30 @@ export function applyReratifyFrontmatter(raw) {
65
85
  if (!statusMatch)
66
86
  return { ok: false, message: "no `status:` field found in frontmatter" };
67
87
  const currentStatus = normalizeFieldValue(statusMatch[2])?.toLowerCase() ?? null;
88
+ let kind = "shipped";
68
89
  if (currentStatus !== IMPLEMENTED_STATUS) {
69
- return {
70
- ok: false,
71
- message: `doc is \`status: ${currentStatus ?? "(empty)"}\`, not \`implemented\` — reratify only applies to a ` +
72
- "slice doc that has already shipped (see docs/slice-doc-schema.md#status-under-re-ratification); " +
73
- "first-time authoring uses `em slice new`, and a doc already `ready-to-implement` may already " +
74
- "have been reratified",
75
- };
90
+ const ratifiedByMatch = fieldLineRegex("ratifiedBy").exec(inner);
91
+ const hasRatifiedBy = ratifiedByMatch !== null && normalizeFieldValue(ratifiedByMatch[2]) !== null;
92
+ if (currentStatus === TARGET_STATUS && hasRatifiedBy) {
93
+ kind = "unshipped";
94
+ }
95
+ else if (currentStatus === TARGET_STATUS) {
96
+ return {
97
+ ok: false,
98
+ message: "doc is `status: ready-to-implement` with no `ratifiedBy:` — it is awaiting ratification " +
99
+ "(a reratify already ran, or it was never signed off), so another version bump would " +
100
+ "double-increment `version:`; record the sign-off with `em slice ratify --by <name>`",
101
+ };
102
+ }
103
+ else {
104
+ return {
105
+ ok: false,
106
+ message: `doc is \`status: ${currentStatus ?? "(empty)"}\` — reratify only applies to a slice doc that has ` +
107
+ "shipped (`status: implemented`) or to a ratified `ready-to-implement` doc that has not (see " +
108
+ "docs/slice-doc-schema.md#status-under-re-ratification); a `draft`/`reviewed` doc is not ratified " +
109
+ "and can simply be edited, and first-time authoring uses `em slice new`",
110
+ };
111
+ }
76
112
  }
77
113
  const versionMatch = fieldLineRegex("version").exec(inner);
78
114
  if (!versionMatch)
@@ -89,7 +125,10 @@ export function applyReratifyFrontmatter(raw) {
89
125
  // Apply from the highest index first so an earlier edit's index stays valid — same convention
90
126
  // markImplemented.ts/ratify.ts use.
91
127
  const edits = [
92
- { index: statusMatch.index, oldLen: statusMatch[0].length, next: `${statusMatch[1]}${TARGET_STATUS}` },
128
+ // MIL-258: the unshipped path is already at the target status — nothing to flip.
129
+ ...(kind === "shipped"
130
+ ? [{ index: statusMatch.index, oldLen: statusMatch[0].length, next: `${statusMatch[1]}${TARGET_STATUS}` }]
131
+ : []),
93
132
  { index: versionMatch.index, oldLen: versionMatch[0].length, next: `${versionMatch[1]}${newVersion}` },
94
133
  ].sort((a, b) => b.index - a.index);
95
134
  let updatedInner = inner;
@@ -105,7 +144,19 @@ export function applyReratifyFrontmatter(raw) {
105
144
  updatedInner = updatedInner.replace(fieldLineWithEolRegex(key), "");
106
145
  }
107
146
  const content = raw.slice(0, range.innerStart) + updatedInner + raw.slice(range.innerEnd);
108
- return { ok: true, content, newVersion };
147
+ return { ok: true, content, newVersion, kind };
148
+ }
149
+ /** Pure: the two facts `runReratify`'s advisory reports, from the doc's own pre-bump
150
+ * `version`/`conformedVersion` plus a scan of every findings file beside the model — see
151
+ * `ReratifyAdvisory`. No refusal here or anywhere downstream; this is data for the CLI layer to
152
+ * print as `warn:` lines. */
153
+ export function reratifyAdvisory(baseDir, sliceKey, currentVersion, conformedVersion) {
154
+ const neverCertified = conformedVersion === null || conformedVersion !== currentVersion;
155
+ let unruledFindingsCount = 0;
156
+ for (const { doc } of listAllFindingsFiles(baseDir)) {
157
+ unruledFindingsCount += unruledFindingsInScope(doc.findings, new Set([sliceKey])).length;
158
+ }
159
+ return { neverCertified, unruledFindingsCount };
109
160
  }
110
161
  /**
111
162
  * Resolves `sliceKey` to its bound doc via the same note-binding join `mark-implemented`/
@@ -151,7 +202,12 @@ export function runReratify(model, refs, baseDir, sliceKey) {
151
202
  if (!result.ok) {
152
203
  return { ok: false, message: `${doc.path}: ${result.message}` };
153
204
  }
205
+ // MIL-214: computed from the doc's PRE-BUMP version/certification (`doc` was resolved before
206
+ // the write below changes `version`) — "was the version we're about to supersede ever fully
207
+ // certified". MIL-258: only meaningful for a SHIPPED version; an unshipped one has no
208
+ // certification to lack, so that path carries no advisory at all.
209
+ const advisory = result.kind === "shipped" ? reratifyAdvisory(baseDir, sliceKey, doc.version, doc.conformedVersion) : null;
154
210
  writeFileSync(absPath, result.content, "utf8");
155
- return { ok: true, path: doc.path, newVersion: result.newVersion };
211
+ return { ok: true, path: doc.path, newVersion: result.newVersion, kind: result.kind, advisory };
156
212
  }
157
213
  //# sourceMappingURL=reratify.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reratify.js","sourceRoot":"","sources":["../../src/cli/reratify.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reratify.js","sourceRoot":"","sources":["../../src/cli/reratify.ts"],"names":[],"mappings":"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"}
@@ -44,7 +44,7 @@ export function checkSkillSync(packagedDir, vendoredDir, installedVersion) {
44
44
  else if (vendoredStamp !== installedVersion) {
45
45
  findings.push({
46
46
  code: "skill-check-stamp-mismatch",
47
- message: `vendored skill's em-version: stamp (${vendoredStamp}) doesn't match installed em (${installedVersion}) — run \`em skill sync\``,
47
+ message: `vendored skill's em-version: stamp (${vendoredStamp}) doesn't match installed em (${installedVersion}) — run \`em skill sync\` (or \`em upgrade\`)`,
48
48
  vendoredStamp,
49
49
  installedVersion,
50
50
  });
@@ -54,7 +54,7 @@ export function checkSkillSync(packagedDir, vendoredDir, installedVersion) {
54
54
  const driftedFiles = plan.changes.map((c) => c.relPath).sort();
55
55
  findings.push({
56
56
  code: "skill-check-content-drift",
57
- message: `vendored skill differs from the packaged skill in ${driftedFiles.length} file(s) — run \`em skill sync\``,
57
+ message: `vendored skill differs from the packaged skill in ${driftedFiles.length} file(s) — run \`em skill sync\` (or \`em upgrade\`)`,
58
58
  driftedFiles,
59
59
  });
60
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"skillCheck.js","sourceRoot":"","sources":["../../src/cli/skillCheck.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skillCheck.js","sourceRoot":"","sources":["../../src/cli/skillCheck.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { NormalizedModel } from "../model/model.js";
2
+ import { RefsResult } from "../model/refs.js";
3
+ import { FindingsDoc } from "./findings.js";
4
+ export type ApplyConformResult = {
5
+ ok: true;
6
+ content: string;
7
+ changed: boolean;
8
+ version: number;
9
+ } | {
10
+ ok: false;
11
+ message: string;
12
+ };
13
+ /**
14
+ * Pure text transform: reads the CURRENT `version:` value (never writes it) and writes
15
+ * `conformedVersion:`/`conformedAt:`/`conformedOn:` in `raw`'s frontmatter block. See module
16
+ * header for the full precondition/idempotency contract. No fs access — the caller reads/writes;
17
+ * see `runSliceConform` below.
18
+ */
19
+ export declare function applyConformFrontmatter(raw: string, sliceKey: string, at: string, on: string): ApplyConformResult;
20
+ /** Scan `<baseDir>/conformance/*-findings.json`, newest filename first, for the first one whose
21
+ * `revision` matches `at` — the "newest findings JSON whose revision == --at" the ruling
22
+ * describes. A malformed candidate is silently skipped (not refused): this is a best-effort
23
+ * lookup for the findings-check gate below, not itself a validator — `em conform-findings
24
+ * check` is where a broken findings file gets a loud diagnosis. Returns null when the
25
+ * `conformance/` directory doesn't exist, or no candidate matches `at`. */
26
+ export declare function findLatestFindingsForRevision(baseDir: string, at: string): {
27
+ path: string;
28
+ doc: FindingsDoc;
29
+ } | null;
30
+ export type RunSliceConformResult = {
31
+ ok: true;
32
+ path: string;
33
+ changed: boolean;
34
+ version: number;
35
+ /** Non-null exactly when `--skip-findings-check` is what let this certification through —
36
+ * the finding ids that were still unruled, for the caller's loud notice. `null` whenever
37
+ * the findings-check gate passed on its own merits (no findings file for this revision, or
38
+ * nothing unruled in scope), whether or not the flag was passed. */
39
+ skippedFindingsCheck: number[] | null;
40
+ } | {
41
+ ok: false;
42
+ message: string;
43
+ };
44
+ /**
45
+ * Resolves `sliceKey` to its bound doc via the same note-binding join `ratify`/`reratify`/
46
+ * `mark-implemented`/`em export` use (MIL-121 cross-binding included), runs the findings-check
47
+ * gate, then reads/applies/writes it. `baseDir` is the `.em` file's directory, same convention
48
+ * every doc/note path in `em` uses.
49
+ */
50
+ export declare function runSliceConform(model: NormalizedModel, refs: RefsResult, baseDir: string, sliceKey: string, at: string, on: string, skipFindingsCheck?: boolean): RunSliceConformResult;