@milehimikey/em 1.14.2 → 1.15.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 (97) hide show
  1. package/.claude/skills/event-modeling/SKILL.md +3 -3
  2. package/.claude/skills/event-modeling-conform/SKILL.md +1 -1
  3. package/.claude/skills/event-modeling-design/SKILL.md +29 -18
  4. package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
  5. package/.claude/skills/event-modeling-engagement/SKILL.md +54 -54
  6. package/.claude/skills/event-modeling-engagement/reference/engagement.md +5 -19
  7. package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
  8. package/.claude/skills/event-modeling-implement/reference/implement.md +26 -23
  9. package/.claude/skills/event-modeling-review/SKILL.md +13 -3
  10. package/.claude/skills/event-modeling-shared/reference/em-dsl.md +230 -227
  11. package/.claude/skills/event-modeling-shared/reference/operating-principles.md +3 -3
  12. package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +58 -27
  13. package/.claude/skills/event-modeling-shared/templates/constitution.md +5 -7
  14. package/.claude-plugin/marketplace.json +2 -2
  15. package/dist/catalog/docJoin.d.ts +17 -1
  16. package/dist/catalog/docJoin.js +7 -1
  17. package/dist/catalog/docJoin.js.map +1 -1
  18. package/dist/catalog/driftSignal.d.ts +16 -12
  19. package/dist/catalog/driftSignal.js +14 -9
  20. package/dist/catalog/driftSignal.js.map +1 -1
  21. package/dist/catalog/sliceDoc.d.ts +51 -0
  22. package/dist/catalog/sliceDoc.js +47 -0
  23. package/dist/catalog/sliceDoc.js.map +1 -1
  24. package/dist/catalog/sliceReadyValidate.js +12 -0
  25. package/dist/catalog/sliceReadyValidate.js.map +1 -1
  26. package/dist/cli/conformScope.d.ts +4 -0
  27. package/dist/cli/conformScope.js +2 -2
  28. package/dist/cli/conformScope.js.map +1 -1
  29. package/dist/cli/coverage.js +7 -3
  30. package/dist/cli/coverage.js.map +1 -1
  31. package/dist/cli/defer.d.ts +61 -2
  32. package/dist/cli/defer.js +204 -23
  33. package/dist/cli/defer.js.map +1 -1
  34. package/dist/cli/engagement.d.ts +13 -5
  35. package/dist/cli/engagement.js +26 -19
  36. package/dist/cli/engagement.js.map +1 -1
  37. package/dist/cli/findings.d.ts +2 -2
  38. package/dist/cli/findings.js +2 -2
  39. package/dist/cli/frontmatterSurgery.d.ts +3 -3
  40. package/dist/cli/frontmatterSurgery.js +3 -3
  41. package/dist/cli/frontmatterSurgery.js.map +1 -1
  42. package/dist/cli/markImplemented.d.ts +20 -18
  43. package/dist/cli/markImplemented.js +94 -15
  44. package/dist/cli/markImplemented.js.map +1 -1
  45. package/dist/cli/ratify.d.ts +36 -6
  46. package/dist/cli/ratify.js +130 -35
  47. package/dist/cli/ratify.js.map +1 -1
  48. package/dist/cli/review.js +3 -3
  49. package/dist/cli/review.js.map +1 -1
  50. package/dist/cli/revise.d.ts +57 -0
  51. package/dist/cli/revise.js +207 -0
  52. package/dist/cli/revise.js.map +1 -0
  53. package/dist/cli/sliceConform.d.ts +4 -3
  54. package/dist/cli/sliceConform.js +29 -12
  55. package/dist/cli/sliceConform.js.map +1 -1
  56. package/dist/cli/status.d.ts +8 -0
  57. package/dist/cli/status.js +7 -4
  58. package/dist/cli/status.js.map +1 -1
  59. package/dist/cli/upgrade.js +7 -4
  60. package/dist/cli/upgrade.js.map +1 -1
  61. package/dist/cli.js +117 -77
  62. package/dist/cli.js.map +1 -1
  63. package/dist/emit/json.d.ts +1 -1
  64. package/dist/emit/json.js +13 -1
  65. package/dist/emit/json.js.map +1 -1
  66. package/dist/emit/statusJson.d.ts +1 -1
  67. package/dist/emit/statusJson.js +4 -1
  68. package/dist/emit/statusJson.js.map +1 -1
  69. package/dist/mcp/server.js +5 -5
  70. package/dist/mcp/server.js.map +1 -1
  71. package/dist/model/rules.d.ts +8 -0
  72. package/dist/model/rules.js +8 -0
  73. package/dist/model/rules.js.map +1 -1
  74. package/dist/model/sliceDocIndex.d.ts +3 -0
  75. package/dist/model/sliceDocIndex.js +5 -4
  76. package/dist/model/sliceDocIndex.js.map +1 -1
  77. package/dist/templates.d.ts +1 -1
  78. package/dist/templates.js +5 -7
  79. package/dist/templates.js.map +1 -1
  80. package/package.json +1 -1
  81. package/plugin/.claude-plugin/plugin.json +2 -2
  82. package/plugin/shared/reference/em-dsl.md +230 -227
  83. package/plugin/shared/reference/operating-principles.md +3 -3
  84. package/plugin/shared/reference/slice-doc-schema.md +58 -27
  85. package/plugin/shared/templates/constitution.md +5 -7
  86. package/plugin/skills/conform/SKILL.md +1 -1
  87. package/plugin/skills/design/SKILL.md +29 -18
  88. package/plugin/skills/discover/SKILL.md +1 -1
  89. package/plugin/skills/engagement/SKILL.md +54 -54
  90. package/plugin/skills/engagement/reference/engagement.md +5 -19
  91. package/plugin/skills/event-modeling/SKILL.md +3 -3
  92. package/plugin/skills/implement/SKILL.md +1 -1
  93. package/plugin/skills/implement/reference/implement.md +26 -23
  94. package/plugin/skills/review/SKILL.md +13 -3
  95. package/dist/cli/reratify.d.ts +0 -58
  96. package/dist/cli/reratify.js +0 -238
  97. package/dist/cli/reratify.js.map +0 -1
@@ -119,12 +119,12 @@ including sessions started from bare `/event-modeling`.
119
119
  - **Version rule: never bump a draft's `version:` on edit.** A `draft`/`reviewed` doc is edited
