@milehimikey/em 1.9.1 → 1.11.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 +31 -12
- package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
- package/.claude/skills/event-modeling-implement/SKILL.md +14 -3
- package/.claude/skills/event-modeling-implement/reference/implement.md +73 -6
- package/.claude/skills/event-modeling-review/SKILL.md +14 -3
- package/.claude/skills/event-modeling-shared/reference/em-dsl.md +110 -11
- package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +4 -1
- package/.claude/skills/event-modeling-shared/templates/constitution.md +111 -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/README.md +8 -1
- package/dist/catalog/docJoin.d.ts +8 -0
- package/dist/catalog/docJoin.js +4 -0
- package/dist/catalog/docJoin.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/cli/ciInit.d.ts +10 -3
- package/dist/cli/ciInit.js +22 -14
- package/dist/cli/ciInit.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/ratify.d.ts +37 -5
- package/dist/cli/ratify.js +106 -9
- package/dist/cli/ratify.js.map +1 -1
- package/dist/cli/reratify.js +14 -5
- package/dist/cli/reratify.js.map +1 -1
- package/dist/cli/review.d.ts +38 -0
- package/dist/cli/review.js +160 -0
- package/dist/cli/review.js.map +1 -0
- package/dist/cli/sliceIndex.d.ts +3 -0
- package/dist/cli/sliceIndex.js +5 -4
- package/dist/cli/sliceIndex.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 +44 -3
- package/dist/cli/status.js +75 -18
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/systemInputs.d.ts +34 -0
- package/dist/cli/systemInputs.js +129 -0
- package/dist/cli/systemInputs.js.map +1 -0
- package/dist/cli.js +362 -23
- package/dist/cli.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 +37 -1
- package/dist/emit/json.js +67 -1
- 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 +6 -0
- package/dist/emit/queryJson.js +33 -0
- package/dist/emit/queryJson.js.map +1 -0
- package/dist/emit/statusJson.d.ts +1 -1
- package/dist/emit/statusJson.js +5 -1
- package/dist/emit/statusJson.js.map +1 -1
- package/dist/emit/systemJson.d.ts +8 -0
- package/dist/emit/systemJson.js +38 -0
- package/dist/emit/systemJson.js.map +1 -0
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +195 -9
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/edges.d.ts +28 -1
- package/dist/model/edges.js +77 -15
- package/dist/model/edges.js.map +1 -1
- package/dist/model/model.d.ts +6 -0
- package/dist/model/model.js +2 -0
- package/dist/model/model.js.map +1 -1
- package/dist/model/qualifiedRef.d.ts +47 -0
- package/dist/model/qualifiedRef.js +100 -0
- package/dist/model/qualifiedRef.js.map +1 -0
- package/dist/model/queryIndex.d.ts +53 -0
- package/dist/model/queryIndex.js +114 -0
- package/dist/model/queryIndex.js.map +1 -0
- package/dist/model/rules.d.ts +88 -0
- package/dist/model/rules.js +101 -0
- package/dist/model/rules.js.map +1 -1
- package/dist/model/sliceDocIndex.d.ts +30 -0
- package/dist/model/sliceDocIndex.js +110 -0
- package/dist/model/sliceDocIndex.js.map +1 -0
- package/dist/model/validate.js +85 -11
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/ast.d.ts +25 -0
- package/dist/parser/parser.d.ts +2 -0
- package/dist/parser/parser.js +104 -34
- package/dist/parser/parser.js.map +1 -1
- package/dist/query/format.d.ts +8 -0
- package/dist/query/format.js +80 -0
- package/dist/query/format.js.map +1 -0
- package/dist/query/pipeline.d.ts +17 -0
- package/dist/query/pipeline.js +38 -0
- package/dist/query/pipeline.js.map +1 -0
- package/dist/query/system.d.ts +60 -0
- package/dist/query/system.js +87 -0
- package/dist/query/system.js.map +1 -0
- package/dist/query/verbs.d.ts +100 -0
- package/dist/query/verbs.js +306 -0
- package/dist/query/verbs.js.map +1 -0
- package/dist/render/drawEdges.js +15 -4
- 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/sliceDiagram.js +1 -0
- package/dist/render/sliceDiagram.js.map +1 -1
- package/dist/system/manifest.d.ts +45 -0
- package/dist/system/manifest.js +178 -0
- package/dist/system/manifest.js.map +1 -0
- package/dist/system/verify.d.ts +88 -0
- package/dist/system/verify.js +263 -0
- package/dist/system/verify.js.map +1 -0
- package/dist/templates.d.ts +14 -1
- package/dist/templates.js +134 -5
- package/dist/templates.js.map +1 -1
- package/dist/util/slug.js +16 -10
- package/dist/util/slug.js.map +1 -1
- package/package.json +10 -1
package/dist/cli/ledgerCheck.js
CHANGED
|
@@ -111,6 +111,127 @@ export function checkLedger(anchorFile, from, to, runGit = realGit) {
|
|
|
111
111
|
: `slice "${sliceKey}": version: bumped (v${oldVersion} -> v${newVersion}) but doc content is unchanged`;
|
|
112
112
|
findings.push({ sliceKey, code, message, oldVersion, newVersion, bodyChanged, lineageChanged: docsLineageChanged });
|
|
113
113
|
}
|
|
114
|
-
return { findings, skipped, checkedCount: keys.length };
|
|
114
|
+
return { findings, waived: [], skipped, checkedCount: keys.length };
|
|
115
|
+
}
|
|
116
|
+
/** The only finding code a waiver may excuse (MIL-185, R9) — see `WaivedLedgerFinding`. */
|
|
117
|
+
const WAIVABLE_LEDGER_CODE = "ledger-content-without-version-bump";
|
|
118
|
+
// `%x00`/`%x01` are git's own pretty-format escapes for those literal bytes — git substitutes
|
|
119
|
+
// them into its OUTPUT, so the argv string handed to spawnSync stays plain ASCII text (an actual
|
|
120
|
+
// embedded NUL byte in an argv string throws in Node's child_process). The output bytes they
|
|
121
|
+
// produce are never valid in a commit hash or trailer value, so they're safe as delimiters when
|
|
122
|
+
// *parsing* `log.stdout` below — same technique as `changelog-git.ts`'s `FS` separator, one step
|
|
123
|
+
// removed because these two also need to round-trip through a `--format` argument first.
|
|
124
|
+
const FORMAT_HASH_SEP = "%x00";
|
|
125
|
+
const FORMAT_RECORD_END = "%x01";
|
|
126
|
+
const HASH_SEP = "\x00";
|
|
127
|
+
const RECORD_END = "\x01";
|
|
128
|
+
/**
|
|
129
|
+
* `Em-Ledger-Waive: <slice-key>` trailers on every commit in `from..to` (`to` null means `HEAD`
|
|
130
|
+
* — an uncommitted working-tree change has no commit to carry a trailer, so it can only be
|
|
131
|
+
* waived via `--waive`; see docs/cli.md). Reads the range oldest-first (`--reverse`) so a slice
|
|
132
|
+
* key repeated across several commits attributes to the **first** (earliest) commit that
|
|
133
|
+
* actually declared the waiver, not the most recent — deterministic for a given repo state, and
|
|
134
|
+
* the answer an auditor wants ("who introduced this waiver").
|
|
135
|
+
*
|
|
136
|
+
* Uses `%(trailers:key=Em-Ledger-Waive,valueonly)` (git's own trailer parser — requires the
|
|
137
|
+
* standard blank-line-separated footer block, same convention `git interpret-trailers` expects)
|
|
138
|
+
* rather than regexing commit messages by hand. A range that fails to resolve (unknown
|
|
139
|
+
* revision, `anchorFile` not in a repo) returns `[]` — routine, matching every other
|
|
140
|
+
* `diff-inputs.ts` git call's "missing is not a crash" stance; `checkLedger`'s own calls against
|
|
141
|
+
* the same revisions already surface a real problem with `--from`/`--to` if there is one.
|
|
142
|
+
*/
|
|
143
|
+
export function readLedgerWaiverTrailers(anchorFile, from, to, runGit = realGit) {
|
|
144
|
+
const toplevel = runGit(["-C", dirname(resolve(anchorFile)), "rev-parse", "--show-toplevel"]);
|
|
145
|
+
if (toplevel.status !== 0)
|
|
146
|
+
return [];
|
|
147
|
+
const repoRoot = toplevel.stdout.trim();
|
|
148
|
+
const range = `${from}..${to ?? "HEAD"}`;
|
|
149
|
+
const log = runGit([
|
|
150
|
+
"-C",
|
|
151
|
+
repoRoot,
|
|
152
|
+
"log",
|
|
153
|
+
"--reverse",
|
|
154
|
+
`--format=%H${FORMAT_HASH_SEP}%(trailers:key=Em-Ledger-Waive,valueonly)${FORMAT_RECORD_END}`,
|
|
155
|
+
range,
|
|
156
|
+
]);
|
|
157
|
+
if (log.status !== 0)
|
|
158
|
+
return [];
|
|
159
|
+
const seen = new Set();
|
|
160
|
+
const waivers = [];
|
|
161
|
+
for (const record of log.stdout.split(RECORD_END)) {
|
|
162
|
+
const body = record.startsWith("\n") ? record.slice(1) : record;
|
|
163
|
+
if (!body.trim())
|
|
164
|
+
continue;
|
|
165
|
+
const sepIndex = body.indexOf(HASH_SEP);
|
|
166
|
+
if (sepIndex === -1)
|
|
167
|
+
continue;
|
|
168
|
+
const commit = body.slice(0, sepIndex);
|
|
169
|
+
const values = body
|
|
170
|
+
.slice(sepIndex + 1)
|
|
171
|
+
.split("\n")
|
|
172
|
+
.map((v) => v.trim())
|
|
173
|
+
.filter((v) => v.length > 0);
|
|
174
|
+
for (const sliceKey of values) {
|
|
175
|
+
if (seen.has(sliceKey))
|
|
176
|
+
continue; // keep only the first (earliest, --reverse) commit
|
|
177
|
+
seen.add(sliceKey);
|
|
178
|
+
waivers.push({ sliceKey, commit });
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return waivers;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Split a `checkLedger` result's findings into still-active and waived (MIL-185, R9), given the
|
|
185
|
+
* flag-provided slice keys (repeatable `--waive <slice-key>`) and the trailer waivers read from
|
|
186
|
+
* the commit range (`readLedgerWaiverTrailers`). Pure — no git access, so flag-only and
|
|
187
|
+
* trailer-only waiver logic is testable without faking a git runner.
|
|
188
|
+
*
|
|
189
|
+
* Only a `ledger-content-without-version-bump` finding is ever waivable (`WAIVABLE_LEDGER_CODE`)
|
|
190
|
+
* — a version regression or a bump-without-content-change stays a hard finding regardless of any
|
|
191
|
+
* waiver naming that slice key. A flag waiver takes precedence over a same-key trailer waiver
|
|
192
|
+
* (both excuse the same finding; the flag is the more explicit, in-hand instruction). A waiver
|
|
193
|
+
* that names a slice key with no matching waivable finding is reported via `unknownWaivers`
|
|
194
|
+
* rather than silently dropped — see `UnknownLedgerWaiver`.
|
|
195
|
+
*/
|
|
196
|
+
export function applyLedgerWaivers(result, flagWaivedKeys, trailerWaivers) {
|
|
197
|
+
const waivableBySliceKey = new Map();
|
|
198
|
+
for (const finding of result.findings) {
|
|
199
|
+
if (finding.code === WAIVABLE_LEDGER_CODE)
|
|
200
|
+
waivableBySliceKey.set(finding.sliceKey, finding);
|
|
201
|
+
}
|
|
202
|
+
const waivedSliceKeys = new Set();
|
|
203
|
+
const waived = [...result.waived];
|
|
204
|
+
const unknownWaivers = [];
|
|
205
|
+
const seenFlagKeys = new Set();
|
|
206
|
+
for (const sliceKey of flagWaivedKeys) {
|
|
207
|
+
if (seenFlagKeys.has(sliceKey))
|
|
208
|
+
continue;
|
|
209
|
+
seenFlagKeys.add(sliceKey);
|
|
210
|
+
const finding = waivableBySliceKey.get(sliceKey);
|
|
211
|
+
const source = { source: "flag" };
|
|
212
|
+
if (finding) {
|
|
213
|
+
waived.push({ ...finding, waivedBy: source });
|
|
214
|
+
waivedSliceKeys.add(sliceKey);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
unknownWaivers.push({ sliceKey, source });
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
for (const trailer of trailerWaivers) {
|
|
221
|
+
if (waivedSliceKeys.has(trailer.sliceKey))
|
|
222
|
+
continue; // already waived by a flag entry
|
|
223
|
+
const finding = waivableBySliceKey.get(trailer.sliceKey);
|
|
224
|
+
const source = { source: "trailer", commit: trailer.commit };
|
|
225
|
+
if (finding) {
|
|
226
|
+
waived.push({ ...finding, waivedBy: source });
|
|
227
|
+
waivedSliceKeys.add(trailer.sliceKey);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
unknownWaivers.push({ sliceKey: trailer.sliceKey, source });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
waived.sort((a, b) => a.sliceKey.localeCompare(b.sliceKey));
|
|
234
|
+
const findings = result.findings.filter((f) => !waivedSliceKeys.has(f.sliceKey));
|
|
235
|
+
return { result: { ...result, findings, waived }, unknownWaivers };
|
|
115
236
|
}
|
|
116
237
|
//# sourceMappingURL=ledgerCheck.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledgerCheck.js","sourceRoot":"","sources":["../../src/cli/ledgerCheck.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,+FAA+F;AAC/F,8FAA8F;AAC9F,6FAA6F;AAC7F,yFAAyF;AACzF,+FAA+F;AAC/F,8FAA8F;AAC9F,EAAE;AACF,+FAA+F;AAC/F,4EAA4E;AAC5E,4FAA4F;AAC5F,kCAAkC;AAElC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAsB,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAa,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"ledgerCheck.js","sourceRoot":"","sources":["../../src/cli/ledgerCheck.ts"],"names":[],"mappings":"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"}
|
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,84 @@
|
|
|
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";
|
|
23
45
|
import { resolveSliceDocJoin } from "../catalog/docJoin.js";
|
|
46
|
+
import { buildModelIndex } from "../model/queryIndex.js";
|
|
24
47
|
import { fieldLineRegex, locateFrontmatterInner, normalizeFieldValue } from "./frontmatterSurgery.js";
|
|
48
|
+
import { REVIEWED_STATUS } from "./review.js";
|
|
25
49
|
import { isValidDateString } from "./stateFile.js";
|
|
26
50
|
/** 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. */
|
|
51
|
+
* (docs/process.md#the-slice-lifecycle-gates): contracts/invariants agreed, open questions
|
|
52
|
+
* resolved or deferred, ready for an implementing agent or engineer to pick up. */
|
|
29
53
|
export const RATIFIED_STATUS = "ready-to-implement";
|
|
54
|
+
/** The statuses the review gate (MIL-201) lets through without `--skip-review`: `reviewed` (the
|
|
55
|
+
* ordinary path — `em slice review` recorded a review session) and `ready-to-implement` (the
|
|
56
|
+
* idempotent re-run, and the post-`reratify` path — see the module header). */
|
|
57
|
+
const RATIFIABLE_STATUSES = [REVIEWED_STATUS, RATIFIED_STATUS];
|
|
58
|
+
/** Doc statuses an upstream producing slice can hold without triggering MIL-198's advisory —
|
|
59
|
+
* the two statuses that mean "this slice's contract is settled enough to build against". */
|
|
60
|
+
const UPSTREAM_SETTLED_STATUSES = [RATIFIED_STATUS, "implemented"];
|
|
61
|
+
/**
|
|
62
|
+
* MIL-198 (ruling R5): for every element in the `sliceKey` slice, walks the query index's `in`
|
|
63
|
+
* adjacency one hop to find producing elements that live in OTHER slices (a producer in the SAME
|
|
64
|
+
* slice isn't a cross-slice dependency), dedupes by upstream slice, and reports every upstream
|
|
65
|
+
* slice whose doc status isn't `ready-to-implement`/`implemented` — sorted by the upstream
|
|
66
|
+
* slice's position on the timeline (`Slice.index`), so the advisory itself reads in the order the
|
|
67
|
+
* team should catch up in. Advisory data only: never refuses, callers decide whether/how to print
|
|
68
|
+
* it. An unknown `sliceKey` (shouldn't happen — the caller already resolved it) yields `[]`
|
|
69
|
+
* rather than throwing.
|
|
70
|
+
*/
|
|
71
|
+
export function upstreamUnratifiedSlices(model, refs, baseDir, sliceKey) {
|
|
72
|
+
const sliceIndex = refs.sliceKeys.indexOf(sliceKey);
|
|
73
|
+
if (sliceIndex === -1)
|
|
74
|
+
return [];
|
|
75
|
+
const slice = model.slices[sliceIndex];
|
|
76
|
+
const index = buildModelIndex(model, refs, baseDir);
|
|
77
|
+
const upstreamSliceIndexes = new Set();
|
|
78
|
+
for (const el of slice.elements) {
|
|
79
|
+
const ref = refs.refById.get(el.id);
|
|
80
|
+
if (!ref)
|
|
81
|
+
continue;
|
|
82
|
+
for (const edge of index.in.get(ref) ?? []) {
|
|
83
|
+
const producer = index.byRef.get(edge.ref);
|
|
84
|
+
if (!producer || producer.sliceIndex === sliceIndex)
|
|
85
|
+
continue;
|
|
86
|
+
upstreamSliceIndexes.add(producer.sliceIndex);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const results = [];
|
|
90
|
+
for (const upstreamIndex of [...upstreamSliceIndexes].sort((a, b) => a - b)) {
|
|
91
|
+
const upstreamKey = refs.sliceKeys[upstreamIndex];
|
|
92
|
+
const status = index.sliceFacts.get(upstreamKey)?.doc.status ?? null;
|
|
93
|
+
if (status !== null && UPSTREAM_SETTLED_STATUSES.includes(status))
|
|
94
|
+
continue;
|
|
95
|
+
results.push({ sliceKey: upstreamKey, status: status ?? "no doc" });
|
|
96
|
+
}
|
|
97
|
+
return results;
|
|
98
|
+
}
|
|
30
99
|
/**
|
|
31
100
|
* Pure text transform: flips `status:` to `ready-to-implement` and sets `ratifiedBy:`/
|
|
32
101
|
* `ratifiedOn:` in `raw`'s frontmatter block. Idempotent (re-applying the same by/on pair once
|
|
@@ -37,9 +106,13 @@ export const RATIFIED_STATUS = "ready-to-implement";
|
|
|
37
106
|
* such refusal when `status` isn't already the target: re-ratifying a slice that has since moved
|
|
38
107
|
* on (e.g. back from `implemented` after a version bump — docs/slice-doc-schema.md#status-under-
|
|
39
108
|
* re-ratification) is the ordinary, expected use of this command, so it always applies cleanly.
|
|
40
|
-
*
|
|
109
|
+
*
|
|
110
|
+
* MIL-201: after that idempotency check, refuses any doc whose status isn't `reviewed` or
|
|
111
|
+
* `ready-to-implement` unless `skipReview` is set — the review gate. `sliceKey` appears only in
|
|
112
|
+
* that refusal message (and in the caller's skip notice); every other refusal here is about the
|
|
113
|
+
* doc's own text. No fs access — the caller reads/writes; see `runRatify` below.
|
|
41
114
|
*/
|
|
42
|
-
export function applyRatifyFrontmatter(raw, ratifiedBy, ratifiedOn) {
|
|
115
|
+
export function applyRatifyFrontmatter(raw, sliceKey, ratifiedBy, ratifiedOn, skipReview = false) {
|
|
43
116
|
const trimmedBy = ratifiedBy.trim();
|
|
44
117
|
if (!trimmedBy)
|
|
45
118
|
return { ok: false, message: "a ratifier name is required (--by)" };
|
|
@@ -66,7 +139,7 @@ export function applyRatifyFrontmatter(raw, ratifiedBy, ratifiedOn) {
|
|
|
66
139
|
const currentOn = onMatch ? normalizeFieldValue(onMatch[2]) : null;
|
|
67
140
|
if (currentStatus === RATIFIED_STATUS && currentBy !== null && currentOn !== null) {
|
|
68
141
|
if (currentBy === trimmedBy && currentOn === ratifiedOn) {
|
|
69
|
-
return { ok: true, content: raw, changed: false }; // idempotent no-op
|
|
142
|
+
return { ok: true, content: raw, changed: false, skippedReviewFrom: null }; // idempotent no-op
|
|
70
143
|
}
|
|
71
144
|
return {
|
|
72
145
|
ok: false,
|
|
@@ -74,6 +147,21 @@ export function applyRatifyFrontmatter(raw, ratifiedBy, ratifiedOn) {
|
|
|
74
147
|
`${trimmedBy} on ${ratifiedOn}`,
|
|
75
148
|
};
|
|
76
149
|
}
|
|
150
|
+
// The review gate (MIL-201, D1). A doc that never passed through `status: reviewed` has not
|
|
151
|
+
// been through the first human gate, so ratifying it collapses two decisions into one — the
|
|
152
|
+
// exact failure this refusal exists to prevent. `--skip-review` is the deliberate, visible
|
|
153
|
+
// escape hatch, not a silent bypass: the caller prints a notice naming the status it skipped.
|
|
154
|
+
const gateStatus = currentStatus ?? "(empty)";
|
|
155
|
+
const gateWouldRefuse = currentStatus === null || !RATIFIABLE_STATUSES.includes(currentStatus);
|
|
156
|
+
if (gateWouldRefuse && !skipReview) {
|
|
157
|
+
return {
|
|
158
|
+
ok: false,
|
|
159
|
+
message: `slice "${sliceKey}" is \`status: ${gateStatus}\` — the review gate comes first: run ` +
|
|
160
|
+
"`em slice review <file> <key> --by <name>` after the review session, or pass " +
|
|
161
|
+
"--skip-review to ratify without one",
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
const skippedReviewFrom = gateWouldRefuse ? gateStatus : null;
|
|
77
165
|
// Match the file's own line-ending style for any freshly-inserted line, same trick
|
|
78
166
|
// markImplemented.ts uses: on a CRLF doc, the text right after the status line's match starts
|
|
79
167
|
// with the "\r\n" that used to terminate it, so reusing it keeps a new line consistent with
|
|
@@ -108,14 +196,14 @@ export function applyRatifyFrontmatter(raw, ratifiedBy, ratifiedOn) {
|
|
|
108
196
|
updatedInner = updatedInner.slice(0, edit.index) + edit.next + updatedInner.slice(edit.index + edit.oldLen);
|
|
109
197
|
}
|
|
110
198
|
const content = raw.slice(0, range.innerStart) + updatedInner + raw.slice(range.innerEnd);
|
|
111
|
-
return { ok: true, content, changed: true };
|
|
199
|
+
return { ok: true, content, changed: true, skippedReviewFrom };
|
|
112
200
|
}
|
|
113
201
|
/**
|
|
114
202
|
* Resolves `sliceKey` to its bound doc via the same note-binding join `mark-implemented`/
|
|
115
203
|
* `--slice-ready`/`em export` use (MIL-121 cross-binding included), then reads/applies/writes
|
|
116
204
|
* it. `baseDir` is the `.em` file's directory, same convention every doc/note path in `em` uses.
|
|
117
205
|
*/
|
|
118
|
-
export function runRatify(model, refs, baseDir, sliceKey, ratifiedBy, ratifiedOn) {
|
|
206
|
+
export function runRatify(model, refs, baseDir, sliceKey, ratifiedBy, ratifiedOn, skipReview = false) {
|
|
119
207
|
const sliceIndex = refs.sliceKeys.indexOf(sliceKey);
|
|
120
208
|
if (sliceIndex === -1) {
|
|
121
209
|
return { ok: false, message: `no slice with export key "${sliceKey}" in this model` };
|
|
@@ -139,13 +227,22 @@ export function runRatify(model, refs, baseDir, sliceKey, ratifiedBy, ratifiedOn
|
|
|
139
227
|
}
|
|
140
228
|
const absPath = join(baseDir, doc.path);
|
|
141
229
|
const raw = readFileSync(absPath, "utf8");
|
|
142
|
-
const result = applyRatifyFrontmatter(raw, ratifiedBy, ratifiedOn);
|
|
230
|
+
const result = applyRatifyFrontmatter(raw, sliceKey, ratifiedBy, ratifiedOn, skipReview);
|
|
143
231
|
if (!result.ok) {
|
|
144
232
|
return { ok: false, message: `${doc.path}: ${result.message}` };
|
|
145
233
|
}
|
|
234
|
+
// MIL-198: computed once the gate above has passed, before the write — advisory only, so it
|
|
235
|
+
// runs the same whether the gate passed on its own merits or via --skip-review.
|
|
236
|
+
const upstreamWarnings = upstreamUnratifiedSlices(model, refs, baseDir, sliceKey);
|
|
146
237
|
if (result.changed) {
|
|
147
238
|
writeFileSync(absPath, result.content, "utf8");
|
|
148
239
|
}
|
|
149
|
-
return {
|
|
240
|
+
return {
|
|
241
|
+
ok: true,
|
|
242
|
+
path: doc.path,
|
|
243
|
+
changed: result.changed,
|
|
244
|
+
skippedReviewFrom: result.skippedReviewFrom,
|
|
245
|
+
upstreamWarnings,
|
|
246
|
+
};
|
|
150
247
|
}
|
|
151
248
|
//# 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
|
|
@@ -89,11 +95,14 @@ export function applyReratifyFrontmatter(raw) {
|
|
|
89
95
|
for (const edit of edits) {
|
|
90
96
|
updatedInner = updatedInner.slice(0, edit.index) + edit.next + updatedInner.slice(edit.index + edit.oldLen);
|
|
91
97
|
}
|
|
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
|
-
|
|
98
|
+
// Clear stale ratifiedBy:/ratifiedOn:/reviewedBy:/reviewedOn: — see module header. A plain
|
|
99
|
+
// `.replace()` (not index-spliced alongside the edits above) is safe here: these four keys are
|
|
100
|
+
// disjoint from `status:`/`version:` and from each other by construction (fieldLineRegex matches
|
|
101
|
+
// one key at a time), so removing them from the ALREADY-updated text can't disturb the edits
|
|
102
|
+
// just applied.
|
|
103
|
+
for (const key of ["ratifiedBy", "ratifiedOn", "reviewedBy", "reviewedOn"]) {
|
|
104
|
+
updatedInner = updatedInner.replace(fieldLineWithEolRegex(key), "");
|
|
105
|
+
}
|
|
97
106
|
const content = raw.slice(0, range.innerStart) + updatedInner + raw.slice(range.innerEnd);
|
|
98
107
|
return { ok: true, content, newVersion };
|
|
99
108
|
}
|
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;
|