@milehimikey/em 1.10.0 → 1.12.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.
- package/.claude/skills/event-modeling/SKILL.md +1 -1
- package/.claude/skills/event-modeling-conform/SKILL.md +5 -1
- package/.claude/skills/event-modeling-design/SKILL.md +41 -14
- package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
- package/.claude/skills/event-modeling-implement/SKILL.md +24 -7
- package/.claude/skills/event-modeling-implement/reference/implement.md +227 -19
- package/.claude/skills/event-modeling-review/SKILL.md +14 -3
- package/.claude/skills/event-modeling-shared/reference/em-dsl.md +80 -15
- package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +43 -1
- package/.claude/skills/event-modeling-shared/templates/constitution.md +118 -0
- package/.claude/skills/event-modeling-shared/templates/model-readme.md +2 -2
- package/.claude/skills/event-modeling-shared/templates/slice.md +4 -0
- package/dist/catalog/build.js +42 -1
- package/dist/catalog/build.js.map +1 -1
- package/dist/catalog/coverage.d.ts +15 -0
- package/dist/catalog/coverage.js +34 -0
- package/dist/catalog/coverage.js.map +1 -0
- package/dist/catalog/docJoin.d.ts +19 -2
- package/dist/catalog/docJoin.js +30 -4
- package/dist/catalog/docJoin.js.map +1 -1
- package/dist/catalog/docModelConsistencyValidate.js +1 -1
- package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
- package/dist/catalog/noteBindingValidate.js +18 -0
- package/dist/catalog/noteBindingValidate.js.map +1 -1
- package/dist/catalog/orphanedSliceDocValidate.d.ts +8 -1
- package/dist/catalog/orphanedSliceDocValidate.js +33 -6
- package/dist/catalog/orphanedSliceDocValidate.js.map +1 -1
- package/dist/catalog/pages.d.ts +16 -1
- package/dist/catalog/pages.js +16 -4
- package/dist/catalog/pages.js.map +1 -1
- package/dist/catalog/sliceDoc.d.ts +8 -0
- package/dist/catalog/sliceDoc.js +2 -0
- package/dist/catalog/sliceDoc.js.map +1 -1
- package/dist/catalog/sliceReadyValidate.d.ts +12 -1
- package/dist/catalog/sliceReadyValidate.js +4 -4
- package/dist/catalog/sliceReadyValidate.js.map +1 -1
- package/dist/cli/agentsMd.js +9 -3
- package/dist/cli/agentsMd.js.map +1 -1
- package/dist/cli/ciInit.js +3 -0
- package/dist/cli/ciInit.js.map +1 -1
- package/dist/cli/conformScope.js +10 -3
- package/dist/cli/conformScope.js.map +1 -1
- package/dist/cli/coverage.d.ts +34 -9
- package/dist/cli/coverage.js +61 -24
- package/dist/cli/coverage.js.map +1 -1
- package/dist/cli/ledgerCheck.d.ts +72 -0
- package/dist/cli/ledgerCheck.js +122 -1
- package/dist/cli/ledgerCheck.js.map +1 -1
- package/dist/cli/markImplemented.js +12 -1
- package/dist/cli/markImplemented.js.map +1 -1
- package/dist/cli/ratify.d.ts +37 -5
- package/dist/cli/ratify.js +123 -10
- package/dist/cli/ratify.js.map +1 -1
- package/dist/cli/reratify.js +26 -6
- package/dist/cli/reratify.js.map +1 -1
- package/dist/cli/review.d.ts +38 -0
- package/dist/cli/review.js +171 -0
- package/dist/cli/review.js.map +1 -0
- package/dist/cli/sliceIndex.d.ts +3 -0
- package/dist/cli/sliceIndex.js +14 -8
- package/dist/cli/sliceIndex.js.map +1 -1
- package/dist/cli/sliceLink.js +16 -0
- package/dist/cli/sliceLink.js.map +1 -1
- package/dist/cli/stateFile.d.ts +10 -0
- package/dist/cli/stateFile.js +14 -0
- package/dist/cli/stateFile.js.map +1 -1
- package/dist/cli/status.d.ts +55 -3
- package/dist/cli/status.js +92 -19
- package/dist/cli/status.js.map +1 -1
- package/dist/cli.js +203 -47
- package/dist/cli.js.map +1 -1
- package/dist/emit/coverageJson.d.ts +2 -2
- package/dist/emit/coverageJson.js +6 -2
- package/dist/emit/coverageJson.js.map +1 -1
- package/dist/emit/freshnessJson.d.ts +1 -1
- package/dist/emit/freshnessJson.js +5 -1
- package/dist/emit/freshnessJson.js.map +1 -1
- package/dist/emit/json.d.ts +45 -1
- package/dist/emit/json.js +82 -3
- package/dist/emit/json.js.map +1 -1
- package/dist/emit/ledgerJson.d.ts +1 -1
- package/dist/emit/ledgerJson.js +6 -1
- package/dist/emit/ledgerJson.js.map +1 -1
- package/dist/emit/queryJson.d.ts +1 -1
- package/dist/emit/queryJson.js +5 -1
- package/dist/emit/queryJson.js.map +1 -1
- package/dist/emit/statusJson.d.ts +1 -1
- package/dist/emit/statusJson.js +10 -1
- package/dist/emit/statusJson.js.map +1 -1
- package/dist/emit/validateJson.d.ts +4 -3
- package/dist/emit/validateJson.js +10 -3
- package/dist/emit/validateJson.js.map +1 -1
- package/dist/mcp/server.js +47 -22
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/continuation.d.ts +23 -0
- package/dist/model/continuation.js +49 -0
- package/dist/model/continuation.js.map +1 -0
- package/dist/model/edges.d.ts +18 -3
- package/dist/model/edges.js +34 -0
- package/dist/model/edges.js.map +1 -1
- package/dist/model/model.d.ts +4 -0
- package/dist/model/model.js +1 -0
- package/dist/model/model.js.map +1 -1
- package/dist/model/queryIndex.d.ts +5 -2
- package/dist/model/queryIndex.js +5 -2
- package/dist/model/queryIndex.js.map +1 -1
- package/dist/model/rules.d.ts +25 -0
- package/dist/model/rules.js +25 -0
- package/dist/model/rules.js.map +1 -1
- package/dist/model/sliceDocIndex.d.ts +12 -5
- package/dist/model/sliceDocIndex.js +18 -7
- package/dist/model/sliceDocIndex.js.map +1 -1
- package/dist/model/validate.js +82 -1
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/ast.d.ts +21 -0
- package/dist/parser/parser.js +96 -32
- package/dist/parser/parser.js.map +1 -1
- package/dist/render/drawEdges.js +7 -0
- package/dist/render/drawEdges.js.map +1 -1
- package/dist/render/drawNotes.d.ts +13 -3
- package/dist/render/drawNotes.js +96 -20
- package/dist/render/drawNotes.js.map +1 -1
- package/dist/render/render.js +6 -5
- package/dist/render/render.js.map +1 -1
- package/dist/render/sliceStatus.d.ts +3 -3
- package/dist/render/sliceStatus.js +27 -29
- package/dist/render/sliceStatus.js.map +1 -1
- package/dist/templates.d.ts +14 -1
- package/dist/templates.js +141 -5
- package/dist/templates.js.map +1 -1
- package/dist/util/localDate.d.ts +2 -0
- package/dist/util/localDate.js +17 -0
- package/dist/util/localDate.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markImplemented.js","sourceRoot":"","sources":["../../src/cli/markImplemented.ts"],"names":[],"mappings":"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
|
|
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;;;;;;GAMG;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,aAAa,IAAI,oBAAoB,KAAK,IAAI,EAAE,CAAC;QACrE,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,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"}
|
package/dist/cli/ratify.d.ts
CHANGED
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
import { NormalizedModel } from "../model/model.js";
|
|
2
2
|
import { RefsResult } from "../model/refs.js";
|
|
3
3
|
/** The status this command flips a slice doc to — the handoff gate
|
|
4
|
-
* (docs/process.md#
|
|
5
|
-
* or deferred, ready for an implementing agent or engineer to pick up. */
|
|
4
|
+
* (docs/process.md#the-slice-lifecycle-gates): contracts/invariants agreed, open questions
|
|
5
|
+
* resolved or deferred, ready for an implementing agent or engineer to pick up. */
|
|
6
6
|
export declare const RATIFIED_STATUS = "ready-to-implement";
|
|
7
|
+
/** One upstream producing slice (in timeline order earlier than the slice being ratified) whose
|
|
8
|
+
* doc hasn't reached `ready-to-implement`/`implemented` yet. `status` is the doc's own status
|
|
9
|
+
* string, or the literal `"no doc"` when no doc is bound/found for that slice at all. */
|
|
10
|
+
export interface UpstreamUnratifiedSlice {
|
|
11
|
+
sliceKey: string;
|
|
12
|
+
status: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* MIL-198 (ruling R5): for every element in the `sliceKey` slice, walks the query index's `in`
|
|
16
|
+
* adjacency one hop to find producing elements that live in OTHER slices (a producer in the SAME
|
|
17
|
+
* slice isn't a cross-slice dependency), dedupes by upstream slice, and reports every upstream
|
|
18
|
+
* slice whose doc status isn't `ready-to-implement`/`implemented` — sorted by the upstream
|
|
19
|
+
* slice's position on the timeline (`Slice.index`), so the advisory itself reads in the order the
|
|
20
|
+
* team should catch up in. Advisory data only: never refuses, callers decide whether/how to print
|
|
21
|
+
* it. An unknown `sliceKey` (shouldn't happen — the caller already resolved it) yields `[]`
|
|
22
|
+
* rather than throwing.
|
|
23
|
+
*/
|
|
24
|
+
export declare function upstreamUnratifiedSlices(model: NormalizedModel, refs: RefsResult, baseDir: string, sliceKey: string): UpstreamUnratifiedSlice[];
|
|
7
25
|
export type ApplyRatifyResult = {
|
|
8
26
|
ok: true;
|
|
9
27
|
content: string;
|
|
10
28
|
changed: boolean;
|
|
29
|
+
/** The doc's status BEFORE the edit, when `--skip-review` is what let this ratification
|
|
30
|
+
* through (i.e. the review gate would otherwise have refused) — `null` whenever the gate
|
|
31
|
+
* passed on its own merits, so the caller prints the skip notice exactly when the flag
|
|
32
|
+
* actually did something. */
|
|
33
|
+
skippedReviewFrom: string | null;
|
|
11
34
|
} | {
|
|
12
35
|
ok: false;
|
|
13
36
|
message: string;
|
|
@@ -22,13 +45,22 @@ export type ApplyRatifyResult = {
|
|
|
22
45
|
* such refusal when `status` isn't already the target: re-ratifying a slice that has since moved
|
|
23
46
|
* on (e.g. back from `implemented` after a version bump — docs/slice-doc-schema.md#status-under-
|
|
24
47
|
* re-ratification) is the ordinary, expected use of this command, so it always applies cleanly.
|
|
25
|
-
*
|
|
48
|
+
*
|
|
49
|
+
* MIL-201: after that idempotency check, refuses any doc whose status isn't `reviewed` or
|
|
50
|
+
* `ready-to-implement` unless `skipReview` is set — the review gate. `sliceKey` appears only in
|
|
51
|
+
* that refusal message (and in the caller's skip notice); every other refusal here is about the
|
|
52
|
+
* doc's own text. No fs access — the caller reads/writes; see `runRatify` below.
|
|
26
53
|
*/
|
|
27
|
-
export declare function applyRatifyFrontmatter(raw: string, ratifiedBy: string, ratifiedOn: string): ApplyRatifyResult;
|
|
54
|
+
export declare function applyRatifyFrontmatter(raw: string, sliceKey: string, ratifiedBy: string, ratifiedOn: string, skipReview?: boolean): ApplyRatifyResult;
|
|
28
55
|
export type RunRatifyResult = {
|
|
29
56
|
ok: true;
|
|
30
57
|
path: string;
|
|
31
58
|
changed: boolean;
|
|
59
|
+
skippedReviewFrom: string | null;
|
|
60
|
+
/** MIL-198's upstream-timeline advisory — see `upstreamUnratifiedSlices` above. Always
|
|
61
|
+
* computed once the gate has passed (whether or not `--skip-review` is what let it
|
|
62
|
+
* through), never gates the ratification itself. */
|
|
63
|
+
upstreamWarnings: UpstreamUnratifiedSlice[];
|
|
32
64
|
} | {
|
|
33
65
|
ok: false;
|
|
34
66
|
message: string;
|
|
@@ -38,4 +70,4 @@ export type RunRatifyResult = {
|
|
|
38
70
|
* `--slice-ready`/`em export` use (MIL-121 cross-binding included), then reads/applies/writes
|
|
39
71
|
* it. `baseDir` is the `.em` file's directory, same convention every doc/note path in `em` uses.
|
|
40
72
|
*/
|
|
41
|
-
export declare function runRatify(model: NormalizedModel, refs: RefsResult, baseDir: string, sliceKey: string, ratifiedBy: string, ratifiedOn: string): RunRatifyResult;
|
|
73
|
+
export declare function runRatify(model: NormalizedModel, refs: RefsResult, baseDir: string, sliceKey: string, ratifiedBy: string, ratifiedOn: string, skipReview?: boolean): RunRatifyResult;
|
package/dist/cli/ratify.js
CHANGED
|
@@ -18,15 +18,85 @@
|
|
|
18
18
|
// never read, never a warning" contract already covers a doc that predates this feature), and
|
|
19
19
|
// this command is the only thing that ever writes them — same "one write path" discipline
|
|
20
20
|
// `mark-implemented` holds for `implementedIn`.
|
|
21
|
+
//
|
|
22
|
+
// MIL-201 — the review gate: ratification is the SECOND of two human gates, and this command now
|
|
23
|
+
// refuses a doc that never passed through the first one (`status: reviewed`, written by
|
|
24
|
+
// `em slice review`). `ready-to-implement` stays legal because it covers both the idempotent
|
|
25
|
+
// re-run and the post-`reratify` path: `em slice reratify` clears `ratifiedBy`/`ratifiedOn` (and
|
|
26
|
+
// `reviewedBy`/`reviewedOn`) and leaves the doc at `ready-to-implement`, so the follow-up
|
|
27
|
+
// `ratify --by` for the new version needs no fresh review session. `--skip-review` is the
|
|
28
|
+
// explicit, auditable escape hatch — it prints a loud one-line notice on stderr and writes
|
|
29
|
+
// nothing about the skip into the file. Never clears `reviewedBy`/`reviewedOn`: the review record
|
|
30
|
+
// is provenance for the version being ratified, not something ratification consumes.
|
|
31
|
+
//
|
|
32
|
+
// MIL-198 — the upstream-timeline advisory: the review/ratify gates above are about THIS slice's
|
|
33
|
+
// own doc; they say nothing about whether the slices it depends on (earlier on the timeline,
|
|
34
|
+
// per the modeling discipline in event-modeling-design/SKILL.md) are themselves far enough
|
|
35
|
+
// along. Ratifying "ahead of" an unratified upstream producer isn't wrong — sometimes the team
|
|
36
|
+
// deliberately works out of order — so this is advisory only and never refuses. `runRatify`
|
|
37
|
+
// walks the query index's `in` adjacency one hop from every element in the ratifying slice to
|
|
38
|
+
// find producing elements that live in OTHER slices (an upstream producer in the SAME slice
|
|
39
|
+
// isn't a cross-slice dependency), dedupes by upstream slice, sorts by timeline position, and
|
|
40
|
+
// reports any whose doc isn't `ready-to-implement`/`implemented` yet. Repeated-view instance
|
|
41
|
+
// hops (`view X again`) are never edges in `ModelIndex.out`/`.in` (queryIndex.ts's own design
|
|
42
|
+
// note), so they never surface here either — nothing extra to filter.
|
|
21
43
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
22
44
|
import { join } from "node:path";
|
|
45
|
+
import { continuationOf } from "../model/continuation.js";
|
|
23
46
|
import { resolveSliceDocJoin } from "../catalog/docJoin.js";
|
|
47
|
+
import { buildModelIndex } from "../model/queryIndex.js";
|
|
24
48
|
import { fieldLineRegex, locateFrontmatterInner, normalizeFieldValue } from "./frontmatterSurgery.js";
|
|
49
|
+
import { REVIEWED_STATUS } from "./review.js";
|
|
25
50
|
import { isValidDateString } from "./stateFile.js";
|
|
26
51
|
/** The status this command flips a slice doc to — the handoff gate
|
|
27
|
-
* (docs/process.md#
|
|
28
|
-
* or deferred, ready for an implementing agent or engineer to pick up. */
|
|
52
|
+
* (docs/process.md#the-slice-lifecycle-gates): contracts/invariants agreed, open questions
|
|
53
|
+
* resolved or deferred, ready for an implementing agent or engineer to pick up. */
|
|
29
54
|
export const RATIFIED_STATUS = "ready-to-implement";
|
|
55
|
+
/** The statuses the review gate (MIL-201) lets through without `--skip-review`: `reviewed` (the
|
|
56
|
+
* ordinary path — `em slice review` recorded a review session) and `ready-to-implement` (the
|
|
57
|
+
* idempotent re-run, and the post-`reratify` path — see the module header). */
|
|
58
|
+
const RATIFIABLE_STATUSES = [REVIEWED_STATUS, RATIFIED_STATUS];
|
|
59
|
+
/** Doc statuses an upstream producing slice can hold without triggering MIL-198's advisory —
|
|
60
|
+
* the two statuses that mean "this slice's contract is settled enough to build against". */
|
|
61
|
+
const UPSTREAM_SETTLED_STATUSES = [RATIFIED_STATUS, "implemented"];
|
|
62
|
+
/**
|
|
63
|
+
* MIL-198 (ruling R5): for every element in the `sliceKey` slice, walks the query index's `in`
|
|
64
|
+
* adjacency one hop to find producing elements that live in OTHER slices (a producer in the SAME
|
|
65
|
+
* slice isn't a cross-slice dependency), dedupes by upstream slice, and reports every upstream
|
|
66
|
+
* slice whose doc status isn't `ready-to-implement`/`implemented` — sorted by the upstream
|
|
67
|
+
* slice's position on the timeline (`Slice.index`), so the advisory itself reads in the order the
|
|
68
|
+
* team should catch up in. Advisory data only: never refuses, callers decide whether/how to print
|
|
69
|
+
* it. An unknown `sliceKey` (shouldn't happen — the caller already resolved it) yields `[]`
|
|
70
|
+
* rather than throwing.
|
|
71
|
+
*/
|
|
72
|
+
export function upstreamUnratifiedSlices(model, refs, baseDir, sliceKey) {
|
|
73
|
+
const sliceIndex = refs.sliceKeys.indexOf(sliceKey);
|
|
74
|
+
if (sliceIndex === -1)
|
|
75
|
+
return [];
|
|
76
|
+
const slice = model.slices[sliceIndex];
|
|
77
|
+
const index = buildModelIndex(model, refs, baseDir);
|
|
78
|
+
const upstreamSliceIndexes = new Set();
|
|
79
|
+
for (const el of slice.elements) {
|
|
80
|
+
const ref = refs.refById.get(el.id);
|
|
81
|
+
if (!ref)
|
|
82
|
+
continue;
|
|
83
|
+
for (const edge of index.in.get(ref) ?? []) {
|
|
84
|
+
const producer = index.byRef.get(edge.ref);
|
|
85
|
+
if (!producer || producer.sliceIndex === sliceIndex)
|
|
86
|
+
continue;
|
|
87
|
+
upstreamSliceIndexes.add(producer.sliceIndex);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const results = [];
|
|
91
|
+
for (const upstreamIndex of [...upstreamSliceIndexes].sort((a, b) => a - b)) {
|
|
92
|
+
const upstreamKey = refs.sliceKeys[upstreamIndex];
|
|
93
|
+
const status = index.sliceFacts.get(upstreamKey)?.doc.status ?? null;
|
|
94
|
+
if (status !== null && UPSTREAM_SETTLED_STATUSES.includes(status))
|
|
95
|
+
continue;
|
|
96
|
+
results.push({ sliceKey: upstreamKey, status: status ?? "no doc" });
|
|
97
|
+
}
|
|
98
|
+
return results;
|
|
99
|
+
}
|
|
30
100
|
/**
|
|
31
101
|
* Pure text transform: flips `status:` to `ready-to-implement` and sets `ratifiedBy:`/
|
|
32
102
|
* `ratifiedOn:` in `raw`'s frontmatter block. Idempotent (re-applying the same by/on pair once
|
|
@@ -37,9 +107,13 @@ export const RATIFIED_STATUS = "ready-to-implement";
|
|
|
37
107
|
* such refusal when `status` isn't already the target: re-ratifying a slice that has since moved
|
|
38
108
|
* on (e.g. back from `implemented` after a version bump — docs/slice-doc-schema.md#status-under-
|
|
39
109
|
* re-ratification) is the ordinary, expected use of this command, so it always applies cleanly.
|
|
40
|
-
*
|
|
110
|
+
*
|
|
111
|
+
* MIL-201: after that idempotency check, refuses any doc whose status isn't `reviewed` or
|
|
112
|
+
* `ready-to-implement` unless `skipReview` is set — the review gate. `sliceKey` appears only in
|
|
113
|
+
* that refusal message (and in the caller's skip notice); every other refusal here is about the
|
|
114
|
+
* doc's own text. No fs access — the caller reads/writes; see `runRatify` below.
|
|
41
115
|
*/
|
|
42
|
-
export function applyRatifyFrontmatter(raw, ratifiedBy, ratifiedOn) {
|
|
116
|
+
export function applyRatifyFrontmatter(raw, sliceKey, ratifiedBy, ratifiedOn, skipReview = false) {
|
|
43
117
|
const trimmedBy = ratifiedBy.trim();
|
|
44
118
|
if (!trimmedBy)
|
|
45
119
|
return { ok: false, message: "a ratifier name is required (--by)" };
|
|
@@ -66,7 +140,7 @@ export function applyRatifyFrontmatter(raw, ratifiedBy, ratifiedOn) {
|
|
|
66
140
|
const currentOn = onMatch ? normalizeFieldValue(onMatch[2]) : null;
|
|
67
141
|
if (currentStatus === RATIFIED_STATUS && currentBy !== null && currentOn !== null) {
|
|
68
142
|
if (currentBy === trimmedBy && currentOn === ratifiedOn) {
|
|
69
|
-
return { ok: true, content: raw, changed: false }; // idempotent no-op
|
|
143
|
+
return { ok: true, content: raw, changed: false, skippedReviewFrom: null }; // idempotent no-op
|
|
70
144
|
}
|
|
71
145
|
return {
|
|
72
146
|
ok: false,
|
|
@@ -74,6 +148,21 @@ export function applyRatifyFrontmatter(raw, ratifiedBy, ratifiedOn) {
|
|
|
74
148
|
`${trimmedBy} on ${ratifiedOn}`,
|
|
75
149
|
};
|
|
76
150
|
}
|
|
151
|
+
// The review gate (MIL-201, D1). A doc that never passed through `status: reviewed` has not
|
|
152
|
+
// been through the first human gate, so ratifying it collapses two decisions into one — the
|
|
153
|
+
// exact failure this refusal exists to prevent. `--skip-review` is the deliberate, visible
|
|
154
|
+
// escape hatch, not a silent bypass: the caller prints a notice naming the status it skipped.
|
|
155
|
+
const gateStatus = currentStatus ?? "(empty)";
|
|
156
|
+
const gateWouldRefuse = currentStatus === null || !RATIFIABLE_STATUSES.includes(currentStatus);
|
|
157
|
+
if (gateWouldRefuse && !skipReview) {
|
|
158
|
+
return {
|
|
159
|
+
ok: false,
|
|
160
|
+
message: `slice "${sliceKey}" is \`status: ${gateStatus}\` — the review gate comes first: run ` +
|
|
161
|
+
"`em slice review <file> <key> --by <name>` after the review session, or pass " +
|
|
162
|
+
"--skip-review to ratify without one",
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
const skippedReviewFrom = gateWouldRefuse ? gateStatus : null;
|
|
77
166
|
// Match the file's own line-ending style for any freshly-inserted line, same trick
|
|
78
167
|
// markImplemented.ts uses: on a CRLF doc, the text right after the status line's match starts
|
|
79
168
|
// with the "\r\n" that used to terminate it, so reusing it keeps a new line consistent with
|
|
@@ -108,20 +197,35 @@ export function applyRatifyFrontmatter(raw, ratifiedBy, ratifiedOn) {
|
|
|
108
197
|
updatedInner = updatedInner.slice(0, edit.index) + edit.next + updatedInner.slice(edit.index + edit.oldLen);
|
|
109
198
|
}
|
|
110
199
|
const content = raw.slice(0, range.innerStart) + updatedInner + raw.slice(range.innerEnd);
|
|
111
|
-
return { ok: true, content, changed: true };
|
|
200
|
+
return { ok: true, content, changed: true, skippedReviewFrom };
|
|
112
201
|
}
|
|
113
202
|
/**
|
|
114
203
|
* Resolves `sliceKey` to its bound doc via the same note-binding join `mark-implemented`/
|
|
115
204
|
* `--slice-ready`/`em export` use (MIL-121 cross-binding included), then reads/applies/writes
|
|
116
205
|
* it. `baseDir` is the `.em` file's directory, same convention every doc/note path in `em` uses.
|
|
117
206
|
*/
|
|
118
|
-
export function runRatify(model, refs, baseDir, sliceKey, ratifiedBy, ratifiedOn) {
|
|
207
|
+
export function runRatify(model, refs, baseDir, sliceKey, ratifiedBy, ratifiedOn, skipReview = false) {
|
|
119
208
|
const sliceIndex = refs.sliceKeys.indexOf(sliceKey);
|
|
120
209
|
if (sliceIndex === -1) {
|
|
121
210
|
return { ok: false, message: `no slice with export key "${sliceKey}" in this model` };
|
|
122
211
|
}
|
|
123
212
|
const slice = model.slices[sliceIndex];
|
|
124
|
-
const { doc } = resolveSliceDocJoin(slice, sliceKey, baseDir, (id) => refs.refById.get(id));
|
|
213
|
+
const { doc, continuationOf: continuationOfKey } = resolveSliceDocJoin(model, refs, slice, sliceKey, baseDir, (id) => refs.refById.get(id));
|
|
214
|
+
// MIL-208: a continuation slice (an again-view-only slice with no legacy doc of its own) has
|
|
215
|
+
// no status/ratification of its own to flip — refuse rather than silently mutating the
|
|
216
|
+
// ORIGINATING slice's doc under this key's name. `doc.continuationOf` is already the
|
|
217
|
+
// "legacy own doc wins" precedence applied (see docJoin.ts): a continuation slice that still
|
|
218
|
+
// carries its own doc is NOT refused here — that's the migration path, flagged instead by the
|
|
219
|
+
// `continuation-has-own-doc` warning.
|
|
220
|
+
if (continuationOfKey) {
|
|
221
|
+
const continuation = continuationOf(model, refs, sliceIndex);
|
|
222
|
+
const viewName = model.byId.get(continuation.viewLogicalId).name;
|
|
223
|
+
return {
|
|
224
|
+
ok: false,
|
|
225
|
+
message: `"${sliceKey}" is a continuation of "${continuationOfKey}" (view "${viewName}" again) — ` +
|
|
226
|
+
`it has no doc of its own; ratify "${continuationOfKey}" instead`,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
125
229
|
if (doc.reason === "no-doc-bound") {
|
|
126
230
|
return {
|
|
127
231
|
ok: false,
|
|
@@ -139,13 +243,22 @@ export function runRatify(model, refs, baseDir, sliceKey, ratifiedBy, ratifiedOn
|
|
|
139
243
|
}
|
|
140
244
|
const absPath = join(baseDir, doc.path);
|
|
141
245
|
const raw = readFileSync(absPath, "utf8");
|
|
142
|
-
const result = applyRatifyFrontmatter(raw, ratifiedBy, ratifiedOn);
|
|
246
|
+
const result = applyRatifyFrontmatter(raw, sliceKey, ratifiedBy, ratifiedOn, skipReview);
|
|
143
247
|
if (!result.ok) {
|
|
144
248
|
return { ok: false, message: `${doc.path}: ${result.message}` };
|
|
145
249
|
}
|
|
250
|
+
// MIL-198: computed once the gate above has passed, before the write — advisory only, so it
|
|
251
|
+
// runs the same whether the gate passed on its own merits or via --skip-review.
|
|
252
|
+
const upstreamWarnings = upstreamUnratifiedSlices(model, refs, baseDir, sliceKey);
|
|
146
253
|
if (result.changed) {
|
|
147
254
|
writeFileSync(absPath, result.content, "utf8");
|
|
148
255
|
}
|
|
149
|
-
return {
|
|
256
|
+
return {
|
|
257
|
+
ok: true,
|
|
258
|
+
path: doc.path,
|
|
259
|
+
changed: result.changed,
|
|
260
|
+
skippedReviewFrom: result.skippedReviewFrom,
|
|
261
|
+
upstreamWarnings,
|
|
262
|
+
};
|
|
150
263
|
}
|
|
151
264
|
//# sourceMappingURL=ratify.js.map
|
package/dist/cli/ratify.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ratify.js","sourceRoot":"","sources":["../../src/cli/ratify.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,0FAA0F;AAC1F,kFAAkF;AAClF,8FAA8F;AAC9F,8FAA8F;AAC9F,wFAAwF;AACxF,8FAA8F;AAC9F,6FAA6F;AAC7F,EAAE;AACF,gGAAgG;AAChG,+FAA+F;AAC/F,0FAA0F;AAC1F,gGAAgG;AAChG,yFAAyF;AACzF,EAAE;AACF,gGAAgG;AAChG,8FAA8F;AAC9F,8FAA8F;AAC9F,0FAA0F;AAC1F,gDAAgD;
|
|
1
|
+
{"version":3,"file":"ratify.js","sourceRoot":"","sources":["../../src/cli/ratify.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/reratify.js
CHANGED
|
@@ -27,6 +27,12 @@
|
|
|
27
27
|
// <name>` apply cleanly afterward — ratify's own idempotent-refusal guard would otherwise read
|
|
28
28
|
// the leftover prior ratifiedBy/ratifiedOn as "already ratified by someone else" and refuse.
|
|
29
29
|
//
|
|
30
|
+
// MIL-201: `reviewedBy:`/`reviewedOn:` are cleared for the same reason and in the same sweep. The
|
|
31
|
+
// review record describes the version that shipped, not the new one — a re-ratified version needs
|
|
32
|
+
// no fresh review session (the doc lands at `ready-to-implement`, which `em slice ratify`'s review
|
|
33
|
+
// gate accepts), but leaving the old review in place would claim the room walked a version it has
|
|
34
|
+
// never seen.
|
|
35
|
+
//
|
|
30
36
|
// Write strategy: the same surgical index-math splicing markImplemented.ts/ratify.ts use, via
|
|
31
37
|
// the shared primitives in ./frontmatterSurgery.js — never a parse+re-serialize. Everything
|
|
32
38
|
// outside the edited value spans — the body, `implementedIn:`, the lineage/`covers` keys, and
|
|
@@ -35,6 +41,7 @@
|
|
|
35
41
|
// stays entirely hand-authored — this command only ever touches the two lifecycle fields above.
|
|
36
42
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
37
43
|
import { join } from "node:path";
|
|
44
|
+
import { continuationOf } from "../model/continuation.js";
|
|
38
45
|
import { resolveSliceDocJoin } from "../catalog/docJoin.js";
|
|
39
46
|
import { fieldLineRegex, fieldLineWithEolRegex, locateFrontmatterInner, normalizeFieldValue } from "./frontmatterSurgery.js";
|
|
40
47
|
/** The status a doc must already be in for `reratify` to apply — mirrors `RATIFIED_STATUS` in
|
|
@@ -89,11 +96,14 @@ export function applyReratifyFrontmatter(raw) {
|
|
|
89
96
|
for (const edit of edits) {
|
|
90
97
|
updatedInner = updatedInner.slice(0, edit.index) + edit.next + updatedInner.slice(edit.index + edit.oldLen);
|
|
91
98
|
}
|
|
92
|
-
// Clear stale ratifiedBy:/ratifiedOn: — see module header. A plain
|
|
93
|
-
// index-spliced alongside the edits above) is safe here: these
|
|
94
|
-
// `status:`/`version:` by construction (fieldLineRegex matches
|
|
95
|
-
// them from the ALREADY-updated text can't disturb the edits
|
|
96
|
-
|
|
99
|
+
// Clear stale ratifiedBy:/ratifiedOn:/reviewedBy:/reviewedOn: — see module header. A plain
|
|
100
|
+
// `.replace()` (not index-spliced alongside the edits above) is safe here: these four keys are
|
|
101
|
+
// disjoint from `status:`/`version:` and from each other by construction (fieldLineRegex matches
|
|
102
|
+
// one key at a time), so removing them from the ALREADY-updated text can't disturb the edits
|
|
103
|
+
// just applied.
|
|
104
|
+
for (const key of ["ratifiedBy", "ratifiedOn", "reviewedBy", "reviewedOn"]) {
|
|
105
|
+
updatedInner = updatedInner.replace(fieldLineWithEolRegex(key), "");
|
|
106
|
+
}
|
|
97
107
|
const content = raw.slice(0, range.innerStart) + updatedInner + raw.slice(range.innerEnd);
|
|
98
108
|
return { ok: true, content, newVersion };
|
|
99
109
|
}
|
|
@@ -109,7 +119,17 @@ export function runReratify(model, refs, baseDir, sliceKey) {
|
|
|
109
119
|
return { ok: false, message: `no slice with export key "${sliceKey}" in this model` };
|
|
110
120
|
}
|
|
111
121
|
const slice = model.slices[sliceIndex];
|
|
112
|
-
const { doc } = resolveSliceDocJoin(slice, sliceKey, baseDir, (id) => refs.refById.get(id));
|
|
122
|
+
const { doc, continuationOf: continuationOfKey } = resolveSliceDocJoin(model, refs, slice, sliceKey, baseDir, (id) => refs.refById.get(id));
|
|
123
|
+
// MIL-208: see runRatify's own comment — a continuation slice has no status of its own.
|
|
124
|
+
if (continuationOfKey) {
|
|
125
|
+
const continuation = continuationOf(model, refs, sliceIndex);
|
|
126
|
+
const viewName = model.byId.get(continuation.viewLogicalId).name;
|
|
127
|
+
return {
|
|
128
|
+
ok: false,
|
|
129
|
+
message: `"${sliceKey}" is a continuation of "${continuationOfKey}" (view "${viewName}" again) — ` +
|
|
130
|
+
`it has no doc of its own; reratify "${continuationOfKey}" instead`,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
113
133
|
if (doc.reason === "no-doc-bound") {
|
|
114
134
|
return {
|
|
115
135
|
ok: false,
|
package/dist/cli/reratify.js.map
CHANGED
|
@@ -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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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { NormalizedModel } from "../model/model.js";
|
|
2
|
+
import { RefsResult } from "../model/refs.js";
|
|
3
|
+
/** The status this command flips a slice doc to — the review gate
|
|
4
|
+
* (docs/process.md#the-slice-lifecycle-gates): the room walked the slice and every open question
|
|
5
|
+
* it raised was resolved. NOT a handoff to an implementer; that's `em slice ratify`. */
|
|
6
|
+
export declare const REVIEWED_STATUS = "reviewed";
|
|
7
|
+
export type ApplyReviewResult = {
|
|
8
|
+
ok: true;
|
|
9
|
+
content: string;
|
|
10
|
+
changed: boolean;
|
|
11
|
+
} | {
|
|
12
|
+
ok: false;
|
|
13
|
+
message: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Pure text transform: flips `status:` to `reviewed` and sets `reviewedBy:`/`reviewedOn:` in
|
|
17
|
+
* `raw`'s frontmatter block. Idempotent (re-applying the same by/on pair once already reviewed is
|
|
18
|
+
* a no-op, `changed: false`, `content` returned byte-identical to `raw`); refuses (`ok: false`)
|
|
19
|
+
* rather than silently overwrite provenance when the doc is already `status: reviewed` with a
|
|
20
|
+
* *different* recorded reviewer/date — mirroring `applyRatifyFrontmatter`'s refusal exactly.
|
|
21
|
+
* Refuses from `ready-to-implement`/`implemented` (see module header). No fs access — the caller
|
|
22
|
+
* reads/writes; see `runReview` below.
|
|
23
|
+
*/
|
|
24
|
+
export declare function applyReviewFrontmatter(raw: string, reviewedBy: string, reviewedOn: string): ApplyReviewResult;
|
|
25
|
+
export type RunReviewResult = {
|
|
26
|
+
ok: true;
|
|
27
|
+
path: string;
|
|
28
|
+
changed: boolean;
|
|
29
|
+
} | {
|
|
30
|
+
ok: false;
|
|
31
|
+
message: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Resolves `sliceKey` to its bound doc via the same note-binding join `ratify`/`mark-implemented`/
|
|
35
|
+
* `--slice-ready`/`em export` use (MIL-121 cross-binding included), then reads/applies/writes it.
|
|
36
|
+
* `baseDir` is the `.em` file's directory, same convention every doc/note path in `em` uses.
|
|
37
|
+
*/
|
|
38
|
+
export declare function runReview(model: NormalizedModel, refs: RefsResult, baseDir: string, sliceKey: string, reviewedBy: string, reviewedOn: string): RunReviewResult;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// `em slice review` (MIL-201): gives `status: reviewed` a mechanical path into the slice doc.
|
|
3
|
+
// `reviewed` has been a first-class value in the status enum since the schema was written
|
|
4
|
+
// (docs/slice-doc-schema.md), but nothing ever wrote it — a facilitator who finished walking a
|
|
5
|
+
// slice in a stakeholder review either hand-edited the frontmatter or (the failure this command
|
|
6
|
+
// exists to prevent) reached straight for `em slice ratify` and collapsed two distinct human
|
|
7
|
+
// gates into one. Review is the FIRST gate: the room agreed the slice reads correctly.
|
|
8
|
+
// Ratification is a separate, later, usually multi-person gate — see
|
|
9
|
+
// docs/process.md#the-slice-lifecycle-gates.
|
|
10
|
+
//
|
|
11
|
+
// Deliberately a clone of ratify.ts's mechanics, not a generalization of them: same note-binding
|
|
12
|
+
// resolution (catalog/docJoin.ts's resolveSliceDocJoin), same `--by`/`--on` validation, same
|
|
13
|
+
// surgical index-splice write via ./frontmatterSurgery.js, same idempotent/refuse-to-overwrite
|
|
14
|
+
// discipline. The two commands read as one family precisely because they are the two ends of the
|
|
15
|
+
// same handoff.
|
|
16
|
+
//
|
|
17
|
+
// Status preconditions (R4, docs/cli.md): legal from `draft` (the ordinary case — a slice doc
|
|
18
|
+
// walked in a review session) and from `reviewed` itself (idempotent re-run, or a refusal when a
|
|
19
|
+
// DIFFERENT reviewer/date is already recorded). Refuses from `ready-to-implement`/`implemented`:
|
|
20
|
+
// review applies BEFORE ratification, and a slice that has already shipped is reopened with
|
|
21
|
+
// `em slice reratify`, not reviewed in place.
|
|
22
|
+
//
|
|
23
|
+
// `reviewedBy`/`reviewedOn` are additive, optional frontmatter keys in every status
|
|
24
|
+
// (docs/slice-doc-schema.md) — exactly like `ratifiedBy`/`ratifiedOn`. `em slice ratify` never
|
|
25
|
+
// clears them (the review record stays as provenance for the version it described);
|
|
26
|
+
// `em slice reratify` does clear them alongside `ratifiedBy`/`ratifiedOn`, since neither the old
|
|
27
|
+
// sign-off nor the old review describes the brand-new version.
|
|
28
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
29
|
+
import { join } from "node:path";
|
|
30
|
+
import { continuationOf } from "../model/continuation.js";
|
|
31
|
+
import { resolveSliceDocJoin } from "../catalog/docJoin.js";
|
|
32
|
+
import { fieldLineRegex, locateFrontmatterInner, normalizeFieldValue } from "./frontmatterSurgery.js";
|
|
33
|
+
import { isValidDateString } from "./stateFile.js";
|
|
34
|
+
/** The status this command flips a slice doc to — the review gate
|
|
35
|
+
* (docs/process.md#the-slice-lifecycle-gates): the room walked the slice and every open question
|
|
36
|
+
* it raised was resolved. NOT a handoff to an implementer; that's `em slice ratify`. */
|
|
37
|
+
export const REVIEWED_STATUS = "reviewed";
|
|
38
|
+
/** Statuses `em slice review` refuses to act on: review applies before ratification, so a doc
|
|
39
|
+
* that has already passed the ratification gate (or shipped) is past the point where "the room
|
|
40
|
+
* reviewed it" is a meaningful new fact about THIS version. */
|
|
41
|
+
const POST_REVIEW_STATUSES = ["ready-to-implement", "implemented"];
|
|
42
|
+
/**
|
|
43
|
+
* Pure text transform: flips `status:` to `reviewed` and sets `reviewedBy:`/`reviewedOn:` in
|
|
44
|
+
* `raw`'s frontmatter block. Idempotent (re-applying the same by/on pair once already reviewed is
|
|
45
|
+
* a no-op, `changed: false`, `content` returned byte-identical to `raw`); refuses (`ok: false`)
|
|
46
|
+
* rather than silently overwrite provenance when the doc is already `status: reviewed` with a
|
|
47
|
+
* *different* recorded reviewer/date — mirroring `applyRatifyFrontmatter`'s refusal exactly.
|
|
48
|
+
* Refuses from `ready-to-implement`/`implemented` (see module header). No fs access — the caller
|
|
49
|
+
* reads/writes; see `runReview` below.
|
|
50
|
+
*/
|
|
51
|
+
export function applyReviewFrontmatter(raw, reviewedBy, reviewedOn) {
|
|
52
|
+
const trimmedBy = reviewedBy.trim();
|
|
53
|
+
if (!trimmedBy)
|
|
54
|
+
return { ok: false, message: "a reviewer name is required (--by)" };
|
|
55
|
+
// Same guard, same rationale as ratify's: an embedded \r/\n could splice a multi-line value
|
|
56
|
+
// into the frontmatter and corrupt the fence, while internal spaces are legitimate in a name.
|
|
57
|
+
if (/[\x00-\x1f\x7f]/.test(trimmedBy)) {
|
|
58
|
+
return { ok: false, message: "reviewer name must not contain control characters" };
|
|
59
|
+
}
|
|
60
|
+
if (!isValidDateString(reviewedOn)) {
|
|
61
|
+
return { ok: false, message: `invalid date "${reviewedOn}" — expected YYYY-MM-DD` };
|
|
62
|
+
}
|
|
63
|
+
const range = locateFrontmatterInner(raw);
|
|
64
|
+
if (!range)
|
|
65
|
+
return { ok: false, message: "no frontmatter block found" };
|
|
66
|
+
const inner = raw.slice(range.innerStart, range.innerEnd);
|
|
67
|
+
const statusMatch = fieldLineRegex("status").exec(inner);
|
|
68
|
+
if (!statusMatch)
|
|
69
|
+
return { ok: false, message: "no `status:` field found in frontmatter" };
|
|
70
|
+
const byMatch = fieldLineRegex("reviewedBy").exec(inner);
|
|
71
|
+
const onMatch = fieldLineRegex("reviewedOn").exec(inner);
|
|
72
|
+
const currentStatus = normalizeFieldValue(statusMatch[2])?.toLowerCase() ?? null;
|
|
73
|
+
const currentBy = byMatch ? normalizeFieldValue(byMatch[2]) : null;
|
|
74
|
+
const currentOn = onMatch ? normalizeFieldValue(onMatch[2]) : null;
|
|
75
|
+
if (currentStatus === REVIEWED_STATUS && currentBy !== null && currentOn !== null) {
|
|
76
|
+
if (currentBy === trimmedBy && currentOn === reviewedOn) {
|
|
77
|
+
return { ok: true, content: raw, changed: false }; // idempotent no-op
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
ok: false,
|
|
81
|
+
message: `already reviewed by ${currentBy} on ${currentOn} — refusing to overwrite with ` +
|
|
82
|
+
`${trimmedBy} on ${reviewedOn}`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (currentStatus !== null && POST_REVIEW_STATUSES.includes(currentStatus)) {
|
|
86
|
+
return {
|
|
87
|
+
ok: false,
|
|
88
|
+
message: `doc is \`status: ${currentStatus}\` — review applies before ratification; a shipped ` +
|
|
89
|
+
"slice is reopened with `em slice reratify`",
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Match the file's own line-ending style for any freshly-inserted line — same trick
|
|
93
|
+
// markImplemented.ts/ratify.ts use (see ratify.ts for the full rationale).
|
|
94
|
+
const afterStatus = inner.slice(statusMatch.index + statusMatch[0].length);
|
|
95
|
+
const eol = afterStatus.startsWith("\r\n") ? "\r\n" : "\n";
|
|
96
|
+
// Whichever of reviewedBy/reviewedOn have no existing line get folded directly into the status
|
|
97
|
+
// edit's replacement text (inserted right after the new status value) rather than added as
|
|
98
|
+
// separate zero-length "insert" edits — same convention as ratify.ts.
|
|
99
|
+
const missingLines = [];
|
|
100
|
+
if (!byMatch)
|
|
101
|
+
missingLines.push(`reviewedBy: ${trimmedBy}`);
|
|
102
|
+
if (!onMatch)
|
|
103
|
+
missingLines.push(`reviewedOn: ${reviewedOn}`);
|
|
104
|
+
const newStatusText = `${statusMatch[1]}${REVIEWED_STATUS}`;
|
|
105
|
+
const statusNext = missingLines.length > 0 ? `${newStatusText}${eol}${missingLines.join(eol)}` : newStatusText;
|
|
106
|
+
// Apply from the highest index first so an earlier edit's index stays valid — same convention
|
|
107
|
+
// markImplemented.ts/ratify.ts use.
|
|
108
|
+
const edits = [
|
|
109
|
+
{ index: statusMatch.index, oldLen: statusMatch[0].length, next: statusNext },
|
|
110
|
+
];
|
|
111
|
+
if (byMatch)
|
|
112
|
+
edits.push({ index: byMatch.index, oldLen: byMatch[0].length, next: `${byMatch[1]}${trimmedBy}` });
|
|
113
|
+
if (onMatch)
|
|
114
|
+
edits.push({ index: onMatch.index, oldLen: onMatch[0].length, next: `${onMatch[1]}${reviewedOn}` });
|
|
115
|
+
edits.sort((a, b) => b.index - a.index);
|
|
116
|
+
let updatedInner = inner;
|
|
117
|
+
for (const edit of edits) {
|
|
118
|
+
updatedInner = updatedInner.slice(0, edit.index) + edit.next + updatedInner.slice(edit.index + edit.oldLen);
|
|
119
|
+
}
|
|
120
|
+
const content = raw.slice(0, range.innerStart) + updatedInner + raw.slice(range.innerEnd);
|
|
121
|
+
return { ok: true, content, changed: true };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Resolves `sliceKey` to its bound doc via the same note-binding join `ratify`/`mark-implemented`/
|
|
125
|
+
* `--slice-ready`/`em export` use (MIL-121 cross-binding included), then reads/applies/writes it.
|
|
126
|
+
* `baseDir` is the `.em` file's directory, same convention every doc/note path in `em` uses.
|
|
127
|
+
*/
|
|
128
|
+
export function runReview(model, refs, baseDir, sliceKey, reviewedBy, reviewedOn) {
|
|
129
|
+
const sliceIndex = refs.sliceKeys.indexOf(sliceKey);
|
|
130
|
+
if (sliceIndex === -1) {
|
|
131
|
+
return { ok: false, message: `no slice with export key "${sliceKey}" in this model` };
|
|
132
|
+
}
|
|
133
|
+
const slice = model.slices[sliceIndex];
|
|
134
|
+
const { doc, continuationOf: continuationOfKey } = resolveSliceDocJoin(model, refs, slice, sliceKey, baseDir, (id) => refs.refById.get(id));
|
|
135
|
+
// MIL-208: see runRatify's own comment — a continuation slice has no status of its own.
|
|
136
|
+
if (continuationOfKey) {
|
|
137
|
+
const continuation = continuationOf(model, refs, sliceIndex);
|
|
138
|
+
const viewName = model.byId.get(continuation.viewLogicalId).name;
|
|
139
|
+
return {
|
|
140
|
+
ok: false,
|
|
141
|
+
message: `"${sliceKey}" is a continuation of "${continuationOfKey}" (view "${viewName}" again) — ` +
|
|
142
|
+
`it has no doc of its own; review "${continuationOfKey}" instead`,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (doc.reason === "no-doc-bound") {
|
|
146
|
+
return {
|
|
147
|
+
ok: false,
|
|
148
|
+
message: `slice "${sliceKey}" has no doc bound via \`note "slices/${sliceKey}.md"\` — bind a slice doc before reviewing it`,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
if (doc.reason === "binding-missing-file") {
|
|
152
|
+
return { ok: false, message: `slice "${sliceKey}" notes "${doc.path}" but no such file exists` };
|
|
153
|
+
}
|
|
154
|
+
if (doc.reason === "frontmatter-invalid") {
|
|
155
|
+
return {
|
|
156
|
+
ok: false,
|
|
157
|
+
message: `slice doc "${doc.path}" has missing or invalid frontmatter — run \`em validate\` for details`,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
const absPath = join(baseDir, doc.path);
|
|
161
|
+
const raw = readFileSync(absPath, "utf8");
|
|
162
|
+
const result = applyReviewFrontmatter(raw, reviewedBy, reviewedOn);
|
|
163
|
+
if (!result.ok) {
|
|
164
|
+
return { ok: false, message: `${doc.path}: ${result.message}` };
|
|
165
|
+
}
|
|
166
|
+
if (result.changed) {
|
|
167
|
+
writeFileSync(absPath, result.content, "utf8");
|
|
168
|
+
}
|
|
169
|
+
return { ok: true, path: doc.path, changed: result.changed };
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=review.js.map
|