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