@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.
Files changed (29) hide show
  1. package/dist/lib/catalogue/coverage-render.d.ts +1 -0
  2. package/dist/lib/catalogue/coverage-render.d.ts.map +1 -1
  3. package/dist/lib/catalogue/coverage-render.js +17 -0
  4. package/dist/lib/catalogue/coverage-render.js.map +1 -1
  5. package/dist/lib/catalogue/coverage-run.d.ts.map +1 -1
  6. package/dist/lib/catalogue/coverage-run.js +7 -2
  7. package/dist/lib/catalogue/coverage-run.js.map +1 -1
  8. package/dist/lib/catalogue/gate-checks.d.ts +20 -0
  9. package/dist/lib/catalogue/gate-checks.d.ts.map +1 -1
  10. package/dist/lib/catalogue/gate-checks.js +67 -0
  11. package/dist/lib/catalogue/gate-checks.js.map +1 -1
  12. package/dist/lib/catalogue/graph-projection.d.ts +74 -0
  13. package/dist/lib/catalogue/graph-projection.d.ts.map +1 -0
  14. package/dist/lib/catalogue/graph-projection.js +322 -0
  15. package/dist/lib/catalogue/graph-projection.js.map +1 -0
  16. package/dist/lib/catalogue/graph-run.d.ts +59 -0
  17. package/dist/lib/catalogue/graph-run.d.ts.map +1 -0
  18. package/dist/lib/catalogue/graph-run.js +112 -0
  19. package/dist/lib/catalogue/graph-run.js.map +1 -0
  20. package/dist/lib/catalogue/impact-run.d.ts +81 -0
  21. package/dist/lib/catalogue/impact-run.d.ts.map +1 -0
  22. package/dist/lib/catalogue/impact-run.js +228 -0
  23. package/dist/lib/catalogue/impact-run.js.map +1 -0
  24. package/dist/lib/catalogue/rubric-coverage-map.yaml +279 -0
  25. package/dist/verbs/catalogue.d.ts.map +1 -1
  26. package/dist/verbs/catalogue.js +56 -0
  27. package/dist/verbs/catalogue.js.map +1 -1
  28. package/package.json +2 -2
  29. 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"}