@milehimikey/em 1.21.0 → 1.22.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 +10 -0
- package/.claude/agents/em-validator.md +1 -0
- package/.claude/skills/event-modeling/SKILL.md +1 -1
- package/.claude/skills/event-modeling-conform/SKILL.md +7 -4
- package/.claude/skills/event-modeling-conform/reference/conform.md +82 -4
- package/.claude/skills/event-modeling-design/SKILL.md +5 -2
- package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
- package/.claude/skills/event-modeling-engagement/SKILL.md +1 -1
- package/.claude/skills/event-modeling-engagement/reference/engagement.md +1 -0
- package/.claude/skills/event-modeling-implement/SKILL.md +5 -3
- package/.claude/skills/event-modeling-implement/reference/implement.md +14 -0
- package/.claude/skills/event-modeling-review/SKILL.md +1 -1
- package/.claude/skills/event-modeling-shared/reference/em-dsl.md +55 -6
- package/.claude/skills/event-modeling-shared/reference/operating-principles.md +26 -15
- package/.claude-plugin/marketplace.json +2 -2
- package/dist/cli/api.d.ts +136 -9
- package/dist/cli/api.js +278 -27
- package/dist/cli/api.js.map +1 -1
- package/dist/cli/bindings.d.ts +152 -0
- package/dist/cli/bindings.js +462 -0
- package/dist/cli/bindings.js.map +1 -0
- package/dist/cli/conformScope.d.ts +32 -0
- package/dist/cli/conformScope.js +68 -5
- package/dist/cli/conformScope.js.map +1 -1
- package/dist/cli/engagement.d.ts +24 -1
- package/dist/cli/engagement.js +50 -6
- package/dist/cli/engagement.js.map +1 -1
- package/dist/cli/engagementBrief.d.ts +127 -0
- package/dist/cli/engagementBrief.js +313 -0
- package/dist/cli/engagementBrief.js.map +1 -0
- package/dist/cli/engagementFile.d.ts +14 -0
- package/dist/cli/engagementFile.js +54 -0
- package/dist/cli/engagementFile.js.map +1 -1
- package/dist/cli/scopeInputs.js +2 -2
- package/dist/cli/scopeInputs.js.map +1 -1
- package/dist/cli/status.d.ts +5 -0
- package/dist/cli/status.js +1 -0
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/upgrade.js +9 -10
- package/dist/cli/upgrade.js.map +1 -1
- package/dist/cli.js +143 -11
- package/dist/cli.js.map +1 -1
- package/dist/emit/api.d.ts +26 -1
- package/dist/emit/api.js +183 -25
- package/dist/emit/api.js.map +1 -1
- package/dist/emit/apiSurfaceJson.d.ts +3 -0
- package/dist/emit/apiSurfaceJson.js +43 -0
- package/dist/emit/apiSurfaceJson.js.map +1 -0
- package/dist/emit/diffJson.d.ts +1 -1
- package/dist/emit/diffJson.js +20 -1
- package/dist/emit/diffJson.js.map +1 -1
- package/dist/emit/engagementJson.d.ts +8 -3
- package/dist/emit/engagementJson.js +31 -4
- package/dist/emit/engagementJson.js.map +1 -1
- package/dist/emit/json.d.ts +42 -1
- package/dist/emit/json.js +65 -6
- package/dist/emit/json.js.map +1 -1
- package/dist/mcp/server.js +92 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/diff.d.ts +19 -1
- package/dist/model/diff.js +99 -0
- package/dist/model/diff.js.map +1 -1
- package/dist/model/model.d.ts +105 -9
- package/dist/model/model.js +116 -20
- package/dist/model/model.js.map +1 -1
- package/dist/model/refs.d.ts +4 -0
- package/dist/model/refs.js +35 -1
- package/dist/model/refs.js.map +1 -1
- package/dist/model/rules.d.ts +61 -0
- package/dist/model/rules.js +72 -0
- package/dist/model/rules.js.map +1 -1
- package/dist/model/validate.js +137 -4
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/ast.d.ts +30 -0
- package/dist/parser/parser.js +67 -1
- package/dist/parser/parser.js.map +1 -1
- package/dist/render/sliceDiagram.js +6 -0
- package/dist/render/sliceDiagram.js.map +1 -1
- package/dist/render/storylineDiagram.js +6 -0
- package/dist/render/storylineDiagram.js.map +1 -1
- package/dist/system/adaptation.d.ts +5 -2
- package/dist/system/adaptation.js +5 -3
- package/dist/system/adaptation.js.map +1 -1
- package/dist/templates.d.ts +4 -0
- package/dist/templates.js +29 -0
- package/dist/templates.js.map +1 -1
- package/package.json +2 -1
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/agents/em-implementer.md +10 -0
- package/plugin/agents/em-validator.md +1 -0
- package/plugin/shared/reference/em-dsl.md +55 -6
- package/plugin/shared/reference/operating-principles.md +26 -15
- package/plugin/skills/conform/SKILL.md +7 -4
- package/plugin/skills/conform/reference/conform.md +82 -4
- package/plugin/skills/design/SKILL.md +5 -2
- package/plugin/skills/discover/SKILL.md +1 -1
- package/plugin/skills/engagement/SKILL.md +1 -1
- package/plugin/skills/engagement/reference/engagement.md +1 -0
- package/plugin/skills/event-modeling/SKILL.md +1 -1
- package/plugin/skills/implement/SKILL.md +5 -3
- package/plugin/skills/implement/reference/implement.md +14 -0
- package/plugin/skills/review/SKILL.md +1 -1
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// GH #449: the per-slice bindings manifest — `conformance/bindings/<slice-key>.yaml`, beside the
|
|
3
|
+
// model. It is a FILE CONTRACT, not a CLI feature: any implementer that can commit a file can
|
|
4
|
+
// write one by hand (see docs/bindings.md for the full schema an em-less agent can author from).
|
|
5
|
+
// This module is `em`'s read side only — it never writes a bindings file.
|
|
6
|
+
//
|
|
7
|
+
// Two halves, both here:
|
|
8
|
+
// - `parseBindingsFile`: shape-validate the YAML (`yaml`'s `parseDocument` + `LineCounter`, the
|
|
9
|
+
// exact approach src/system/manifest.ts already uses for `system.yaml` — no new dependency).
|
|
10
|
+
// Pure: text in, a `BindingsFile` or line-numbered errors out. Never touches the filesystem.
|
|
11
|
+
// - `runBindingsCheck` and friends: `em conform bindings check` — deterministic, grep-level
|
|
12
|
+
// verification that every bound file exists under `--repo` and contains its bound identifier
|
|
13
|
+
// (plain substring, never code-parsed — language-agnostic by construction). Also resolves
|
|
14
|
+
// each element's `ref` against the compiled model's own export refs (model/refs.ts), so a
|
|
15
|
+
// bindings file that drifted from a renamed/removed element is caught as `unknown-ref`
|
|
16
|
+
// rather than silently "passing" because nobody looked at the file content.
|
|
17
|
+
//
|
|
18
|
+
// Advisory only (GH #449's own words): nothing here is wired into `em validate` or
|
|
19
|
+
// `--slice-ready`, and `em conform bindings check`'s exit code stays 0 unless `--exit-code` is
|
|
20
|
+
// given — the same opt-in-gate posture as `em refs --reachable-from`.
|
|
21
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
22
|
+
import { join } from "node:path";
|
|
23
|
+
import { LineCounter, parseDocument, isMap, isSeq, isScalar } from "yaml";
|
|
24
|
+
/** The bindings-file schema version `em` writes expectations against. There is no writer in
|
|
25
|
+
* `em` itself (the file contract is hand-authored, or written by any other tool) — this is
|
|
26
|
+
* purely what `parseBindingsFile` accepts. */
|
|
27
|
+
export const BINDINGS_SCHEMA_VERSION = "1.0";
|
|
28
|
+
/** Where every per-slice bindings file lives, relative to the model's own directory. */
|
|
29
|
+
export const BINDINGS_DIR = "conformance/bindings";
|
|
30
|
+
/** The conventional path for one slice's bindings file, relative to the model directory. */
|
|
31
|
+
export function bindingsFilePath(sliceKey) {
|
|
32
|
+
return `${BINDINGS_DIR}/${sliceKey}.yaml`;
|
|
33
|
+
}
|
|
34
|
+
/** A `<kind>.<slug>` element ref, lowercase dot-separated — the bare form valid WITHIN a bindings
|
|
35
|
+
* file (the slice itself is already named by the file, so no `<sliceKey>/` prefix like `em
|
|
36
|
+
* export`'s refs carry). */
|
|
37
|
+
const REF_RE = /^[a-z][a-z0-9]*\.[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
38
|
+
const TOP_KEYS = new Set(["bindingsSchemaVersion", "slice", "elements", "invariants"]);
|
|
39
|
+
const ELEMENT_KEYS = new Set(["ref", "file", "identifier", "note"]);
|
|
40
|
+
const INVARIANT_KEYS = new Set(["id", "enforcedIn", "testedIn"]);
|
|
41
|
+
const SITE_KEYS = new Set(["file", "identifier"]);
|
|
42
|
+
/**
|
|
43
|
+
* Shape-validate a bindings file's YAML text. `expectedSlice`, when given, is the slice key the
|
|
44
|
+
* file's NAME says it binds (`conformance/bindings/<expectedSlice>.yaml`) — a `slice:` field
|
|
45
|
+
* disagreeing with it is a shape error, since "per-slice, named by the file" is the convention
|
|
46
|
+
* the whole scheme (parallel slice PRs never touching the same file) depends on. Never throws;
|
|
47
|
+
* every problem is a `"line N: ..."`-prefixed string (no line for a document-level problem),
|
|
48
|
+
* document-level issues first, then one entry at a time — same error style
|
|
49
|
+
* src/system/manifest.ts's `parseManifest` uses for the sibling `system.yaml` contract.
|
|
50
|
+
*/
|
|
51
|
+
export function parseBindingsFile(text, expectedSlice) {
|
|
52
|
+
const errors = [];
|
|
53
|
+
const lineCounter = new LineCounter();
|
|
54
|
+
const doc = parseDocument(text, { lineCounter, prettyErrors: false });
|
|
55
|
+
const lineOf = (node) => {
|
|
56
|
+
const range = node && typeof node === "object" && "range" in node ? node.range : undefined;
|
|
57
|
+
return range ? lineCounter.linePos(range[0]).line : undefined;
|
|
58
|
+
};
|
|
59
|
+
const invalid = (message, line) => errors.push(line !== undefined ? `line ${line}: ${message}` : message);
|
|
60
|
+
if (doc.errors.length > 0) {
|
|
61
|
+
for (const e of doc.errors)
|
|
62
|
+
invalid(`YAML parse error: ${e.message.trim()}`, e.linePos?.[0]?.line);
|
|
63
|
+
return { ok: false, errors };
|
|
64
|
+
}
|
|
65
|
+
const root = doc.contents;
|
|
66
|
+
if (!isMap(root)) {
|
|
67
|
+
invalid("bindings file must be a YAML mapping with `bindingsSchemaVersion`, `slice`, `elements`, `invariants`");
|
|
68
|
+
return { ok: false, errors };
|
|
69
|
+
}
|
|
70
|
+
for (const pair of root.items) {
|
|
71
|
+
const key = scalarString(pair.key);
|
|
72
|
+
if (key === undefined || !TOP_KEYS.has(key)) {
|
|
73
|
+
invalid(`unknown top-level key ${describeKey(pair.key)} — expected one of: ${[...TOP_KEYS].join(", ")}`, lineOf(pair));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const versionNode = root.get("bindingsSchemaVersion", true);
|
|
77
|
+
const version = scalarString(versionNode);
|
|
78
|
+
if (version === undefined) {
|
|
79
|
+
invalid(`missing or non-string \`bindingsSchemaVersion\` — set \`bindingsSchemaVersion: "${BINDINGS_SCHEMA_VERSION}"\``, lineOf(versionNode));
|
|
80
|
+
}
|
|
81
|
+
else if (version !== BINDINGS_SCHEMA_VERSION) {
|
|
82
|
+
invalid(`unsupported bindingsSchemaVersion "${version}" — this em accepts "${BINDINGS_SCHEMA_VERSION}"`, lineOf(versionNode));
|
|
83
|
+
}
|
|
84
|
+
const sliceNode = root.get("slice", true);
|
|
85
|
+
const slice = scalarString(sliceNode);
|
|
86
|
+
if (slice === undefined || slice.trim() === "") {
|
|
87
|
+
invalid("`slice` must be a non-empty string (the slice export key this file binds)", lineOf(sliceNode));
|
|
88
|
+
}
|
|
89
|
+
else if (expectedSlice !== undefined && slice.trim() !== expectedSlice) {
|
|
90
|
+
invalid(`\`slice: ${slice}\` does not match this file's name — a bindings file is named ` +
|
|
91
|
+
`\`${bindingsFilePath(expectedSlice)}\`, so \`slice:\` must be "${expectedSlice}"`, lineOf(sliceNode));
|
|
92
|
+
}
|
|
93
|
+
const elements = [];
|
|
94
|
+
const elementsNode = root.get("elements", true);
|
|
95
|
+
if (elementsNode !== undefined && !isExplicitNull(elementsNode)) {
|
|
96
|
+
if (!isSeq(elementsNode)) {
|
|
97
|
+
invalid("`elements` must be a list of { ref, file, identifier, note? }", lineOf(elementsNode));
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
elementsNode.items.forEach((item, i) => {
|
|
101
|
+
const line = lineOf(item) ?? lineOf(elementsNode);
|
|
102
|
+
if (!isMap(item)) {
|
|
103
|
+
invalid(`elements[${i}] must be a mapping with \`ref\`, \`file\`, \`identifier\``, line);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
for (const p of item.items) {
|
|
107
|
+
const k = scalarString(p.key);
|
|
108
|
+
if (k === undefined || !ELEMENT_KEYS.has(k))
|
|
109
|
+
invalid(`elements[${i}]: unknown key ${describeKey(p.key)} — expected ref, file, identifier, note`, lineOf(p));
|
|
110
|
+
}
|
|
111
|
+
const ref = scalarString(item.get("ref", true));
|
|
112
|
+
const file = scalarString(item.get("file", true));
|
|
113
|
+
const identifier = scalarString(item.get("identifier", true));
|
|
114
|
+
if (ref === undefined || ref.trim() === "")
|
|
115
|
+
invalid(`elements[${i}]: \`ref\` must be a non-empty string ("<kind>.<slug>")`, line);
|
|
116
|
+
else if (!REF_RE.test(ref.trim()))
|
|
117
|
+
invalid(`elements[${i}]: \`ref\` "${ref}" doesn't look like "<kind>.<slug>" (lowercase, dot-separated, e.g. "event.order-placed")`, line);
|
|
118
|
+
if (file === undefined || file.trim() === "")
|
|
119
|
+
invalid(`elements[${i}]: \`file\` must be a non-empty repo-relative path`, line);
|
|
120
|
+
if (identifier === undefined || identifier.trim() === "")
|
|
121
|
+
invalid(`elements[${i}]: \`identifier\` must be a non-empty string`, line);
|
|
122
|
+
const noteNode = item.get("note", true);
|
|
123
|
+
let note = null;
|
|
124
|
+
if (noteNode !== undefined && !isExplicitNull(noteNode)) {
|
|
125
|
+
const n = scalarString(noteNode);
|
|
126
|
+
if (n === undefined)
|
|
127
|
+
invalid(`elements[${i}]: \`note\` must be a string`, lineOf(noteNode));
|
|
128
|
+
else
|
|
129
|
+
note = n;
|
|
130
|
+
}
|
|
131
|
+
if (ref !== undefined && ref.trim() !== "" && file !== undefined && file.trim() !== "" && identifier !== undefined && identifier.trim() !== "") {
|
|
132
|
+
elements.push({ ref: ref.trim(), file: file.trim(), identifier, note });
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const invariants = [];
|
|
138
|
+
const invariantsNode = root.get("invariants", true);
|
|
139
|
+
if (invariantsNode !== undefined && !isExplicitNull(invariantsNode)) {
|
|
140
|
+
if (!isSeq(invariantsNode)) {
|
|
141
|
+
invalid("`invariants` must be a list of { id, enforcedIn: {file, identifier}, testedIn: {file, identifier} }", lineOf(invariantsNode));
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
invariantsNode.items.forEach((item, i) => {
|
|
145
|
+
const line = lineOf(item) ?? lineOf(invariantsNode);
|
|
146
|
+
if (!isMap(item)) {
|
|
147
|
+
invalid(`invariants[${i}] must be a mapping with \`id\`, \`enforcedIn\`, \`testedIn\``, line);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
for (const p of item.items) {
|
|
151
|
+
const k = scalarString(p.key);
|
|
152
|
+
if (k === undefined || !INVARIANT_KEYS.has(k))
|
|
153
|
+
invalid(`invariants[${i}]: unknown key ${describeKey(p.key)} — expected id, enforcedIn, testedIn`, lineOf(p));
|
|
154
|
+
}
|
|
155
|
+
const id = scalarString(item.get("id", true));
|
|
156
|
+
if (id === undefined || id.trim() === "")
|
|
157
|
+
invalid(`invariants[${i}]: \`id\` must be a non-empty string ("INV-...")`, line);
|
|
158
|
+
else if (!/^INV-/.test(id.trim()))
|
|
159
|
+
invalid(`invariants[${i}]: \`id\` "${id}" doesn't look like an INV-* token`, line);
|
|
160
|
+
const parseSite = (key) => {
|
|
161
|
+
const siteNode = item.get(key, true);
|
|
162
|
+
const siteLine = lineOf(siteNode) ?? line;
|
|
163
|
+
if (!isMap(siteNode)) {
|
|
164
|
+
invalid(`invariants[${i}].${key} must be a mapping with \`file\`, \`identifier\``, siteLine);
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
for (const p of siteNode.items) {
|
|
168
|
+
const k = scalarString(p.key);
|
|
169
|
+
if (k === undefined || !SITE_KEYS.has(k))
|
|
170
|
+
invalid(`invariants[${i}].${key}: unknown key ${describeKey(p.key)} — expected file, identifier`, lineOf(p));
|
|
171
|
+
}
|
|
172
|
+
const file = scalarString(siteNode.get("file", true));
|
|
173
|
+
const identifier = scalarString(siteNode.get("identifier", true));
|
|
174
|
+
if (file === undefined || file.trim() === "")
|
|
175
|
+
invalid(`invariants[${i}].${key}.file must be a non-empty repo-relative path`, siteLine);
|
|
176
|
+
if (identifier === undefined || identifier.trim() === "")
|
|
177
|
+
invalid(`invariants[${i}].${key}.identifier must be a non-empty string`, siteLine);
|
|
178
|
+
if (file !== undefined && file.trim() !== "" && identifier !== undefined && identifier.trim() !== "") {
|
|
179
|
+
return { file: file.trim(), identifier };
|
|
180
|
+
}
|
|
181
|
+
return undefined;
|
|
182
|
+
};
|
|
183
|
+
const enforcedIn = parseSite("enforcedIn");
|
|
184
|
+
const testedIn = parseSite("testedIn");
|
|
185
|
+
if (id !== undefined && id.trim() !== "" && enforcedIn && testedIn) {
|
|
186
|
+
invariants.push({ id: id.trim(), enforcedIn, testedIn });
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (errors.length > 0)
|
|
192
|
+
return { ok: false, errors };
|
|
193
|
+
return {
|
|
194
|
+
ok: true,
|
|
195
|
+
doc: { bindingsSchemaVersion: version, slice: slice.trim(), elements, invariants },
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function isExplicitNull(node) {
|
|
199
|
+
return isScalar(node) && node.value === null;
|
|
200
|
+
}
|
|
201
|
+
/** A scalar node's value as a string — `undefined` for a missing node, a non-scalar, or a
|
|
202
|
+
* non-string scalar (same discipline src/system/manifest.ts's `scalarString` holds: a number/
|
|
203
|
+
* boolean/null is never silently coerced to a string). */
|
|
204
|
+
function scalarString(node) {
|
|
205
|
+
if (!isScalar(node))
|
|
206
|
+
return undefined;
|
|
207
|
+
return typeof node.value === "string" ? node.value : undefined;
|
|
208
|
+
}
|
|
209
|
+
function describeKey(node) {
|
|
210
|
+
if (isScalar(node))
|
|
211
|
+
return `"${String(node.value)}"`;
|
|
212
|
+
return "(non-scalar key)";
|
|
213
|
+
}
|
|
214
|
+
// ---- `em conform bindings check` ----------------------------------------------------------
|
|
215
|
+
export const BINDINGS_CHECK_SCHEMA_VERSION = "1.0";
|
|
216
|
+
/** Every `<slice-key>` with a `conformance/bindings/<slice-key>.yaml` beside the model, sorted —
|
|
217
|
+
* deterministic file order for both the text report and `--json`. `[]` when the directory
|
|
218
|
+
* doesn't exist (bindings are opt-in; no files yet is not an error). */
|
|
219
|
+
export function listBindingsSliceKeys(modelDir) {
|
|
220
|
+
let names;
|
|
221
|
+
try {
|
|
222
|
+
names = readdirSync(join(modelDir, BINDINGS_DIR));
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
return names
|
|
228
|
+
.filter((n) => n.endsWith(".yaml"))
|
|
229
|
+
.map((n) => n.slice(0, -".yaml".length))
|
|
230
|
+
.sort();
|
|
231
|
+
}
|
|
232
|
+
/** The bare `<kind>.<slug>` refs (no `<sliceKey>/` prefix) the compiled model actually declares
|
|
233
|
+
* for `sliceKey` — what a bindings file's `elements[].ref` is checked against. */
|
|
234
|
+
function elementRefsForSlice(refs, sliceKey) {
|
|
235
|
+
const prefix = `${sliceKey}/`;
|
|
236
|
+
const out = new Set();
|
|
237
|
+
for (const ref of refs.refById.values()) {
|
|
238
|
+
if (ref.startsWith(prefix))
|
|
239
|
+
out.add(ref.slice(prefix.length));
|
|
240
|
+
}
|
|
241
|
+
return out;
|
|
242
|
+
}
|
|
243
|
+
/** Grep-level only: does `file` (resolved under `repoDir`) exist, and does it contain
|
|
244
|
+
* `identifier` as a plain substring. Never parses code, never cares about language. */
|
|
245
|
+
function checkSite(repoDir, site) {
|
|
246
|
+
const absPath = join(repoDir, site.file);
|
|
247
|
+
let fileExists = false;
|
|
248
|
+
try {
|
|
249
|
+
fileExists = statSync(absPath).isFile();
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
fileExists = false;
|
|
253
|
+
}
|
|
254
|
+
let identifierFound = false;
|
|
255
|
+
if (fileExists) {
|
|
256
|
+
try {
|
|
257
|
+
identifierFound = readFileSync(absPath, "utf8").includes(site.identifier);
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
identifierFound = false;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return { file: site.file, identifier: site.identifier, fileExists, identifierFound, ok: fileExists && identifierFound };
|
|
264
|
+
}
|
|
265
|
+
function checkElement(repoDir, el, validRefs) {
|
|
266
|
+
if (!validRefs.has(el.ref)) {
|
|
267
|
+
return { ref: el.ref, file: el.file, identifier: el.identifier, note: el.note, knownRef: false, fileExists: null, identifierFound: null, ok: false };
|
|
268
|
+
}
|
|
269
|
+
const site = checkSite(repoDir, el);
|
|
270
|
+
return {
|
|
271
|
+
ref: el.ref,
|
|
272
|
+
file: el.file,
|
|
273
|
+
identifier: el.identifier,
|
|
274
|
+
note: el.note,
|
|
275
|
+
knownRef: true,
|
|
276
|
+
fileExists: site.fileExists,
|
|
277
|
+
identifierFound: site.identifierFound,
|
|
278
|
+
ok: site.ok,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function checkInvariant(repoDir, inv) {
|
|
282
|
+
const enforcedIn = checkSite(repoDir, inv.enforcedIn);
|
|
283
|
+
const testedIn = checkSite(repoDir, inv.testedIn);
|
|
284
|
+
return { id: inv.id, enforcedIn, testedIn, ok: enforcedIn.ok && testedIn.ok };
|
|
285
|
+
}
|
|
286
|
+
function checkOneBindingsFile(refs, modelDir, repoDir, sliceKey) {
|
|
287
|
+
const path = bindingsFilePath(sliceKey);
|
|
288
|
+
const absPath = join(modelDir, path);
|
|
289
|
+
if (!existsSync(absPath)) {
|
|
290
|
+
return { path, slice: sliceKey, kind: "missing", ok: false, errors: [`no bindings file at ${path}`], elements: [], invariants: [] };
|
|
291
|
+
}
|
|
292
|
+
let text;
|
|
293
|
+
try {
|
|
294
|
+
text = readFileSync(absPath, "utf8");
|
|
295
|
+
}
|
|
296
|
+
catch (e) {
|
|
297
|
+
return { path, slice: sliceKey, kind: "malformed", ok: false, errors: [`could not read ${path}: ${e.message}`], elements: [], invariants: [] };
|
|
298
|
+
}
|
|
299
|
+
const parsed = parseBindingsFile(text, sliceKey);
|
|
300
|
+
if (!parsed.ok) {
|
|
301
|
+
return { path, slice: sliceKey, kind: "malformed", ok: false, errors: parsed.errors, elements: [], invariants: [] };
|
|
302
|
+
}
|
|
303
|
+
if (!refs.sliceKeys.includes(parsed.doc.slice)) {
|
|
304
|
+
return { path, slice: parsed.doc.slice, kind: "unknown-slice", ok: false, errors: [`slice "${parsed.doc.slice}" is not in the model`], elements: [], invariants: [] };
|
|
305
|
+
}
|
|
306
|
+
const validRefs = elementRefsForSlice(refs, parsed.doc.slice);
|
|
307
|
+
const elements = parsed.doc.elements.map((el) => checkElement(repoDir, el, validRefs));
|
|
308
|
+
const invariants = parsed.doc.invariants.map((inv) => checkInvariant(repoDir, inv));
|
|
309
|
+
const ok = elements.every((e) => e.ok) && invariants.every((i) => i.ok);
|
|
310
|
+
return { path, slice: parsed.doc.slice, kind: "checked", ok, errors: [], elements, invariants };
|
|
311
|
+
}
|
|
312
|
+
function summarize(files) {
|
|
313
|
+
let filesOk = 0;
|
|
314
|
+
let elementsChecked = 0;
|
|
315
|
+
let elementsOk = 0;
|
|
316
|
+
let invariantsChecked = 0;
|
|
317
|
+
let invariantsOk = 0;
|
|
318
|
+
for (const f of files) {
|
|
319
|
+
if (f.ok)
|
|
320
|
+
filesOk++;
|
|
321
|
+
elementsChecked += f.elements.length;
|
|
322
|
+
elementsOk += f.elements.filter((e) => e.ok).length;
|
|
323
|
+
invariantsChecked += f.invariants.length;
|
|
324
|
+
invariantsOk += f.invariants.filter((i) => i.ok).length;
|
|
325
|
+
}
|
|
326
|
+
return {
|
|
327
|
+
filesChecked: files.length,
|
|
328
|
+
filesOk,
|
|
329
|
+
filesFailed: files.length - filesOk,
|
|
330
|
+
elementsChecked,
|
|
331
|
+
elementsOk,
|
|
332
|
+
elementsFailed: elementsChecked - elementsOk,
|
|
333
|
+
invariantsChecked,
|
|
334
|
+
invariantsOk,
|
|
335
|
+
invariantsFailed: invariantsChecked - invariantsOk,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* `em conform bindings check <model.em> --repo <path> [--slice <key>]`'s core: with `sliceKey`,
|
|
340
|
+
* checks exactly that one `conformance/bindings/<sliceKey>.yaml` (reporting `missing` rather than
|
|
341
|
+
* an empty result when it doesn't exist — the caller asked for this one, by name); without it,
|
|
342
|
+
* checks every bindings file present (an empty `files` list, `ok: true`, when none exist yet —
|
|
343
|
+
* bindings are opt-in). `modelDir` is the model's own directory (`dirname(<model>.em)`, the same
|
|
344
|
+
* convention every doc/note/conformance path in `em` uses); `repoDir` is `--repo`, resolved as
|
|
345
|
+
* given (never required to be a git repository — this check never shells out to git).
|
|
346
|
+
*/
|
|
347
|
+
export function runBindingsCheck(refs, modelDir, repoDir, sliceKey) {
|
|
348
|
+
const sliceKeys = sliceKey !== undefined ? [sliceKey] : listBindingsSliceKeys(modelDir);
|
|
349
|
+
const files = sliceKeys.map((key) => checkOneBindingsFile(refs, modelDir, repoDir, key));
|
|
350
|
+
return { ok: files.every((f) => f.ok), slice: sliceKey ?? null, files, summary: summarize(files) };
|
|
351
|
+
}
|
|
352
|
+
/** `em conform bindings check --json` document. Explicit nulls, deterministic key order, no
|
|
353
|
+
* schema field reused from any other surface. */
|
|
354
|
+
export function buildBindingsCheckJson(result) {
|
|
355
|
+
const doc = {
|
|
356
|
+
bindingsCheckSchemaVersion: BINDINGS_CHECK_SCHEMA_VERSION,
|
|
357
|
+
slice: result.slice,
|
|
358
|
+
ok: result.ok,
|
|
359
|
+
files: result.files.map((f) => ({
|
|
360
|
+
path: f.path,
|
|
361
|
+
slice: f.slice,
|
|
362
|
+
kind: f.kind,
|
|
363
|
+
ok: f.ok,
|
|
364
|
+
errors: f.errors,
|
|
365
|
+
elements: f.elements.map((e) => ({
|
|
366
|
+
ref: e.ref,
|
|
367
|
+
file: e.file,
|
|
368
|
+
identifier: e.identifier,
|
|
369
|
+
note: e.note,
|
|
370
|
+
knownRef: e.knownRef,
|
|
371
|
+
fileExists: e.fileExists,
|
|
372
|
+
identifierFound: e.identifierFound,
|
|
373
|
+
ok: e.ok,
|
|
374
|
+
})),
|
|
375
|
+
invariants: f.invariants.map((i) => ({
|
|
376
|
+
id: i.id,
|
|
377
|
+
enforcedIn: {
|
|
378
|
+
file: i.enforcedIn.file,
|
|
379
|
+
identifier: i.enforcedIn.identifier,
|
|
380
|
+
fileExists: i.enforcedIn.fileExists,
|
|
381
|
+
identifierFound: i.enforcedIn.identifierFound,
|
|
382
|
+
ok: i.enforcedIn.ok,
|
|
383
|
+
},
|
|
384
|
+
testedIn: {
|
|
385
|
+
file: i.testedIn.file,
|
|
386
|
+
identifier: i.testedIn.identifier,
|
|
387
|
+
fileExists: i.testedIn.fileExists,
|
|
388
|
+
identifierFound: i.testedIn.identifierFound,
|
|
389
|
+
ok: i.testedIn.ok,
|
|
390
|
+
},
|
|
391
|
+
ok: i.ok,
|
|
392
|
+
})),
|
|
393
|
+
})),
|
|
394
|
+
summary: result.summary,
|
|
395
|
+
};
|
|
396
|
+
return JSON.stringify(doc, null, 2);
|
|
397
|
+
}
|
|
398
|
+
/** The reason a single element/invariant-site check failed, for the text report — `null` on a
|
|
399
|
+
* pass. Checked in the same order the checker itself short-circuits. Takes the two flags rather
|
|
400
|
+
* than a `SiteCheck` so it also reads an `ElementCheck` with `knownRef: true` (whose
|
|
401
|
+
* `fileExists`/`identifierFound` are booleans in practice, `boolean | null` only in the type —
|
|
402
|
+
* never called on a `knownRef: false` element, which has its own "unknown ref" message). */
|
|
403
|
+
function siteFailureReason(flags) {
|
|
404
|
+
if (!flags.fileExists)
|
|
405
|
+
return "file not found";
|
|
406
|
+
if (!flags.identifierFound)
|
|
407
|
+
return "identifier not found";
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
410
|
+
/** The plain-text report `em conform bindings check` prints (no `--json`): per-binding pass/fail
|
|
411
|
+
* lines, then one summary line. Exported so tests can assert on it without spawning the CLI. */
|
|
412
|
+
export function renderBindingsCheckText(result) {
|
|
413
|
+
const lines = [];
|
|
414
|
+
if (result.files.length === 0) {
|
|
415
|
+
lines.push(result.slice !== null ? `no bindings files found for slice "${result.slice}"` : `no bindings files found (${BINDINGS_DIR}/*.yaml)`);
|
|
416
|
+
return lines.join("\n");
|
|
417
|
+
}
|
|
418
|
+
for (const f of result.files) {
|
|
419
|
+
lines.push(`${f.path} (slice "${f.slice}")`);
|
|
420
|
+
if (f.kind === "missing") {
|
|
421
|
+
lines.push(` [FAIL] ${f.errors[0]}`);
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
if (f.kind === "malformed") {
|
|
425
|
+
lines.push(" [FAIL] malformed bindings file:");
|
|
426
|
+
for (const e of f.errors)
|
|
427
|
+
lines.push(` - ${e}`);
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
if (f.kind === "unknown-slice") {
|
|
431
|
+
lines.push(` [FAIL] ${f.errors[0]}`);
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
if (f.elements.length === 0 && f.invariants.length === 0) {
|
|
435
|
+
lines.push(" (no elements or invariants bound)");
|
|
436
|
+
}
|
|
437
|
+
for (const e of f.elements) {
|
|
438
|
+
if (!e.knownRef) {
|
|
439
|
+
lines.push(` [FAIL] ${e.ref} -> ${e.file} ("${e.identifier}") — unknown element ref (not in the model)`);
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
const reason = siteFailureReason(e);
|
|
443
|
+
lines.push(` [${e.ok ? "ok" : "FAIL"}] ${e.ref} -> ${e.file} ("${e.identifier}")${reason ? ` — ${reason}` : ""}`);
|
|
444
|
+
}
|
|
445
|
+
for (const i of f.invariants) {
|
|
446
|
+
for (const [label, site] of [
|
|
447
|
+
["enforced", i.enforcedIn],
|
|
448
|
+
["tested", i.testedIn],
|
|
449
|
+
]) {
|
|
450
|
+
const reason = siteFailureReason(site);
|
|
451
|
+
lines.push(` [${site.ok ? "ok" : "FAIL"}] ${i.id} ${label}: ${site.file} ("${site.identifier}")${reason ? ` — ${reason}` : ""}`);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
const s = result.summary;
|
|
456
|
+
lines.push("");
|
|
457
|
+
lines.push(`summary: ${s.filesChecked} file(s) checked, ${s.filesFailed} failed; ` +
|
|
458
|
+
`${s.elementsChecked} element binding(s), ${s.elementsFailed} failed; ` +
|
|
459
|
+
`${s.invariantsChecked} invariant binding(s), ${s.invariantsFailed} failed`);
|
|
460
|
+
return lines.join("\n");
|
|
461
|
+
}
|
|
462
|
+
//# sourceMappingURL=bindings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bindings.js","sourceRoot":"","sources":["../../src/cli/bindings.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,11 +17,19 @@ export interface SliceDocFacts {
|
|
|
17
17
|
* pre-1.15 `status: implemented`). The scope predicate, in place of `status === "implemented"`:
|
|
18
18
|
* a slice whose next version is an open `draft` still has shipped code to check. */
|
|
19
19
|
shipped: boolean;
|
|
20
|
+
/** GH #451 (storyline models): the storyline model file this slice's body lives in — posix,
|
|
21
|
+
* relative to the root model's directory (`Slice.file` from model/model.ts) — or `null` for a
|
|
22
|
+
* slice declared in the root file. Echoed on `CandidateSlice` below so the agent knows which
|
|
23
|
+
* scratch file to edit without a second lookup against the model: `<model>-asis.em` when
|
|
24
|
+
* `null`, else that file's own `-asis` sibling (`seedAsisModel`, below). */
|
|
25
|
+
file: string | null;
|
|
20
26
|
}
|
|
21
27
|
export interface CandidateSlice {
|
|
22
28
|
key: string;
|
|
23
29
|
matchedBy: "implementedIn" | "full";
|
|
24
30
|
paths: string[];
|
|
31
|
+
/** GH #451: see `SliceDocFacts.file`. */
|
|
32
|
+
file: string | null;
|
|
25
33
|
}
|
|
26
34
|
/** The `em conform-scope` JSON document (ticket MIL-100). `lastConformance` echoes what was
|
|
27
35
|
* parsed from the state file even under `--full` — the caller always knows what was on record,
|
|
@@ -104,6 +112,14 @@ export declare function changedPathsStaged(repo: string, runGit?: GitRunner, lab
|
|
|
104
112
|
export interface SeedAsisResult {
|
|
105
113
|
asisPath: string;
|
|
106
114
|
gitignoreUpdated: boolean;
|
|
115
|
+
/** GH #451 (storyline models): one entry per storyline model file the root declares (`in` or
|
|
116
|
+
* the default `<slug>/<slug>.em`) — the file byte-copied to its own `-asis` sibling, and the
|
|
117
|
+
* path written into `asisPath`'s own `storyline … in "…"` declaration (see below). `[]` for a
|
|
118
|
+
* model with no storyline files — not omitted, so the JSON shape stays stable either way. */
|
|
119
|
+
storylineFiles: {
|
|
120
|
+
file: string;
|
|
121
|
+
asisFile: string;
|
|
122
|
+
}[];
|
|
107
123
|
}
|
|
108
124
|
/**
|
|
109
125
|
* `--seed-asis`: byte-copy `modelFile` to `<dirname(modelFile)>/<stem>-asis.em`, and make sure
|
|
@@ -115,5 +131,21 @@ export interface SeedAsisResult {
|
|
|
115
131
|
* model the repo holds. Falls back to a `.gitignore` right next to the model when the model
|
|
116
132
|
* isn't inside a git repo at all. Idempotent: never appends a second `*-asis.em` line if one
|
|
117
133
|
* (exactly, on its own line) is already present anywhere in the file.
|
|
134
|
+
*
|
|
135
|
+
* GH #451 (storyline models): a root that declares a storyline without a body (GH #421 — its
|
|
136
|
+
* slices live in their own `<slug>/<slug>.em` file) has NO slice bodies of its own to rewrite in
|
|
137
|
+
* `<model>-asis.em` for an in-scope slice that lives in one of those files — editing the root
|
|
138
|
+
* copy alone leaves the agent nowhere to write the as-is picture, and editing the CANONICAL
|
|
139
|
+
* storyline file directly (the only other file that exists) would corrupt it, not scratch it.
|
|
140
|
+
* So this also byte-copies each storyline file the root declares to its own `-asis` sibling and
|
|
141
|
+
* rewrites the copied root's declaration line to `in` that sibling instead of the canonical file
|
|
142
|
+
* — `em diff <model>.em <model>-asis.em` then reads the canonical file on one side and the
|
|
143
|
+
* scratch copies on the other, exactly as the inline-block case always has. Reparses the root
|
|
144
|
+
* text itself (not a caller-supplied `NormalizedModel`) specifically so `source`/`after` come
|
|
145
|
+
* back exactly as the root declares them, never as the cross-file inheritance
|
|
146
|
+
* `loadModelAst`/`compileModelFile` apply when the root's own declaration omits `source` (a
|
|
147
|
+
* storyline file's own header fills that gap on the COMPILED model, which would otherwise get
|
|
148
|
+
* redundantly copied onto the rewritten root line). A model with no external storylines (the
|
|
149
|
+
* common case) is byte-copied exactly as before — a no-op change for every non-storyline model.
|
|
118
150
|
*/
|
|
119
151
|
export declare function seedAsisModel(modelFile: string, runGit?: GitRunner): SeedAsisResult;
|