@milehimikey/em 1.14.2 → 1.16.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 (125) hide show
  1. package/.claude/agents/em-implementer.md +12 -2
  2. package/.claude/agents/em-validator.md +2 -1
  3. package/.claude/skills/event-modeling/SKILL.md +3 -3
  4. package/.claude/skills/event-modeling-conform/SKILL.md +1 -1
  5. package/.claude/skills/event-modeling-design/SKILL.md +29 -18
  6. package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
  7. package/.claude/skills/event-modeling-engagement/SKILL.md +60 -56
  8. package/.claude/skills/event-modeling-engagement/reference/engagement.md +13 -19
  9. package/.claude/skills/event-modeling-implement/SKILL.md +3 -3
  10. package/.claude/skills/event-modeling-implement/reference/implement.md +40 -27
  11. package/.claude/skills/event-modeling-review/SKILL.md +13 -3
  12. package/.claude/skills/event-modeling-shared/reference/em-dsl.md +234 -228
  13. package/.claude/skills/event-modeling-shared/reference/operating-principles.md +3 -3
  14. package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +69 -27
  15. package/.claude/skills/event-modeling-shared/templates/constitution.md +5 -7
  16. package/.claude-plugin/marketplace.json +2 -2
  17. package/dist/catalog/deferQueue.d.ts +20 -0
  18. package/dist/catalog/deferQueue.js +63 -0
  19. package/dist/catalog/deferQueue.js.map +1 -0
  20. package/dist/catalog/docJoin.d.ts +22 -1
  21. package/dist/catalog/docJoin.js +13 -4
  22. package/dist/catalog/docJoin.js.map +1 -1
  23. package/dist/catalog/docModelConsistencyValidate.js +4 -8
  24. package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
  25. package/dist/catalog/driftSignal.d.ts +16 -12
  26. package/dist/catalog/driftSignal.js +14 -9
  27. package/dist/catalog/driftSignal.js.map +1 -1
  28. package/dist/catalog/sliceDoc.d.ts +51 -0
  29. package/dist/catalog/sliceDoc.js +47 -0
  30. package/dist/catalog/sliceDoc.js.map +1 -1
  31. package/dist/catalog/sliceReadyValidate.js +19 -1
  32. package/dist/catalog/sliceReadyValidate.js.map +1 -1
  33. package/dist/catalog/sliceSections.d.ts +5 -0
  34. package/dist/catalog/sliceSections.js +11 -2
  35. package/dist/catalog/sliceSections.js.map +1 -1
  36. package/dist/cli/conformScope.d.ts +4 -0
  37. package/dist/cli/conformScope.js +2 -2
  38. package/dist/cli/conformScope.js.map +1 -1
  39. package/dist/cli/coverage.js +7 -3
  40. package/dist/cli/coverage.js.map +1 -1
  41. package/dist/cli/defer.d.ts +106 -2
  42. package/dist/cli/defer.js +357 -24
  43. package/dist/cli/defer.js.map +1 -1
  44. package/dist/cli/engagement.d.ts +26 -5
  45. package/dist/cli/engagement.js +55 -28
  46. package/dist/cli/engagement.js.map +1 -1
  47. package/dist/cli/engagementFile.d.ts +2 -0
  48. package/dist/cli/engagementFile.js +5 -3
  49. package/dist/cli/engagementFile.js.map +1 -1
  50. package/dist/cli/findings.d.ts +2 -2
  51. package/dist/cli/findings.js +2 -2
  52. package/dist/cli/frontmatterSurgery.d.ts +3 -3
  53. package/dist/cli/frontmatterSurgery.js +3 -3
  54. package/dist/cli/frontmatterSurgery.js.map +1 -1
  55. package/dist/cli/markImplemented.d.ts +23 -18
  56. package/dist/cli/markImplemented.js +99 -15
  57. package/dist/cli/markImplemented.js.map +1 -1
  58. package/dist/cli/ratify.d.ts +36 -6
  59. package/dist/cli/ratify.js +130 -35
  60. package/dist/cli/ratify.js.map +1 -1
  61. package/dist/cli/review.js +3 -3
  62. package/dist/cli/review.js.map +1 -1
  63. package/dist/cli/revise.d.ts +67 -0
  64. package/dist/cli/revise.js +229 -0
  65. package/dist/cli/revise.js.map +1 -0
  66. package/dist/cli/sliceConform.d.ts +4 -3
  67. package/dist/cli/sliceConform.js +29 -12
  68. package/dist/cli/sliceConform.js.map +1 -1
  69. package/dist/cli/status.d.ts +30 -6
  70. package/dist/cli/status.js +59 -19
  71. package/dist/cli/status.js.map +1 -1
  72. package/dist/cli/upgrade.js +17 -12
  73. package/dist/cli/upgrade.js.map +1 -1
  74. package/dist/cli.js +173 -85
  75. package/dist/cli.js.map +1 -1
  76. package/dist/emit/engagementJson.d.ts +7 -4
  77. package/dist/emit/engagementJson.js +11 -4
  78. package/dist/emit/engagementJson.js.map +1 -1
  79. package/dist/emit/json.d.ts +1 -1
  80. package/dist/emit/json.js +18 -5
  81. package/dist/emit/json.js.map +1 -1
  82. package/dist/emit/statusJson.d.ts +1 -1
  83. package/dist/emit/statusJson.js +6 -1
  84. package/dist/emit/statusJson.js.map +1 -1
  85. package/dist/mcp/server.js +5 -5
  86. package/dist/mcp/server.js.map +1 -1
  87. package/dist/model/continuation.d.ts +11 -1
  88. package/dist/model/continuation.js +29 -0
  89. package/dist/model/continuation.js.map +1 -1
  90. package/dist/model/resolveSlice.d.ts +19 -0
  91. package/dist/model/resolveSlice.js +69 -0
  92. package/dist/model/resolveSlice.js.map +1 -0
  93. package/dist/model/rules.d.ts +8 -0
  94. package/dist/model/rules.js +8 -0
  95. package/dist/model/rules.js.map +1 -1
  96. package/dist/model/sliceDocIndex.d.ts +5 -0
  97. package/dist/model/sliceDocIndex.js +6 -4
  98. package/dist/model/sliceDocIndex.js.map +1 -1
  99. package/dist/model/validate.js +5 -2
  100. package/dist/model/validate.js.map +1 -1
  101. package/dist/parser/parser.js +55 -1
  102. package/dist/parser/parser.js.map +1 -1
  103. package/dist/templates.d.ts +1 -1
  104. package/dist/templates.js +5 -7
  105. package/dist/templates.js.map +1 -1
  106. package/package.json +1 -1
  107. package/plugin/.claude-plugin/plugin.json +2 -2
  108. package/plugin/agents/em-implementer.md +12 -2
  109. package/plugin/agents/em-validator.md +2 -1
  110. package/plugin/shared/reference/em-dsl.md +234 -228
  111. package/plugin/shared/reference/operating-principles.md +3 -3
  112. package/plugin/shared/reference/slice-doc-schema.md +69 -27
  113. package/plugin/shared/templates/constitution.md +5 -7
  114. package/plugin/skills/conform/SKILL.md +1 -1
  115. package/plugin/skills/design/SKILL.md +29 -18
  116. package/plugin/skills/discover/SKILL.md +1 -1
  117. package/plugin/skills/engagement/SKILL.md +60 -56
  118. package/plugin/skills/engagement/reference/engagement.md +13 -19
  119. package/plugin/skills/event-modeling/SKILL.md +3 -3
  120. package/plugin/skills/implement/SKILL.md +3 -3
  121. package/plugin/skills/implement/reference/implement.md +40 -27
  122. package/plugin/skills/review/SKILL.md +13 -3
  123. package/dist/cli/reratify.d.ts +0 -58
  124. package/dist/cli/reratify.js +0 -238
  125. package/dist/cli/reratify.js.map +0 -1
