@milehimikey/em 1.16.1 → 1.18.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 +3 -2
- package/.claude/skills/event-modeling-conform/reference/conform.md +7 -0
- 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 +28 -6
- package/.claude/skills/event-modeling-engagement/reference/engagement.md +5 -4
- package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
- package/.claude/skills/event-modeling-implement/reference/implement.md +18 -8
- package/.claude/skills/event-modeling-review/SKILL.md +1 -1
- package/.claude/skills/event-modeling-shared/reference/em-dsl.md +107 -10
- package/.claude/skills/event-modeling-shared/reference/methodology.md +268 -0
- package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +122 -15
- package/.claude/skills/event-modeling-shared/templates/slice.md +11 -3
- package/.claude-plugin/marketplace.json +2 -2
- package/dist/catalog/docJoin.d.ts +13 -5
- package/dist/catalog/docJoin.js +6 -1
- package/dist/catalog/docJoin.js.map +1 -1
- 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/signedBodyValidate.d.ts +7 -0
- package/dist/catalog/signedBodyValidate.js +29 -0
- package/dist/catalog/signedBodyValidate.js.map +1 -0
- package/dist/catalog/sliceDoc.d.ts +53 -7
- package/dist/catalog/sliceDoc.js +89 -10
- package/dist/catalog/sliceDoc.js.map +1 -1
- package/dist/catalog/sliceReadyValidate.d.ts +23 -2
- package/dist/catalog/sliceReadyValidate.js +54 -22
- 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 +60 -17
- package/dist/cli/defer.js +187 -86
- package/dist/cli/defer.js.map +1 -1
- package/dist/cli/engagement.d.ts +46 -0
- package/dist/cli/engagement.js +156 -1
- package/dist/cli/engagement.js.map +1 -1
- package/dist/cli/engagementFoundation.d.ts +47 -0
- package/dist/cli/engagementFoundation.js +164 -0
- package/dist/cli/engagementFoundation.js.map +1 -0
- package/dist/cli/frontmatterSurgery.d.ts +5 -0
- package/dist/cli/frontmatterSurgery.js +15 -0
- package/dist/cli/frontmatterSurgery.js.map +1 -1
- package/dist/cli/ledgerCheck.d.ts +5 -1
- package/dist/cli/ledgerCheck.js +50 -20
- package/dist/cli/ledgerCheck.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 +378 -0
- package/dist/cli/prdTriage.js.map +1 -0
- package/dist/cli/ratify.d.ts +14 -2
- package/dist/cli/ratify.js +34 -6
- package/dist/cli/ratify.js.map +1 -1
- package/dist/cli/refsCheck.d.ts +78 -0
- package/dist/cli/refsCheck.js +153 -0
- package/dist/cli/refsCheck.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/revise.d.ts +12 -3
- package/dist/cli/revise.js +43 -10
- 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/sliceConform.js +9 -0
- package/dist/cli/sliceConform.js.map +1 -1
- 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 +26 -5
- package/dist/cli/status.js +28 -6
- 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 +537 -8
- 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 +430 -57
- 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 -1
- package/dist/emit/engagementJson.js +27 -1
- package/dist/emit/engagementJson.js.map +1 -1
- package/dist/emit/json.d.ts +21 -1
- package/dist/emit/json.js +29 -2
- package/dist/emit/json.js.map +1 -1
- package/dist/emit/ledgerJson.d.ts +1 -1
- package/dist/emit/ledgerJson.js +6 -1
- package/dist/emit/ledgerJson.js.map +1 -1
- package/dist/emit/queryJson.d.ts +1 -1
- package/dist/emit/queryJson.js +3 -1
- package/dist/emit/queryJson.js.map +1 -1
- package/dist/emit/refsJson.d.ts +4 -0
- package/dist/emit/refsJson.js +19 -0
- package/dist/emit/refsJson.js.map +1 -0
- 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 +5 -2
- package/dist/emit/validateJson.js +41 -2
- 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 +79 -14
- 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 +167 -1
- package/dist/model/rules.js +164 -3
- 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 +9 -1
- package/dist/parser/lexer.js +17 -2
- 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/shared/reference/em-dsl.md +107 -10
- package/plugin/shared/reference/methodology.md +268 -0
- package/plugin/shared/reference/slice-doc-schema.md +122 -15
- package/plugin/shared/templates/slice.md +11 -3
- package/plugin/skills/conform/SKILL.md +3 -2
- package/plugin/skills/conform/reference/conform.md +7 -0
- 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 +28 -6
- package/plugin/skills/engagement/reference/engagement.md +5 -4
- 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 -8
- package/plugin/skills/review/SKILL.md +1 -1
|
@@ -2,13 +2,14 @@ import { Diagnostic } from "../model/validate.js";
|
|
|
2
2
|
import { NormalizedModel } from "../model/model.js";
|
|
3
3
|
import { RefsResult } from "../model/refs.js";
|
|
4
4
|
import { SliceReadyGates } from "../catalog/sliceReadyValidate.js";
|
|
5
|
+
import type { ShapeReport } from "../cli/shape.js";
|
|
5
6
|
export declare const VALIDATE_SCHEMA_VERSION = "1.0";
|
|
6
7
|
/** Build the plain `em validate <file> --json` document — the serialized diagnostics array
|
|
7
8
|
* (stable `code`s, `refs`, line numbers, `usageCategory`) plus a pass/fail summary. Works on
|
|
8
9
|
* a model with errors; `ok` mirrors `!hasErrors(diagnostics)`, the same predicate that gates
|
|
9
10
|
* `em validate`'s exit code. */
|
|
10
11
|
export declare function buildValidateJson(file: string, diagnostics: Diagnostic[]): string;
|
|
11
|
-
export declare const VALIDATE_SLICE_READY_SCHEMA_VERSION = "1.
|
|
12
|
+
export declare const VALIDATE_SLICE_READY_SCHEMA_VERSION = "1.4";
|
|
12
13
|
/** Build the `em validate <file> --slice-ready <key> --json` document — the machine verdict
|
|
13
14
|
* replacing the two hand-parsed English sentences ("is ready-to-implement" /
|
|
14
15
|
* "is NOT ready-to-implement") plus scraped warning prose. `gates` names each of the 5
|
|
@@ -20,7 +21,7 @@ export declare const VALIDATE_SLICE_READY_SCHEMA_VERSION = "1.2";
|
|
|
20
21
|
* both-ends-of-a-flow diagnostic on one of its own elements); `diagnostics` carries that full
|
|
21
22
|
* scoped list so a consumer sees exactly why, never just the 4 named gates. `continuationOf`
|
|
22
23
|
* (MIL-208) is `null` for an ordinary slice or when `gates` is `null`. */
|
|
23
|
-
export declare function buildSliceReadyJson(file: string, sliceKey: string, gates: SliceReadyGates | null, diagnostics: Diagnostic[], ready: boolean, continuationOf: string | null): string;
|
|
24
|
+
export declare function buildSliceReadyJson(file: string, sliceKey: string, gates: SliceReadyGates | null, diagnostics: Diagnostic[], ready: boolean, continuationOf: string | null, reviewSkipped?: string | null, advisories?: Diagnostic[]): string;
|
|
24
25
|
export declare const VALIDATE_LIST_SCHEMA_VERSION = "1.1";
|
|
25
26
|
/** One `--list-issues`/`--list-divergences`/`--list-public` entry — the structured replacement
|
|
26
27
|
* for the ` issue :12 slice "X" command "Y": text` eyeball format. `elementRef` is the same
|
|
@@ -55,3 +56,5 @@ export declare function collectMarkers(model: NormalizedModel, refs: RefsResult,
|
|
|
55
56
|
* same errors-only list text mode still prints (`em validate` fails the run on genuine
|
|
56
57
|
* errors regardless of which `--list-*` flag was passed). */
|
|
57
58
|
export declare function buildValidateListJson(file: string, markers: MarkerEntry[], diagnostics: Diagnostic[]): string;
|
|
59
|
+
export declare const VALIDATE_SHAPE_SCHEMA_VERSION = "1.0";
|
|
60
|
+
export declare function buildShapeJson(file: string, report: ShapeReport, modelErrors: number): string;
|
|
@@ -55,7 +55,15 @@ export function buildValidateJson(file, diagnostics) {
|
|
|
55
55
|
// - MIL-266: `slice-ready-structured-section-malformed` (error) can join the scoped diagnostics
|
|
56
56
|
// — a doc whose generated regions or `### Scenario:` blocks don't parse. Diagnostic-only:
|
|
57
57
|
// `gates` is unchanged.
|
|
58
|
-
|
|
58
|
+
// 1.3 (GH #260, 1.17.0): top-level `reviewSkipped: string | null` — the status `em slice ratify
|
|
59
|
+
// --skip-review` ratified from when that bypass is what let the ratification through; null for a
|
|
60
|
+
// reviewed ratification, a doc predating 1.17, an unusable doc, or an unknown slice. Informational
|
|
61
|
+
// (not a gate): a host decides whether an unreviewed ratification passes. Additive-only.
|
|
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";
|
|
59
67
|
/** Build the `em validate <file> --slice-ready <key> --json` document — the machine verdict
|
|
60
68
|
* replacing the two hand-parsed English sentences ("is ready-to-implement" /
|
|
61
69
|
* "is NOT ready-to-implement") plus scraped warning prose. `gates` names each of the 5
|
|
@@ -67,7 +75,7 @@ export const VALIDATE_SLICE_READY_SCHEMA_VERSION = "1.2";
|
|
|
67
75
|
* both-ends-of-a-flow diagnostic on one of its own elements); `diagnostics` carries that full
|
|
68
76
|
* scoped list so a consumer sees exactly why, never just the 4 named gates. `continuationOf`
|
|
69
77
|
* (MIL-208) is `null` for an ordinary slice or when `gates` is `null`. */
|
|
70
|
-
export function buildSliceReadyJson(file, sliceKey, gates, diagnostics, ready, continuationOf) {
|
|
78
|
+
export function buildSliceReadyJson(file, sliceKey, gates, diagnostics, ready, continuationOf, reviewSkipped = null, advisories = []) {
|
|
71
79
|
const doc = {
|
|
72
80
|
validateSliceReadySchemaVersion: VALIDATE_SLICE_READY_SCHEMA_VERSION,
|
|
73
81
|
generator: { name: GENERATOR_NAME, version: GENERATOR_VERSION },
|
|
@@ -75,8 +83,10 @@ export function buildSliceReadyJson(file, sliceKey, gates, diagnostics, ready, c
|
|
|
75
83
|
sliceKey,
|
|
76
84
|
gates,
|
|
77
85
|
continuationOf,
|
|
86
|
+
reviewSkipped,
|
|
78
87
|
ready,
|
|
79
88
|
diagnostics: diagnostics.map(serializeDiagnosticWithUsage),
|
|
89
|
+
advisories: advisories.map(serializeDiagnosticWithUsage),
|
|
80
90
|
};
|
|
81
91
|
return JSON.stringify(doc, null, 2);
|
|
82
92
|
}
|
|
@@ -137,4 +147,33 @@ export function buildValidateListJson(file, markers, diagnostics) {
|
|
|
137
147
|
};
|
|
138
148
|
return JSON.stringify(doc, null, 2);
|
|
139
149
|
}
|
|
150
|
+
// 1.0 (GH #282): initial shape — `em validate --shape --json`. `rules[]` carries every shape-family
|
|
151
|
+
// rule (zero-count ones too, so a consumer sees what was checked), each with its `findings` (the
|
|
152
|
+
// diagnostics that count: message, line, refs) and `waived` (excused by `--waive-file`, never
|
|
153
|
+
// counted). `summary.findings` / `summary.waived` total them; `clean` is `summary.findings === 0`.
|
|
154
|
+
// `staleWaivers` lists waive-file lines that excused nothing (stale key or unknown rule code).
|
|
155
|
+
// `modelErrors` is the count of error diagnostics elsewhere in the model (shape output is
|
|
156
|
+
// incomplete while it is non-zero). Advisory: the exit code is 0 whatever the content.
|
|
157
|
+
export const VALIDATE_SHAPE_SCHEMA_VERSION = "1.0";
|
|
158
|
+
export function buildShapeJson(file, report, modelErrors) {
|
|
159
|
+
const ser = (d) => ({ message: d.message, line: d.line ?? null, refs: d.refs ?? [] });
|
|
160
|
+
const doc = {
|
|
161
|
+
shapeSchemaVersion: VALIDATE_SHAPE_SCHEMA_VERSION,
|
|
162
|
+
generator: { name: GENERATOR_NAME, version: GENERATOR_VERSION },
|
|
163
|
+
file,
|
|
164
|
+
clean: report.findings === 0,
|
|
165
|
+
modelErrors,
|
|
166
|
+
summary: { findings: report.findings, waived: report.waived, rules: report.rules.length },
|
|
167
|
+
staleWaivers: report.staleWaivers,
|
|
168
|
+
rules: report.rules.map((r) => ({
|
|
169
|
+
code: r.code,
|
|
170
|
+
title: r.title,
|
|
171
|
+
docAnchor: r.docAnchor,
|
|
172
|
+
count: r.findings.length,
|
|
173
|
+
findings: r.findings.map(ser),
|
|
174
|
+
waived: r.waived.map(ser),
|
|
175
|
+
})),
|
|
176
|
+
};
|
|
177
|
+
return JSON.stringify(doc, null, 2);
|
|
178
|
+
}
|
|
140
179
|
//# 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,10 +42,12 @@ 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
|
-
import { engagementPlanFor, engagementStatusFor } from "../cli/engagement.js";
|
|
47
|
+
import { engagementMembersFor, engagementPlanFor, engagementStatusFor } from "../cli/engagement.js";
|
|
48
|
+
import { checkFoundation } from "../cli/engagementFoundation.js";
|
|
46
49
|
import { readOpenEngagements } from "../cli/engagementFile.js";
|
|
47
|
-
import { buildEngagementPlanJson, buildEngagementStatusJson } from "../emit/engagementJson.js";
|
|
50
|
+
import { buildEngagementFoundationJson, buildEngagementPlanJson, buildEngagementStatusJson } from "../emit/engagementJson.js";
|
|
48
51
|
import { buildSliceSyncJson, runSliceSync } from "../cli/sliceSync.js";
|
|
49
52
|
import { buildCoverageReport, resolveScopedSlices, resolveCoverageSliceKey } from "../cli/coverage.js";
|
|
50
53
|
import { buildCoverageJson } from "../emit/coverageJson.js";
|
|
@@ -68,6 +71,7 @@ import { buildMetricsJson } from "../emit/metricsJson.js";
|
|
|
68
71
|
import { runSystemScope } from "../cli/scopeInputs.js";
|
|
69
72
|
import { buildScopeJson } from "../emit/scopeJson.js";
|
|
70
73
|
import { checkFindingsFile, buildCheckFindingsJson } from "../cli/findings.js";
|
|
74
|
+
import { checkPrdTriage, buildCheckPrdTriageJson } from "../cli/prdTriage.js";
|
|
71
75
|
import { compileForQuery } from "../query/pipeline.js";
|
|
72
76
|
import { buildQuerySystem } from "../query/system.js";
|
|
73
77
|
import { queryConsumers, queryProducers, queryDownstream, queryUpstream, querySlices, queryInvariant, queryField, queryPath, } from "../query/verbs.js";
|
|
@@ -212,12 +216,25 @@ export function createServer() {
|
|
|
212
216
|
"`em validate <file> --json` prints: a pass/fail summary plus every diagnostic (code, " +
|
|
213
217
|
"message, line, refs, usageCategory). Works even when the model has errors — this is " +
|
|
214
218
|
"the tool to call first when you just need to know what's wrong, or to confirm a model " +
|
|
215
|
-
"is clean before exporting it."
|
|
216
|
-
|
|
217
|
-
|
|
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 }) => {
|
|
218
229
|
const compiled = compileWithValidation(file);
|
|
219
230
|
if ("error" in compiled)
|
|
220
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
|
+
}
|
|
221
238
|
return textResult(buildValidateJson(file, compiled.allDiagnostics));
|
|
222
239
|
});
|
|
223
240
|
server.registerTool("slice_ready", {
|
|
@@ -228,16 +245,27 @@ export function createServer() {
|
|
|
228
245
|
"contract current for a public-touching slice), the " +
|
|
229
246
|
"overall `ready` boolean, and the scoped diagnostics behind it. Call this before " +
|
|
230
247
|
"implementing a slice — never infer readiness yourself from `export_slice`'s content.",
|
|
231
|
-
inputSchema: {
|
|
232
|
-
|
|
248
|
+
inputSchema: {
|
|
249
|
+
file: fileParam,
|
|
250
|
+
sliceKey: sliceKeyParam,
|
|
251
|
+
requireRatifiedHash: z
|
|
252
|
+
.boolean()
|
|
253
|
+
.default(false)
|
|
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"),
|
|
259
|
+
},
|
|
260
|
+
}, async ({ file, sliceKey, requireRatifiedHash, roster }) => {
|
|
233
261
|
const compiled = compileWithValidation(file);
|
|
234
262
|
if ("error" in compiled)
|
|
235
263
|
return errorResult(compiled.error);
|
|
236
264
|
const { model, refs, allDiagnostics, source, diagnostics } = compiled;
|
|
237
265
|
const baseDir = dirname(file);
|
|
238
266
|
const contractInput = { file, source, diagnostics };
|
|
239
|
-
const { scoped, ready, result } = computeSliceReadiness(model, refs, baseDir, sliceKey, contractInput, allDiagnostics);
|
|
240
|
-
return textResult(buildSliceReadyJson(file, sliceKey, result?.gates ?? null, scoped, ready, result?.continuationOf ?? 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));
|
|
241
269
|
});
|
|
242
270
|
server.registerTool("slice_sync", {
|
|
243
271
|
title: "Check slice docs' generated regions against the model",
|
|
@@ -478,7 +506,7 @@ export function createServer() {
|
|
|
478
506
|
const emVersion = compiledFiles
|
|
479
507
|
.map(({ file }) => resolveEmVersionStatusEntry(file, GENERATOR_VERSION))
|
|
480
508
|
.filter((e) => e !== null);
|
|
481
|
-
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);
|
|
482
510
|
return textResult(buildStatusJson(report));
|
|
483
511
|
});
|
|
484
512
|
server.registerTool("upgrade", {
|
|
@@ -769,6 +797,20 @@ export function createServer() {
|
|
|
769
797
|
}, async ({ path }) => {
|
|
770
798
|
return textResult(buildCheckFindingsJson(checkFindingsFile(path)));
|
|
771
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
|
+
});
|
|
772
814
|
server.registerTool("query", {
|
|
773
815
|
title: "Deterministic graph queries over the compiled model",
|
|
774
816
|
description: "Return the same JSON document `em query <verb> <files...> --json` prints (MIL-168): " +
|
|
@@ -797,13 +839,14 @@ export function createServer() {
|
|
|
797
839
|
context: z.string().optional().describe("slices: match a slice with an event in this @Context"),
|
|
798
840
|
persona: z.string().optional().describe("slices: match a slice with a ui in this @Persona"),
|
|
799
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"),
|
|
800
843
|
id: z.string().optional().describe("invariant: the INV-* id to look up"),
|
|
801
844
|
testsDir: z.string().optional().describe("invariant: directory to scan for test files citing this id"),
|
|
802
845
|
name: z.string().optional().describe("field: the field's name"),
|
|
803
846
|
from: z.string().optional().describe("path: the starting element's export ref or display name"),
|
|
804
847
|
to: z.string().optional().describe("path: the ending element's export ref or display name"),
|
|
805
848
|
},
|
|
806
|
-
}, 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 }) => {
|
|
807
850
|
if (testsDir !== undefined) {
|
|
808
851
|
if (!existsSync(testsDir))
|
|
809
852
|
return errorResult(`testsDir not found: ${testsDir}`);
|
|
@@ -848,7 +891,7 @@ export function createServer() {
|
|
|
848
891
|
return textResult(buildQueryJson(verb, files, { of, depth: depth ?? null }, result.results));
|
|
849
892
|
}
|
|
850
893
|
case "slices": {
|
|
851
|
-
const filters = { pattern, status, context, persona, tag };
|
|
894
|
+
const filters = { pattern, status, context, persona, tag, storyline };
|
|
852
895
|
const result = querySlices(system, filters);
|
|
853
896
|
if (!result.ok)
|
|
854
897
|
return errorResult(result.error);
|
|
@@ -979,7 +1022,9 @@ export function createServer() {
|
|
|
979
1022
|
"the engagement's slices in dependency levels over model.edges (loops-to excluded), each " +
|
|
980
1023
|
"with its --slice-ready verdict, branch impl/<key>, base (always main — every slice PR " +
|
|
981
1024
|
"targets main, MIL-280), and any computed hold (not-ready, " +
|
|
982
|
-
"upstream-outside-engagement-unmerged); level widths vs the parallel ceiling
|
|
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`) — " +
|
|
1026
|
+
"the model-wide gaps the engagement's slices share (repeated-invariant, event-without-tag, shared-trigger, " +
|
|
1027
|
+
"doc-model-mismatch), to put to the human in ONE question round before fan-out. Read-only. " +
|
|
983
1028
|
"Tool error when the engagement is missing or has a cycle.",
|
|
984
1029
|
inputSchema: { file: fileParam, slug: slugParam },
|
|
985
1030
|
}, async ({ file, slug }) => {
|
|
@@ -1009,6 +1054,26 @@ export function createServer() {
|
|
|
1009
1054
|
return errorResult(`em engagement status: ${result.message}`);
|
|
1010
1055
|
return textResult(buildEngagementStatusJson(result.status));
|
|
1011
1056
|
});
|
|
1057
|
+
server.registerTool("engagement_foundation", {
|
|
1058
|
+
title: "Check the foundation PR is in the code for an engagement's events",
|
|
1059
|
+
description: "Return the same JSON document `em engagement foundation <file> <slug> --code <dir> --json` prints (GH #240): " +
|
|
1060
|
+
"for every event the engagement's slices emit or consume, whether a file under `code` carries an identifier " +
|
|
1061
|
+
"derived from its name (OrderPlaced / order_placed / ORDER_PLACED / order-placed) and, in those files, each " +
|
|
1062
|
+
"model field and tag field — per event `present` | `incomplete` (missingFields / missingTagFields named) | " +
|
|
1063
|
+
"`missing-event`, so the lead can tell \"foundation absent\" from \"foundation incomplete\" before fan-out. " +
|
|
1064
|
+
"A text scan, not a type check. Read-only.",
|
|
1065
|
+
inputSchema: { file: fileParam, slug: slugParam, code: z.string().describe("the target repository directory to scan") },
|
|
1066
|
+
}, async ({ file, slug, code }) => {
|
|
1067
|
+
if (!existsSync(code) || !statSync(code).isDirectory())
|
|
1068
|
+
return errorResult(`em engagement foundation: --code ${code} is not a directory`);
|
|
1069
|
+
const compiled = compileFile(file);
|
|
1070
|
+
if ("error" in compiled)
|
|
1071
|
+
return errorResult(compiled.error);
|
|
1072
|
+
const members = engagementMembersFor({ file, model: compiled.model, refs: compiled.refs, baseDir: dirname(file) }, slug);
|
|
1073
|
+
if (!members.ok)
|
|
1074
|
+
return errorResult(`em engagement foundation: ${members.message}`);
|
|
1075
|
+
return textResult(buildEngagementFoundationJson(file, slug, checkFoundation(compiled.model, members.members, members.idx, code)));
|
|
1076
|
+
});
|
|
1012
1077
|
return server;
|
|
1013
1078
|
}
|
|
1014
1079
|
//# sourceMappingURL=server.js.map
|