120
120
  in place. Check the release state with `em status <model>.em --json`: the model is
121
121
  **pre-release** when its `modelVersion` entry has `design: null` and
122
- `slices.byStatus.implemented === 0`. Pre-release: never run `em slice reratify`; edit
122
+ `slices.byStatus.shipped === 0`. Pre-release: never run `em slice revise`; edit
123
123
  `draft`/`reviewed` docs in place and leave `version:` as it is. A pre-release doc that is
124
124
  already ratified (`ready-to-implement` with `ratifiedBy`) carries a human sign-off: STOP,
125
125
  record the needed change as an open question, and let the ratifier decide. Released (either
126
- condition false): changing an `implemented` or ratified doc goes through `em slice reratify`
127
- (see `event-modeling-design`).
126
+ condition false): changing a shipped or ratified doc goes through `em slice revise`, which
127
+ opens the next version as a `draft` (see `event-modeling-design`).
128
128
  - **Pre-commit check (STOP on any finding).** Stage the session's files, then run both:
129
129
  1. `em system scope --staged` from the repository root. Any `seam-crossing` error → STOP:
130
130
  unstage the other model's files and record a seam change request instead.
@@ -67,8 +67,13 @@ to decide `frontmatter-invalid` without re-deriving frontmatter-shape rules of i
67
67
  | `reviewedOn` | string | `YYYY-MM-DD` | written only by `em slice review` (MIL-201); joined into `em export`'s `slice.doc.reviewedOn` (schema `1.11`) |
68
68
  | `ratifiedBy` | string | free text (typically a person's name) | written only by `em slice ratify` (MIL-165 — see [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-slice-ratify-file-slice-key---by-name)); joined into `em export`'s `slice.doc.ratifiedBy` (schema `1.8`) and `em slice index`'s Ratified by column |
69
69
  | `ratifiedOn` | string | `YYYY-MM-DD` | written only by `em slice ratify` (MIL-165); joined into `em export`'s `slice.doc.ratifiedOn` (schema `1.8`) |
70
- | `meaningConfirmed` | boolean | `true` | written only by `em slice ratify`/`reratify --meaning-unchanged` (MIL-238 — see [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-slice-ratify-file-slice-key---by-name)): the API-first sign-off on a public-touching slice — this version does not change what the public contract means. Joined into `em export`'s `slice.doc.meaningConfirmed` (schema `1.15`; `false` when absent) |
71
- | `contractChange` | string | quoted free text (`contractChange: "<why>"`) | written only by `em slice ratify`/`reratify --contract-change "<why>"` (MIL-238): the API-first sign-off on a public-touching slice — why a consumer must read this change differently. Joined into `em export`'s `slice.doc.contractChange` (schema `1.15`, quotes stripped; `null` when absent) |
70
+ | `ratifiedRef` | string | full commit sha | written only by `em slice ratify` (MIL-284 — see [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-slice-ratify-file-slice-key---by-name)) when the model directory is inside a git repository: `HEAD` at ratification, the commit whose tree holds the body that was signed (ratify refuses a doc with uncommitted changes so this holds). Absent when ratified before 1.15 or outside git. Cleared by `em slice reratify`. Joined into `em export`'s `slice.doc.ratifiedRef` (schema `1.16`). Not a target-repo revision: `em slice conform --at` still names that itself |
71
+ | `ratifiedHash` | string | `sha256:<64 hex>` | written only by `em slice ratify` (MIL-284): `sha256` over the doc body (everything after the frontmatter fence, EOLs normalised) — the signed content's identity without git. Cleared by `em slice reratify`. Read by `em validate --slice-ready` (`slice-ready-body-changed-since-ratification`); joined into `em export`'s `slice.doc.ratifiedHash` (schema `1.16`) |
72
+ | `shippedVersion` | integer | positive integer | written only by `em slice mark-implemented` (MIL-284): the doc's `version:` when the merge was recorded. With `shippedRef`/`shippedOn`/`implementedIn`, joined into `em export`'s `slice.doc.shipped` (schema `1.16`). Additive in 1.15 — `status`/`implementedIn` still carry the lifecycle for every reader |
73
+ | `shippedRef` | string | full commit sha | written only by `em slice mark-implemented` (MIL-284): the doc's `ratifiedRef` at merge time, i.e. the ref the shipped version was signed at; absent when the doc had none |
74
+ | `shippedOn` | string | `YYYY-MM-DD` | written only by `em slice mark-implemented` (MIL-284): the local date of the merge record, or `--on <date>` |
75
+ | `meaningConfirmed` | boolean | `true` | written only by `em slice ratify --meaning-unchanged` (MIL-238 — see [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-slice-ratify-file-slice-key---by-name)): the API-first sign-off on a public-touching slice — this version does not change what the public contract means. Joined into `em export`'s `slice.doc.meaningConfirmed` (schema `1.15`; `false` when absent) |
76
+ | `contractChange` | string | quoted free text (`contractChange: "<why>"`) | written only by `em slice ratify --contract-change "<why>"` (MIL-238): the API-first sign-off on a public-touching slice — why a consumer must read this change differently. Joined into `em export`'s `slice.doc.contractChange` (schema `1.15`, quotes stripped; `null` when absent) |
72
77
  | `owner` | string | free text (typically a person or team name) | hand-filled — no `em` command writes it; joined into `em export`'s `slice.doc.owner` (schema `1.9`, MIL-171), `em slice index`'s Owner column, and `em status`'s per-slice `owners[]` |
73
78
  | `tracking` | string | free text (typically an external ticket/issue URL) | hand-filled — no `em` command writes it; joined into `em export`'s `slice.doc.tracking` (schema `1.9`, MIL-171) and `em slice index`'s Tracking column. This is the exact field `em-tracker-bridge` reads to find the ticket mirroring this slice — `em` only stores and displays it, it never talks to a tracker itself |
74
79
  | `conformedVersion` | integer | positive integer | written only by `em slice conform` (MIL-214 — see [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-slice-conform-file-slice-key---at-rev)): this slice's `version:` at the time a conform sweep last certified it. Joined into `em export`'s `slice.doc.conformedVersion` (schema `1.13`); paired with `version` to compute `slice.doc.driftSignal`'s `"uncertified"` case |
@@ -245,7 +250,7 @@ straight through to the originating slice's own doc, exactly the way a ratified
245
250
  binding resolves a covered slice — same `doc.found`/`status`/`driftSignal`, plus a
246
251
  `continuationOf: <originating-key>` field naming why. `em export`, `em status`, `em coverage`,
247
252
  `em slice index`, `em catalog`, and the render pipeline's Slice Status legend all resolve a
248
- continuation slice this way; `em slice ratify`/`review`/`reratify`/`mark-implemented` and
253
+ continuation slice this way; `em slice ratify`/`review`/`revise`/`mark-implemented` and
249
254
  `em slice new --wire` refuse on one outright, naming the originating slice to act on instead —
250
255
  a continuation slice has no status/ratification of its own to flip.
251
256
 
@@ -482,7 +487,7 @@ prior one — exactly the ambiguity a live, current-version-only section avoids.
482
487
  **Deferral marker (MIL-275).** A question this version will not answer is not left `- [ ]` and
483
488
  not deleted: `em slice defer` checks it and rewrites it as `- [x] <original> — v<current>:
484
489
  <decision>; deferred to v<n> (<date>[, <by>])`. The `deferred to v<n>` marker is what
485
- `em slice reratify` reads: when a bump reaches v<n> it rewrites each such item back to
490
+ `em slice revise` (and `mark-implemented`, which opens v<n> at merge when something is deferred to it) reads: when the doc reaches v<n> it rewrites each such item back to
486
491
  `- [ ] <original>`, so the question must be resolved or re-deferred before `--slice-ready` passes
487
492
  again. The prune rule above does not apply to a deferred item before v<n> (it stays as the
488
493
  record); once reopened it is an ordinary open question.
@@ -497,26 +502,51 @@ actually happened on re-ratification).
497
502
 