@@ -78,8 +78,8 @@ export declare function lookupFindingsBesideReport(baseDir: string, reportPath:
78
78
  /** Every `conformance/*-findings.json` beside `baseDir`, newest filename first, that parses and
79
79
  * shape-validates — a malformed candidate is silently skipped (`em conform-findings check` is
80
80
  * the loud diagnosis for a broken file, not this scan). Shared by `cli/sliceConform.ts`'s
81
- * `findLatestFindingsForRevision` (filters to one `revision`) and `em slice reratify`'s advisory
82
- * (`reratifyAdvisory`, cli/reratify.ts — looks across every past run, not just one revision).
81
+ * `findLatestFindingsForRevision` (filters to one `revision`) and `em slice revise`'s advisory
82
+ * (`reviseAdvisory`, cli/revise.ts — looks across every past run, not just one revision).
83
83
  * Returns `[]` when `conformance/` doesn't exist. */
84
84
  export declare function listAllFindingsFiles(baseDir: string): {
85
85
  path: string;
@@ -205,8 +205,8 @@ export function lookupFindingsBesideReport(baseDir, reportPath) {
205
205
  /** Every `conformance/*-findings.json` beside `baseDir`, newest filename first, that parses and
206
206
  * shape-validates — a malformed candidate is silently skipped (`em conform-findings check` is
207
207
  * the loud diagnosis for a broken file, not this scan). Shared by `cli/sliceConform.ts`'s
208
- * `findLatestFindingsForRevision` (filters to one `revision`) and `em slice reratify`'s advisory
209
- * (`reratifyAdvisory`, cli/reratify.ts — looks across every past run, not just one revision).
208
+ * `findLatestFindingsForRevision` (filters to one `revision`) and `em slice revise`'s advisory
209
+ * (`reviseAdvisory`, cli/revise.ts — looks across every past run, not just one revision).
210
210
  * Returns `[]` when `conformance/` doesn't exist. */
211
211
  export function listAllFindingsFiles(baseDir) {
212
212
  const dir = join(baseDir, "conformance");
@@ -12,9 +12,9 @@ export declare function normalizeFieldValue(raw: string | undefined): string | n
12
12
  /** Same anchor as `fieldLineRegex`, but captures through the line's own trailing EOL (or
13
13
  * end-of-string, for a field that happens to be the frontmatter's last line) so a match can be
14
14
  * spliced out ENTIRELY — key, value, and terminator — rather than just replaced. Used by
15
- * `em slice reratify` (reratify.ts) to drop a now-stale `ratifiedBy:`/`ratifiedOn:` pair: those
16
- * fields describe who signed off the PRIOR version, and silently leaving them in place would
17
- * make a fresh version look already ratified. */
15
+ * `em slice revise` (revise.ts, MIL-283 — formerly `reratify`) to drop the now-stale sign-off
16
+ * keys (`SIGN_OFF_KEYS` there): those fields describe who signed off the PRIOR version, and
17
+ * silently leaving them in place would make a fresh version look already ratified. */
18
18
  export declare function fieldLineWithEolRegex(key: string): RegExp;
19
19
  /** Byte offsets of the frontmatter block's inner lines (between the two `---` fences), located
20
20
  * by walking lines with `indexOf` rather than `split(/\r?\n/)` — a rewrite can't afford the
@@ -33,9 +33,9 @@ export function normalizeFieldValue(raw) {
33
33
  /** Same anchor as `fieldLineRegex`, but captures through the line's own trailing EOL (or
34
34
  * end-of-string, for a field that happens to be the frontmatter's last line) so a match can be
35
35
  * spliced out ENTIRELY — key, value, and terminator — rather than just replaced. Used by
36
- * `em slice reratify` (reratify.ts) to drop a now-stale `ratifiedBy:`/`ratifiedOn:` pair: those
37
- * fields describe who signed off the PRIOR version, and silently leaving them in place would
38
- * make a fresh version look already ratified. */
36
+ * `em slice revise` (revise.ts, MIL-283 — formerly `reratify`) to drop the now-stale sign-off
37
+ * keys (`SIGN_OFF_KEYS` there): those fields describe who signed off the PRIOR version, and
38
+ * silently leaving them in place would make a fresh version look already ratified. */
39
39
  export function fieldLineWithEolRegex(key) {
40
40
  return new RegExp(`^${key}[ \\t]*:[ \\t]*[^\\r\\n]*\\r?\\n?`, "im");
41
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatterSurgery.js","sourceRoot":"","sources":["../../src/cli/frontmatterSurgery.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,uFAAuF;AACvF,4FAA4F;AAC5F,yFAAyF;AACzF,yFAAyF;AACzF,8FAA8F;AAC9F,gGAAgG;AAChG,sEAAsE;AACtE,EAAE;AACF,+FAA+F;AAE/F;;;;mDAImD;AACnD,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,gGAAgG;IAChG,6FAA6F;IAC7F,6FAA6F;IAC7F,+FAA+F;IAC/F,OAAO,IAAI,MAAM,CAAC,KAAK,GAAG,8BAA8B,EAAE,IAAI,CAAC,CAAC;AAClE,CAAC;AAED;;;qBAGqB;AACrB,MAAM,UAAU,mBAAmB,CAAC,GAAuB;IACzD,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;kDAKkD;AAClD,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,OAAO,IAAI,MAAM,CAAC,IAAI,GAAG,mCAAmC,EAAE,IAAI,CAAC,CAAC;AACtE,CAAC;AAED;;;;;0FAK0F;AAC1F,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9C,IAAI,GAAG,GAAG,UAAU,CAAC;IACrB,OAAO,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC1C,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QACvC,CAAC;QACD,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,MAAM;QACrB,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"frontmatterSurgery.js","sourceRoot":"","sources":["../../src/cli/frontmatterSurgery.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,uFAAuF;AACvF,4FAA4F;AAC5F,yFAAyF;AACzF,yFAAyF;AACzF,8FAA8F;AAC9F,gGAAgG;AAChG,sEAAsE;AACtE,EAAE;AACF,+FAA+F;AAE/F;;;;mDAImD;AACnD,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,gGAAgG;IAChG,6FAA6F;IAC7F,6FAA6F;IAC7F,+FAA+F;IAC/F,OAAO,IAAI,MAAM,CAAC,KAAK,GAAG,8BAA8B,EAAE,IAAI,CAAC,CAAC;AAClE,CAAC;AAED;;;qBAGqB;AACrB,MAAM,UAAU,mBAAmB,CAAC,GAAuB;IACzD,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;uFAKuF;AACvF,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,OAAO,IAAI,MAAM,CAAC,IAAI,GAAG,mCAAmC,EAAE,IAAI,CAAC,CAAC;AACtE,CAAC;AAED;;;;;0FAK0F;AAC1F,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9C,IAAI,GAAG,GAAG,UAAU,CAAC;IACrB,OAAO,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC1C,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QACvC,CAAC;QACD,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,MAAM;QACrB,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { NormalizedModel } from "../model/model.js";
2
2
  import { RefsResult } from "../model/refs.js";
3
+ import { QueuedItem } from "../catalog/deferQueue.js";
3
4
  export type ApplyFrontmatterResult = {
4
5
  ok: true;
5
6
  content: string;
@@ -8,27 +9,18 @@ export type ApplyFrontmatterResult = {
8
9
  ok: false;
9
10
  message: string;
10
11
  };
11
- /**
12
- * Pure text transform: flips `status:` to `implemented` and sets `implementedIn:` to `prUrl` in
13
- * `raw`'s frontmatter block. Idempotent (re-applying the same URL is a no-op, `changed: false`,
14
- * `content` returned byte-identical to `raw`); refuses (`ok: false`) rather than overwrite
15
- * provenance when the doc is already `status: implemented` with a *different* `implementedIn`.
16
- *
17
- * MIL-277 (GH #222): refuses any doc that isn't `ready-to-implement` or `implemented`. This
18
- * command is the step AFTER ratification — the implement contract (§6) and the engagement skill
19
- * both run it at merge without re-checking status, so without a gate here an agent pointed at a
20
- * `draft` or `reviewed` slice would record it as shipped with no human sign-off. Same posture as
21
- * `review.ts`/`ratify.ts` refusing out-of-order statuses; deliberately no escape flag, because
22
- * `em slice ratify` IS the escape hatch (it has its own `--skip-review`). `implemented` stays
23
- * legal so the idempotent re-run and the "status already implemented, `implementedIn` missing"
24
- * repair (MIL-103 AC#5) keep working — neither skips a lifecycle step.
25
- * No fs access — the caller reads/writes; see `runMarkImplemented` below.
26
- */
27
- export declare function applyImplementedFrontmatter(raw: string, prUrl: string): ApplyFrontmatterResult;
12
+ export declare function applyImplementedFrontmatter(raw: string, prUrl: string, shippedOn?: string | null): ApplyFrontmatterResult;
28
13
  export type RunMarkImplementedResult = {
29
14
  ok: true;
30
15
  path: string;
31
16
  changed: boolean;
17
+ /** MIL-283: set when the merge opened the next version as a `draft` because at least one
18
+ * Open Question was deferred to it — `version` is the new draft's, `reopened` the count. */
19
+ openedDraft: {
20
+ version: number;
21
+ reopened: number;
22
+ injected: number;
23
+ } | null;
32
24
  } | {
33
25
  ok: false;
34
26
  message: string;
@@ -40,4 +32,17 @@ export type RunMarkImplementedResult = {
40
32
  * `doc.path`), then reads/applies/writes it. `baseDir` is the `.em` file's directory, same
41
33
  * convention every doc/note path in `em` uses.
42
34
  */
43
- export declare function runMarkImplemented(model: NormalizedModel, refs: RefsResult, baseDir: string, sliceKey: string, prUrl: string): RunMarkImplementedResult;
35
+ export declare function runMarkImplemented(model: NormalizedModel, refs: RefsResult, baseDir: string, sliceKey: string, prUrl: string, shippedOn?: string | null): RunMarkImplementedResult;
36
+ /** Pure: when `content` (a freshly implemented doc) has a question deferred to v<version+1>,
37
+ * returns it with the next draft opened (`openNextDraft`); else returns it unchanged. One call:
38
+ * `openNextDraft` is pure and reports how many questions it re-opened, so "was anything
39
+ * deferred to v<N+1>" is read off its result rather than decided by a second scan that would
40
+ * have to agree with it on what the deferral marker looks like. */
41
+ export declare function nextDraftIfDeferred(content: string, queuedFor?: (version: number) => QueuedItem[]): {
42
+ content: string;
43
+ openedDraft: {
44
+ version: number;
45
+ reopened: number;
46
+ injected: number;
47
+ } | null;
48
+ };
@@ -1,11 +1,13 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // `em slice mark-implemented` (MIL-103): promotes the lifecycle flip that used to live only in
3
3
  // em-sdd-bridge's `em-sdd-mark-implemented <slice-key> <pr-url>` (see reference/implement.md §6)
4
- // into `em` itself, the same way MIL-87 promoted `--slice-ready`. Sets exactly two frontmatter
5
- // fields — `status: implemented` and `implementedIn: <pr-url>` — on the slice doc resolved from
6
- // the key via the SAME note-binding resolution `--slice-ready`/`em export` use
7
- // (catalog/docJoin.ts's resolveSliceDocJoin). Never touches `version:` (a bump here is an `em
8
- // ledger` defect per docs/slice-doc-schema.md) and never touches the markdown body.
4
+ // into `em` itself, the same way MIL-87 promoted `--slice-ready`. Flips `status: implemented`,
5
+ // sets `implementedIn: <pr-url>` and writes the shipped record beside it (MIL-284:
6
+ // `shippedVersion:`/`shippedRef:`/`shippedOn:`) on the slice doc resolved from the key via the
7
+ // SAME note-binding resolution `--slice-ready`/`em export` use (catalog/docJoin.ts's
8
+ // resolveSliceDocJoin). Then, only when an Open Question was deferred to v<N+1> (MIL-283), opens
9
+ // that next version as a `draft` through `revise.ts`'s `openNextDraft` — the one path on which
10
+ // `version:` moves here, and the body changes only to re-open those questions.
9
11
  //
10
12
  // Write strategy: surgical index-math splicing on the raw file text, not a parse+re-serialize
11
13
  // (sliceDoc.ts's own parser is deliberately read-only and drops everything not in its `SliceDoc`
@@ -33,6 +35,8 @@ import { join } from "node:path";
33
35
  import { continuationOf } from "../model/continuation.js";
34
36
  import { resolveSliceDocJoin } from "../catalog/docJoin.js";
35
37
  import { fieldLineRegex, locateFrontmatterInner, normalizeFieldValue } from "./frontmatterSurgery.js";
38
+ import { openNextDraft } from "./revise.js";
39
+ import { clearQueue, readQueue } from "./defer.js";
36
40
  /** The status a doc must hold for `mark-implemented` to flip it: ratified, not yet shipped. */
37
41
  const RATIFIED_STATUS = "ready-to-implement";
38
42
  const IMPLEMENTED_STATUS = "implemented";
@@ -49,10 +53,56 @@ const IMPLEMENTED_STATUS = "implemented";
49
53
  * `review.ts`/`ratify.ts` refusing out-of-order statuses; deliberately no escape flag, because
50
54
  * `em slice ratify` IS the escape hatch (it has its own `--skip-review`). `implemented` stays
51
55
  * legal so the idempotent re-run and the "status already implemented, `implementedIn` missing"
52
- * repair (MIL-103 AC#5) keep working — neither skips a lifecycle step.
56
+ * repair (MIL-103 AC#5) keep working — neither skips a lifecycle step. MIL-283 widens the
57
+ * idempotent re-run to any doc whose shipped record already names this URL, whatever its working
58
+ * `status` — the merge itself may have opened v<N+1> as a `draft`, and a re-run (the engagement
59
+ * skill's per-level pass, a CI retry) must still no-op rather than hit the gate.
53
60
  * No fs access — the caller reads/writes; see `runMarkImplemented` below.
54
61
  */
55
- export function applyImplementedFrontmatter(raw, prUrl) {
62
+ /**
63
+ * MIL-284: the shipped record, written beside `implementedIn:` — `shippedVersion:` (the doc's
64
+ * `version:` now), `shippedRef:` (its `ratifiedRef:`, when it has one) and `shippedOn:`
65
+ * (`shippedOn`, the local date). Each key that already has a line is replaced in place; the rest
66
+ * are inserted right after `implementedIn:`. Since MIL-283 this record, not `status`, is what
67
+ * every lifecycle reader decides on (`shippedRecordOf` in catalog/sliceDoc.ts), so
68
+ * `shippedVersion:`/`shippedRef:` are ALWAYS written on a real flip — a v2 merge that left a
69
+ * stale `shippedVersion: 1` beside `version: 2` would read as an unshipped delta forever. Only
70
+ * `shippedOn:` depends on the caller: `null` (the pure default, no clock here) skips it. Pure.
71
+ */
72
+ function withShippedRecord(inner, eol, shippedOn) {
73
+ const implMatch = fieldLineRegex("implementedIn").exec(inner);
74
+ if (!implMatch)
75
+ return inner; // unreachable after the edits above; defensive
76
+ const versionMatch = fieldLineRegex("version").exec(inner);
77
+ const refMatch = fieldLineRegex("ratifiedRef").exec(inner);
78
+ const version = versionMatch ? normalizeFieldValue(versionMatch[2]) : null;
79
+ const ref = refMatch ? normalizeFieldValue(refMatch[2]) : null;
80
+ const wanted = [
81
+ ["shippedVersion", version],
82
+ ["shippedRef", ref],
83
+ ["shippedOn", shippedOn],
84
+ ];
85
+ const edits = [];
86
+ const fresh = [];
87
+ for (const [key, value] of wanted) {
88
+ if (value === null)
89
+ continue;
90
+ const m = fieldLineRegex(key).exec(inner);
91
+ if (m)
92
+ edits.push({ index: m.index, oldLen: m[0].length, next: `${m[1]}${value}` });
93
+ else
94
+ fresh.push(`${key}: ${value}`);
95
+ }
96
+ if (fresh.length > 0) {
97
+ edits.push({ index: implMatch.index, oldLen: implMatch[0].length, next: `${implMatch[0]}${eol}${fresh.join(eol)}` });
98
+ }
99
+ edits.sort((a, b) => b.index - a.index);
100
+ let out = inner;
101
+ for (const edit of edits)
102
+ out = out.slice(0, edit.index) + edit.next + out.slice(edit.index + edit.oldLen);
103
+ return out;
104
+ }
105
+ export function applyImplementedFrontmatter(raw, prUrl, shippedOn = null) {
56
106
  const trimmedUrl = prUrl.trim();
57
107
  if (!trimmedUrl)
58
108
  return { ok: false, message: "a PR URL is required" };
@@ -72,14 +122,24 @@ export function applyImplementedFrontmatter(raw, prUrl) {
72
122
  const implMatch = fieldLineRegex("implementedIn").exec(inner);
73
123
  const currentStatus = normalizeFieldValue(statusMatch[2])?.toLowerCase() ?? null;
74
124
  const currentImplementedIn = implMatch ? normalizeFieldValue(implMatch[2]) : null;
75
- if (currentStatus === IMPLEMENTED_STATUS && currentImplementedIn !== null) {
125
+ const shippedVersionMatch = fieldLineRegex("shippedVersion").exec(inner);
126
+ const hasShippedRecord = currentStatus === IMPLEMENTED_STATUS || (shippedVersionMatch !== null && normalizeFieldValue(shippedVersionMatch[2]) !== null);
127
+ // A merge already recorded — the read-both rule `shippedRecordOf` applies: `status: implemented`,
128
+ // or a `shippedVersion:` under any working status (MIL-283 opened the next draft at merge). The
129
+ // same URL is the idempotent no-op; a different one refuses rather than overwrite provenance. A
130
+ // `ready-to-implement` doc over a shipped record is the NEXT version's merge — it falls through
131
+ // to the ordinary flip below, which replaces the link and the record.
132
+ if (hasShippedRecord && currentImplementedIn !== null && currentStatus !== RATIFIED_STATUS) {
76
133
  if (currentImplementedIn === trimmedUrl) {
77
134
  return { ok: true, content: raw, changed: false }; // idempotent no-op
78
135
  }
136
+ const nextVersionNote = currentStatus === IMPLEMENTED_STATUS
137
+ ? ""
138
+ : `; the doc is \`status: ${currentStatus ?? "(empty)"}\` for its next version — ratify that before marking its merge`;
79
139
  return {
80
140
  ok: false,
81
141
  message: `already marked implemented with a different URL (existing: ${currentImplementedIn}, ` +
82
- `requested: ${trimmedUrl}) — refusing to overwrite`,
142
+ `requested: ${trimmedUrl}) — refusing to overwrite${nextVersionNote}`,
83
143
  };
84
144
  }
85
145
  if (currentStatus !== RATIFIED_STATUS && currentStatus !== IMPLEMENTED_STATUS) {
@@ -115,6 +175,8 @@ export function applyImplementedFrontmatter(raw, prUrl) {
115
175
  const eol = rest.startsWith("\r\n") ? "\r\n" : "\n";
116
176
  updatedInner = inner.slice(0, statusMatch.index) + `${statusMatch[1]}implemented` + `${eol}implementedIn: ${trimmedUrl}` + rest;
117
177
  }
178
+ const afterStatus = inner.slice(statusMatch.index + statusMatch[0].length);
179
+ updatedInner = withShippedRecord(updatedInner, afterStatus.startsWith("\r\n") ? "\r\n" : "\n", shippedOn);
118
180
  const content = raw.slice(0, range.innerStart) + updatedInner + raw.slice(range.innerEnd);
119
181
  return { ok: true, content, changed: true };
120
182
  }
@@ -125,7 +187,7 @@ export function applyImplementedFrontmatter(raw, prUrl) {
125
187
  * `doc.path`), then reads/applies/writes it. `baseDir` is the `.em` file's directory, same
126
188
  * convention every doc/note path in `em` uses.
127
189
  */
128
- export function runMarkImplemented(model, refs, baseDir, sliceKey, prUrl) {
190
+ export function runMarkImplemented(model, refs, baseDir, sliceKey, prUrl, shippedOn = null) {
129
191
  const sliceIndex = refs.sliceKeys.indexOf(sliceKey);
130
192
  if (sliceIndex === -1) {
131
193
  return { ok: false, message: `no slice with export key "${sliceKey}" in this model` };
@@ -159,13 +221,35 @@ export function runMarkImplemented(model, refs, baseDir, sliceKey, prUrl) {
159
221
  }
160
222
  const absPath = join(baseDir, doc.path);
161
223
  const raw = readFileSync(absPath, "utf8");
162
- const result = applyImplementedFrontmatter(raw, prUrl);
224
+ const result = applyImplementedFrontmatter(raw, prUrl, shippedOn);
163
225
  if (!result.ok) {
164
226
  return { ok: false, message: `${doc.path}: ${result.message}` };
165
227
  }
166
- if (result.changed) {
167
- writeFileSync(absPath, result.content, "utf8");
168
- }
169
- return { ok: true, path: doc.path, changed: result.changed };
228
+ if (!result.changed)
229
+ return { ok: true, path: doc.path, changed: false, openedDraft: null };
230
+ // MIL-283: the shipped version is recorded; if the ratified doc deferred any question to the
231
+ // NEXT version, that version is known work — open it as a `draft` right now so the deferred
232
+ // questions are back on the list (and `shippedVersion:` keeps saying v<N> shipped). A doc with
233
+ // nothing deferred stays `implemented` until someone runs `em slice revise`. Only on the real
234
+ // flip (`changed`), never on the idempotent re-run or the missing-link repair of an already
235
+ // implemented doc — those recorded their shipment before.
236
+ // GH #236: a question queued by `em slice defer` while the doc was ratified counts the same —
237
+ // it is injected into the draft, and the queue is cleared once the draft is on disk.
238
+ const next = nextDraftIfDeferred(result.content, (v) => readQueue(baseDir, sliceKey, v).items);
239
+ writeFileSync(absPath, next.content, "utf8");
240
+ if (next.openedDraft && next.openedDraft.injected > 0)
241
+ clearQueue(baseDir, sliceKey, next.openedDraft.version);
242
+ return { ok: true, path: doc.path, changed: true, openedDraft: next.openedDraft };
243
+ }
244
+ /** Pure: when `content` (a freshly implemented doc) has a question deferred to v<version+1>,
245
+ * returns it with the next draft opened (`openNextDraft`); else returns it unchanged. One call:
246
+ * `openNextDraft` is pure and reports how many questions it re-opened, so "was anything
247
+ * deferred to v<N+1>" is read off its result rather than decided by a second scan that would
248
+ * have to agree with it on what the deferral marker looks like. */
249
+ export function nextDraftIfDeferred(content, queuedFor) {
250
+ const opened = openNextDraft(content, { queuedFor });
251
+ if (!opened.ok || opened.reopened + opened.injected === 0)
252
+ return { content, openedDraft: null };
253
+ return { content: opened.content, openedDraft: { version: opened.newVersion, reopened: opened.reopened, injected: opened.injected } };
170
254
  }
171
255
  //# sourceMappingURL=markImplemented.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"markImplemented.js","sourceRoot":"","sources":["../../src/cli/markImplemented.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,+FAA+F;AAC/F,iGAAiG;AACjG,+FAA+F;AAC/F,gGAAgG;AAChG,+EAA+E;AAC/E,8FAA8F;AAC9F,oFAAoF;AACpF,EAAE;AACF,8FAA8F;AAC9F,iGAAiG;AACjG,6FAA6F;AAC7F,8FAA8F;AAC9F,gGAAgG;AAChG,+FAA+F;AAC/F,4FAA4F;AAC5F,4FAA4F;AAC5F,iGAAiG;AACjG,6FAA6F;AAC7F,8EAA8E;AAC9E,EAAE;AACF,uFAAuF;AACvF,4FAA4F;AAC5F,+FAA+F;AAC/F,oFAAoF;AACpF,EAAE;AACF,+FAA+F;AAC/F,kGAAkG;AAClG,gGAAgG;AAChG,sDAAsD;AAEtD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAMtG,+FAA+F;AAC/F,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAC7C,MAAM,kBAAkB,GAAG,aAAa,CAAC;AAEzC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,2BAA2B,CAAC,GAAW,EAAE,KAAa;IACpE,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;IACvE,0FAA0F;IAC1F,0FAA0F;IAC1F,sFAAsF;IACtF,IAAI,qBAAqB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,0DAA0D,EAAE,CAAC;IAC5F,CAAC;IAED,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC;IACxE,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE1D,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzD,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,yCAAyC,EAAE,CAAC;IAE3F,MAAM,SAAS,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,aAAa,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,IAAI,CAAC;IACjF,MAAM,oBAAoB,GAAG,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAElF,IAAI,aAAa,KAAK,kBAAkB,IAAI,oBAAoB,KAAK,IAAI,EAAE,CAAC;QAC1E,IAAI,oBAAoB,KAAK,UAAU,EAAE,CAAC;YACxC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,mBAAmB;QACxE,CAAC;QACD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EACL,8DAA8D,oBAAoB,IAAI;gBACtF,cAAc,UAAU,2BAA2B;SACtD,CAAC;IACJ,CAAC;IAED,IAAI,aAAa,KAAK,eAAe,IAAI,aAAa,KAAK,kBAAkB,EAAE,CAAC;QAC9E,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EACL,oBAAoB,aAAa,IAAI,SAAS,0CAA0C;gBACxF,eAAe,eAAe,iEAAiE;SAClG,CAAC;IACJ,CAAC;IAED,8FAA8F;IAC9F,6FAA6F;IAC7F,+FAA+F;IAC/F,2FAA2F;IAC3F,wCAAwC;IACxC,IAAI,YAAoB,CAAC;IACzB,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,KAAK,GAAG;YACZ,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,aAAa,EAAE;YACjG,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,UAAU,EAAE,EAAE;SAC9F,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QACpC,YAAY,GAAG,KAAK,CAAC;QACrB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9G,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,eAAe,GAAG,WAAW,CAAC,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAClE,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC1C,mFAAmF;QACnF,6FAA6F;QAC7F,4FAA4F;QAC5F,kDAAkD;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;QACpD,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,GAAG,WAAW,CAAC,CAAC,CAAC,aAAa,GAAG,GAAG,GAAG,kBAAkB,UAAU,EAAE,GAAG,IAAI,CAAC;IAClI,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC1F,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC9C,CAAC;AAMD;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAsB,EACtB,IAAgB,EAChB,OAAe,EACf,QAAgB,EAChB,KAAa;IAEb,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpD,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,6BAA6B,QAAQ,iBAAiB,EAAE,CAAC;IACxF,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,iBAAiB,EAAE,GAAG,mBAAmB,CACpE,KAAK,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,OAAO,EACP,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAE,CAC9B,CAAC;IAEF,wFAAwF;IACxF,IAAI,iBAAiB,EAAE,CAAC;QACtB,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAE,CAAC;QAC9D,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,aAAa,CAAE,CAAC,IAAI,CAAC;QAClE,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EACL,IAAI,QAAQ,2BAA2B,iBAAiB,YAAY,QAAQ,aAAa;gBACzF,+CAA+C,iBAAiB,WAAW;SAC9E,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QAClC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,UAAU,QAAQ,yCAAyC,QAAQ,yDAAyD;SACtI,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,sBAAsB,EAAE,CAAC;QAC1C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,QAAQ,YAAY,GAAG,CAAC,IAAI,2BAA2B,EAAE,CAAC;IACnG,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,qBAAqB,EAAE,CAAC;QACzC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,cAAc,GAAG,CAAC,IAAI,wEAAwE;SACxG,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,2BAA2B,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;IAClE,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;AAC/D,CAAC"}
1
+ {"version":3,"file":"markImplemented.js","sourceRoot":"","sources":["../../src/cli/markImplemented.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { NormalizedModel } from "../model/model.js";
2
2
  import { RefsResult } from "../model/refs.js";
3
+ import { GitRunner } from "./diff-inputs.js";
3
4
  /** MIL-238: the ratifier's API-first statement about this version of a public-touching slice. */
4
5
  export type MeaningConfirmation = {
5
6
  kind: "meaning-unchanged";
@@ -29,9 +30,10 @@ export declare function stripMeaningConfirmation(inner: string): string;
29
30
  * (docs/process.md#the-slice-lifecycle-gates): contracts/invariants agreed, open questions
30
31
  * resolved or deferred, ready for an implementing agent or engineer to pick up. */
31
32
  export declare const RATIFIED_STATUS = "ready-to-implement";
32
- /** One upstream producing slice (in timeline order earlier than the slice being ratified) whose
33
- * doc hasn't reached `ready-to-implement`/`implemented` yet. `status` is the doc's own status
34
- * string, or the literal `"no doc"` when no doc is bound/found for that slice at all. */
33
+ /** One upstream producing slice (in timeline order earlier than the slice being ratified) that
34
+ * is neither shipped (its shipped record, MIL-283) nor ratified (`ready-to-implement`). `status`
35
+ * is the doc's own status string, or the literal `"no doc"` when no doc is bound/found for that
36
+ * slice at all. */
35
37
  export interface UpstreamUnratifiedSlice {
36
38
  sliceKey: string;
37
39
  status: string;
@@ -40,7 +42,7 @@ export interface UpstreamUnratifiedSlice {
40
42
  * MIL-198 (ruling R5): for every element in the `sliceKey` slice, walks the query index's `in`
41
43
  * adjacency one hop to find producing elements that live in OTHER slices (a producer in the SAME
42
44
  * slice isn't a cross-slice dependency), dedupes by upstream slice, and reports every upstream
43
- * slice whose doc status isn't `ready-to-implement`/`implemented` — sorted by the upstream
45
+ * slice that is neither shipped nor `ready-to-implement` — sorted by the upstream
44
46
  * slice's position on the timeline (`Slice.index`), so the advisory itself reads in the order the
45
47
  * team should catch up in. Advisory data only: never refuses, callers decide whether/how to print
46
48
  * it. An unknown `sliceKey` (shouldn't happen — the caller already resolved it) yields `[]`
@@ -76,7 +78,35 @@ export type ApplyRatifyResult = {
76
78
  * that refusal message (and in the caller's skip notice); every other refusal here is about the
77
79
  * doc's own text. No fs access — the caller reads/writes; see `runRatify` below.
78
80
  */
79
- export declare function applyRatifyFrontmatter(raw: string, sliceKey: string, ratifiedBy: string, ratifiedOn: string, skipReview?: boolean, confirmation?: MeaningConfirmation | null): ApplyRatifyResult;
81
+ /**
82
+ * MIL-284: what `em slice ratify` records as the ratified content's address — `ratifiedRef:` (the
83
+ * commit whose tree holds the body being signed; null outside a git repository) and
84
+ * `ratifiedHash:` (`sha256:` over the body, always). `runRatify` resolves it via
85
+ * `resolveRatifiedIdentity`; the pure transform just writes whatever it is handed, so tests and
86
+ * non-git callers can pass their own.
87
+ */
88
+ export interface RatifiedIdentity {
89
+ ref: string | null;
90
+ hash: string;
91
+ }
92
+ export type RatifiedIdentityResult = {
93
+ ok: true;
94
+ identity: RatifiedIdentity;
95
+ } | {
96
+ ok: false;
97
+ message: string;
98
+ };
99
+ /**
100
+ * MIL-284: computes the identity `applyRatifyFrontmatter` records. The hash needs no git. The
101
+ * ref does, and ratifying a doc with uncommitted changes would record a ref whose tree does not
102
+ * hold the body being signed — so inside a repository that is a refusal, not a warning. Outside
103
+ * one (`git` null, or the model dir is not in a work tree) the ref is simply absent: the hash
104
+ * still gives the ratified body an identity, and `--slice-ready` still checks it. Every git call
105
+ * runs `-C baseDir` — the model's directory, never the process cwd — so a model nested in a
106
+ * larger repository, or run from elsewhere, resolves against the right work tree.
107
+ */
108
+ export declare function resolveRatifiedIdentity(git: GitRunner | null, baseDir: string, docPath: string, raw: string): RatifiedIdentityResult;
109
+ export declare function applyRatifyFrontmatter(raw: string, sliceKey: string, ratifiedBy: string, ratifiedOn: string, skipReview?: boolean, confirmation?: MeaningConfirmation | null, identity?: RatifiedIdentity | null): ApplyRatifyResult;
80
110
  export type RunRatifyResult = {
81
111
  ok: true;
82
112
  path: string;
@@ -95,4 +125,4 @@ export type RunRatifyResult = {
95
125
  * `--slice-ready`/`em export` use (MIL-121 cross-binding included), then reads/applies/writes
96
126
  * it. `baseDir` is the `.em` file's directory, same convention every doc/note path in `em` uses.
97
127
  */
98
- export declare function runRatify(model: NormalizedModel, refs: RefsResult, baseDir: string, sliceKey: string, ratifiedBy: string, ratifiedOn: string, skipReview?: boolean, confirmation?: MeaningConfirmation | null): RunRatifyResult;
128
+ export declare function runRatify(model: NormalizedModel, refs: RefsResult, baseDir: string, sliceKey: string, ratifiedBy: string, ratifiedOn: string, skipReview?: boolean, confirmation?: MeaningConfirmation | null, git?: GitRunner | null): RunRatifyResult;