@milehimikey/em 1.17.0 → 1.18.1
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 +7 -4
- package/.claude/agents/em-validator.md +2 -2
- package/.claude/skills/event-modeling/SKILL.md +1 -1
- package/.claude/skills/event-modeling-conform/SKILL.md +1 -1
- package/.claude/skills/event-modeling-design/SKILL.md +46 -5
- package/.claude/skills/event-modeling-discover/SKILL.md +43 -8
- package/.claude/skills/event-modeling-discover/reference/extract.md +6 -1
- package/.claude/skills/event-modeling-discover/reference/prd-rubric.md +102 -0
- package/.claude/skills/event-modeling-discover/reference/prd-spec-path.md +171 -0
- package/.claude/skills/event-modeling-engagement/SKILL.md +21 -9
- package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
- package/.claude/skills/event-modeling-implement/reference/implement.md +18 -0
- package/.claude/skills/event-modeling-review/SKILL.md +4 -2
- package/.claude/skills/event-modeling-shared/reference/em-dsl.md +94 -6
- package/.claude/skills/event-modeling-shared/reference/methodology.md +268 -0
- package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +96 -2
- package/.claude/skills/event-modeling-shared/templates/slice.md +11 -3
- package/.claude-plugin/marketplace.json +2 -2
- package/dist/catalog/docModelConsistencyValidate.js +160 -0
- package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
- package/dist/catalog/invariantsValidate.d.ts +2 -0
- package/dist/catalog/invariantsValidate.js +67 -1
- package/dist/catalog/invariantsValidate.js.map +1 -1
- package/dist/catalog/scenarioQualityValidate.d.ts +4 -0
- package/dist/catalog/scenarioQualityValidate.js +148 -0
- package/dist/catalog/scenarioQualityValidate.js.map +1 -0
- package/dist/catalog/scenarios.d.ts +5 -0
- package/dist/catalog/scenarios.js +80 -0
- package/dist/catalog/scenarios.js.map +1 -1
- package/dist/catalog/sliceDoc.d.ts +4 -0
- package/dist/catalog/sliceDoc.js +16 -7
- package/dist/catalog/sliceDoc.js.map +1 -1
- package/dist/catalog/sliceReadyValidate.d.ts +11 -2
- package/dist/catalog/sliceReadyValidate.js +62 -3
- package/dist/catalog/sliceReadyValidate.js.map +1 -1
- package/dist/catalog/sliceSections.d.ts +3 -2
- package/dist/catalog/sliceSections.js +99 -9
- package/dist/catalog/sliceSections.js.map +1 -1
- package/dist/cli/ciInit.d.ts +4 -11
- package/dist/cli/ciInit.js +24 -6
- package/dist/cli/ciInit.js.map +1 -1
- package/dist/cli/coverage.d.ts +9 -0
- package/dist/cli/coverage.js +18 -0
- package/dist/cli/coverage.js.map +1 -1
- package/dist/cli/defer.d.ts +28 -0
- package/dist/cli/defer.js +87 -4
- package/dist/cli/defer.js.map +1 -1
- package/dist/cli/engagement.d.ts +13 -2
- package/dist/cli/engagement.js +60 -5
- package/dist/cli/engagement.js.map +1 -1
- package/dist/cli/engagementFile.d.ts +2 -0
- package/dist/cli/engagementFile.js +3 -1
- package/dist/cli/engagementFile.js.map +1 -1
- package/dist/cli/markImplemented.d.ts +14 -10
- package/dist/cli/markImplemented.js +49 -1
- package/dist/cli/markImplemented.js.map +1 -1
- package/dist/cli/prdTriage.d.ts +109 -0
- package/dist/cli/prdTriage.js +393 -0
- package/dist/cli/prdTriage.js.map +1 -0
- package/dist/cli/render-inputs.d.ts +2 -0
- package/dist/cli/render-inputs.js +4 -0
- package/dist/cli/render-inputs.js.map +1 -1
- package/dist/cli/review.d.ts +17 -2
- package/dist/cli/review.js +39 -10
- package/dist/cli/review.js.map +1 -1
- package/dist/cli/revise.d.ts +2 -0
- package/dist/cli/revise.js +7 -2
- package/dist/cli/revise.js.map +1 -1
- package/dist/cli/shape.d.ts +27 -0
- package/dist/cli/shape.js +77 -0
- package/dist/cli/shape.js.map +1 -0
- package/dist/cli/sliceIndex.d.ts +6 -1
- package/dist/cli/sliceIndex.js +28 -13
- package/dist/cli/sliceIndex.js.map +1 -1
- package/dist/cli/sliceNew.d.ts +4 -1
- package/dist/cli/sliceNew.js +26 -9
- package/dist/cli/sliceNew.js.map +1 -1
- package/dist/cli/status.d.ts +21 -1
- package/dist/cli/status.js +25 -3
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/storylineSuggest.d.ts +26 -0
- package/dist/cli/storylineSuggest.js +252 -0
- package/dist/cli/storylineSuggest.js.map +1 -0
- package/dist/cli/upgrade.d.ts +15 -3
- package/dist/cli/upgrade.js +516 -7
- package/dist/cli/upgrade.js.map +1 -1
- package/dist/cli/upgradeReshape.d.ts +60 -0
- package/dist/cli/upgradeReshape.js +425 -0
- package/dist/cli/upgradeReshape.js.map +1 -0
- package/dist/cli.js +311 -35
- package/dist/cli.js.map +1 -1
- package/dist/emit/dot.d.ts +2 -0
- package/dist/emit/dot.js +44 -8
- package/dist/emit/dot.js.map +1 -1
- package/dist/emit/engagementJson.d.ts +4 -3
- package/dist/emit/engagementJson.js +11 -4
- package/dist/emit/engagementJson.js.map +1 -1
- package/dist/emit/json.d.ts +21 -1
- package/dist/emit/json.js +26 -2
- package/dist/emit/json.js.map +1 -1
- package/dist/emit/queryJson.d.ts +1 -1
- package/dist/emit/queryJson.js +3 -1
- package/dist/emit/queryJson.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/emit/theme.d.ts +1 -0
- package/dist/emit/theme.js +13 -0
- package/dist/emit/theme.js.map +1 -1
- package/dist/emit/validateJson.d.ts +9 -5
- package/dist/emit/validateJson.js +40 -5
- package/dist/emit/validateJson.js.map +1 -1
- package/dist/layout/grid.d.ts +5 -1
- package/dist/layout/grid.js +93 -2
- package/dist/layout/grid.js.map +1 -1
- package/dist/mcp/server.js +46 -11
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/edges.d.ts +7 -0
- package/dist/model/edges.js +33 -16
- package/dist/model/edges.js.map +1 -1
- package/dist/model/model.d.ts +33 -0
- package/dist/model/model.js +87 -3
- package/dist/model/model.js.map +1 -1
- package/dist/model/queryIndex.js +2 -2
- package/dist/model/queryIndex.js.map +1 -1
- package/dist/model/refs.js +8 -5
- package/dist/model/refs.js.map +1 -1
- package/dist/model/rules.d.ts +149 -0
- package/dist/model/rules.js +144 -0
- package/dist/model/rules.js.map +1 -1
- package/dist/model/shapeLint.d.ts +12 -0
- package/dist/model/shapeLint.js +170 -0
- package/dist/model/shapeLint.js.map +1 -0
- package/dist/model/storylines.d.ts +51 -0
- package/dist/model/storylines.js +188 -0
- package/dist/model/storylines.js.map +1 -0
- package/dist/model/validate.d.ts +6 -1
- package/dist/model/validate.js +317 -14
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/againSugar.d.ts +30 -0
- package/dist/parser/againSugar.js +105 -0
- package/dist/parser/againSugar.js.map +1 -0
- package/dist/parser/ast.d.ts +33 -0
- package/dist/parser/lexer.d.ts +2 -0
- package/dist/parser/lexer.js +4 -0
- package/dist/parser/lexer.js.map +1 -1
- package/dist/parser/parser.js +284 -4
- package/dist/parser/parser.js.map +1 -1
- package/dist/query/format.js +1 -0
- package/dist/query/format.js.map +1 -1
- package/dist/query/verbs.d.ts +4 -0
- package/dist/query/verbs.js +30 -3
- package/dist/query/verbs.js.map +1 -1
- package/dist/render/drawEdges.js +100 -4
- package/dist/render/drawEdges.js.map +1 -1
- package/dist/render/render.js +20 -2
- package/dist/render/render.js.map +1 -1
- package/dist/render/sliceDiagram.js +5 -5
- package/dist/render/sliceDiagram.js.map +1 -1
- package/dist/render/storylineBands.d.ts +11 -0
- package/dist/render/storylineBands.js +80 -0
- package/dist/render/storylineBands.js.map +1 -0
- package/dist/render/storylineDiagram.d.ts +14 -0
- package/dist/render/storylineDiagram.js +142 -0
- package/dist/render/storylineDiagram.js.map +1 -0
- package/dist/roster/check.d.ts +32 -0
- package/dist/roster/check.js +92 -0
- package/dist/roster/check.js.map +1 -0
- package/dist/roster/context.d.ts +3 -0
- package/dist/roster/context.js +23 -0
- package/dist/roster/context.js.map +1 -0
- package/dist/roster/init.d.ts +15 -0
- package/dist/roster/init.js +52 -0
- package/dist/roster/init.js.map +1 -0
- package/dist/roster/roster.d.ts +79 -0
- package/dist/roster/roster.js +298 -0
- package/dist/roster/roster.js.map +1 -0
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/agents/em-implementer.md +7 -4
- package/plugin/agents/em-validator.md +2 -2
- package/plugin/shared/reference/em-dsl.md +94 -6
- package/plugin/shared/reference/methodology.md +268 -0
- package/plugin/shared/reference/slice-doc-schema.md +96 -2
- package/plugin/shared/templates/slice.md +11 -3
- package/plugin/skills/conform/SKILL.md +1 -1
- package/plugin/skills/design/SKILL.md +46 -5
- package/plugin/skills/discover/SKILL.md +43 -8
- package/plugin/skills/discover/reference/extract.md +6 -1
- package/plugin/skills/discover/reference/prd-rubric.md +103 -0
- package/plugin/skills/discover/reference/prd-spec-path.md +172 -0
- package/plugin/skills/engagement/SKILL.md +21 -9
- package/plugin/skills/event-modeling/SKILL.md +1 -1
- package/plugin/skills/implement/SKILL.md +1 -1
- package/plugin/skills/implement/reference/implement.md +18 -0
- package/plugin/skills/review/SKILL.md +4 -2
|
@@ -59,19 +59,24 @@ export function buildValidateJson(file, diagnostics) {
|
|
|
59
59
|
// --skip-review` ratified from when that bypass is what let the ratification through; null for a
|
|
60
60
|
// reviewed ratification, a doc predating 1.17, an unusable doc, or an unknown slice. Informational
|
|
61
61
|
// (not a gate): a host decides whether an unreviewed ratification passes. Additive-only.
|
|
62
|
-
|
|
62
|
+
// 1.4 (GH #293, 1.18.0): top-level `advisories: Diagnostic[]` — diagnostics of advisory rules
|
|
63
|
+
// (RuleDef.advisory, e.g. the scenario-quality warnings) concerning this slice. They are listed
|
|
64
|
+
// but never gate `ready`; under `--strict` they are promoted into `diagnostics` as errors and
|
|
65
|
+
// `advisories` is empty. Additive-only.
|
|
66
|
+
export const VALIDATE_SLICE_READY_SCHEMA_VERSION = "1.4";
|
|
63
67
|
/** Build the `em validate <file> --slice-ready <key> --json` document — the machine verdict
|
|
64
68
|
* replacing the two hand-parsed English sentences ("is ready-to-implement" /
|
|
65
69
|
* "is NOT ready-to-implement") plus scraped warning prose. `gates` names each of the 5
|
|
66
70
|
* conditions individually (see `computeSliceReadyGates`, catalog/sliceReadyValidate.ts);
|
|
67
71
|
* `null` when `sliceKey` matches no slice in the model (the `slice-ready-unknown-slice` error
|
|
68
72
|
* case — nothing to gate). `ready` is the same predicate driving `em validate`'s exit code
|
|
69
|
-
* for `--slice-ready` (scoped diagnostics
|
|
70
|
-
*
|
|
71
|
-
*
|
|
73
|
+
* for `--slice-ready` (no error-severity scoped diagnostics and no warning whose code is in the
|
|
74
|
+
* gating list of GH #332, see docs/cli.md; any other warning is listed in `diagnostics` but never
|
|
75
|
+
* flips it) — it is the AND of the gates only when `gates` is non-null AND nothing gating
|
|
76
|
+
* remains (e.g. a `both-ends-of-a-flow/*` warning on one of its own elements); `diagnostics` carries that full
|
|
72
77
|
* scoped list so a consumer sees exactly why, never just the 4 named gates. `continuationOf`
|
|
73
78
|
* (MIL-208) is `null` for an ordinary slice or when `gates` is `null`. */
|
|
74
|
-
export function buildSliceReadyJson(file, sliceKey, gates, diagnostics, ready, continuationOf, reviewSkipped = null) {
|
|
79
|
+
export function buildSliceReadyJson(file, sliceKey, gates, diagnostics, ready, continuationOf, reviewSkipped = null, advisories = []) {
|
|
75
80
|
const doc = {
|
|
76
81
|
validateSliceReadySchemaVersion: VALIDATE_SLICE_READY_SCHEMA_VERSION,
|
|
77
82
|
generator: { name: GENERATOR_NAME, version: GENERATOR_VERSION },
|
|
@@ -82,6 +87,7 @@ export function buildSliceReadyJson(file, sliceKey, gates, diagnostics, ready, c
|
|
|
82
87
|
reviewSkipped,
|
|
83
88
|
ready,
|
|
84
89
|
diagnostics: diagnostics.map(serializeDiagnosticWithUsage),
|
|
90
|
+
advisories: advisories.map(serializeDiagnosticWithUsage),
|
|
85
91
|
};
|
|
86
92
|
return JSON.stringify(doc, null, 2);
|
|
87
93
|
}
|
|
@@ -142,4 +148,33 @@ export function buildValidateListJson(file, markers, diagnostics) {
|
|
|
142
148
|
};
|
|
143
149
|
return JSON.stringify(doc, null, 2);
|
|
144
150
|
}
|
|
151
|
+
// 1.0 (GH #282): initial shape — `em validate --shape --json`. `rules[]` carries every shape-family
|
|
152
|
+
// rule (zero-count ones too, so a consumer sees what was checked), each with its `findings` (the
|
|
153
|
+
// diagnostics that count: message, line, refs) and `waived` (excused by `--waive-file`, never
|
|
154
|
+
// counted). `summary.findings` / `summary.waived` total them; `clean` is `summary.findings === 0`.
|
|
155
|
+
// `staleWaivers` lists waive-file lines that excused nothing (stale key or unknown rule code).
|
|
156
|
+
// `modelErrors` is the count of error diagnostics elsewhere in the model (shape output is
|
|
157
|
+
// incomplete while it is non-zero). Advisory: the exit code is 0 whatever the content.
|
|
158
|
+
export const VALIDATE_SHAPE_SCHEMA_VERSION = "1.0";
|
|
159
|
+
export function buildShapeJson(file, report, modelErrors) {
|
|
160
|
+
const ser = (d) => ({ message: d.message, line: d.line ?? null, refs: d.refs ?? [] });
|
|
161
|
+
const doc = {
|
|
162
|
+
shapeSchemaVersion: VALIDATE_SHAPE_SCHEMA_VERSION,
|
|
163
|
+
generator: { name: GENERATOR_NAME, version: GENERATOR_VERSION },
|
|
164
|
+
file,
|
|
165
|
+
clean: report.findings === 0,
|
|
166
|
+
modelErrors,
|
|
167
|
+
summary: { findings: report.findings, waived: report.waived, rules: report.rules.length },
|
|
168
|
+
staleWaivers: report.staleWaivers,
|
|
169
|
+
rules: report.rules.map((r) => ({
|
|
170
|
+
code: r.code,
|
|
171
|
+
title: r.title,
|
|
172
|
+
docAnchor: r.docAnchor,
|
|
173
|
+
count: r.findings.length,
|
|
174
|
+
findings: r.findings.map(ser),
|
|
175
|
+
waived: r.waived.map(ser),
|
|
176
|
+
})),
|
|
177
|
+
};
|
|
178
|
+
return JSON.stringify(doc, null, 2);
|
|
179
|
+
}
|
|
145
180
|
//# sourceMappingURL=validateJson.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateJson.js","sourceRoot":"","sources":["../../src/emit/validateJson.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,yFAAyF;AACzF,gFAAgF;AAChF,+FAA+F;AAC/F,+FAA+F;AAC/F,6FAA6F;AAC7F,iDAAiD;AACjD,EAAE;AACF,qFAAqF;AACrF,gGAAgG;AAChG,6FAA6F;AAC7F,oFAAoF;AACpF,EAAE;AACF,uFAAuF;AACvF,+FAA+F;AAC/F,uFAAuF;AACvF,0DAA0D;AAE1D,OAAO,EAAc,mBAAmB,EAAE,+BAA+B,EAAE,MAAM,sBAAsB,CAAC;AACxG,OAAO,EAAE,KAAK,EAAY,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"validateJson.js","sourceRoot":"","sources":["../../src/emit/validateJson.ts"],"names":[],"mappings":"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"}
|
package/dist/layout/grid.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Element, NormalizedModel } from "../model/model.js";
|
|
2
|
-
export type Band = "header" | "automation" | "ui" | "api" | "event";
|
|
2
|
+
export type Band = "storyline" | "header" | "automation" | "ui" | "api" | "event";
|
|
3
3
|
export declare const HEADER_KEY = "__header";
|
|
4
|
+
export declare const STORYLINE_KEY = "__storyline";
|
|
4
5
|
export interface GridRow {
|
|
5
6
|
key: string;
|
|
6
7
|
label: string;
|
|
@@ -26,6 +27,9 @@ export interface LayoutOptions {
|
|
|
26
27
|
/** Keep the structural command/view rows even when empty. */
|
|
27
28
|
keepEmptyLanes?: boolean;
|
|
28
29
|
}
|
|
30
|
+
/** Every alternative of the given event's `event A | B @Ctx` line, in declaration order
|
|
31
|
+
* (just the event itself when it has no alternatives). The first one is the grid cell's element. */
|
|
32
|
+
export declare function alternativesOf(model: NormalizedModel, el: Element): Element[];
|
|
29
33
|
export declare function placeholderId(row: number, col: number): string;
|
|
30
34
|
export declare function headerCellId(col: number): string;
|
|
31
35
|
/** Node id at a grid coordinate (header cell, element, or placeholder). */
|
package/dist/layout/grid.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// Turns a normalized model into a rigid R x C grid.
|
|
3
3
|
//
|
|
4
4
|
// Rows (bands), top -> bottom:
|
|
5
|
+
// -. storyline (only when the model declares `storyline` blocks, GH #277: a labelled band
|
|
6
|
+
// per run of a storyline's columns, drawn in render/storylineBands.ts)
|
|
5
7
|
// 0. header (slice names — one visible cell per column)
|
|
6
8
|
// 1. automation (single row, only if the model uses automation elements)
|
|
7
9
|
// 2. ui (one row per persona)
|
|
@@ -13,6 +15,14 @@
|
|
|
13
15
|
// Every (row, col) without a real element becomes an invisible placeholder so
|
|
14
16
|
// that rank chains and weighted column edges keep the grid perfectly aligned.
|
|
15
17
|
export const HEADER_KEY = "__header";
|
|
18
|
+
export const STORYLINE_KEY = "__storyline";
|
|
19
|
+
/** Every alternative of the given event's `event A | B @Ctx` line, in declaration order
|
|
20
|
+
* (just the event itself when it has no alternatives). The first one is the grid cell's element. */
|
|
21
|
+
export function alternativesOf(model, el) {
|
|
22
|
+
if (el.alternativeGroup === undefined)
|
|
23
|
+
return [el];
|
|
24
|
+
return model.elements.filter((e) => e.alternativeGroup === el.alternativeGroup && e.sliceIndex === el.sliceIndex);
|
|
25
|
+
}
|
|
16
26
|
export function placeholderId(row, col) {
|
|
17
27
|
return `__ph_${row}_${col}`;
|
|
18
28
|
}
|
|
@@ -26,6 +36,48 @@ export function nodeIdAt(grid, row, col) {
|
|
|
26
36
|
const el = grid.cells[row][col];
|
|
27
37
|
return el ? el.id : placeholderId(row, col);
|
|
28
38
|
}
|
|
39
|
+
/** A `view … again` instance may share an api cell with other `again` instances (GH #287). */
|
|
40
|
+
function isStackable(el) {
|
|
41
|
+
return el.kind === "view" && el.again === true;
|
|
42
|
+
}
|
|
43
|
+
/** The deepest api-cell stack any column needs: the largest count of `again` views in one slice
|
|
44
|
+
* whose api cell holds nothing but `again` views. 1 when nothing stacks. */
|
|
45
|
+
function apiStackDepth(model) {
|
|
46
|
+
let depth = 1;
|
|
47
|
+
for (const slice of model.slices) {
|
|
48
|
+
const api = slice.elements.filter((e) => e.kind === "command" || e.kind === "view");
|
|
49
|
+
if (api.length > 1 && api.every(isStackable))
|
|
50
|
+
depth = Math.max(depth, api.length);
|
|
51
|
+
}
|
|
52
|
+
return depth;
|
|
53
|
+
}
|
|
54
|
+
/** Slice indexes that are continuation-shaped: every non-`ui` element is an `again` view (at
|
|
55
|
+
* least one). Only these slices stack their `ui` boxes (GH #287). */
|
|
56
|
+
function continuationSlices(model) {
|
|
57
|
+
const out = new Set();
|
|
58
|
+
for (const slice of model.slices) {
|
|
59
|
+
const nonUi = slice.elements.filter((e) => e.kind !== "ui");
|
|
60
|
+
if (nonUi.length > 0 && nonUi.every(isStackable))
|
|
61
|
+
out.add(slice.index);
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
/** Per persona, the deepest ui-cell stack any continuation column needs (screens of one persona
|
|
66
|
+
* stack like the views do in the api lane). */
|
|
67
|
+
function uiStackDepths(model, continuation) {
|
|
68
|
+
const depths = new Map();
|
|
69
|
+
for (const slice of model.slices) {
|
|
70
|
+
if (!continuation.has(slice.index))
|
|
71
|
+
continue;
|
|
72
|
+
const counts = new Map();
|
|
73
|
+
for (const e of slice.elements)
|
|
74
|
+
if (e.kind === "ui")
|
|
75
|
+
counts.set(e.persona, (counts.get(e.persona) ?? 0) + 1);
|
|
76
|
+
for (const [persona, n] of counts)
|
|
77
|
+
depths.set(persona, Math.max(depths.get(persona) ?? 1, n));
|
|
78
|
+
}
|
|
79
|
+
return depths;
|
|
80
|
+
}
|
|
29
81
|
function rowKeyForElement(el) {
|
|
30
82
|
switch (el.kind) {
|
|
31
83
|
case "ui":
|
|
@@ -44,28 +96,67 @@ function rowKeyForElement(el) {
|
|
|
44
96
|
}
|
|
45
97
|
export function layout(model, opts = {}) {
|
|
46
98
|
const rows = [];
|
|
99
|
+
if ((model.storylines ?? []).length > 0) {
|
|
100
|
+
rows.push({ key: STORYLINE_KEY, label: "Storyline", band: "storyline" });
|
|
101
|
+
}
|
|
47
102
|
rows.push({ key: HEADER_KEY, label: "", band: "header" });
|
|
48
103
|
if (model.hasAutomation) {
|
|
49
104
|
rows.push({ key: "automation", label: "Automation", band: "automation" });
|
|
50
105
|
}
|
|
106
|
+
const continuation = continuationSlices(model);
|
|
107
|
+
const uiDepths = uiStackDepths(model, continuation);
|
|
51
108
|
for (const persona of model.personas) {
|
|
52
109
|
rows.push({ key: `ui:${persona}`, label: persona, band: "ui" });
|
|
110
|
+
// GH #287: extra rows (`ui:<persona>:2`, …) for screens stacked in one continuation column.
|
|
111
|
+
for (let n = 2; n <= (uiDepths.get(persona) ?? 1); n++)
|
|
112
|
+
rows.push({ key: `ui:${persona}:${n}`, label: "", band: "ui" });
|
|
53
113
|
}
|
|
54
114
|
rows.push({ key: "api", label: "API", band: "api" });
|
|
55
115
|
for (const context of model.contexts) {
|
|
56
116
|
rows.push({ key: `event:${context}`, label: context, band: "event" });
|
|
57
117
|
}
|
|
118
|
+
// GH #287: several `again` views of one continuation slice stack in its api cell, so the api
|
|
119
|
+
// lane grows by one extra row per additional stacked view (`api:2`, `api:3`, …) — only the
|
|
120
|
+
// columns that stack use them, every other cell there is an invisible spacer.
|
|
121
|
+
const stackDepth = apiStackDepth(model);
|
|
122
|
+
if (stackDepth > 1) {
|
|
123
|
+
const apiAt = rows.findIndex((r) => r.key === "api");
|
|
124
|
+
const extra = [];
|
|
125
|
+
for (let n = 2; n <= stackDepth; n++)
|
|
126
|
+
extra.push({ key: `api:${n}`, label: "", band: "api" });
|
|
127
|
+
rows.splice(apiAt + 1, 0, ...extra);
|
|
128
|
+
}
|
|
58
129
|
const indexOf = new Map();
|
|
59
130
|
rows.forEach((r, i) => indexOf.set(r.key, i));
|
|
60
131
|
const cols = model.slices.length;
|
|
61
132
|
const cells = rows.map(() => new Array(cols).fill(null));
|
|
62
133
|
const collisions = [];
|
|
134
|
+
const stacked = new Map(); // col -> views already in its api cell
|
|
135
|
+
const uiStacked = new Map(); // `${persona}|${col}` -> screens already in that ui cell
|
|
63
136
|
for (const el of model.elements) {
|
|
64
|
-
|
|
137
|
+
let r = indexOf.get(rowKeyForElement(el));
|
|
65
138
|
if (r === undefined)
|
|
66
139
|
continue; // unreachable, rows cover all kinds
|
|
67
140
|
const c = el.sliceIndex;
|
|
68
|
-
|
|
141
|
+
// GH #287: `again` views stack in the api lane, and screens of one persona stack in its ui
|
|
142
|
+
// lane, inside a continuation column.
|
|
143
|
+
if (isStackable(el) && cells[r][c] && isStackable(cells[r][c])) {
|
|
144
|
+
const depth = (stacked.get(c) ?? 1) + 1;
|
|
145
|
+
stacked.set(c, depth);
|
|
146
|
+
r = indexOf.get(`api:${depth}`);
|
|
147
|
+
}
|
|
148
|
+
if (el.kind === "ui" && cells[r][c] && continuation.has(c)) {
|
|
149
|
+
const k = `${el.persona}|${c}`;
|
|
150
|
+
const depth = (uiStacked.get(k) ?? 1) + 1;
|
|
151
|
+
uiStacked.set(k, depth);
|
|
152
|
+
r = indexOf.get(`ui:${el.persona}:${depth}`);
|
|
153
|
+
}
|
|
154
|
+
const occupant = cells[r][c];
|
|
155
|
+
// GH #278: alternatives of one `event A | B @Ctx` line share their context's cell — the
|
|
156
|
+
// first is the cell's element, the rest are drawn inside its box (emit/dot.ts).
|
|
157
|
+
if (occupant && el.alternativeGroup !== undefined && occupant.alternativeGroup === el.alternativeGroup)
|
|
158
|
+
continue;
|
|
159
|
+
if (occupant) {
|
|
69
160
|
collisions.push({ rowKey: rows[r].key, col: c, kept: cells[r][c], dropped: el });
|
|
70
161
|
continue;
|
|
71
162
|
}
|
package/dist/layout/grid.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid.js","sourceRoot":"","sources":["../../src/layout/grid.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,oDAAoD;AACpD,EAAE;AACF,+BAA+B;AAC/B,iEAAiE;AACjE,8EAA8E;AAC9E,2CAA2C;AAC3C,+EAA+E;AAC/E,mDAAmD;AACnD,EAAE;AACF,gEAAgE;AAChE,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAM9E,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC;AA+
|
|
1
|
+
{"version":3,"file":"grid.js","sourceRoot":"","sources":["../../src/layout/grid.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/server.js
CHANGED
|
@@ -30,10 +30,11 @@ import { ParseError } from "../parser/parser.js";
|
|
|
30
30
|
import { hasErrors } from "../model/validate.js";
|
|
31
31
|
import { diffModels } from "../model/diff.js";
|
|
32
32
|
import { buildExport, buildSliceExport, GENERATOR_VERSION } from "../emit/json.js";
|
|
33
|
-
import { buildValidateJson, buildSliceReadyJson, buildValidateListJson, collectMarkers } from "../emit/validateJson.js";
|
|
33
|
+
import { buildValidateJson, buildShapeJson, buildSliceReadyJson, buildValidateListJson, collectMarkers } from "../emit/validateJson.js";
|
|
34
34
|
import { buildDiffJson } from "../emit/diffJson.js";
|
|
35
35
|
import { runApiCheck } from "../cli/api.js";
|
|
36
36
|
import { buildApiCheckJson } from "../emit/apiCheckJson.js";
|
|
37
|
+
import { buildShapeReport, readWaiveFile } from "../cli/shape.js";
|
|
37
38
|
import { validateLineage } from "../catalog/lineageValidate.js";
|
|
38
39
|
import { validateFrontmatterCoherence } from "../catalog/frontmatterCoherenceValidate.js";
|
|
39
40
|
import { validateNoteBindings } from "../catalog/noteBindingValidate.js";
|
|
@@ -41,6 +42,7 @@ import { validateDocModelConsistency } from "../catalog/docModelConsistencyValid
|
|
|
41
42
|
import { validateOrphanedSliceDocs } from "../catalog/orphanedSliceDocValidate.js";
|
|
42
43
|
import { validateModelVersionStale } from "../catalog/modelVersionValidate.js";
|
|
43
44
|
import { validateInvariants } from "../catalog/invariantsValidate.js";
|
|
45
|
+
import { loadRoster } from "../roster/roster.js";
|
|
44
46
|
import { computeSliceReadiness } from "../catalog/sliceReadyValidate.js";
|
|
45
47
|
import { engagementMembersFor, engagementPlanFor, engagementStatusFor } from "../cli/engagement.js";
|
|
46
48
|
import { checkFoundation } from "../cli/engagementFoundation.js";
|
|
@@ -69,6 +71,7 @@ import { buildMetricsJson } from "../emit/metricsJson.js";
|
|
|
69
71
|
import { runSystemScope } from "../cli/scopeInputs.js";
|
|
70
72
|
import { buildScopeJson } from "../emit/scopeJson.js";
|
|
71
73
|
import { checkFindingsFile, buildCheckFindingsJson } from "../cli/findings.js";
|
|
74
|
+
import { checkPrdTriage, buildCheckPrdTriageJson } from "../cli/prdTriage.js";
|
|
72
75
|
import { compileForQuery } from "../query/pipeline.js";
|
|
73
76
|
import { buildQuerySystem } from "../query/system.js";
|
|
74
77
|
import { queryConsumers, queryProducers, queryDownstream, queryUpstream, querySlices, queryInvariant, queryField, queryPath, } from "../query/verbs.js";
|
|
@@ -213,12 +216,25 @@ export function createServer() {
|
|
|
213
216
|
"`em validate <file> --json` prints: a pass/fail summary plus every diagnostic (code, " +
|
|
214
217
|
"message, line, refs, usageCategory). Works even when the model has errors — this is " +
|
|
215
218
|
"the tool to call first when you just need to know what's wrong, or to confirm a model " +
|
|
216
|
-
"is clean before exporting it."
|
|
217
|
-
|
|
218
|
-
|
|
219
|
+
"is clean before exporting it. With `shape: true` (GH #282) it returns the " +
|
|
220
|
+
"`em validate <file> --shape --json` document instead: only the advisory shape-family " +
|
|
221
|
+
"lints, per-rule finding arrays with refs (`shapeSchemaVersion`), never a failure; " +
|
|
222
|
+
"`waiveFile` (a path, only with `shape`) baselines accepted slice keys.",
|
|
223
|
+
inputSchema: {
|
|
224
|
+
file: fileParam,
|
|
225
|
+
shape: z.boolean().default(false).describe("GH #282: return the shape-lint view (`em validate --shape --json`) instead of the full diagnostics"),
|
|
226
|
+
waiveFile: z.string().optional().describe("with `shape`: path of a waive file (one slice key per line, `#` comments) whose shape findings are listed as waived, not counted"),
|
|
227
|
+
},
|
|
228
|
+
}, async ({ file, shape, waiveFile }) => {
|
|
219
229
|
const compiled = compileWithValidation(file);
|
|
220
230
|
if ("error" in compiled)
|
|
221
231
|
return errorResult(compiled.error);
|
|
232
|
+
if (waiveFile && !shape)
|
|
233
|
+
return errorResult("waiveFile applies only with shape: true");
|
|
234
|
+
if (shape) {
|
|
235
|
+
const report = buildShapeReport(compiled.allDiagnostics, waiveFile ? readWaiveFile(waiveFile) : []);
|
|
236
|
+
return textResult(buildShapeJson(file, report, compiled.allDiagnostics.filter((d) => d.severity === "error").length));
|
|
237
|
+
}
|
|
222
238
|
return textResult(buildValidateJson(file, compiled.allDiagnostics));
|
|
223
239
|
});
|
|
224
240
|
server.registerTool("slice_ready", {
|
|
@@ -236,16 +252,20 @@ export function createServer() {
|
|
|
236
252
|
.boolean()
|
|
237
253
|
.default(false)
|
|
238
254
|
.describe("GH #256 strict mode (`em validate --slice-ready --require-ratified-hash`): a ready-to-implement doc with no `ratifiedHash:` is not ready"),
|
|
255
|
+
roster: z
|
|
256
|
+
.string()
|
|
257
|
+
.optional()
|
|
258
|
+
.describe("GH #259: path of the ratifier roster to check `ratifiedBy` against (`em validate --slice-ready --roster`); omitted = the nearest ratifiers.yaml above the model, none = unrestricted"),
|
|
239
259
|
},
|
|
240
|
-
}, async ({ file, sliceKey, requireRatifiedHash }) => {
|
|
260
|
+
}, async ({ file, sliceKey, requireRatifiedHash, roster }) => {
|
|
241
261
|
const compiled = compileWithValidation(file);
|
|
242
262
|
if ("error" in compiled)
|
|
243
263
|
return errorResult(compiled.error);
|
|
244
264
|
const { model, refs, allDiagnostics, source, diagnostics } = compiled;
|
|
245
265
|
const baseDir = dirname(file);
|
|
246
266
|
const contractInput = { file, source, diagnostics };
|
|
247
|
-
const { scoped, ready, result } = computeSliceReadiness(model, refs, baseDir, sliceKey, contractInput, allDiagnostics, { requireRatifiedHash });
|
|
248
|
-
return textResult(buildSliceReadyJson(file, sliceKey, result?.gates ?? null, scoped, ready, result?.continuationOf ?? null, result?.reviewSkipped ?? null));
|
|
267
|
+
const { scoped, advisories, ready, result } = computeSliceReadiness(model, refs, baseDir, sliceKey, contractInput, allDiagnostics, { requireRatifiedHash, rosterPath: roster });
|
|
268
|
+
return textResult(buildSliceReadyJson(file, sliceKey, result?.gates ?? null, scoped, ready, result?.continuationOf ?? null, result?.reviewSkipped ?? null, advisories));
|
|
249
269
|
});
|
|
250
270
|
server.registerTool("slice_sync", {
|
|
251
271
|
title: "Check slice docs' generated regions against the model",
|
|
@@ -486,7 +506,7 @@ export function createServer() {
|
|
|
486
506
|
const emVersion = compiledFiles
|
|
487
507
|
.map(({ file }) => resolveEmVersionStatusEntry(file, GENERATOR_VERSION))
|
|
488
508
|
.filter((e) => e !== null);
|
|
489
|
-
const report = buildStatusReport(files, sliceFacts, openIssuesCount, invariants, conformance, statusDiagnostics, modelVersion, emVersion, statusSystemBlock(files[0]), readOpenEngagements(files));
|
|
509
|
+
const report = buildStatusReport(files, sliceFacts, openIssuesCount, invariants, conformance, statusDiagnostics, modelVersion, emVersion, statusSystemBlock(files[0]), readOpenEngagements(files), loadRoster(dirname(files[0])).state);
|
|
490
510
|
return textResult(buildStatusJson(report));
|
|
491
511
|
});
|
|
492
512
|
server.registerTool("upgrade", {
|
|
@@ -777,6 +797,20 @@ export function createServer() {
|
|
|
777
797
|
}, async ({ path }) => {
|
|
778
798
|
return textResult(buildCheckFindingsJson(checkFindingsFile(path)));
|
|
779
799
|
});
|
|
800
|
+
server.registerTool("discover_triage_check", {
|
|
801
|
+
title: "Check a PRD/spec discovery triage record",
|
|
802
|
+
description: "Return the same JSON document `em discover triage-check <path> --json` prints (GH #295): " +
|
|
803
|
+
"whether a discovery/prd-triage.json is valid (prdTriageSchemaVersion 1.0, the shipped " +
|
|
804
|
+
"rubric version, every statement/storyline quote appearing verbatim in the input " +
|
|
805
|
+
"document, every statement carrying a category and outcome, modeled/rewritten ones a " +
|
|
806
|
+
"group and storyline). `source` overrides the file's own `source` path.",
|
|
807
|
+
inputSchema: {
|
|
808
|
+
path: z.string().describe("path to a discovery/prd-triage.json file"),
|
|
809
|
+
source: z.string().optional().describe("the input PRD/spec to check quotes against (default: the file's own `source`)"),
|
|
810
|
+
},
|
|
811
|
+
}, async ({ path, source }) => {
|
|
812
|
+
return textResult(buildCheckPrdTriageJson(checkPrdTriage(path, { source })));
|
|
813
|
+
});
|
|
780
814
|
server.registerTool("query", {
|
|
781
815
|
title: "Deterministic graph queries over the compiled model",
|
|
782
816
|
description: "Return the same JSON document `em query <verb> <files...> --json` prints (MIL-168): " +
|
|
@@ -805,13 +839,14 @@ export function createServer() {
|
|
|
805
839
|
context: z.string().optional().describe("slices: match a slice with an event in this @Context"),
|
|
806
840
|
persona: z.string().optional().describe("slices: match a slice with a ui in this @Persona"),
|
|
807
841
|
tag: z.string().optional().describe("slices: match a slice with an event carrying this tag key"),
|
|
842
|
+
storyline: z.string().optional().describe("slices: match a slice declared in this `storyline` block"),
|
|
808
843
|
id: z.string().optional().describe("invariant: the INV-* id to look up"),
|
|
809
844
|
testsDir: z.string().optional().describe("invariant: directory to scan for test files citing this id"),
|
|
810
845
|
name: z.string().optional().describe("field: the field's name"),
|
|
811
846
|
from: z.string().optional().describe("path: the starting element's export ref or display name"),
|
|
812
847
|
to: z.string().optional().describe("path: the ending element's export ref or display name"),
|
|
813
848
|
},
|
|
814
|
-
}, async ({ files, verb, event, of, depth, pattern, status, context, persona, tag, id, testsDir, name, from, to }) => {
|
|
849
|
+
}, async ({ files, verb, event, of, depth, pattern, status, context, persona, tag, storyline, id, testsDir, name, from, to }) => {
|
|
815
850
|
if (testsDir !== undefined) {
|
|
816
851
|
if (!existsSync(testsDir))
|
|
817
852
|
return errorResult(`testsDir not found: ${testsDir}`);
|
|
@@ -856,7 +891,7 @@ export function createServer() {
|
|
|
856
891
|
return textResult(buildQueryJson(verb, files, { of, depth: depth ?? null }, result.results));
|
|
857
892
|
}
|
|
858
893
|
case "slices": {
|
|
859
|
-
const filters = { pattern, status, context, persona, tag };
|
|
894
|
+
const filters = { pattern, status, context, persona, tag, storyline };
|
|
860
895
|
const result = querySlices(system, filters);
|
|
861
896
|
if (!result.ok)
|
|
862
897
|
return errorResult(result.error);
|
|
@@ -987,7 +1022,7 @@ export function createServer() {
|
|
|
987
1022
|
"the engagement's slices in dependency levels over model.edges (loops-to excluded), each " +
|
|
988
1023
|
"with its --slice-ready verdict, branch impl/<key>, base (always main — every slice PR " +
|
|
989
1024
|
"targets main, MIL-280), and any computed hold (not-ready, " +
|
|
990
|
-
"upstream-outside-engagement-unmerged); level widths vs the parallel ceiling; and `preflight` (GH #239) — " +
|
|
1025
|
+
"upstream-outside-engagement-unmerged); level widths vs the parallel ceiling; and `preflight` (GH #239, plus a `shape` kind per shape-family lint firing on the engagement's slices, GH #282 — answered by a `shape-accepted:` bullet in `.event-modeling.md`) — " +
|
|
991
1026
|
"the model-wide gaps the engagement's slices share (repeated-invariant, event-without-tag, shared-trigger, " +
|
|
992
1027
|
"doc-model-mismatch), to put to the human in ONE question round before fan-out. Read-only. " +
|
|
993
1028
|
"Tool error when the engagement is missing or has a cycle.",
|