@sdd-method/sdd-cli 0.10.0 → 0.11.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/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/catalogue/aggregate.d.ts +39 -0
- package/dist/lib/catalogue/aggregate.d.ts.map +1 -0
- package/dist/lib/catalogue/aggregate.js +344 -0
- package/dist/lib/catalogue/aggregate.js.map +1 -0
- package/dist/lib/catalogue/aggregation-manifest-loader.d.ts +25 -0
- package/dist/lib/catalogue/aggregation-manifest-loader.d.ts.map +1 -0
- package/dist/lib/catalogue/aggregation-manifest-loader.js +111 -0
- package/dist/lib/catalogue/aggregation-manifest-loader.js.map +1 -0
- package/dist/lib/catalogue/build.d.ts +42 -0
- package/dist/lib/catalogue/build.d.ts.map +1 -0
- package/dist/lib/catalogue/build.js +373 -0
- package/dist/lib/catalogue/build.js.map +1 -0
- package/dist/lib/catalogue/builders/adr-supersedes.d.ts +14 -0
- package/dist/lib/catalogue/builders/adr-supersedes.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/adr-supersedes.js +62 -0
- package/dist/lib/catalogue/builders/adr-supersedes.js.map +1 -0
- package/dist/lib/catalogue/builders/adrs.d.ts +27 -0
- package/dist/lib/catalogue/builders/adrs.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/adrs.js +191 -0
- package/dist/lib/catalogue/builders/adrs.js.map +1 -0
- package/dist/lib/catalogue/builders/c4-containers.d.ts +16 -0
- package/dist/lib/catalogue/builders/c4-containers.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/c4-containers.js +169 -0
- package/dist/lib/catalogue/builders/c4-containers.js.map +1 -0
- package/dist/lib/catalogue/builders/c4-systems.d.ts +10 -0
- package/dist/lib/catalogue/builders/c4-systems.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/c4-systems.js +99 -0
- package/dist/lib/catalogue/builders/c4-systems.js.map +1 -0
- package/dist/lib/catalogue/builders/capabilities.d.ts +11 -0
- package/dist/lib/catalogue/builders/capabilities.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/capabilities.js +173 -0
- package/dist/lib/catalogue/builders/capabilities.js.map +1 -0
- package/dist/lib/catalogue/builders/capability-edges.d.ts +27 -0
- package/dist/lib/catalogue/builders/capability-edges.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/capability-edges.js +166 -0
- package/dist/lib/catalogue/builders/capability-edges.js.map +1 -0
- package/dist/lib/catalogue/builders/contracts.d.ts +15 -0
- package/dist/lib/catalogue/builders/contracts.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/contracts.js +153 -0
- package/dist/lib/catalogue/builders/contracts.js.map +1 -0
- package/dist/lib/catalogue/builders/domains.d.ts +10 -0
- package/dist/lib/catalogue/builders/domains.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/domains.js +93 -0
- package/dist/lib/catalogue/builders/domains.js.map +1 -0
- package/dist/lib/catalogue/builders/event-edges.d.ts +20 -0
- package/dist/lib/catalogue/builders/event-edges.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/event-edges.js +112 -0
- package/dist/lib/catalogue/builders/event-edges.js.map +1 -0
- package/dist/lib/catalogue/builders/events.d.ts +26 -0
- package/dist/lib/catalogue/builders/events.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/events.js +99 -0
- package/dist/lib/catalogue/builders/events.js.map +1 -0
- package/dist/lib/catalogue/builders/feature-groups.d.ts +10 -0
- package/dist/lib/catalogue/builders/feature-groups.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/feature-groups.js +118 -0
- package/dist/lib/catalogue/builders/feature-groups.js.map +1 -0
- package/dist/lib/catalogue/builders/features.d.ts +35 -0
- package/dist/lib/catalogue/builders/features.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/features.js +206 -0
- package/dist/lib/catalogue/builders/features.js.map +1 -0
- package/dist/lib/catalogue/builders/glossary-xref.d.ts +11 -0
- package/dist/lib/catalogue/builders/glossary-xref.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/glossary-xref.js +107 -0
- package/dist/lib/catalogue/builders/glossary-xref.js.map +1 -0
- package/dist/lib/catalogue/builders/glossary.d.ts +14 -0
- package/dist/lib/catalogue/builders/glossary.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/glossary.js +150 -0
- package/dist/lib/catalogue/builders/glossary.js.map +1 -0
- package/dist/lib/catalogue/builders/index.d.ts +57 -0
- package/dist/lib/catalogue/builders/index.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/index.js +33 -0
- package/dist/lib/catalogue/builders/index.js.map +1 -0
- package/dist/lib/catalogue/builders/integrations.d.ts +12 -0
- package/dist/lib/catalogue/builders/integrations.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/integrations.js +85 -0
- package/dist/lib/catalogue/builders/integrations.js.map +1 -0
- package/dist/lib/catalogue/builders/persona-journey-edges.d.ts +26 -0
- package/dist/lib/catalogue/builders/persona-journey-edges.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/persona-journey-edges.js +133 -0
- package/dist/lib/catalogue/builders/persona-journey-edges.js.map +1 -0
- package/dist/lib/catalogue/builders/personas.d.ts +22 -0
- package/dist/lib/catalogue/builders/personas.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/personas.js +150 -0
- package/dist/lib/catalogue/builders/personas.js.map +1 -0
- package/dist/lib/catalogue/builders/product-edges.d.ts +15 -0
- package/dist/lib/catalogue/builders/product-edges.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/product-edges.js +97 -0
- package/dist/lib/catalogue/builders/product-edges.js.map +1 -0
- package/dist/lib/catalogue/builders/products.d.ts +26 -0
- package/dist/lib/catalogue/builders/products.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/products.js +57 -0
- package/dist/lib/catalogue/builders/products.js.map +1 -0
- package/dist/lib/catalogue/builders/repo-edges.d.ts +18 -0
- package/dist/lib/catalogue/builders/repo-edges.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/repo-edges.js +113 -0
- package/dist/lib/catalogue/builders/repo-edges.js.map +1 -0
- package/dist/lib/catalogue/builders/repositories.d.ts +78 -0
- package/dist/lib/catalogue/builders/repositories.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/repositories.js +204 -0
- package/dist/lib/catalogue/builders/repositories.js.map +1 -0
- package/dist/lib/catalogue/builders/service-contract.d.ts +11 -0
- package/dist/lib/catalogue/builders/service-contract.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/service-contract.js +53 -0
- package/dist/lib/catalogue/builders/service-contract.js.map +1 -0
- package/dist/lib/catalogue/builders/services.d.ts +15 -0
- package/dist/lib/catalogue/builders/services.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/services.js +40 -0
- package/dist/lib/catalogue/builders/services.js.map +1 -0
- package/dist/lib/catalogue/builders/user-journeys.d.ts +24 -0
- package/dist/lib/catalogue/builders/user-journeys.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/user-journeys.js +253 -0
- package/dist/lib/catalogue/builders/user-journeys.js.map +1 -0
- package/dist/lib/catalogue/canonical-schema.yaml +624 -0
- package/dist/lib/catalogue/cli-version.d.ts +10 -0
- package/dist/lib/catalogue/cli-version.d.ts.map +1 -0
- package/dist/lib/catalogue/cli-version.js +10 -0
- package/dist/lib/catalogue/cli-version.js.map +1 -0
- package/dist/lib/catalogue/csv-reader.d.ts +7 -0
- package/dist/lib/catalogue/csv-reader.d.ts.map +1 -0
- package/dist/lib/catalogue/csv-reader.js +97 -0
- package/dist/lib/catalogue/csv-reader.js.map +1 -0
- package/dist/lib/catalogue/csv-writer.d.ts +29 -0
- package/dist/lib/catalogue/csv-writer.d.ts.map +1 -0
- package/dist/lib/catalogue/csv-writer.js +55 -0
- package/dist/lib/catalogue/csv-writer.js.map +1 -0
- package/dist/lib/catalogue/findings.d.ts +27 -0
- package/dist/lib/catalogue/findings.d.ts.map +1 -0
- package/dist/lib/catalogue/findings.js +34 -0
- package/dist/lib/catalogue/findings.js.map +1 -0
- package/dist/lib/catalogue/fk-validator.d.ts +44 -0
- package/dist/lib/catalogue/fk-validator.d.ts.map +1 -0
- package/dist/lib/catalogue/fk-validator.js +90 -0
- package/dist/lib/catalogue/fk-validator.js.map +1 -0
- package/dist/lib/catalogue/index.d.ts +27 -0
- package/dist/lib/catalogue/index.d.ts.map +1 -0
- package/dist/lib/catalogue/index.js +18 -0
- package/dist/lib/catalogue/index.js.map +1 -0
- package/dist/lib/catalogue/manifest-loader.d.ts +47 -0
- package/dist/lib/catalogue/manifest-loader.d.ts.map +1 -0
- package/dist/lib/catalogue/manifest-loader.js +161 -0
- package/dist/lib/catalogue/manifest-loader.js.map +1 -0
- package/dist/lib/catalogue/schema-compat.d.ts +47 -0
- package/dist/lib/catalogue/schema-compat.d.ts.map +1 -0
- package/dist/lib/catalogue/schema-compat.js +52 -0
- package/dist/lib/catalogue/schema-compat.js.map +1 -0
- package/dist/lib/catalogue/schema-loader.d.ts +58 -0
- package/dist/lib/catalogue/schema-loader.d.ts.map +1 -0
- package/dist/lib/catalogue/schema-loader.js +86 -0
- package/dist/lib/catalogue/schema-loader.js.map +1 -0
- package/dist/lib/catalogue/traceability-loader.d.ts +56 -0
- package/dist/lib/catalogue/traceability-loader.d.ts.map +1 -0
- package/dist/lib/catalogue/traceability-loader.js +217 -0
- package/dist/lib/catalogue/traceability-loader.js.map +1 -0
- package/dist/lib/catalogue/validate.d.ts +16 -0
- package/dist/lib/catalogue/validate.d.ts.map +1 -0
- package/dist/lib/catalogue/validate.js +137 -0
- package/dist/lib/catalogue/validate.js.map +1 -0
- package/dist/lib/catalogue/version.d.ts +3 -0
- package/dist/lib/catalogue/version.d.ts.map +1 -0
- package/dist/lib/catalogue/version.js +18 -0
- package/dist/lib/catalogue/version.js.map +1 -0
- package/dist/lib/mcp/build-info.d.ts +1 -1
- package/dist/lib/mcp/build-info.js +1 -1
- package/dist/verbs/catalogue.d.ts +3 -0
- package/dist/verbs/catalogue.d.ts.map +1 -0
- package/dist/verbs/catalogue.js +60 -0
- package/dist/verbs/catalogue.js.map +1 -0
- package/package.json +3 -3
- package/scripts/copy-yaml-assets.mjs +38 -0
- package/scripts/sync-canonical-schema.sh +39 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// Traceability manifest loader — walks `docs/domains/**/*.traceability.yaml`
|
|
2
|
+
// and returns parsed declarations.
|
|
3
|
+
//
|
|
4
|
+
// The traceability manifest is per-capability declarative metadata that
|
|
5
|
+
// the canonical builder reads to populate `capabilities.csv` and the
|
|
6
|
+
// five capability_* edge catalogues (services, adrs, features,
|
|
7
|
+
// contracts, events). One YAML per capability; the canonical layout is
|
|
8
|
+
// `docs/domains/{domain}/product/{capability}.traceability.yaml`.
|
|
9
|
+
//
|
|
10
|
+
// Schema reference: docs/method/methods/capability-traceability-manifest-template.yaml
|
|
11
|
+
// in sdd-method (per ADR 0047 / capability-spec-template.md).
|
|
12
|
+
import { readdir, readFile, stat } from "node:fs/promises";
|
|
13
|
+
import { join, relative, sep } from "node:path";
|
|
14
|
+
import { parse as parseYaml } from "yaml";
|
|
15
|
+
const DOMAINS_DIR_REL = join("docs", "domains");
|
|
16
|
+
export async function loadTraceabilityManifests(opts) {
|
|
17
|
+
const root = join(opts.sddPath, DOMAINS_DIR_REL);
|
|
18
|
+
let yamlPaths;
|
|
19
|
+
try {
|
|
20
|
+
yamlPaths = await collectYamlPaths(root, /\.traceability\.yaml$/);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
const code = err.code;
|
|
24
|
+
if (code === "ENOENT") {
|
|
25
|
+
// No domains dir → no traceability data; return empty.
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
const manifests = [];
|
|
31
|
+
for (const path of yamlPaths.sort()) {
|
|
32
|
+
const text = await readFile(path, "utf-8");
|
|
33
|
+
let raw;
|
|
34
|
+
try {
|
|
35
|
+
raw = parseYaml(text);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
opts.findings.add("convention", `failed to parse YAML at ${relative(opts.sddPath, path)}: ${err.message}`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (!raw || typeof raw !== "object") {
|
|
42
|
+
opts.findings.add("convention", `${relative(opts.sddPath, path)}: not an object — skipped`);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const obj = raw;
|
|
46
|
+
const cap = obj["capability"] ?? {};
|
|
47
|
+
const capId = String(cap["id"] ?? "").trim();
|
|
48
|
+
if (capId === "") {
|
|
49
|
+
opts.findings.add("convention", `${relative(opts.sddPath, path)}: missing capability.id`);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const relPath = relative(opts.sddPath, path);
|
|
53
|
+
const domainFromPath = inferDomainFromPath(relPath);
|
|
54
|
+
const declaredDomain = String(cap["domain"] ?? "").trim();
|
|
55
|
+
if (declaredDomain && domainFromPath && declaredDomain !== domainFromPath) {
|
|
56
|
+
opts.findings.add("divergence", `${relPath}: capability.domain="${declaredDomain}" disagrees with path domain "${domainFromPath}"`);
|
|
57
|
+
}
|
|
58
|
+
const capability = {
|
|
59
|
+
id: capId,
|
|
60
|
+
domain: declaredDomain || domainFromPath,
|
|
61
|
+
...(typeof cap["capability_spec"] === "string"
|
|
62
|
+
? { capability_spec: cap["capability_spec"] }
|
|
63
|
+
: {}),
|
|
64
|
+
...(typeof cap["feature_directory"] === "string"
|
|
65
|
+
? { feature_directory: cap["feature_directory"] }
|
|
66
|
+
: {}),
|
|
67
|
+
...(typeof cap["status"] === "string" ? { status: cap["status"] } : {}),
|
|
68
|
+
};
|
|
69
|
+
manifests.push({
|
|
70
|
+
path,
|
|
71
|
+
relPath,
|
|
72
|
+
domainFromPath,
|
|
73
|
+
capability,
|
|
74
|
+
traceability: extractTraceabilityBlock(obj["traceability"]),
|
|
75
|
+
data: raw,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return manifests;
|
|
79
|
+
}
|
|
80
|
+
function extractTraceabilityBlock(raw) {
|
|
81
|
+
if (!raw || typeof raw !== "object")
|
|
82
|
+
return {};
|
|
83
|
+
const t = raw;
|
|
84
|
+
const runway = t["runway"];
|
|
85
|
+
const adrs = t["adrs"];
|
|
86
|
+
const services = t["services"];
|
|
87
|
+
const contracts = t["contracts"];
|
|
88
|
+
return {
|
|
89
|
+
...(runway && typeof runway === "object" ? { runway: extractRunway(runway) } : {}),
|
|
90
|
+
...(Array.isArray(adrs) ? { adrs: extractAdrs(adrs) } : {}),
|
|
91
|
+
...(Array.isArray(services) ? { services: extractServices(services) } : {}),
|
|
92
|
+
...(contracts && typeof contracts === "object"
|
|
93
|
+
? { contracts: extractContracts(contracts) }
|
|
94
|
+
: {}),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function extractRunway(raw) {
|
|
98
|
+
if (!raw || typeof raw !== "object")
|
|
99
|
+
return {};
|
|
100
|
+
const r = raw;
|
|
101
|
+
const enables = Array.isArray(r["enables"])
|
|
102
|
+
? r["enables"].filter((e) => typeof e === "string")
|
|
103
|
+
: undefined;
|
|
104
|
+
return {
|
|
105
|
+
...(typeof r["classification"] === "string"
|
|
106
|
+
? { classification: r["classification"] }
|
|
107
|
+
: {}),
|
|
108
|
+
...(enables ? { enables } : {}),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function extractAdrs(raw) {
|
|
112
|
+
const out = [];
|
|
113
|
+
for (const item of raw) {
|
|
114
|
+
if (!item || typeof item !== "object")
|
|
115
|
+
continue;
|
|
116
|
+
const o = item;
|
|
117
|
+
const id = String(o["id"] ?? "").trim();
|
|
118
|
+
if (!id)
|
|
119
|
+
continue;
|
|
120
|
+
out.push({
|
|
121
|
+
id,
|
|
122
|
+
...(typeof o["path"] === "string" ? { path: o["path"] } : {}),
|
|
123
|
+
...(typeof o["relationship"] === "string"
|
|
124
|
+
? { relationship: o["relationship"] }
|
|
125
|
+
: {}),
|
|
126
|
+
...(typeof o["notes"] === "string" ? { notes: o["notes"] } : {}),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return out;
|
|
130
|
+
}
|
|
131
|
+
function extractServices(raw) {
|
|
132
|
+
const out = [];
|
|
133
|
+
for (const item of raw) {
|
|
134
|
+
if (!item || typeof item !== "object")
|
|
135
|
+
continue;
|
|
136
|
+
const o = item;
|
|
137
|
+
const id = String(o["id"] ?? "").trim();
|
|
138
|
+
if (!id)
|
|
139
|
+
continue;
|
|
140
|
+
out.push({
|
|
141
|
+
id,
|
|
142
|
+
...(typeof o["owner_domain"] === "string"
|
|
143
|
+
? { owner_domain: o["owner_domain"] }
|
|
144
|
+
: {}),
|
|
145
|
+
...(typeof o["role"] === "string" ? { role: o["role"] } : {}),
|
|
146
|
+
...(typeof o["status"] === "string" ? { status: o["status"] } : {}),
|
|
147
|
+
...(typeof o["notes"] === "string" ? { notes: o["notes"] } : {}),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
function extractContracts(raw) {
|
|
153
|
+
const o = raw;
|
|
154
|
+
const arr = (key) => {
|
|
155
|
+
const v = o[key];
|
|
156
|
+
if (!Array.isArray(v))
|
|
157
|
+
return undefined;
|
|
158
|
+
return v.filter((s) => typeof s === "string");
|
|
159
|
+
};
|
|
160
|
+
const openapi = arr("openapi");
|
|
161
|
+
const proto = arr("proto");
|
|
162
|
+
const avro = arr("avro");
|
|
163
|
+
return {
|
|
164
|
+
...(openapi ? { openapi } : {}),
|
|
165
|
+
...(proto ? { proto } : {}),
|
|
166
|
+
...(avro ? { avro } : {}),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function inferDomainFromPath(relPath) {
|
|
170
|
+
const parts = relPath.split(sep);
|
|
171
|
+
const idx = parts.indexOf("domains");
|
|
172
|
+
if (idx === -1 || idx + 1 >= parts.length)
|
|
173
|
+
return "";
|
|
174
|
+
return parts[idx + 1] ?? "";
|
|
175
|
+
}
|
|
176
|
+
async function collectYamlPaths(dir, pattern) {
|
|
177
|
+
const out = [];
|
|
178
|
+
let entries;
|
|
179
|
+
try {
|
|
180
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
const code = err.code;
|
|
184
|
+
if (code === "ENOENT")
|
|
185
|
+
return [];
|
|
186
|
+
throw err;
|
|
187
|
+
}
|
|
188
|
+
for (const entry of entries) {
|
|
189
|
+
const full = join(dir, entry.name);
|
|
190
|
+
if (entry.isDirectory()) {
|
|
191
|
+
out.push(...(await collectYamlPaths(full, pattern)));
|
|
192
|
+
}
|
|
193
|
+
else if (entry.isFile() && pattern.test(entry.name)) {
|
|
194
|
+
out.push(full);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return out;
|
|
198
|
+
}
|
|
199
|
+
/** Convenience: read a file's first non-empty line, returning the trimmed value. */
|
|
200
|
+
export async function readFirstNonEmptyLine(path) {
|
|
201
|
+
try {
|
|
202
|
+
const s = await stat(path);
|
|
203
|
+
if (!s.isFile())
|
|
204
|
+
return "";
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return "";
|
|
208
|
+
}
|
|
209
|
+
const text = await readFile(path, "utf-8");
|
|
210
|
+
for (const line of text.split(/\r?\n/)) {
|
|
211
|
+
const t = line.trim();
|
|
212
|
+
if (t !== "")
|
|
213
|
+
return t;
|
|
214
|
+
}
|
|
215
|
+
return "";
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=traceability-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traceability-loader.js","sourceRoot":"","sources":["../../../src/lib/catalogue/traceability-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ValidateInputs {
|
|
2
|
+
/** SDD repo root (defaults to cwd). */
|
|
3
|
+
readonly sddPath?: string;
|
|
4
|
+
/** Strict mode — non-zero exit on any finding. */
|
|
5
|
+
readonly strict?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface ValidateResult {
|
|
8
|
+
readonly exitCode: number;
|
|
9
|
+
readonly schemaVersion: string;
|
|
10
|
+
readonly internalFkPass: boolean;
|
|
11
|
+
readonly columnShapeOk: boolean;
|
|
12
|
+
readonly findingsCount: number;
|
|
13
|
+
}
|
|
14
|
+
export type Writer = (s: string) => void;
|
|
15
|
+
export declare function runCatalogueValidate(inputs: ValidateInputs, write: Writer): Promise<ValidateResult>;
|
|
16
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/lib/catalogue/validate.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,kDAAkD;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;AAEzC,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,cAAc,CAAC,CA4GzB"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// `sdd-cli catalogue validate` — re-validate an existing catalogues/
|
|
2
|
+
// directory without rebuilding. Two checks per the canonical CLI spec:
|
|
3
|
+
//
|
|
4
|
+
// 1. Column-shape check: every CSV's header row must match the
|
|
5
|
+
// canonical schema's declared columns (exact set + order).
|
|
6
|
+
// 2. FK validation: full pass over the loaded rows, internal mode
|
|
7
|
+
// (external FKs treated per their declared flag — same semantics
|
|
8
|
+
// as `catalogue build`). Adopters who want post-merge validation
|
|
9
|
+
// run `catalogue aggregate` instead.
|
|
10
|
+
//
|
|
11
|
+
// Outputs the same shape of findings as `build` so consumers can pipe
|
|
12
|
+
// either through the same parser. Exit 0 on PASS; non-zero on shape
|
|
13
|
+
// drift OR internal-FK FAIL.
|
|
14
|
+
import { stat } from "node:fs/promises";
|
|
15
|
+
import { join, resolve } from "node:path";
|
|
16
|
+
import { CLI_VERSION } from "./cli-version.js";
|
|
17
|
+
import { readCatalogueCsv } from "./csv-reader.js";
|
|
18
|
+
import { writeCatalogue } from "./csv-writer.js";
|
|
19
|
+
import { FindingsLog } from "./findings.js";
|
|
20
|
+
import { validateForeignKeys } from "./fk-validator.js";
|
|
21
|
+
import { loadCanonicalSchema } from "./schema-loader.js";
|
|
22
|
+
export async function runCatalogueValidate(inputs, write) {
|
|
23
|
+
const sddPath = resolve(inputs.sddPath ?? process.cwd());
|
|
24
|
+
const cataloguesDir = join(sddPath, "catalogues");
|
|
25
|
+
const schema = await loadCanonicalSchema();
|
|
26
|
+
write(`sdd-cli catalogue validate (canonical schema ${schema.schemaVersion}, cli ${CLI_VERSION})\n`);
|
|
27
|
+
// Existence check on catalogues/ — fail fast with a clear message.
|
|
28
|
+
try {
|
|
29
|
+
const s = await stat(cataloguesDir);
|
|
30
|
+
if (!s.isDirectory()) {
|
|
31
|
+
throw new Error(`catalogues/ at ${cataloguesDir} exists but is not a directory`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
if (err.code === "ENOENT") {
|
|
36
|
+
throw new Error(`catalogues/ not found at ${cataloguesDir}\n` +
|
|
37
|
+
` Run \`sdd-cli catalogue build\` before \`validate\`.`);
|
|
38
|
+
}
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
const findings = new FindingsLog();
|
|
42
|
+
const rowsByCatalogue = new Map();
|
|
43
|
+
let columnShapeOk = true;
|
|
44
|
+
for (const cat of schema.catalogues) {
|
|
45
|
+
const filePath = join(cataloguesDir, `${cat.name}.csv`);
|
|
46
|
+
let parsed;
|
|
47
|
+
try {
|
|
48
|
+
parsed = await readCatalogueCsv(filePath);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (err.code === "ENOENT") {
|
|
52
|
+
// Missing file is a shape failure — every catalogue declared in
|
|
53
|
+
// the schema MUST have a CSV (headers-only acceptable).
|
|
54
|
+
findings.add("convention", `catalogues/${cat.name}.csv missing — every schema catalogue must have a file (headers-only acceptable)`);
|
|
55
|
+
columnShapeOk = false;
|
|
56
|
+
rowsByCatalogue.set(cat.name, []);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
throw err;
|
|
60
|
+
}
|
|
61
|
+
const expected = cat.columns.map((c) => c.name);
|
|
62
|
+
const drift = compareColumns(expected, parsed.columns);
|
|
63
|
+
if (drift !== null) {
|
|
64
|
+
findings.add("convention", `catalogues/${cat.name}.csv: column shape drift — ${drift}`);
|
|
65
|
+
columnShapeOk = false;
|
|
66
|
+
}
|
|
67
|
+
rowsByCatalogue.set(cat.name, parsed.rows);
|
|
68
|
+
}
|
|
69
|
+
const fk = validateForeignKeys(schema, rowsByCatalogue, findings);
|
|
70
|
+
// Report.
|
|
71
|
+
const findingsText = findings.render();
|
|
72
|
+
if (findingsText)
|
|
73
|
+
write(`\n${findingsText}\n`);
|
|
74
|
+
if (columnShapeOk) {
|
|
75
|
+
write(`\nColumn-shape check: PASS\n`);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
write(`\nColumn-shape check: FAIL\n`);
|
|
79
|
+
}
|
|
80
|
+
if (fk.internalPass) {
|
|
81
|
+
write(`FK validation (internal): PASS\n`);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
write(`FK validation (internal): FAIL (${fk.internalFailures.length} dangling)\n`);
|
|
85
|
+
for (const f of fk.internalFailures) {
|
|
86
|
+
write(` ${f.catalogue}.${f.column}: row pk=${f.referencingRow} → ${f.target}=${f.value || "<empty>"}\n`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (fk.externalFindings > 0) {
|
|
90
|
+
write(`External findings: ${fk.externalFindings} (validated by aggregator)\n`);
|
|
91
|
+
}
|
|
92
|
+
// Force-touch writeCatalogue to keep imports honest if a future
|
|
93
|
+
// refactor wants to re-emit a cleaned-up file from validate. Today
|
|
94
|
+
// validate is read-only.
|
|
95
|
+
void writeCatalogue;
|
|
96
|
+
const strictFail = inputs.strict === true && findings.count() > 0;
|
|
97
|
+
const exitCode = !columnShapeOk || !fk.internalPass || strictFail ? 1 : 0;
|
|
98
|
+
return {
|
|
99
|
+
exitCode,
|
|
100
|
+
schemaVersion: schema.schemaVersion,
|
|
101
|
+
internalFkPass: fk.internalPass,
|
|
102
|
+
columnShapeOk,
|
|
103
|
+
findingsCount: findings.count(),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Compare a CSV's actual column header against the schema's declared
|
|
108
|
+
* column order. Returns null if exactly equal (order included), or a
|
|
109
|
+
* one-line description of the drift otherwise.
|
|
110
|
+
*/
|
|
111
|
+
function compareColumns(expected, actual) {
|
|
112
|
+
if (expected.length === actual.length) {
|
|
113
|
+
let equal = true;
|
|
114
|
+
for (let i = 0; i < expected.length; i++) {
|
|
115
|
+
if (expected[i] !== actual[i]) {
|
|
116
|
+
equal = false;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (equal)
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
const expectedSet = new Set(expected);
|
|
124
|
+
const actualSet = new Set(actual);
|
|
125
|
+
const missing = expected.filter((c) => !actualSet.has(c));
|
|
126
|
+
const extra = actual.filter((c) => !expectedSet.has(c));
|
|
127
|
+
if (missing.length === 0 && extra.length === 0) {
|
|
128
|
+
return `column order differs (expected: ${expected.join(",")} | got: ${actual.join(",")})`;
|
|
129
|
+
}
|
|
130
|
+
const parts = [];
|
|
131
|
+
if (missing.length > 0)
|
|
132
|
+
parts.push(`missing: ${missing.join(",")}`);
|
|
133
|
+
if (extra.length > 0)
|
|
134
|
+
parts.push(`unexpected: ${extra.join(",")}`);
|
|
135
|
+
return parts.join("; ");
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/lib/catalogue/validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/lib/catalogue/version.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;AAEzC,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYtE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// `sdd-cli catalogue version` — prints the canonical schema version
|
|
2
|
+
// and the sdd-cli version pin so adopters can verify their tooling
|
|
3
|
+
// matches the schema they expect.
|
|
4
|
+
import { CLI_VERSION } from "./cli-version.js";
|
|
5
|
+
import { SCHEMA_COMPAT } from "./schema-compat.js";
|
|
6
|
+
import { loadCanonicalSchema } from "./schema-loader.js";
|
|
7
|
+
export async function runCatalogueVersion(write) {
|
|
8
|
+
const schema = await loadCanonicalSchema();
|
|
9
|
+
write([
|
|
10
|
+
`sdd-cli ${CLI_VERSION}`,
|
|
11
|
+
`catalogue schema ${schema.schemaVersion}`,
|
|
12
|
+
`accepted catalogue range ${SCHEMA_COMPAT.catalogue_schema}`,
|
|
13
|
+
`accepted sdd_manifest ${SCHEMA_COMPAT.sdd_manifest}`,
|
|
14
|
+
`accepted aggregation ${SCHEMA_COMPAT.aggregation_manifest}`,
|
|
15
|
+
"",
|
|
16
|
+
].join("\n"));
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/lib/catalogue/version.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,mEAAmE;AACnE,kCAAkC;AAElC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAIzD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,KAAa;IACrD,MAAM,MAAM,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC3C,KAAK,CACH;QACE,8BAA8B,WAAW,EAAE;QAC3C,8BAA8B,MAAM,CAAC,aAAa,EAAE;QACpD,8BAA8B,aAAa,CAAC,gBAAgB,EAAE;QAC9D,8BAA8B,aAAa,CAAC,YAAY,EAAE;QAC1D,8BAA8B,aAAa,CAAC,oBAAoB,EAAE;QAClE,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;AACJ,CAAC"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* released; Phase 6 of the MCP plan may swap this for a generated file
|
|
4
4
|
* populated by `npm version`.
|
|
5
5
|
*/
|
|
6
|
-
export declare const SERVER_VERSION = "0.
|
|
6
|
+
export declare const SERVER_VERSION = "0.11.0";
|
|
7
7
|
export declare const DISTRIBUTION = "sdd-method";
|
|
8
8
|
export declare const MCP_PROTOCOL_SPEC_VERSION = "2025-06-18";
|
|
9
9
|
//# sourceMappingURL=build-info.d.ts.map
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* populated by `npm version`.
|
|
5
5
|
*/
|
|
6
6
|
// Mirror of package.json version — bump in lockstep on release.
|
|
7
|
-
export const SERVER_VERSION = "0.
|
|
7
|
+
export const SERVER_VERSION = "0.11.0";
|
|
8
8
|
export const DISTRIBUTION = "sdd-method";
|
|
9
9
|
export const MCP_PROTOCOL_SPEC_VERSION = "2025-06-18";
|
|
10
10
|
//# sourceMappingURL=build-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogue.d.ts","sourceRoot":"","sources":["../../src/verbs/catalogue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0BzC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4FxD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { runCatalogueBuild, runCatalogueAggregate, runCatalogueValidate, runCatalogueVersion, } from "../lib/catalogue/index.js";
|
|
2
|
+
export function registerCatalogue(program) {
|
|
3
|
+
const catalogue = program
|
|
4
|
+
.command("catalogue")
|
|
5
|
+
.description("Build, aggregate, and validate per-SDD catalogues per ADR 0134");
|
|
6
|
+
catalogue
|
|
7
|
+
.command("build")
|
|
8
|
+
.description("Build catalogues for the current SDD repo from method-defined sources")
|
|
9
|
+
.option("--sdd-path <path>", "Path to the SDD repo root (defaults to cwd)")
|
|
10
|
+
.option("--out <path>", "Output directory for catalogues/ (defaults to <sdd-path>/catalogues)")
|
|
11
|
+
.option("--strict", "Treat findings as failures (default: only internal FK FAIL exits non-zero)")
|
|
12
|
+
.action(async (opts) => {
|
|
13
|
+
const result = await runCatalogueBuild({
|
|
14
|
+
...(opts.sddPath !== undefined ? { sddPath: opts.sddPath } : {}),
|
|
15
|
+
...(opts.out !== undefined ? { outDir: opts.out } : {}),
|
|
16
|
+
...(opts.strict !== undefined ? { strict: opts.strict } : {}),
|
|
17
|
+
}, (s) => process.stdout.write(s));
|
|
18
|
+
if (result.exitCode !== 0)
|
|
19
|
+
process.exit(result.exitCode);
|
|
20
|
+
});
|
|
21
|
+
catalogue
|
|
22
|
+
.command("aggregate")
|
|
23
|
+
.description("Aggregate sibling SDD catalogues into a single ecosystem catalogue")
|
|
24
|
+
.option("--sdd-path <path>", "Path to the ecosystem-root SDD repo (defaults to cwd)")
|
|
25
|
+
.option("--manifest <path>", "Path to the aggregation manifest (defaults to orchestration/aggregation-manifest.yaml)")
|
|
26
|
+
.option("--out <path>", "Output directory for aggregated catalogues/ (defaults to <sdd-path>/catalogues-aggregated)")
|
|
27
|
+
.option("--strict", "Treat findings as failures")
|
|
28
|
+
.action(async (opts) => {
|
|
29
|
+
const result = await runCatalogueAggregate({
|
|
30
|
+
...(opts.sddPath !== undefined ? { sddPath: opts.sddPath } : {}),
|
|
31
|
+
...(opts.manifest !== undefined
|
|
32
|
+
? { manifestPath: opts.manifest }
|
|
33
|
+
: {}),
|
|
34
|
+
...(opts.out !== undefined ? { outDir: opts.out } : {}),
|
|
35
|
+
...(opts.strict !== undefined ? { strict: opts.strict } : {}),
|
|
36
|
+
}, (s) => process.stdout.write(s));
|
|
37
|
+
if (result.exitCode !== 0)
|
|
38
|
+
process.exit(result.exitCode);
|
|
39
|
+
});
|
|
40
|
+
catalogue
|
|
41
|
+
.command("validate")
|
|
42
|
+
.description("Re-run column-shape + FK validation against existing catalogues/ (no rebuild)")
|
|
43
|
+
.option("--sdd-path <path>", "Path to the SDD repo root (defaults to cwd)")
|
|
44
|
+
.option("--strict", "Treat findings as failures")
|
|
45
|
+
.action(async (opts) => {
|
|
46
|
+
const result = await runCatalogueValidate({
|
|
47
|
+
...(opts.sddPath !== undefined ? { sddPath: opts.sddPath } : {}),
|
|
48
|
+
...(opts.strict !== undefined ? { strict: opts.strict } : {}),
|
|
49
|
+
}, (s) => process.stdout.write(s));
|
|
50
|
+
if (result.exitCode !== 0)
|
|
51
|
+
process.exit(result.exitCode);
|
|
52
|
+
});
|
|
53
|
+
catalogue
|
|
54
|
+
.command("version")
|
|
55
|
+
.description("Print the catalogue schema version + sdd-cli version pin")
|
|
56
|
+
.action(async () => {
|
|
57
|
+
await runCatalogueVersion((s) => process.stdout.write(s));
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=catalogue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogue.js","sourceRoot":"","sources":["../../src/verbs/catalogue.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdd-method/sdd-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Method-layer CLI for SDD repository lifecycle — init, sync, validate, list, plan, generate-claude-md, mcp serve. v0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
|
+
"description": "Method-layer CLI for SDD repository lifecycle — init, sync, validate, list, plan, generate-claude-md, mcp serve, catalogue {build,aggregate,validate,version}. v0.11.0 ships the canonical catalogue surface per ADR 0134 + schema 2.1.0 (ADR 0136): per-SDD catalogue build covering all four profiles, federation aggregator, validate + version subcommands, and the C4 + persona/journey/product-edge builders that complete Phase 2. v0.10.0 added reverse profile + reverse-baseline support (the fourth distribution baseline), enabling sync against brownfield reverse-SDD corpora alongside platform/app/integration profiles.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sdd-method",
|
|
7
7
|
"sdd",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"NOTICE"
|
|
36
36
|
],
|
|
37
37
|
"scripts": {
|
|
38
|
-
"build": "tsc",
|
|
38
|
+
"build": "tsc && node scripts/copy-yaml-assets.mjs",
|
|
39
39
|
"typecheck": "tsc --noEmit",
|
|
40
40
|
"test": "npm run build && vitest run",
|
|
41
41
|
"test:watch": "vitest",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Copy YAML asset files from src/ to dist/ preserving relative paths.
|
|
3
|
+
// Run as a postbuild step (tsc doesn't copy non-TS files).
|
|
4
|
+
//
|
|
5
|
+
// Currently the only such asset is src/lib/catalogue/canonical-schema.yaml,
|
|
6
|
+
// vendored from sdd-method per the SCHEMA_COMPAT contract in
|
|
7
|
+
// src/lib/catalogue/schema-compat.ts. Add more YAML assets here as the
|
|
8
|
+
// canonical builder grows.
|
|
9
|
+
|
|
10
|
+
import { mkdir, readdir, copyFile, stat } from "node:fs/promises";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { dirname, join, relative } from "node:path";
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
const SRC = join(__dirname, "..", "src");
|
|
17
|
+
const DEST = join(__dirname, "..", "dist");
|
|
18
|
+
|
|
19
|
+
async function* walk(dir) {
|
|
20
|
+
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
21
|
+
const full = join(dir, entry.name);
|
|
22
|
+
if (entry.isDirectory()) {
|
|
23
|
+
yield* walk(full);
|
|
24
|
+
} else if (entry.name.endsWith(".yaml") || entry.name.endsWith(".yml")) {
|
|
25
|
+
yield full;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let copied = 0;
|
|
31
|
+
for await (const srcFile of walk(SRC)) {
|
|
32
|
+
const rel = relative(SRC, srcFile);
|
|
33
|
+
const destFile = join(DEST, rel);
|
|
34
|
+
await mkdir(dirname(destFile), { recursive: true });
|
|
35
|
+
await copyFile(srcFile, destFile);
|
|
36
|
+
copied++;
|
|
37
|
+
}
|
|
38
|
+
console.log(`copy-yaml-assets: ${copied} file(s) copied to dist/`);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Sync the canonical catalogue-schema.yaml from sdd-method into sdd-cli's
|
|
3
|
+
# vendored copy. Run when sdd-method publishes a new schema_version that
|
|
4
|
+
# sdd-cli should adopt (per SCHEMA_COMPAT range in src/lib/catalogue/schema-compat.ts).
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# scripts/sync-canonical-schema.sh # sync from default ~/Projects/sdd-method
|
|
8
|
+
# scripts/sync-canonical-schema.sh /path/to/sdd-method # sync from explicit path
|
|
9
|
+
#
|
|
10
|
+
# After syncing, run:
|
|
11
|
+
# npm run build && npm test
|
|
12
|
+
# to verify nothing in the canonical changed in a way SCHEMA_COMPAT can't accept.
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
SDD_METHOD_PATH="${1:-$HOME/Projects/sdd-method}"
|
|
17
|
+
SOURCE="$SDD_METHOD_PATH/docs/method/methods/catalogue-schema.yaml"
|
|
18
|
+
DEST="$(dirname "$0")/../src/lib/catalogue/canonical-schema.yaml"
|
|
19
|
+
|
|
20
|
+
if [[ ! -f "$SOURCE" ]]; then
|
|
21
|
+
echo "ERROR: canonical schema not found at $SOURCE" >&2
|
|
22
|
+
echo " Pass the sdd-method repo path as the first argument." >&2
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
OLD_VERSION=""
|
|
27
|
+
if [[ -f "$DEST" ]]; then
|
|
28
|
+
OLD_VERSION=$(grep -E '^schema_version:' "$DEST" | head -1 | sed -E 's/.*"([^"]+)".*/\1/')
|
|
29
|
+
fi
|
|
30
|
+
NEW_VERSION=$(grep -E '^schema_version:' "$SOURCE" | head -1 | sed -E 's/.*"([^"]+)".*/\1/')
|
|
31
|
+
|
|
32
|
+
cp "$SOURCE" "$DEST"
|
|
33
|
+
|
|
34
|
+
if [[ -n "$OLD_VERSION" && "$OLD_VERSION" != "$NEW_VERSION" ]]; then
|
|
35
|
+
echo "Synced canonical-schema.yaml: $OLD_VERSION -> $NEW_VERSION"
|
|
36
|
+
echo "Check src/lib/catalogue/schema-compat.ts catalogue_schema range covers $NEW_VERSION."
|
|
37
|
+
else
|
|
38
|
+
echo "Synced canonical-schema.yaml @ $NEW_VERSION (unchanged)"
|
|
39
|
+
fi
|