@sdd-method/sdd-cli 1.4.0 → 1.6.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/dist/lib/catalogue/coverage-render.d.ts +1 -0
- package/dist/lib/catalogue/coverage-render.d.ts.map +1 -1
- package/dist/lib/catalogue/coverage-render.js +17 -0
- package/dist/lib/catalogue/coverage-render.js.map +1 -1
- package/dist/lib/catalogue/coverage-run.d.ts.map +1 -1
- package/dist/lib/catalogue/coverage-run.js +7 -2
- package/dist/lib/catalogue/coverage-run.js.map +1 -1
- package/dist/lib/catalogue/gate-checks.d.ts +20 -0
- package/dist/lib/catalogue/gate-checks.d.ts.map +1 -1
- package/dist/lib/catalogue/gate-checks.js +67 -0
- package/dist/lib/catalogue/gate-checks.js.map +1 -1
- package/dist/lib/catalogue/graph-projection.d.ts +74 -0
- package/dist/lib/catalogue/graph-projection.d.ts.map +1 -0
- package/dist/lib/catalogue/graph-projection.js +322 -0
- package/dist/lib/catalogue/graph-projection.js.map +1 -0
- package/dist/lib/catalogue/graph-run.d.ts +59 -0
- package/dist/lib/catalogue/graph-run.d.ts.map +1 -0
- package/dist/lib/catalogue/graph-run.js +112 -0
- package/dist/lib/catalogue/graph-run.js.map +1 -0
- package/dist/lib/catalogue/impact-run.d.ts +81 -0
- package/dist/lib/catalogue/impact-run.d.ts.map +1 -0
- package/dist/lib/catalogue/impact-run.js +228 -0
- package/dist/lib/catalogue/impact-run.js.map +1 -0
- package/dist/lib/catalogue/rubric-coverage-map.yaml +279 -0
- package/dist/verbs/catalogue.d.ts.map +1 -1
- package/dist/verbs/catalogue.js +56 -0
- package/dist/verbs/catalogue.js.map +1 -1
- package/package.json +2 -2
- package/scripts/sync-canonical-schema.sh +21 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph projection — `sdd-cli catalogue graph` (M-ADR 0205 §4.6, Phase C0b).
|
|
3
|
+
*
|
|
4
|
+
* Derives a typed node/edge list (JSON Lines) from built catalogues. The
|
|
5
|
+
* projection is DERIVED, never authored, never a second source of truth:
|
|
6
|
+
* regenerated on every run, digest-stamped, not committed. The derivation
|
|
7
|
+
* rule is the C0a rule table (catalogue-engine-evolution plan), keyed on
|
|
8
|
+
* the rubric-coverage-map's `kind` × the schema's FK arity:
|
|
9
|
+
*
|
|
10
|
+
* entity (less `applications`) → nodes, id = "<catalogue>/<pk>"
|
|
11
|
+
* entity FK columns → edges typed "<catalogue>.<column>"
|
|
12
|
+
* edge, 2 FKs → edges, declaration order = source→target;
|
|
13
|
+
* a row with an empty nullable endpoint
|
|
14
|
+
* degrades to a property record, never an edge
|
|
15
|
+
* edge, 3 FKs → edges with declared endpoint pairs
|
|
16
|
+
* (THREE_FK_ENDPOINTS below)
|
|
17
|
+
* edge, 1 FK → property records on the FK owner
|
|
18
|
+
* `applications` → excluded (C0a ruling 2026-08-06: filtered
|
|
19
|
+
* view of products — its rows ARE product
|
|
20
|
+
* rows; emitting it creates edge-less
|
|
21
|
+
* shadow nodes beside the products nodes)
|
|
22
|
+
* finding / enum kinds → excluded (diagnostics / vocabularies)
|
|
23
|
+
*
|
|
24
|
+
* Emission reads the PARSED CSV ROWS, deliberately not an engine readback:
|
|
25
|
+
* the engine's load TRY_CASTs typed columns and silently nulls unparseable
|
|
26
|
+
* cells (a real, measured case: prose in a date-typed column). A projection
|
|
27
|
+
* that inherits cast smoothing is no longer a faithful derivation of the
|
|
28
|
+
* CSV canon. C1's impact queries run on the engine; this emission does not.
|
|
29
|
+
*
|
|
30
|
+
* Every edge endpoint and property owner MUST resolve to a node record in
|
|
31
|
+
* the same export — a dangling reference here is a defect in the projection,
|
|
32
|
+
* not a finding about the estate (the FK layer already reports those). A
|
|
33
|
+
* candidate whose endpoint does not resolve is OMITTED and COUNTED, loudly,
|
|
34
|
+
* in the header and summary: `omitted_external` for external /
|
|
35
|
+
* external-for-profiles FKs (expected at member tier, resolving at
|
|
36
|
+
* aggregate), `omitted_unresolved` for the rest (mirrors an FK-layer
|
|
37
|
+
* finding). Stub nodes are never emitted — inventing nodes is the failure
|
|
38
|
+
* mode the C0a rule exists to prevent.
|
|
39
|
+
*/
|
|
40
|
+
import { createHash } from "node:crypto";
|
|
41
|
+
/** Node-kind catalogues excluded from projection by C0a ruling. */
|
|
42
|
+
const EXCLUDED_NODE_CATALOGUES = new Set(["applications"]);
|
|
43
|
+
/**
|
|
44
|
+
* Declared endpoint pairs for the three 3-FK edge catalogues (C0a).
|
|
45
|
+
* `product_platform_dependencies` is SERVICE-FIRST — the aggregator already
|
|
46
|
+
* derives product→capability (cross_sdd_platform_capability) by joining
|
|
47
|
+
* target_service_id, so a capability-first rule would emit the same
|
|
48
|
+
* relationship twice; its resolution is per-row in projectRow below.
|
|
49
|
+
*/
|
|
50
|
+
const THREE_FK_ENDPOINTS = {
|
|
51
|
+
system_external_dependency: ["c4_system_id", "external_system_id"],
|
|
52
|
+
cross_sdd_platform_capability: [
|
|
53
|
+
"consuming_product_id",
|
|
54
|
+
"platform_capability_id",
|
|
55
|
+
],
|
|
56
|
+
product_platform_dependencies: null, // per-row: target_service_id, else target_capability_id
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Kinds must cover every schema catalogue — a catalogue without a kind
|
|
60
|
+
* cannot be classified and the projection must not guess (the map is
|
|
61
|
+
* guarded method-side by the entity-scoring-coverage correspondence
|
|
62
|
+
* instance; this is the consumer-side half of that guarantee).
|
|
63
|
+
*/
|
|
64
|
+
export function assertKindCoverage(schema, kinds) {
|
|
65
|
+
const missing = schema.catalogues
|
|
66
|
+
.map((c) => c.name)
|
|
67
|
+
.filter((n) => !kinds.has(n));
|
|
68
|
+
if (missing.length > 0) {
|
|
69
|
+
throw new Error(`rubric-coverage-map has no kind for: ${missing.join(", ")} — ` +
|
|
70
|
+
`sync the vendored map (it must cover every schema catalogue).`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export function projectGraph(schema, kinds, rowsByCatalogue, tier,
|
|
74
|
+
/**
|
|
75
|
+
* When provided (M-ADR 0206 §4.6), every edge record is stamped with its
|
|
76
|
+
* declared `class` and RESOLVED `impact_flow` (role-conditional flows
|
|
77
|
+
* resolve per row), so consumers need no map lookup. Additive fields; the
|
|
78
|
+
* export regenerates per run, so the format change costs one restated
|
|
79
|
+
* determinism proof.
|
|
80
|
+
*/
|
|
81
|
+
semantics) {
|
|
82
|
+
assertKindCoverage(schema, kinds);
|
|
83
|
+
const stampFor = (type, props) => {
|
|
84
|
+
if (semantics === undefined)
|
|
85
|
+
return {};
|
|
86
|
+
const decl = type.includes(".")
|
|
87
|
+
? semantics.entityFks.get(type)
|
|
88
|
+
: semantics.edges.get(type);
|
|
89
|
+
if (decl === undefined) {
|
|
90
|
+
throw new Error(`graph: relationship ${type} has no declaration in the ` +
|
|
91
|
+
`rubric-coverage-map (M-ADR 0206) — sync the vendored map.`);
|
|
92
|
+
}
|
|
93
|
+
const flow = decl.impactFlow ??
|
|
94
|
+
decl.impactFlowBy.values[(props[decl.impactFlowBy.column] ?? "").trim()];
|
|
95
|
+
if (flow === undefined) {
|
|
96
|
+
throw new Error(`graph: ${type} resolves flow by column '${decl.impactFlowBy.column}' ` +
|
|
97
|
+
`but the row value is not in the declared map.`);
|
|
98
|
+
}
|
|
99
|
+
return { class: decl.class, impact_flow: flow };
|
|
100
|
+
};
|
|
101
|
+
const nodeCats = schema.catalogues.filter((c) => kinds.get(c.name) === "entity" && !EXCLUDED_NODE_CATALOGUES.has(c.name));
|
|
102
|
+
const edgeCats = schema.catalogues.filter((c) => kinds.get(c.name) === "edge");
|
|
103
|
+
// Pass 1 — the node set. Endpoint resolution below is against THIS
|
|
104
|
+
// export's nodes, which is exactly the per-export invariant.
|
|
105
|
+
const nodeIds = new Set();
|
|
106
|
+
const nodeLines = [];
|
|
107
|
+
for (const cat of nodeCats) {
|
|
108
|
+
for (const row of rowsByCatalogue.get(cat.name) ?? []) {
|
|
109
|
+
const key = cell(row, cat.primaryKey);
|
|
110
|
+
const id = `${cat.name}/${key}`;
|
|
111
|
+
nodeIds.add(id);
|
|
112
|
+
nodeLines.push(jsonLine({
|
|
113
|
+
t: "node",
|
|
114
|
+
id,
|
|
115
|
+
catalogue: cat.name,
|
|
116
|
+
key,
|
|
117
|
+
properties: propsOf(cat, row, new Set([cat.primaryKey])),
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const resolveTarget = (fk, value) => {
|
|
122
|
+
const [refCat, refCol] = fk.references.split(".");
|
|
123
|
+
// The rule resolves FK values against node PKs; a reference to a
|
|
124
|
+
// non-PK column would resolve against the wrong namespace. All 127
|
|
125
|
+
// parsed FKs reference `.id` today — guard it rather than assume it.
|
|
126
|
+
const refDef = schema.catalogues.find((c) => c.name === refCat);
|
|
127
|
+
if (refDef && refDef.primaryKey !== refCol) {
|
|
128
|
+
throw new Error(`FK ${fk.column} references non-PK column ${fk.references} — ` +
|
|
129
|
+
`the projection cannot resolve non-PK references.`);
|
|
130
|
+
}
|
|
131
|
+
const target = `${refCat}/${value}`;
|
|
132
|
+
return nodeIds.has(target) ? target : null;
|
|
133
|
+
};
|
|
134
|
+
const isExternal = (fk) => fk.external || (fk.externalForProfiles ?? []).length > 0;
|
|
135
|
+
const edgeLines = [];
|
|
136
|
+
const propertyLines = [];
|
|
137
|
+
const omissions = { external: 0, unresolved: 0 };
|
|
138
|
+
const emitEdge = (cat, row, type, sourceFk, targetFk) => {
|
|
139
|
+
const sv = cell(row, sourceFk.column);
|
|
140
|
+
const tv = cell(row, targetFk.column);
|
|
141
|
+
const source = resolveTarget(sourceFk, sv);
|
|
142
|
+
const target = resolveTarget(targetFk, tv);
|
|
143
|
+
if (source === null || target === null) {
|
|
144
|
+
const failedFk = source === null ? sourceFk : targetFk;
|
|
145
|
+
if (isExternal(failedFk))
|
|
146
|
+
omissions.external += 1;
|
|
147
|
+
else
|
|
148
|
+
omissions.unresolved += 1;
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const props = propsOf(cat, row, new Set([sourceFk.column, targetFk.column]));
|
|
152
|
+
edgeLines.push(jsonLine({
|
|
153
|
+
t: "edge",
|
|
154
|
+
type,
|
|
155
|
+
...stampFor(type, props),
|
|
156
|
+
source,
|
|
157
|
+
target,
|
|
158
|
+
properties: props,
|
|
159
|
+
}));
|
|
160
|
+
};
|
|
161
|
+
const emitProperty = (cat, row, ownerFk) => {
|
|
162
|
+
const ov = cell(row, ownerFk.column);
|
|
163
|
+
const owner = ov === "" ? null : resolveTarget(ownerFk, ov);
|
|
164
|
+
if (owner === null) {
|
|
165
|
+
if (ov !== "" && isExternal(ownerFk))
|
|
166
|
+
omissions.external += 1;
|
|
167
|
+
else
|
|
168
|
+
omissions.unresolved += 1;
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
propertyLines.push(jsonLine({
|
|
172
|
+
t: "property",
|
|
173
|
+
owner,
|
|
174
|
+
catalogue: cat.name,
|
|
175
|
+
via: ownerFk.column,
|
|
176
|
+
properties: propsOf(cat, row, new Set([ownerFk.column])),
|
|
177
|
+
}));
|
|
178
|
+
};
|
|
179
|
+
// Pass 2a — edges from edge catalogues, schema declaration order.
|
|
180
|
+
for (const cat of edgeCats) {
|
|
181
|
+
const fks = cat.foreignKeys;
|
|
182
|
+
for (const row of rowsByCatalogue.get(cat.name) ?? []) {
|
|
183
|
+
if (fks.length === 1) {
|
|
184
|
+
// Attribute table the metamodel calls an edge: the other "end" is
|
|
185
|
+
// an enum/key/name — a property record, never an edge.
|
|
186
|
+
emitProperty(cat, row, fks[0]);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
let sourceFk;
|
|
190
|
+
let targetFk;
|
|
191
|
+
if (fks.length === 2) {
|
|
192
|
+
[sourceFk, targetFk] = fks;
|
|
193
|
+
}
|
|
194
|
+
else if (cat.name === "product_platform_dependencies") {
|
|
195
|
+
sourceFk = fks.find((f) => f.column === "product_id");
|
|
196
|
+
const svc = cell(row, "target_service_id");
|
|
197
|
+
const cap = cell(row, "target_capability_id");
|
|
198
|
+
const targetCol = svc !== ""
|
|
199
|
+
? "target_service_id"
|
|
200
|
+
: cap !== ""
|
|
201
|
+
? "target_capability_id"
|
|
202
|
+
: null;
|
|
203
|
+
if (targetCol === null) {
|
|
204
|
+
// Neither target declared: property-only row on the product.
|
|
205
|
+
emitProperty(cat, row, sourceFk);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
targetFk = fks.find((f) => f.column === targetCol);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
const pair = THREE_FK_ENDPOINTS[cat.name];
|
|
212
|
+
if (pair === undefined || pair === null) {
|
|
213
|
+
throw new Error(`edge catalogue ${cat.name} has ${fks.length} FKs and no declared ` +
|
|
214
|
+
`endpoint pair — extend THREE_FK_ENDPOINTS (a C0a-level decision, ` +
|
|
215
|
+
`not a default).`);
|
|
216
|
+
}
|
|
217
|
+
sourceFk = fks.find((f) => f.column === pair[0]);
|
|
218
|
+
targetFk = fks.find((f) => f.column === pair[1]);
|
|
219
|
+
}
|
|
220
|
+
if (sourceFk === undefined || targetFk === undefined) {
|
|
221
|
+
throw new Error(`edge catalogue ${cat.name}: declared endpoint column missing from ` +
|
|
222
|
+
`schema foreign_keys — schema and rule table disagree.`);
|
|
223
|
+
}
|
|
224
|
+
const sv = cell(row, sourceFk.column);
|
|
225
|
+
const tv = cell(row, targetFk.column);
|
|
226
|
+
if (sv === "" || tv === "") {
|
|
227
|
+
// Empty nullable endpoint: degrade to a property record on the
|
|
228
|
+
// present endpoint (screen_action is the live case — measured
|
|
229
|
+
// 2026-08-06: all 85+1,652 rows on both estates have no event_id).
|
|
230
|
+
const present = sv !== "" ? sourceFk : tv !== "" ? targetFk : null;
|
|
231
|
+
if (present === null) {
|
|
232
|
+
omissions.unresolved += 1; // no endpoint at all — counted, never guessed
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
emitProperty(cat, row, present);
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
emitEdge(cat, row, cat.name, sourceFk, targetFk);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Pass 2b — edges carried on node rows (41 FK columns on 22 catalogues;
|
|
242
|
+
// 34–40% of all edges on the measured estates — the third of the graph
|
|
243
|
+
// the naive "edge catalogues = edges" rule drops).
|
|
244
|
+
for (const cat of nodeCats) {
|
|
245
|
+
for (const fk of cat.foreignKeys) {
|
|
246
|
+
for (const row of rowsByCatalogue.get(cat.name) ?? []) {
|
|
247
|
+
const value = cell(row, fk.column);
|
|
248
|
+
if (value === "")
|
|
249
|
+
continue;
|
|
250
|
+
const source = `${cat.name}/${cell(row, cat.primaryKey)}`;
|
|
251
|
+
const target = resolveTarget(fk, value);
|
|
252
|
+
if (target === null) {
|
|
253
|
+
if (isExternal(fk))
|
|
254
|
+
omissions.external += 1;
|
|
255
|
+
else
|
|
256
|
+
omissions.unresolved += 1;
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
edgeLines.push(jsonLine({
|
|
260
|
+
t: "edge",
|
|
261
|
+
type: `${cat.name}.${fk.column}`,
|
|
262
|
+
...stampFor(`${cat.name}.${fk.column}`, {}),
|
|
263
|
+
source,
|
|
264
|
+
target,
|
|
265
|
+
properties: {},
|
|
266
|
+
}));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const body = [...nodeLines, ...edgeLines, ...propertyLines];
|
|
271
|
+
const bodyText = body.map((l) => `${l}\n`).join("");
|
|
272
|
+
const digest = createHash("sha256").update(bodyText, "utf8").digest("hex");
|
|
273
|
+
const counts = {
|
|
274
|
+
nodes: nodeLines.length,
|
|
275
|
+
edges: edgeLines.length,
|
|
276
|
+
properties: propertyLines.length,
|
|
277
|
+
omittedExternal: omissions.external,
|
|
278
|
+
omittedUnresolved: omissions.unresolved,
|
|
279
|
+
};
|
|
280
|
+
const header = jsonLine({
|
|
281
|
+
t: "header",
|
|
282
|
+
format: "sdd-graph/1",
|
|
283
|
+
schema_version: schema.schemaVersion,
|
|
284
|
+
tier,
|
|
285
|
+
nodes: counts.nodes,
|
|
286
|
+
edges: counts.edges,
|
|
287
|
+
properties: counts.properties,
|
|
288
|
+
omitted_external: counts.omittedExternal,
|
|
289
|
+
omitted_unresolved: counts.omittedUnresolved,
|
|
290
|
+
digest: `sha256:${digest}`,
|
|
291
|
+
});
|
|
292
|
+
return { text: `${header}\n${bodyText}`, counts, digest };
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Row columns as a properties object: schema column order (deterministic),
|
|
296
|
+
* empty string omitted (the schema's own convention — empty means absent),
|
|
297
|
+
* excluded columns (PK / endpoint / owner) carried structurally instead.
|
|
298
|
+
* Values stay the strings the CSV canon holds — no cast, no smoothing.
|
|
299
|
+
*/
|
|
300
|
+
function propsOf(cat, row, exclude) {
|
|
301
|
+
const out = {};
|
|
302
|
+
for (const col of cat.columns) {
|
|
303
|
+
if (exclude.has(col.name))
|
|
304
|
+
continue;
|
|
305
|
+
const v = row[col.name];
|
|
306
|
+
const s = v === null || v === undefined ? "" : String(v);
|
|
307
|
+
if (s === "")
|
|
308
|
+
continue;
|
|
309
|
+
out[col.name] = s;
|
|
310
|
+
}
|
|
311
|
+
return out;
|
|
312
|
+
}
|
|
313
|
+
/** JSON.stringify with stable insertion-order keys — the whole line contract. */
|
|
314
|
+
function jsonLine(obj) {
|
|
315
|
+
return JSON.stringify(obj);
|
|
316
|
+
}
|
|
317
|
+
/** One cell as the trimmed string the CSV canon holds ('' = absent). */
|
|
318
|
+
function cell(row, column) {
|
|
319
|
+
const v = row[column];
|
|
320
|
+
return v === null || v === undefined ? "" : String(v).trim();
|
|
321
|
+
}
|
|
322
|
+
//# sourceMappingURL=graph-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-projection.js","sourceRoot":"","sources":["../../../src/lib/catalogue/graph-projection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestrator for `sdd-cli catalogue graph` — loads the schema, the
|
|
3
|
+
* vendored rubric-coverage-map (the node/edge kind authority; the schema
|
|
4
|
+
* itself does not declare kind), and the catalogues directory, projects
|
|
5
|
+
* the graph (graph-projection.ts holds the derivation rule), writes the
|
|
6
|
+
* JSONL export, and prints the counts + digest so the figures are stated
|
|
7
|
+
* on every run, not discoverable after the fact.
|
|
8
|
+
*
|
|
9
|
+
* The export is regenerated on every invocation and is NOT committed
|
|
10
|
+
* (M-ADR 0205 §4.6): default output is `<catalogues-dir>-graph.jsonl`
|
|
11
|
+
* beside the catalogues directory, which adopter .gitignore entries cover.
|
|
12
|
+
* Tier is explicit, never inferred, same discipline as every other reader.
|
|
13
|
+
*/
|
|
14
|
+
import { type GraphCounts, type GraphTier } from "./graph-projection.js";
|
|
15
|
+
/**
|
|
16
|
+
* Vendored copy of sdd-method's orchestration/rubric-coverage-map.yaml —
|
|
17
|
+
* byte-identical to the canonical (rubric-coverage-map-drift.test.ts guards
|
|
18
|
+
* it, same one-way contract as canonical-schema.yaml). The build copies it
|
|
19
|
+
* alongside the compiled module via scripts/copy-yaml-assets.mjs.
|
|
20
|
+
*/
|
|
21
|
+
export declare const VENDORED_COVERAGE_MAP_PATH: string;
|
|
22
|
+
/** Impact-flow token (M-ADR 0206 §4.1): which endpoint RECEIVES impact. */
|
|
23
|
+
export type ImpactFlow = "toward-source" | "toward-target" | "both" | "none";
|
|
24
|
+
export interface FlowByColumn {
|
|
25
|
+
readonly column: string;
|
|
26
|
+
readonly values: Readonly<Record<string, ImpactFlow>>;
|
|
27
|
+
}
|
|
28
|
+
export interface RelationshipDecl {
|
|
29
|
+
readonly class: string;
|
|
30
|
+
readonly impactFlow?: ImpactFlow;
|
|
31
|
+
readonly impactFlowBy?: FlowByColumn;
|
|
32
|
+
}
|
|
33
|
+
export interface RelationshipSemantics {
|
|
34
|
+
/** catalogue name -> kind (entity | edge | finding | enum). */
|
|
35
|
+
readonly kinds: ReadonlyMap<string, string>;
|
|
36
|
+
/** edge catalogue name -> its declaration. */
|
|
37
|
+
readonly edges: ReadonlyMap<string, RelationshipDecl>;
|
|
38
|
+
/** "catalogue.column" -> declaration, for entity-carried FKs. */
|
|
39
|
+
readonly entityFks: ReadonlyMap<string, RelationshipDecl>;
|
|
40
|
+
}
|
|
41
|
+
export declare function loadRelationshipSemantics(mapPath?: string): Promise<RelationshipSemantics>;
|
|
42
|
+
export declare function loadCatalogueKinds(mapPath?: string): Promise<Map<string, string>>;
|
|
43
|
+
export interface GraphRunInputs {
|
|
44
|
+
/** SDD repo root (defaults to cwd). */
|
|
45
|
+
readonly sddPath?: string;
|
|
46
|
+
/** Catalogues directory, relative to the SDD root (default `catalogues`). */
|
|
47
|
+
readonly cataloguesDir?: string;
|
|
48
|
+
/** Explicit tier, never inferred. Default member. */
|
|
49
|
+
readonly tier?: GraphTier;
|
|
50
|
+
/** Output path (default `<resolved catalogues dir>-graph.jsonl`). */
|
|
51
|
+
readonly out?: string;
|
|
52
|
+
}
|
|
53
|
+
export interface GraphRunResult {
|
|
54
|
+
readonly exitCode: number;
|
|
55
|
+
readonly counts?: GraphCounts;
|
|
56
|
+
readonly outPath?: string;
|
|
57
|
+
}
|
|
58
|
+
export declare function runCatalogueGraph(inputs: GraphRunInputs, write: (s: string) => void): Promise<GraphRunResult>;
|
|
59
|
+
//# sourceMappingURL=graph-run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-run.d.ts","sourceRoot":"","sources":["../../../src/lib/catalogue/graph-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAUH,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,SAAS,EACf,MAAM,uBAAuB,CAAC;AAE/B;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,QAGtC,CAAC;AAEF,2EAA2E;AAC3E,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,eAAe,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;CACvD;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;CACtC;AAED,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACtD,iEAAiE;IACjE,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC3D;AA6CD,wBAAsB,yBAAyB,CAC7C,OAAO,GAAE,MAAmC,GAC3C,OAAO,CAAC,qBAAqB,CAAC,CAiBhC;AAED,wBAAsB,kBAAkB,CACtC,OAAO,GAAE,MAAmC,GAC3C,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAS9B;AAED,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,qDAAqD;IACrD,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GACzB,OAAO,CAAC,cAAc,CAAC,CA4CzB"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestrator for `sdd-cli catalogue graph` — loads the schema, the
|
|
3
|
+
* vendored rubric-coverage-map (the node/edge kind authority; the schema
|
|
4
|
+
* itself does not declare kind), and the catalogues directory, projects
|
|
5
|
+
* the graph (graph-projection.ts holds the derivation rule), writes the
|
|
6
|
+
* JSONL export, and prints the counts + digest so the figures are stated
|
|
7
|
+
* on every run, not discoverable after the fact.
|
|
8
|
+
*
|
|
9
|
+
* The export is regenerated on every invocation and is NOT committed
|
|
10
|
+
* (M-ADR 0205 §4.6): default output is `<catalogues-dir>-graph.jsonl`
|
|
11
|
+
* beside the catalogues directory, which adopter .gitignore entries cover.
|
|
12
|
+
* Tier is explicit, never inferred, same discipline as every other reader.
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync } from "node:fs";
|
|
15
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
import { join, resolve } from "node:path";
|
|
18
|
+
import { parse as parseYaml } from "yaml";
|
|
19
|
+
import { readCatalogueCsv } from "./csv-reader.js";
|
|
20
|
+
import { loadCanonicalSchema } from "./schema-loader.js";
|
|
21
|
+
import { projectGraph, } from "./graph-projection.js";
|
|
22
|
+
/**
|
|
23
|
+
* Vendored copy of sdd-method's orchestration/rubric-coverage-map.yaml —
|
|
24
|
+
* byte-identical to the canonical (rubric-coverage-map-drift.test.ts guards
|
|
25
|
+
* it, same one-way contract as canonical-schema.yaml). The build copies it
|
|
26
|
+
* alongside the compiled module via scripts/copy-yaml-assets.mjs.
|
|
27
|
+
*/
|
|
28
|
+
export const VENDORED_COVERAGE_MAP_PATH = join(fileURLToPath(new URL(".", import.meta.url)), "rubric-coverage-map.yaml");
|
|
29
|
+
function toDecl(where, e) {
|
|
30
|
+
if (e.class === undefined) {
|
|
31
|
+
throw new Error(`rubric-coverage-map: ${where} has no class declaration (M-ADR 0206)`);
|
|
32
|
+
}
|
|
33
|
+
if ((e.impact_flow === undefined) === (e.impact_flow_by === undefined)) {
|
|
34
|
+
throw new Error(`rubric-coverage-map: ${where} must declare exactly one of impact_flow / impact_flow_by`);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
class: e.class,
|
|
38
|
+
...(e.impact_flow !== undefined
|
|
39
|
+
? { impactFlow: e.impact_flow }
|
|
40
|
+
: {}),
|
|
41
|
+
...(e.impact_flow_by !== undefined
|
|
42
|
+
? {
|
|
43
|
+
impactFlowBy: {
|
|
44
|
+
column: e.impact_flow_by.column,
|
|
45
|
+
values: e.impact_flow_by.values,
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
: {}),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export async function loadRelationshipSemantics(mapPath = VENDORED_COVERAGE_MAP_PATH) {
|
|
52
|
+
const raw = parseYaml(await readFile(mapPath, "utf-8"));
|
|
53
|
+
const kinds = new Map();
|
|
54
|
+
const edges = new Map();
|
|
55
|
+
const entityFks = new Map();
|
|
56
|
+
for (const [name, entry] of Object.entries(raw.coverage)) {
|
|
57
|
+
kinds.set(name, entry.kind);
|
|
58
|
+
if (entry.kind === "edge") {
|
|
59
|
+
edges.set(name, toDecl(`edge ${name}`, entry));
|
|
60
|
+
}
|
|
61
|
+
for (const [col, decl] of Object.entries(entry.relationships ?? {})) {
|
|
62
|
+
entityFks.set(`${name}.${col}`, toDecl(`entity FK ${name}.${col}`, decl));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { kinds, edges, entityFks };
|
|
66
|
+
}
|
|
67
|
+
export async function loadCatalogueKinds(mapPath = VENDORED_COVERAGE_MAP_PATH) {
|
|
68
|
+
const raw = parseYaml(await readFile(mapPath, "utf-8"));
|
|
69
|
+
const kinds = new Map();
|
|
70
|
+
for (const [name, entry] of Object.entries(raw.coverage)) {
|
|
71
|
+
kinds.set(name, entry.kind);
|
|
72
|
+
}
|
|
73
|
+
return kinds;
|
|
74
|
+
}
|
|
75
|
+
export async function runCatalogueGraph(inputs, write) {
|
|
76
|
+
const sddRoot = resolve(inputs.sddPath ?? process.cwd());
|
|
77
|
+
const dir = resolve(sddRoot, inputs.cataloguesDir ?? "catalogues");
|
|
78
|
+
const tier = inputs.tier ?? "member";
|
|
79
|
+
const outPath = inputs.out !== undefined
|
|
80
|
+
? resolve(sddRoot, inputs.out)
|
|
81
|
+
: `${dir}-graph.jsonl`;
|
|
82
|
+
if (!existsSync(dir)) {
|
|
83
|
+
write(`catalogues directory not found at ${dir}\n` +
|
|
84
|
+
` Run \`sdd-cli catalogue build\` (or aggregate) first — the graph ` +
|
|
85
|
+
`is derived from built catalogues, never authored.\n`);
|
|
86
|
+
return { exitCode: 2 };
|
|
87
|
+
}
|
|
88
|
+
const schema = await loadCanonicalSchema();
|
|
89
|
+
const kinds = await loadCatalogueKinds();
|
|
90
|
+
const semantics = await loadRelationshipSemantics();
|
|
91
|
+
const rowsByCatalogue = new Map();
|
|
92
|
+
for (const cat of schema.catalogues) {
|
|
93
|
+
const filePath = join(dir, `${cat.name}.csv`);
|
|
94
|
+
if (!existsSync(filePath))
|
|
95
|
+
continue;
|
|
96
|
+
const parsed = await readCatalogueCsv(filePath);
|
|
97
|
+
rowsByCatalogue.set(cat.name, parsed.rows);
|
|
98
|
+
}
|
|
99
|
+
const projection = projectGraph(schema, kinds, rowsByCatalogue, tier, semantics);
|
|
100
|
+
await writeFile(outPath, projection.text, "utf-8");
|
|
101
|
+
const c = projection.counts;
|
|
102
|
+
write(`graph projection (${tier} tier, schema ${schema.schemaVersion})\n`);
|
|
103
|
+
write(` nodes: ${c.nodes}\n`);
|
|
104
|
+
write(` edges: ${c.edges}\n`);
|
|
105
|
+
write(` property records: ${c.properties}\n`);
|
|
106
|
+
write(` omitted (external, resolves at aggregation): ${c.omittedExternal}\n`);
|
|
107
|
+
write(` omitted (unresolved — mirrors FK findings): ${c.omittedUnresolved}\n`);
|
|
108
|
+
write(` digest: sha256:${projection.digest}\n`);
|
|
109
|
+
write(` wrote ${outPath}\n`);
|
|
110
|
+
return { exitCode: 0, counts: c, outPath };
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=graph-run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-run.js","sourceRoot":"","sources":["../../../src/lib/catalogue/graph-run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transitive impact analysis — `sdd-cli catalogue impact` (M-ADR 0206 §4.6).
|
|
3
|
+
*
|
|
4
|
+
* Impact traverses the graph-projection edge set BY DECLARED SEMANTICS: every
|
|
5
|
+
* relationship carries an impact-flow token in the rubric-coverage-map
|
|
6
|
+
* (M-ADR 0206 §4.1) naming which endpoint RECEIVES impact — `toward-source`
|
|
7
|
+
* (dependency shape: a change at the target propagates to the source),
|
|
8
|
+
* `toward-target` (membership shape: a part's change reaches its whole),
|
|
9
|
+
* `both` (realisation), `none` (xref, lineage records, attributes). One
|
|
10
|
+
* relationship (`service_event`) resolves its flow per row from a named
|
|
11
|
+
* column (§4.2). The closure is the set of nodes impact can reach from the
|
|
12
|
+
* seed along declared propagation directions, computed by recursive SQL
|
|
13
|
+
* (`WITH RECURSIVE`) on the Phase A engine.
|
|
14
|
+
*
|
|
15
|
+
* THE CO-DIRECTIONALITY INVARIANT (§4.4, a condition of 0206's acceptance):
|
|
16
|
+
* the Phase C mirror-dedup heuristic is retired because under the declared
|
|
17
|
+
* tokens every true-mirror pair propagates the SAME direction. That premise
|
|
18
|
+
* is exercised, not assumed: buildImpactPropagation asserts that no node
|
|
19
|
+
* pair receives propagation in BOTH directions from two DIFFERENT
|
|
20
|
+
* single-direction relationship types, and fails loudly naming the pair and
|
|
21
|
+
* types. A single relationship declaring `both` is deliberate bidirectional
|
|
22
|
+
* coupling and is exempt; a self-referential type contributing both
|
|
23
|
+
* directions from different rows (a hierarchy cycle) is likewise exempt.
|
|
24
|
+
* A future token edit that would silently bring the undirected flood back
|
|
25
|
+
* trips this assertion instead.
|
|
26
|
+
*
|
|
27
|
+
* Cycle discipline: the recursion carries NO depth column — recursive UNION
|
|
28
|
+
* deduplicates whole rows, and a depth column makes every lap of a cycle a
|
|
29
|
+
* "new" row: the query that looks more informative is the query that never
|
|
30
|
+
* terminates. As a bare id-set the closure saturates and stops.
|
|
31
|
+
*/
|
|
32
|
+
import { type ImpactFlow, type RelationshipSemantics } from "./graph-run.js";
|
|
33
|
+
import { type GraphTier } from "./graph-projection.js";
|
|
34
|
+
export interface ImpactEdge {
|
|
35
|
+
readonly source: string;
|
|
36
|
+
readonly target: string;
|
|
37
|
+
readonly type: string;
|
|
38
|
+
/** Non-endpoint columns of the underlying row (the projection's edge properties). */
|
|
39
|
+
readonly properties?: Readonly<Record<string, string>>;
|
|
40
|
+
}
|
|
41
|
+
/** One resolved propagation step: if `from` is impacted, `to` is impacted. */
|
|
42
|
+
export interface PropagationEdge {
|
|
43
|
+
readonly from: string;
|
|
44
|
+
readonly to: string;
|
|
45
|
+
readonly type: string;
|
|
46
|
+
}
|
|
47
|
+
export interface PropagationBuild {
|
|
48
|
+
readonly edges: readonly PropagationEdge[];
|
|
49
|
+
/** Declared edges whose resolved flow is `none` (not traversed). */
|
|
50
|
+
readonly flowNone: number;
|
|
51
|
+
/** Propagation-step counts by resolved flow token. */
|
|
52
|
+
readonly byFlow: ReadonlyMap<ImpactFlow, number>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolve every declared edge into propagation steps per its flow, and
|
|
56
|
+
* exercise the §4.4 co-directionality invariant.
|
|
57
|
+
*/
|
|
58
|
+
export declare function buildImpactPropagation(edges: readonly ImpactEdge[], semantics: RelationshipSemantics): PropagationBuild;
|
|
59
|
+
/**
|
|
60
|
+
* Closure of `seed` over resolved propagation edges, on the engine.
|
|
61
|
+
* Exported for the fixture controls; the verb goes through runCatalogueImpact.
|
|
62
|
+
*/
|
|
63
|
+
export declare function computeImpactClosure(propagation: readonly PropagationEdge[], seed: string): Promise<string[]>;
|
|
64
|
+
export interface ImpactResult {
|
|
65
|
+
readonly seed: string;
|
|
66
|
+
/** Reachable node ids (seed excluded), sorted. */
|
|
67
|
+
readonly closure: readonly string[];
|
|
68
|
+
readonly byCatalogue: ReadonlyMap<string, number>;
|
|
69
|
+
}
|
|
70
|
+
export interface ImpactRunInputs {
|
|
71
|
+
/** Node id to compute impact of, in the export's "<catalogue>/<pk>" form. */
|
|
72
|
+
readonly of: string;
|
|
73
|
+
readonly sddPath?: string;
|
|
74
|
+
readonly cataloguesDir?: string;
|
|
75
|
+
readonly tier?: GraphTier;
|
|
76
|
+
}
|
|
77
|
+
export declare function runCatalogueImpact(inputs: ImpactRunInputs, write: (s: string) => void): Promise<{
|
|
78
|
+
exitCode: number;
|
|
79
|
+
result?: ImpactResult;
|
|
80
|
+
}>;
|
|
81
|
+
//# sourceMappingURL=impact-run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impact-run.d.ts","sourceRoot":"","sources":["../../../src/lib/catalogue/impact-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAOH,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAErE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACxD;AAED,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAC3C,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;CAClD;AA6BD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,SAAS,EAAE,qBAAqB,GAC/B,gBAAgB,CAmElB;AAMD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,SAAS,eAAe,EAAE,EACvC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,EAAE,CAAC,CAiCnB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;CAC3B;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GACzB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,YAAY,CAAA;CAAE,CAAC,CAyFtD"}
|