498
503
  ## `status` under re-ratification
499
504
 
500
- When a new version is ratified for a slice whose previous version already shipped, `status`
501
- tracks the **current version's** implementation state, not a running "has this ever shipped"
502
- flag. Ratifying v2 on an `implemented` slice flips `status` back to `ready-to-implement`, while
503
- `implementedIn` keeps naming the v1 PR until v2 ships. That deliberate mismatch — version 2,
504
- implemented-link still pointing at v1's work — is not staleness, it's the **drift signal**: a
505
- reader, `em export`'s `slice.doc.driftSignal` (`"unpropagated-delta"`, schema `1.5`, MIL-85), and
506
- the event-modeling skill's `conform` phase all read it the same way — a ratified delta hasn't
507
- shipped yet, not a fresh finding against the still-live v1 code. `em validate`'s
508
- frontmatter-coherence check (MIL-85) deliberately never flags this combination — only
509
- `status: implemented` with no `implementedIn` link at all is checkable incoherence; see
505
+ Since 1.15.0 (MIL-283) two separate facts live in the frontmatter, and every reader knows which
506
+ one it is asking about:
507
+
508
+ - **`status` is the working state** of the doc's current `version:` — `draft`, `reviewed`,
509
+ `ready-to-implement`, `implemented`.
510
+ - **The shipped record is what is in production**: `shippedVersion:`/`shippedRef:`/`shippedOn:`
511
+ (written by `em slice mark-implemented`, MIL-284) together with `implementedIn:`. For a doc
512
+ shipped before 1.15 — no `shippedVersion:` — the read-both rule applies: `status: implemented`
513
+ means "shipped at the current `version:`". The one function that answers "has a version of this
514
+ slice shipped, and which" is `shippedRecordOf()` (`src/catalog/sliceDoc.ts`); `em export`
515
+ publishes its answer as `slice.doc.shipped`.
516
+
517
+ So a shipped slice can be a `draft` again. `em slice revise <key>`
518
+ ([cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-slice-revise-file-slice-key)) opens v<N+1> as `status: draft`, bumps
519
+ `version:`, clears the prior version's review and sign-off, and leaves `implementedIn`/`shipped*`
520
+ alone — v<N> stays shipped. `em slice mark-implemented` does the same automatically at merge when a
521
+ question was deferred to v<N+1> (`em slice defer`), so known work is on the list the moment the
522
+ previous version lands. Version 2 then takes both human gates like version 1 did: `em slice review
523
+ --by`, then `em slice ratify --by` (which records a fresh `ratifiedRef`/`ratifiedHash`).
524
+
525
+ The deliberate mismatch — `version: 2` open while `implementedIn`/`shippedVersion` still name v1's
526
+ work — is not staleness, it's the **drift signal**: `em export`'s `slice.doc.driftSignal` is
527
+ `"unpropagated-delta"` whenever `version` is past the shipped version (MIL-85/283), and the
528
+ event-modeling skill's `conform` phase reads it as "a delta hasn't shipped yet", not a fresh finding
529
+ against the still-live v1 code. `em validate`'s frontmatter-coherence check (MIL-85) never flags it;
530
+ only a shipped slice with no `implementedIn` link at all is checkable incoherence
531
+ (`implemented-without-link`); see
510
532
  [validation.md#frontmatter-coherence](https://github.com/milehimikey/em/blob/main/docs/validation.md#frontmatter-coherence).
511
533
 
512
- **An unshipped version has nothing to flip back** (MIL-258). A ratified doc that has not shipped
513
- yet (`status: ready-to-implement` with `ratifiedBy:` set) changes the same way: `em slice
514
- reratify` bumps `version:` and clears `ratifiedBy`/`ratifiedOn`/`reviewedBy`/`reviewedOn` (and `meaningConfirmed`/`contractChange`, MIL-238), but
515
- leaves `status` at `ready-to-implement` (and any `implementedIn` as it was — an absent one stays
516
- absent). This is the path for an answered gap mid-build. In both cases the new version is not
517
- ratified until `em slice ratify --by <name>` records the sign-off. A `ready-to-implement` doc with
518
- no `ratifiedBy` is awaiting that sign-off, so a second `reratify` refuses rather than
519
- double-bump; `draft`/`reviewed` docs are not ratified and are simply edited.
534
+ **Which readers decide on the shipped record, not `status`** (MIL-283): `em status`'s
535
+ `byStatus.shipped` count and its conformance scope, `em coverage --strict`'s default scope, `em
536
+ conform-scope` / `em conform-supersede`'s in-scope slices, `em slice conform` (legal when shipped;
537
+ `conformedVersion:` is the **shipped** version), the engagement Ledger's inferred `merged` and its
538
+ outside-upstream hold, `em upgrade`'s pre-release signal, `em slice ratify`'s upstream advisory, and
539
+ `driftSignal`. `byStatus.implemented`, the render/legend colouring and `--slice-ready` still read the
540
+ working `status` — that is what they are about.
541
+
542
+ **A ratified version that never shipped** (`status: ready-to-implement` with `ratifiedBy:` set — a
543
+ gap answered mid-build) is revised the same way: `draft`, `version + 1`, sign-off cleared; the
544
+ ratification of v<N> is withdrawn and nothing shipped, so no shipped record is written. **A
545
+ `ready-to-implement` doc with no `ratifiedBy`** is the leftover of a pre-1.15 `reratify` (which
546
+ bumped the version and left the doc unsigned at that status); no command produces it any more and
547
+ `em slice ratify` no longer accepts it — `em slice revise` reopens it as a `draft` at the same
548
+ version, and the normal road follows. `draft`/`reviewed` docs are not ratified and are simply
549
+ edited; `revise` refuses them ("the next version is already open").
520
550
 
521
551
  Pair a re-ratification with a `## Delta` section (see
522
552
  [Delta section: grammar and lifecycle](#delta-section-grammar-and-lifecycle) above) recording
@@ -526,10 +556,11 @@ the ratified change in typed operation blocks, so it's reviewable without openin
526
556
  see [cli.md#em-ledger-file](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-ledger-file)) checks that `version:` and a slice doc's
527
557
  content (body + lineage refs) always change together across two git revisions — a version bump
528
558
  with no real content change, or a content change with no version bump, is a ledger bug.
529
- It **deliberately excludes `status`/`implementedIn`** from what counts as "content" for exactly
530
- the reason this section explains: a re-ratification legitimately flips `status` and leaves
531
- `implementedIn` naming prior work, with no version bump of its own — including either field in
532
- the comparison would flag every ordinary lifecycle transition as a false positive.
559
+ It **deliberately excludes `status`/`implementedIn`** (and the `shipped*` keys) from what counts
560
+ as "content" for exactly the reason this section explains: a lifecycle transition legitimately
561
+ moves `status` and leaves `implementedIn`/`shippedVersion` naming prior work, with no version bump
562
+ of its own — including those fields in the comparison would flag every ordinary lifecycle
563
+ transition as a false positive.
533
564
 
534
565
  ## Unknown keys
535
566
 
@@ -563,7 +594,7 @@ legacy form; they're frontmatter-only from the day they were introduced.
563
594
  - [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-render-file) — slice status colors
564
595
  - [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-catalog-files) — pattern / doc lookup
565
596
  - [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-slice-ratify-file-slice-key---by-name) — `em slice ratify`, the mechanized ratification act (`ratifiedBy`/`ratifiedOn`, schema `1.8`, MIL-165)
566
- - [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-slice-reratify-file-slice-key) — `em slice reratify`, the mechanized re-ratification version bump/status flip (MIL-161)
597
+ - [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-slice-revise-file-slice-key) — `em slice revise`, which opens the next version as a draft (the successor of `reratify`)
567
598
  - [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-export-file) — the `em export` join (`slice.pattern`/`slice.doc`, schema `1.4`, MIL-91), including `owner`/`tracking` (schema `1.9`, MIL-171)
568
599
  - [cli.md](https://github.com/milehimikey/em/blob/main/docs/cli.md#em-diff-old-new) — the `em diff` lineage annotation (schema `1.6`, MIL-84)
569
600
  - [validation.md#lineage](https://github.com/milehimikey/em/blob/main/docs/validation.md#lineage) — `em validate`'s lineage-ref resolution (MIL-84)
@@ -23,9 +23,9 @@ NAMED human and an ISO date, hand-filled at sign-off (no `em` command writes thi
23
23
  unratified, says so, and does not proceed on unilateral style or stack decisions for a first slice.
24
24
 
25
25
  `em status` reports this document as present or absent per model — existence only. em never reads
26
- or validates its content, and the CLI parses nothing here. Three lines are read as plain text by
26
+ or validates its content, and the CLI parses nothing here. Two lines are read as plain text by
27
27
  the engagement skill and its sub-agents, so keep their exact shape: `- **Test command:**` (the
28
- validator), `- **Merge strategy:**` and `- **Agent models:**` (the engagement skill). In a spec-kit
28
+ validator) and `- **Agent models:**` (the engagement skill). In a spec-kit
29
29
  project they merge under the same headings in `.specify/memory/constitution.md`.
30
30
  -->
31
31
 
@@ -120,11 +120,9 @@ it is silent, these apply.
120
120
  amend** — a `covers:` doc ships as one PR for both keys; a read model is one doc, so a later
121
121
  `again` instance is a continuation of the doc that first declared it, not a PR of its own. See
122
122
  the agent guide's §5/§10.
123
- - **Merge strategy:** merge-commits-when-stacked
124
- {{**How do PRs merge, and what happens when one PR depends on another?** Merge commits whenever
125
- a dependent PR is open; squash only a PR with no open dependent (implement contract §8 rule 2a).
126
- Keep this exact line: it is the only value the engagement skill accepts, and it refuses to run
127
- without it.}}
123
+ - **Merge strategy:** {{squash | merge commit | rebase — the project's own choice. Every slice PR
124
+ is cut from and targets `main` (implement contract §8 rule 2), so no PR ever depends on
125
+ another and any strategy works; em reads nothing from this line.}}
128
126
  - **Agent models:** implementer=sonnet, validator=sonnet, reviewer=sonnet, critic=opus
129
127
  {{**Which model runs each em sub-agent?** Keep this exact line shape, with the defaults shown or
130
128
  your own choices. The critic must run on a different model from the implementer; `critic=codex`
@@ -1,9 +1,9 @@
1
1
  {
2
- "name": "em-1-14-2",
2
+ "name": "em-1-15-0",
3
3
  "owner": {
4
4
  "name": "Mike Key"
5
5
  },
6
- "description": "em v1.14.2: the Event Modeling skill bundle and MCP server as a Claude Code plugin.",
6
+ "description": "em v1.15.0: the Event Modeling skill bundle and MCP server as a Claude Code plugin.",
7
7
  "plugins": [
8
8
  {
9
9
  "name": "em",
@@ -3,7 +3,8 @@ import { NormalizedModel, Slice } from "../model/model.js";
3
3
  import { RefsResult } from "../model/refs.js";
4
4
  import { Diagnostic } from "../model/validate.js";
5
5
  import { DriftSignalKind } from "./driftSignal.js";
6
- import { SliceDoc, SliceRef } from "./sliceDoc.js";
6
+ import { ShippedRecord, SliceDoc, SliceRef } from "./sliceDoc.js";
7
+ export type { ShippedRecord } from "./sliceDoc.js";
7
8
  export declare const NOTE_SLICE_PATH: RegExp;
8
9
  /** One cross-binding candidate's resolution against `sliceKey`'s ratification requirement:
9
10
  * the target file doesn't exist, exists but its frontmatter isn't usable, exists and is usable
@@ -66,6 +67,21 @@ export interface SliceDocExport {
66
67
  /** MIL-165: when this doc was ratified (frontmatter `ratifiedOn:`, `YYYY-MM-DD`), written only
67
68
  * by `em slice ratify` — null when absent, same as `ratifiedBy`. */
68
69
  ratifiedOn: string | null;
70
+ /** MIL-284: the commit (full sha) whose tree holds the ratified body (frontmatter
71
+ * `ratifiedRef:`), written only by `em slice ratify` inside a git repository — null when
72
+ * absent (ratified before em 1.15, by hand, or outside git). The ratified content's address. */
73
+ ratifiedRef: string | null;
74
+ /** MIL-284: `sha256:<hex>` over the doc body at ratification (frontmatter `ratifiedHash:`),
75
+ * written only by `em slice ratify` — null when absent. `--slice-ready` compares it to the
76
+ * current body (`slice-ready-body-changed-since-ratification`). */
77
+ ratifiedHash: string | null;
78
+ /** MIL-283/284: the shipped record — `em slice mark-implemented`'s `shippedVersion:`/
79
+ * `shippedRef:`/`shippedOn:` beside `implementedIn:`, or, for a doc shipped before em 1.15
80
+ * (no `shippedVersion:`), the `status: implemented` it carries (read-both rule,
81
+ * `shippedRecordOf`). Null when nothing has shipped. THIS — not `status` — is what every
82
+ * lifecycle reader decides on since 1.15.0: `status` is the working state, and a shipped slice
83
+ * can be `draft` again while its earlier version stays shipped. */
84
+ shipped: ShippedRecord | null;
69
85
  /** MIL-171: who (a person or team) holds this slice, from frontmatter `owner:` — hand-filled,
70
86
  * no `em` command writes it. Null when absent. */
71
87
  owner: string | null;
@@ -39,7 +39,7 @@ import { continuationOf } from "../model/continuation.js";
39
39
  import { makeDiag } from "../model/rules.js";
40
40
  import { classifyImplementationDrift } from "./driftSignal.js";
41
41
  import { readSliceDoc } from "./readSliceDoc.js";
42
- import { hasUsableFrontmatter } from "./sliceDoc.js";
42
+ import { hasUsableFrontmatter, shippedRecordOf } from "./sliceDoc.js";
43
43
  // Matches a `note "slices/<key>.md"` value's path shape, to pull `<key>` back out for the
44
44
  // MIL-121 cross-binding search below (and MIL-126's mismatch sweep, catalog/noteBindingValidate.ts)
45
45
  // — same kebab-slug grammar sliceDoc.ts's SLICE_REF uses.
@@ -72,6 +72,9 @@ const EMPTY_CONTENT = {
72
72
  reviewedOn: null,
73
73
  ratifiedBy: null,
74
74
  ratifiedOn: null,
75
+ ratifiedRef: null,
76
+ ratifiedHash: null,
77
+ shipped: null,
75
78
  owner: null,
76
79
  tracking: null,
77
80
  conformedVersion: null,
@@ -189,6 +192,9 @@ function foundDoc(path, parsed) {
189
192
  reviewedOn: parsed.reviewedOn,
190
193
  ratifiedBy: parsed.ratifiedBy,
191
194
  ratifiedOn: parsed.ratifiedOn,
195
+ ratifiedRef: parsed.ratifiedRef,
196
+ ratifiedHash: parsed.ratifiedHash,
197
+ shipped: shippedRecordOf(parsed),
192
198
  owner: parsed.owner,
193
199
  tracking: parsed.tracking,
194
200
  conformedVersion: parsed.conformedVersion,
@@ -1 +1 @@
1
- {"version":3,"file":"docJoin.js","sourceRoot":"","sources":["../../src/catalog/docJoin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"docJoin.js","sourceRoot":"","sources":["../../src/catalog/docJoin.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,26 @@
1
1
  import { SliceDoc } from "./sliceDoc.js";
2
2
  export type DriftSignalKind =
3
- /** status: implemented, implementedIn set, conformedVersion === version — certified current. */
3
+ /** shipped, implementedIn set, the doc's version IS the shipped version and conformedVersion
4
+ * matches it — certified current. */
4
5
  "in-sync"
5
- /** status not implemented, implementedIn absent — normal pre-ship state. */
6
+ /** nothing shipped, implementedIn absent — normal pre-ship state. */
6
7
  | "never-implemented"
7
- /** status not implemented, implementedIn still set — a ratified delta hasn't shipped yet.
8
- * Expected, not a defect: never surface this as fresh drift or a validate diagnostic. */
8
+ /** a ratified/drafted delta hasn't shipped yet: either the doc's `version:` is past the shipped
9
+ * version (MIL-283 — a later draft is open over a shipped version), or (pre-1.15 shape) status
10
+ * is off `implemented` while `implementedIn` still names the prior version's PR. Expected, not
11
+ * a defect: never surface this as fresh drift or a validate diagnostic. */
9
12
  | "unpropagated-delta"
10
- /** status: implemented, implementedIn absent — genuine incoherence (em validate warns). */
13
+ /** shipped, implementedIn absent — genuine incoherence (em validate warns). */
11
14
  | "implemented-without-link"
12
- /** status: implemented, implementedIn set, but conformedVersion is absent or doesn't match the
13
- * current version — nobody has certified THIS version yet. Expected post-ship default, not a
14
- * defect: never surface this as an `em validate` diagnostic (see
15
+ /** shipped, implementedIn set, the doc's version is the shipped version, but conformedVersion
16
+ * is absent or doesn't match — nobody has certified THIS version yet. Expected post-ship
17
+ * default, not a defect: never surface this as an `em validate` diagnostic (see
15
18
  * catalog/frontmatterCoherenceValidate.ts, which only ever flags implemented-without-link). */
16
19
  | "uncertified";
17
20
  /**
18
- * Classify a doc's status/implementedIn/version/conformedVersion quadruple. Takes a `Pick`
19
- * rather than the full `SliceDoc` so callers building a partial/synthetic doc (tests, future
20
- * callers) don't need every field.
21
+ * Classify a doc's drift from its shipped record (MIL-283: `shippedRecordOf`, which reads the
22
+ * `shipped*` keys and, for a doc written before 1.15, `status: implemented`), its `implementedIn`,
23
+ * its working `version` and `conformedVersion`. Takes a `Pick` rather than the full `SliceDoc`
24
+ * so callers building a partial/synthetic doc (tests, future callers) don't need every field.
21
25
  */
22
- export declare function classifyImplementationDrift(doc: Pick<SliceDoc, "status" | "implementedIn" | "version" | "conformedVersion">): DriftSignalKind;
26
+ export declare function classifyImplementationDrift(doc: Pick<SliceDoc, "status" | "implementedIn" | "version" | "conformedVersion" | "ratifiedRef" | "shippedVersion" | "shippedRef" | "shippedOn">): DriftSignalKind;
@@ -21,18 +21,23 @@
21
21
  // reratify`) invalidates the prior certification even though `status`/`implementedIn` still read
22
22
  // "shipped" — so this is not folded into `in-sync` and not flagged by `em validate` (same
23
23
  // "expected, not a defect" treatment `unpropagated-delta` gets).
24
+ import { shippedRecordOf } from "./sliceDoc.js";
24
25
  /**
25
- * Classify a doc's status/implementedIn/version/conformedVersion quadruple. Takes a `Pick`
26
- * rather than the full `SliceDoc` so callers building a partial/synthetic doc (tests, future
27
- * callers) don't need every field.
26
+ * Classify a doc's drift from its shipped record (MIL-283: `shippedRecordOf`, which reads the
27
+ * `shipped*` keys and, for a doc written before 1.15, `status: implemented`), its `implementedIn`,
28
+ * its working `version` and `conformedVersion`. Takes a `Pick` rather than the full `SliceDoc`
29
+ * so callers building a partial/synthetic doc (tests, future callers) don't need every field.
28
30
  */
29
31
  export function classifyImplementationDrift(doc) {
30
32
  const hasLink = typeof doc.implementedIn === "string" && doc.implementedIn.trim().length > 0;
31
- if (doc.status === "implemented") {
32
- if (!hasLink)
33
- return "implemented-without-link";
34
- return doc.conformedVersion !== null && doc.conformedVersion === doc.version ? "in-sync" : "uncertified";
35
- }
36
- return hasLink ? "unpropagated-delta" : "never-implemented";
33
+ const shipped = shippedRecordOf(doc);
34
+ if (shipped === null)
35
+ return hasLink ? "unpropagated-delta" : "never-implemented";
36
+ if (!hasLink)
37
+ return "implemented-without-link";
38
+ // A later version is open (draft/reviewed/ready-to-implement) over the shipped one.
39
+ if (shipped.version !== null && doc.version !== null && doc.version > shipped.version)
40
+ return "unpropagated-delta";
41
+ return doc.conformedVersion !== null && doc.conformedVersion === shipped.version ? "in-sync" : "uncertified";
37
42
  }
38
43
  //# sourceMappingURL=driftSignal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"driftSignal.js","sourceRoot":"","sources":["../../src/catalog/driftSignal.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,4FAA4F;AAC5F,uFAAuF;AACvF,2FAA2F;AAC3F,iGAAiG;AACjG,yFAAyF;AACzF,kCAAkC;AAClC,EAAE;AACF,6FAA6F;AAC7F,iGAAiG;AACjG,iGAAiG;AACjG,mGAAmG;AACnG,2FAA2F;AAC3F,EAAE;AACF,6FAA6F;AAC7F,gGAAgG;AAChG,mFAAmF;AACnF,8FAA8F;AAC9F,8FAA8F;AAC9F,wFAAwF;AACxF,iGAAiG;AACjG,0FAA0F;AAC1F,iEAAiE;AAoBjE;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CACzC,GAAgF;IAEhF,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,aAAa,KAAK,QAAQ,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7F,IAAI,GAAG,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;QACjC,IAAI,CAAC,OAAO;YAAE,OAAO,0BAA0B,CAAC;QAChD,OAAO,GAAG,CAAC,gBAAgB,KAAK,IAAI,IAAI,GAAG,CAAC,gBAAgB,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC;IAC3G,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,mBAAmB,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"driftSignal.js","sourceRoot":"","sources":["../../src/catalog/driftSignal.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,4FAA4F;AAC5F,uFAAuF;AACvF,2FAA2F;AAC3F,iGAAiG;AACjG,yFAAyF;AACzF,kCAAkC;AAClC,EAAE;AACF,6FAA6F;AAC7F,iGAAiG;AACjG,iGAAiG;AACjG,mGAAmG;AACnG,2FAA2F;AAC3F,EAAE;AACF,6FAA6F;AAC7F,gGAAgG;AAChG,mFAAmF;AACnF,8FAA8F;AAC9F,8FAA8F;AAC9F,wFAAwF;AACxF,iGAAiG;AACjG,0FAA0F;AAC1F,iEAAiE;AAEjE,OAAO,EAAE,eAAe,EAAY,MAAM,eAAe,CAAC;AAqB1D;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CACzC,GAGC;IAED,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,aAAa,KAAK,QAAQ,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7F,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,mBAAmB,CAAC;IAClF,IAAI,CAAC,OAAO;QAAE,OAAO,0BAA0B,CAAC;IAChD,oFAAoF;IACpF,IAAI,OAAO,CAAC,OAAO,KAAK,IAAI,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,IAAI,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO;QAAE,OAAO,oBAAoB,CAAC;IACnH,OAAO,GAAG,CAAC,gBAAgB,KAAK,IAAI,IAAI,GAAG,CAAC,gBAAgB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC;AAC/G,CAAC"}
@@ -82,6 +82,25 @@ export interface SliceDoc {
82
82
  * to find the ticket mirroring this slice — its export name/shape (docJoin.ts) is a
83
83
  * cross-tool contract, not just an internal display field. */
84
84
  tracking: string | null;
85
+ /** MIL-284: `ratifiedRef:` — the commit (full sha) whose tree holds the body that was ratified,
86
+ * written only by `em slice ratify` when the model dir is inside a git repository; null when
87
+ * absent (a doc ratified before em 1.15, or outside git). The ratified content's address. */
88
+ ratifiedRef: string | null;
89
+ /** MIL-284: `ratifiedHash:` — `sha256:<hex>` over the doc body at ratification (see
90
+ * `sliceDocBodyHash`), written only by `em slice ratify`; null when absent. Identity that
91
+ * needs no git: `--slice-ready` compares it to the current body
92
+ * (`slice-ready-body-changed-since-ratification`). */
93
+ ratifiedHash: string | null;
94
+ /** MIL-284: `shippedVersion:` — this doc's `version:` at the moment `em slice mark-implemented`
95
+ * recorded the merge; null when absent (shipped before em 1.15, or never). The three
96
+ * `shipped*` keys plus `implementedIn` are the shipped record the lifecycle's readers move to
97
+ * in MIL-283; here they are additive. */
98
+ shippedVersion: number | null;
99
+ /** MIL-284: `shippedRef:` — the `ratifiedRef` of the version that shipped, copied at
100
+ * mark-implemented time; null when the doc had none. */
101
+ shippedRef: string | null;
102
+ /** MIL-284: `shippedOn:` — `YYYY-MM-DD`, the local date mark-implemented ran; null when absent. */
103
+ shippedOn: string | null;
85
104
  /** MIL-214: `conformedVersion:` — this slice's `version:` at the time a conform sweep last
86
105
  * certified it, or null when never certified. Written only by `em slice conform`. Paired with
87
106
  * `version` to compute `driftSignal`'s `uncertified` case (catalog/driftSignal.ts). */
@@ -155,4 +174,36 @@ export declare function hasUsableFrontmatter(doc: Pick<SliceDoc, "frontmatterPre
155
174
  * starts with a letter.
156
175
  */
157
176
  export declare function parseSliceRef(raw: string): SliceRef;
177
+ /** MIL-284/283: the shipped record — what `em slice mark-implemented` wrote at merge, or, for a
178
+ * doc shipped before em 1.15 (no `shippedVersion:`), what `status: implemented` meant then. */
179
+ export interface ShippedRecord {
180
+ /** The doc's `version:` when the merge was recorded (`shippedVersion:`); for a pre-1.15
181
+ * `implemented` doc, its current `version:` (null when that is unparseable). */
182
+ version: number | null;
183
+ /** The `ratifiedRef` that version was signed at (`shippedRef:`), or null when the doc had none. */
184
+ ratifiedRef: string | null;
185
+ /** The merged PR/commit URL — the same `implementedIn:` the doc carries at top level. */
186
+ implementedIn: string | null;
187
+ /** `YYYY-MM-DD`, the local date mark-implemented ran (`shippedOn:`), or null when absent. */
188
+ on: string | null;
189
+ }
190
+ /**
191
+ * MIL-283: THE question every lifecycle reader asks — "has a version of this slice shipped, and
192
+ * which?" — answered from the shipped record, not from `status`. `status` is the WORKING state:
193
+ * since 1.15.0 a shipped slice can read `status: draft` again (`em slice mark-implemented` opens
194
+ * the next version when a question is deferred to it; `em slice revise` on demand) while its v1
195
+ * stays shipped. The read-both rule for docs written before 1.15.0: `status: implemented` with no
196
+ * `shippedVersion:` is shipped at its current `version:`. Anything else is not shipped — a
197
+ * `ready-to-implement` doc still carrying a prior `implementedIn:` (the 1.13–1.14 reratify
198
+ * state) included; `driftSignal` reads that as `unpropagated-delta`, as it always did.
199
+ */
200
+ export declare function shippedRecordOf(doc: Pick<SliceDoc, "status" | "version" | "implementedIn" | "ratifiedRef" | "shippedVersion" | "shippedRef" | "shippedOn">): ShippedRecord | null;
201
+ /** MIL-284: the identity `em slice ratify` records as `ratifiedHash:` and `--slice-ready` checks
202
+ * against: `sha256:<hex>` over the doc BODY — everything after the closing frontmatter fence (or
203
+ * the whole doc when there is none), EOLs normalised to `\n` by `splitFrontmatter`'s split/join.
204
+ * Frontmatter is excluded on purpose: the ratify edit itself, `mark-implemented` and `conform`
205
+ * touch only frontmatter, without changing what was ratified. `em slice defer` is NOT in that
206
+ * list — it rewrites a body line (the Open Questions item), so a deferral belongs before the
207
+ * sign-off; after it, the hash no longer matches and `--slice-ready` says so. */
208
+ export declare function sliceDocBodyHash(markdown: string): string;
158
209
  export declare function parseSliceDoc(markdown: string): SliceDoc;
@@ -66,6 +66,18 @@
66
66
  // `--contract-change "<why>"` -> `contractChange: "<why>"`). Additive, tolerate-unknown-fields:
67
67
  // absent on every doc predating this feature, and on every non-public slice ratified without
68
68
  // either flag.
69
+ //
70
+ // `ratifiedRef`/`ratifiedHash` and `shippedVersion`/`shippedRef`/`shippedOn` (MIL-284, the
71
+ // additive half of MIL-283 "ratification has an address") give the two lifecycle facts an exact
72
+ // identity. `ratifiedRef` is the commit whose tree holds the ratified body and `ratifiedHash` the
73
+ // `sha256:` of that body (`sliceDocBodyHash`, below) — written only by `em slice ratify`, which
74
+ // refuses a doc with uncommitted changes so the ref really does hold what was signed. The
75
+ // `shipped*` trio is written only by `em slice mark-implemented` beside `implementedIn`: the
76
+ // version that shipped, the ref it was ratified at, the local date. Flat keys, not a nested
77
+ // block, because this parser is line-based (no yaml dependency, see above) and because every
78
+ // writer in cli/*.ts is a surgical single-line splice. Additive, tolerate-unknown-fields; the
79
+ // readers that will DECIDE on `shipped*` instead of `status` are MIL-283's breaking half.
80
+ import { createHash } from "node:crypto";
69
81
  import { marked } from "marked";
70
82
  /** Frontmatter keys docs/slice-doc-schema.md's required-vs-optional table marks
71
83
  * required at every `status` — the mechanical basis for `frontmatter-invalid`
@@ -193,6 +205,36 @@ function splitFrontmatter(markdown) {
193
205
  return { fields: new Map(), body: markdown, frontmatterPresent: false };
194
206
  return { fields, body: lines.slice(closeIndex + 1).join("\n"), frontmatterPresent: true };
195
207
  }
208
+ /**
209
+ * MIL-283: THE question every lifecycle reader asks — "has a version of this slice shipped, and
210
+ * which?" — answered from the shipped record, not from `status`. `status` is the WORKING state:
211
+ * since 1.15.0 a shipped slice can read `status: draft` again (`em slice mark-implemented` opens
212
+ * the next version when a question is deferred to it; `em slice revise` on demand) while its v1
213
+ * stays shipped. The read-both rule for docs written before 1.15.0: `status: implemented` with no
214
+ * `shippedVersion:` is shipped at its current `version:`. Anything else is not shipped — a
215
+ * `ready-to-implement` doc still carrying a prior `implementedIn:` (the 1.13–1.14 reratify
216
+ * state) included; `driftSignal` reads that as `unpropagated-delta`, as it always did.
217
+ */
218
+ export function shippedRecordOf(doc) {
219
+ if (doc.shippedVersion !== null) {
220
+ return { version: doc.shippedVersion, ratifiedRef: doc.shippedRef, implementedIn: doc.implementedIn, on: doc.shippedOn };
221
+ }
222
+ if (doc.status === "implemented") {
223
+ return { version: doc.version, ratifiedRef: doc.ratifiedRef, implementedIn: doc.implementedIn, on: null };
224
+ }
225
+ return null;
226
+ }
227
+ /** MIL-284: the identity `em slice ratify` records as `ratifiedHash:` and `--slice-ready` checks
228
+ * against: `sha256:<hex>` over the doc BODY — everything after the closing frontmatter fence (or
229
+ * the whole doc when there is none), EOLs normalised to `\n` by `splitFrontmatter`'s split/join.
230
+ * Frontmatter is excluded on purpose: the ratify edit itself, `mark-implemented` and `conform`
231
+ * touch only frontmatter, without changing what was ratified. `em slice defer` is NOT in that
232
+ * list — it rewrites a body line (the Open Questions item), so a deferral belongs before the
233
+ * sign-off; after it, the hash no longer matches and `--slice-ready` says so. */
234
+ export function sliceDocBodyHash(markdown) {
235
+ const { body } = splitFrontmatter(markdown);
236
+ return `sha256:${createHash("sha256").update(body, "utf8").digest("hex")}`;
237
+ }
196
238
  export function parseSliceDoc(markdown) {
197
239
  const { fields, body, frontmatterPresent } = splitFrontmatter(markdown);
198
240
  const legacyMatch = body.match(STATUS_LINE);
@@ -219,6 +261,11 @@ export function parseSliceDoc(markdown) {
219
261
  reviewedOn: fields.get("reviewedon") ?? null,
220
262
  ratifiedBy: fields.get("ratifiedby") ?? null,
221
263
  ratifiedOn: fields.get("ratifiedon") ?? null,
264
+ ratifiedRef: fields.get("ratifiedref") ?? null,
265
+ ratifiedHash: fields.get("ratifiedhash") ?? null,
266
+ shippedVersion: parseVersion(fields.get("shippedversion")),
267
+ shippedRef: fields.get("shippedref") ?? null,
268
+ shippedOn: fields.get("shippedon") ?? null,
222
269
  owner: fields.get("owner") ?? null,
223
270
  tracking: fields.get("tracking") ?? null,
224
271
  conformedVersion: parseVersion(fields.get("conformedversion")),
@@ -1 +1 @@
1
- {"version":3,"file":"sliceDoc.js","sourceRoot":"","sources":["../../src/catalog/sliceDoc.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sliceDoc.js","sourceRoot":"","sources":["../../src/catalog/sliceDoc.ts"],"names":[],"mappings":"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"}
@@ -27,6 +27,7 @@
27
27
  import { makeDiag, pushDiag } from "../model/rules.js";
28
28
  import { resolveSliceDocJoin } from "./docJoin.js";
29
29
  import { readSliceDoc } from "./readSliceDoc.js";
30
+ import { sliceDocBodyHash } from "./sliceDoc.js";
30
31
  import { findStructuredSectionProblems } from "./sliceSections.js";
31
32
  import { contractStatus, slicePublicTouching } from "./apiFirst.js";
32
33
  /** MIL-238 (briefing R10): the API-first gate's diagnostic for one slice, or null when the slice
@@ -115,6 +116,17 @@ export function validateSliceReady(model, refs, baseDir, sliceKey, contract) {
115
116
  // actually supplied status/version above, not always this slice's own file.
116
117
  const boundKey = doc.path.replace(/^slices\//, "").replace(/\.md$/, "");
117
118
  const parsed = readSliceDoc(baseDir, boundKey);
119
+ // MIL-284: the ratified body has an identity now. A doc whose body moved after `em slice
120
+ // ratify` recorded `ratifiedHash:` is not the spec that was signed — the ratification stands
121
+ // on content that is gone. Only checked when a hash exists (a doc ratified before em 1.15 has
122
+ // none and is judged on `ratifiedBy` alone, as before) and only at ready-to-implement.
123
+ if (doc.status === "ready-to-implement" && doc.ratifiedHash !== null && sliceDocBodyHash(parsed.raw) !== doc.ratifiedHash) {
124
+ pushDiag(diags, "slice-ready-body-changed-since-ratification", {
125
+ message: `slice "${sliceKey}"'s doc ${doc.path} was edited after ratification (body no longer matches ratifiedHash) — revert, or re-ratify the new content`,
126
+ line: slice.line,
127
+ refs: [sliceKey],
128
+ });
129
+ }
118
130
  if (parsed.openQuestionsUnchecked > 0) {
119
131
  pushDiag(diags, "slice-ready-open-questions-unchecked", {
120
132
  message: `slice "${sliceKey}" has ${parsed.openQuestionsUnchecked} of ${parsed.openQuestionsTotal} Open Question(s) unchecked`,