@sdd-method/sdd-cli 0.57.0 → 0.59.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 +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/catalogue/aggregate.d.ts +20 -0
- package/dist/lib/catalogue/aggregate.d.ts.map +1 -1
- package/dist/lib/catalogue/aggregate.js +93 -0
- package/dist/lib/catalogue/aggregate.js.map +1 -1
- package/dist/lib/catalogue/builders/screens.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/screens.js +23 -1
- package/dist/lib/catalogue/builders/screens.js.map +1 -1
- package/dist/lib/catalogue/canonical-schema.yaml +39 -3
- package/dist/lib/conformance/binding.d.ts +23 -0
- package/dist/lib/conformance/binding.d.ts.map +1 -0
- package/dist/lib/conformance/binding.js +34 -0
- package/dist/lib/conformance/binding.js.map +1 -0
- package/dist/lib/conformance/finding.d.ts +5 -0
- package/dist/lib/conformance/finding.d.ts.map +1 -0
- package/dist/lib/conformance/finding.js +59 -0
- package/dist/lib/conformance/finding.js.map +1 -0
- package/dist/lib/conformance/index.d.ts +63 -0
- package/dist/lib/conformance/index.d.ts.map +1 -0
- package/dist/lib/conformance/index.js +285 -0
- package/dist/lib/conformance/index.js.map +1 -0
- package/dist/verbs/conformance.d.ts +3 -0
- package/dist/verbs/conformance.d.ts.map +1 -0
- package/dist/verbs/conformance.js +33 -0
- package/dist/verbs/conformance.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export type ConformanceTarget = "code-vs-contract" | "binding-vs-reality";
|
|
2
|
+
export interface ExtractorSpec {
|
|
3
|
+
extractor: string;
|
|
4
|
+
source?: string;
|
|
5
|
+
suffix?: string;
|
|
6
|
+
}
|
|
7
|
+
interface ReconcileSpec {
|
|
8
|
+
binding: string;
|
|
9
|
+
block: string;
|
|
10
|
+
note?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface Check {
|
|
13
|
+
id: string;
|
|
14
|
+
target: ConformanceTarget;
|
|
15
|
+
declared: ExtractorSpec | ExtractorSpec[];
|
|
16
|
+
observed: ExtractorSpec | ExtractorSpec[];
|
|
17
|
+
normalise?: "none" | "lower-nosep" | "leaf";
|
|
18
|
+
denom?: "union" | "declared";
|
|
19
|
+
reconcile?: ReconcileSpec;
|
|
20
|
+
candidates?: {
|
|
21
|
+
declared_only?: string;
|
|
22
|
+
observed_only?: string;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export interface CheckResult {
|
|
26
|
+
id: string;
|
|
27
|
+
target: ConformanceTarget;
|
|
28
|
+
declared: number;
|
|
29
|
+
observed: number;
|
|
30
|
+
matched: number;
|
|
31
|
+
conformancePct: number;
|
|
32
|
+
denom: "union" | "declared";
|
|
33
|
+
matchedNames: string[];
|
|
34
|
+
declaredNotObserved: string[];
|
|
35
|
+
observedNotDeclared: string[];
|
|
36
|
+
candidates: {
|
|
37
|
+
declared_only?: string;
|
|
38
|
+
observed_only?: string;
|
|
39
|
+
};
|
|
40
|
+
needsTriage: boolean;
|
|
41
|
+
implementationRepo?: string;
|
|
42
|
+
role?: string;
|
|
43
|
+
lifecycle?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface ConformanceOptions {
|
|
46
|
+
targetRepo: string;
|
|
47
|
+
config?: string;
|
|
48
|
+
codeRoot?: string;
|
|
49
|
+
check?: string;
|
|
50
|
+
json: boolean;
|
|
51
|
+
reconcile: boolean;
|
|
52
|
+
strict: boolean;
|
|
53
|
+
emitFinding?: string;
|
|
54
|
+
runDate?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface ConformanceResult {
|
|
57
|
+
exitCode: number;
|
|
58
|
+
results: CheckResult[];
|
|
59
|
+
skipped: string[];
|
|
60
|
+
}
|
|
61
|
+
export declare function runConformance(opts: ConformanceOptions, stdout?: (line: string) => void): Promise<ConformanceResult>;
|
|
62
|
+
export {};
|
|
63
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/conformance/index.ts"],"names":[],"mappings":"AAsBA,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,GAAG,oBAAoB,CAAC;AAE1E,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,aAAa,GAAG,aAAa,EAAE,CAAC;IAC1C,QAAQ,EAAE,aAAa,GAAG,aAAa,EAAE,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,MAAM,CAAC;IAC5C,KAAK,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IAC7B,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,UAAU,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjE;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,OAAO,GAAG,UAAU,CAAC;IAC5B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,UAAU,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,WAAW,EAAE,OAAO,CAAC;IAErB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAyQD,wBAAsB,cAAc,CAClC,IAAI,EAAE,kBAAkB,EACxB,MAAM,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAA2C,GACpE,OAAO,CAAC,iBAAiB,CAAC,CAyC5B"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { isAbsolute, resolve } from "node:path";
|
|
5
|
+
import { parse as parseYaml } from "yaml";
|
|
6
|
+
import { deriveChecksFromBinding, hasBinding, } from "./binding.js";
|
|
7
|
+
import { writeFindings } from "./finding.js";
|
|
8
|
+
// ---------------------------------------------------------------- path + extractors
|
|
9
|
+
function resolveSource(targetRepo, source, codeRoot) {
|
|
10
|
+
// `@code/...` resolves against --code-root (the checkout root of implementation member repos —
|
|
11
|
+
// code typically lives in a repo separate from the spec SDD). Absent code-root → unresolved → skip.
|
|
12
|
+
if (source.startsWith("@code/")) {
|
|
13
|
+
return codeRoot ? resolve(codeRoot, source.slice("@code/".length)) : "";
|
|
14
|
+
}
|
|
15
|
+
const expanded = source.startsWith("~") ? source.replace(/^~/, homedir()) : source;
|
|
16
|
+
return isAbsolute(expanded) ? expanded : resolve(targetRepo, expanded);
|
|
17
|
+
}
|
|
18
|
+
const markdownProviderSignals = async (path) => {
|
|
19
|
+
const out = new Set();
|
|
20
|
+
let inTable = false;
|
|
21
|
+
for (const raw of (await readFile(path, "utf-8")).split("\n")) {
|
|
22
|
+
const s = raw.trim();
|
|
23
|
+
if (!s.startsWith("|")) {
|
|
24
|
+
inTable = false;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const cells = s.replace(/^\||\|$/g, "").split("|").map((c) => c.trim());
|
|
28
|
+
const first = cells[0] ?? "";
|
|
29
|
+
if (first === "" || /^[-: ]+$/.test(first))
|
|
30
|
+
continue;
|
|
31
|
+
// Mercedes uses "Provider Signal"; VW/rFMS use "Provider Field" — both name the vendor surface col.
|
|
32
|
+
if (first === "Provider Signal" || first === "Provider Field") {
|
|
33
|
+
inTable = true;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (inTable) {
|
|
37
|
+
let sig = first.replace(/`/g, "").trim();
|
|
38
|
+
if (!sig || sig === "—" || sig.startsWith("Computed") || sig.startsWith("MB "))
|
|
39
|
+
continue;
|
|
40
|
+
sig = sig.replace(/\([^)]*\)/g, "").replace(/\[\]/g, "").trim(); // drop inline "(...)" notes + array markers
|
|
41
|
+
// Range shorthand: `datacoldTemp1..6` / `setpointTemp1..3` -> one declared name per index.
|
|
42
|
+
const range = sig.match(/^(.*?)(\d+)\.\.(\d+)$/);
|
|
43
|
+
if (range?.[1] !== undefined) {
|
|
44
|
+
const base = range[1];
|
|
45
|
+
for (let i = Number(range[2]); i <= Number(range[3]); i++)
|
|
46
|
+
out.add(`${base}${i}`);
|
|
47
|
+
}
|
|
48
|
+
else if (sig) {
|
|
49
|
+
out.add(sig);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
};
|
|
55
|
+
const javaStringConst = async (path) => {
|
|
56
|
+
const out = new Set();
|
|
57
|
+
const re = /public\s+static\s+final\s+String\s+\w+\s*=\s*"([^"]+)"/g;
|
|
58
|
+
const text = await readFile(path, "utf-8");
|
|
59
|
+
for (const m of text.matchAll(re))
|
|
60
|
+
if (m[1])
|
|
61
|
+
out.add(m[1]);
|
|
62
|
+
return out;
|
|
63
|
+
};
|
|
64
|
+
// Vendor field/signal names expressed as Java DTO fields (`private Double latitude;`) or record
|
|
65
|
+
// components (`Long hrTotalVehicleDistance,`). The shape VW (FidSignal) and the rFMS DTOs use, vs
|
|
66
|
+
// Mercedes' string-constant class. Targeted at pure data classes/records (DTO files).
|
|
67
|
+
const javaFieldNames = async (path) => {
|
|
68
|
+
const out = new Set();
|
|
69
|
+
const text = await readFile(path, "utf-8");
|
|
70
|
+
// class fields: [modifier] <Type> <name>;
|
|
71
|
+
for (const m of text.matchAll(/(?:private|protected|public)\s+[\w<>,.\s]+?\s+(\w+)\s*;/g)) {
|
|
72
|
+
if (m[1])
|
|
73
|
+
out.add(m[1]);
|
|
74
|
+
}
|
|
75
|
+
// record components: <Type> <name>, | <Type> <name>) (Type uppercase-initial, name lowercase-initial)
|
|
76
|
+
for (const m of text.matchAll(/\b[A-Z][\w<>.]*\s+([a-z]\w*)\s*[,)]/g)) {
|
|
77
|
+
if (m[1])
|
|
78
|
+
out.add(m[1]);
|
|
79
|
+
}
|
|
80
|
+
// Wire aliases: @JsonProperty("long") / @SerializedName("...") name the on-the-wire field, which is
|
|
81
|
+
// what the provider-surface grounding declares — emit it alongside the Java identifier.
|
|
82
|
+
for (const m of text.matchAll(/@(?:JsonProperty|SerializedName|JsonAlias)\s*\(\s*"([^"]+)"/g)) {
|
|
83
|
+
if (m[1])
|
|
84
|
+
out.add(m[1]);
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
};
|
|
88
|
+
const yamlProducedEvents = async (path) => {
|
|
89
|
+
const out = new Set();
|
|
90
|
+
const doc = parseYaml(await readFile(path, "utf-8"));
|
|
91
|
+
for (const p of doc?.events?.produces ?? []) {
|
|
92
|
+
const schema = p?.schema;
|
|
93
|
+
if (typeof schema === "string") {
|
|
94
|
+
const base = schema.split("/").pop() ?? schema;
|
|
95
|
+
out.add(base.replace(/\.avsc$/, ""));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
};
|
|
100
|
+
const tsAvscRefs = async (path) => {
|
|
101
|
+
const out = new Set();
|
|
102
|
+
const text = await readFile(path, "utf-8");
|
|
103
|
+
for (const m of text.matchAll(/([A-Za-z0-9_-]+)\.avsc/g))
|
|
104
|
+
if (m[1])
|
|
105
|
+
out.add(m[1]);
|
|
106
|
+
return out;
|
|
107
|
+
};
|
|
108
|
+
const dirListing = async (path, spec) => {
|
|
109
|
+
const suffix = spec.suffix ?? "";
|
|
110
|
+
const entries = await readdir(path);
|
|
111
|
+
return new Set(entries
|
|
112
|
+
.filter((f) => f.endsWith(suffix))
|
|
113
|
+
.map((f) => (suffix ? f.slice(0, -suffix.length) : f)));
|
|
114
|
+
};
|
|
115
|
+
const REGISTRY = {
|
|
116
|
+
"markdown-provider-signals": markdownProviderSignals,
|
|
117
|
+
"markdown-provider-fields": markdownProviderSignals, // same fn; matches "Provider Signal" | "Provider Field"
|
|
118
|
+
"java-string-const": javaStringConst,
|
|
119
|
+
"java-field-names": javaFieldNames,
|
|
120
|
+
"yaml-produced-events": yamlProducedEvents,
|
|
121
|
+
"ts-avsc-refs": tsAvscRefs,
|
|
122
|
+
"dir-listing": dirListing,
|
|
123
|
+
};
|
|
124
|
+
// ---------------------------------------------------------------- diff core
|
|
125
|
+
function norm(s, mode) {
|
|
126
|
+
if (mode === "leaf") {
|
|
127
|
+
// Match a nested/dotted declared path against a leaf code identifier: take the last dotted
|
|
128
|
+
// segment, drop array markers, then lower-nosep. `statusInfo.truStatus` ~ `truStatus`.
|
|
129
|
+
const leaf = s.split(".").pop() ?? s;
|
|
130
|
+
return leaf.replace(/\[\]/g, "").replace(/[-_./ ]/g, "").toLowerCase();
|
|
131
|
+
}
|
|
132
|
+
return mode === "lower-nosep" ? s.replace(/[-_./ ]/g, "").toLowerCase() : s;
|
|
133
|
+
}
|
|
134
|
+
async function extract(targetRepo, codeRoot, spec) {
|
|
135
|
+
const specs = Array.isArray(spec) ? spec : [spec];
|
|
136
|
+
const values = new Set();
|
|
137
|
+
let ok = true;
|
|
138
|
+
for (const sp of specs) {
|
|
139
|
+
const fn = REGISTRY[sp.extractor];
|
|
140
|
+
if (!fn)
|
|
141
|
+
throw new Error(`unknown extractor: ${sp.extractor}`);
|
|
142
|
+
const path = sp.source ? resolveSource(targetRepo, sp.source, codeRoot) : "";
|
|
143
|
+
if (!path || !existsSync(path)) {
|
|
144
|
+
ok = false;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
for (const v of await fn(path, sp))
|
|
148
|
+
values.add(v);
|
|
149
|
+
}
|
|
150
|
+
return { values, ok };
|
|
151
|
+
}
|
|
152
|
+
async function runCheck(targetRepo, codeRoot, chk, member) {
|
|
153
|
+
const dRes = await extract(targetRepo, codeRoot, chk.declared);
|
|
154
|
+
const oRes = await extract(targetRepo, codeRoot, chk.observed);
|
|
155
|
+
if (!dRes.ok || !oRes.ok)
|
|
156
|
+
return null; // SKIP — a source is absent here
|
|
157
|
+
const mode = chk.normalise ?? "none";
|
|
158
|
+
const dMap = new Map([...dRes.values].map((x) => [norm(x, mode), x]));
|
|
159
|
+
const oMap = new Map([...oRes.values].map((x) => [norm(x, mode), x]));
|
|
160
|
+
const D = new Set(dMap.keys());
|
|
161
|
+
const O = new Set(oMap.keys());
|
|
162
|
+
const matched = [...D].filter((k) => O.has(k));
|
|
163
|
+
const dOnly = [...D].filter((k) => !O.has(k));
|
|
164
|
+
const oOnly = [...O].filter((k) => !D.has(k));
|
|
165
|
+
const denom = (chk.denom ?? "union") === "declared" ? D.size : new Set([...D, ...O]).size;
|
|
166
|
+
return {
|
|
167
|
+
id: chk.id,
|
|
168
|
+
target: chk.target,
|
|
169
|
+
declared: D.size,
|
|
170
|
+
observed: O.size,
|
|
171
|
+
matched: matched.length,
|
|
172
|
+
conformancePct: denom ? Math.round((matched.length / denom) * 100) : 0,
|
|
173
|
+
denom: chk.denom ?? "union",
|
|
174
|
+
matchedNames: matched.map((k) => dMap.get(k)).sort(),
|
|
175
|
+
declaredNotObserved: dOnly.map((k) => dMap.get(k)).sort(),
|
|
176
|
+
observedNotDeclared: oOnly.map((k) => oMap.get(k)).sort(),
|
|
177
|
+
candidates: chk.candidates ?? {},
|
|
178
|
+
needsTriage: dOnly.length > 0 || oOnly.length > 0,
|
|
179
|
+
...(member?.repo ? { implementationRepo: member.repo } : {}),
|
|
180
|
+
...(member?.role ? { role: member.role } : {}),
|
|
181
|
+
...(member?.lifecycle ? { lifecycle: member.lifecycle } : {}),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
// ---------------------------------------------------------------- output
|
|
185
|
+
function printHuman(r, out) {
|
|
186
|
+
out(`\n=== ${r.id} [${r.target}] ===\n`);
|
|
187
|
+
out(`declared=${r.declared} observed=${r.observed} matched=${r.matched} ` +
|
|
188
|
+
`conformance=${r.conformancePct}% (matched/${r.denom})\n`);
|
|
189
|
+
if (r.matchedNames.length)
|
|
190
|
+
out(` [OK] matched: ${r.matchedNames.join(", ")}\n`);
|
|
191
|
+
if (r.declaredNotObserved.length) {
|
|
192
|
+
out(` [!] declared-not-observed (${r.declaredNotObserved.length}) -> NEEDS-TRIAGE ` +
|
|
193
|
+
`[${r.candidates.declared_only ?? ""}]:\n`);
|
|
194
|
+
for (const m of r.declaredNotObserved)
|
|
195
|
+
out(` - ${m}\n`);
|
|
196
|
+
}
|
|
197
|
+
if (r.observedNotDeclared.length) {
|
|
198
|
+
out(` [!] observed-not-declared (${r.observedNotDeclared.length}) -> NEEDS-TRIAGE ` +
|
|
199
|
+
`[${r.candidates.observed_only ?? ""}]:\n`);
|
|
200
|
+
for (const m of r.observedNotDeclared)
|
|
201
|
+
out(` - ${m}\n`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function printReconcile(chk, r, out) {
|
|
205
|
+
if (!chk.reconcile || r.target !== "binding-vs-reality")
|
|
206
|
+
return;
|
|
207
|
+
const rc = chk.reconcile;
|
|
208
|
+
out(`\n--- reconcile ${r.id} -> regenerate \`${rc.block}\` in ${rc.binding} (ADR 0181 §2.3) ---\n`);
|
|
209
|
+
out(`# generated from the observed-set (${r.observed} schemas); the binding cannot drift if generated.\n`);
|
|
210
|
+
if (rc.note)
|
|
211
|
+
out(`# NOTE: ${rc.note}\n`);
|
|
212
|
+
const full = [...new Set([...r.matchedNames, ...r.observedNotDeclared])].sort();
|
|
213
|
+
out(`${rc.block.split(".")[0]}:\n`);
|
|
214
|
+
out(` produces: # ${full.length} schemas (was ${r.declared} declared)\n`);
|
|
215
|
+
for (const name of full)
|
|
216
|
+
out(` - schema: party/events/${name}.avsc\n`);
|
|
217
|
+
if (r.declaredNotObserved.length) {
|
|
218
|
+
out(` # DROP (dangling — no such schema in code/contracts): ${r.declaredNotObserved.join(", ")}\n`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
async function planChecks(opts, stdout) {
|
|
222
|
+
// Resolution order: explicit --config wins; else the ADR 0181 binding (checks derived from it);
|
|
223
|
+
// else the conventional .sdd/conformance-checks.yaml; else nothing to do.
|
|
224
|
+
if (!opts.config && hasBinding(opts.targetRepo)) {
|
|
225
|
+
const derived = await deriveChecksFromBinding(opts.targetRepo);
|
|
226
|
+
return derived.map((d) => ({ check: d.check, member: d.member }));
|
|
227
|
+
}
|
|
228
|
+
const configPath = opts.config
|
|
229
|
+
? resolveSource(opts.targetRepo, opts.config, opts.codeRoot)
|
|
230
|
+
: resolve(opts.targetRepo, ".sdd/conformance-checks.yaml");
|
|
231
|
+
if (!existsSync(configPath)) {
|
|
232
|
+
stdout(`[skip] no spec↔implementation binding (.sdd/implementation-binding.yaml, ADR 0181) and no ` +
|
|
233
|
+
`checks file at ${configPath}\n`);
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
const parsed = parseYaml(await readFile(configPath, "utf-8"));
|
|
237
|
+
return (parsed?.checks ?? []).map((check) => ({ check }));
|
|
238
|
+
}
|
|
239
|
+
export async function runConformance(opts, stdout = (line) => process.stdout.write(line)) {
|
|
240
|
+
let planned = await planChecks(opts, stdout);
|
|
241
|
+
if (planned === null)
|
|
242
|
+
return { exitCode: 0, results: [], skipped: [] };
|
|
243
|
+
if (opts.check)
|
|
244
|
+
planned = planned.filter((p) => p.check.id === opts.check);
|
|
245
|
+
const results = [];
|
|
246
|
+
const skipped = [];
|
|
247
|
+
const reconcileByline = new Map();
|
|
248
|
+
for (const { check, member } of planned) {
|
|
249
|
+
const r = await runCheck(opts.targetRepo, opts.codeRoot, check, member);
|
|
250
|
+
if (r) {
|
|
251
|
+
results.push(r);
|
|
252
|
+
reconcileByline.set(r.id, check);
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
skipped.push(check.id);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (opts.json) {
|
|
259
|
+
stdout(JSON.stringify({ checks: results, skipped }, null, 2) + "\n");
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
stdout("Conformance-reverse (advisory; disposition is triage — ADR 0180 §2.3).\n");
|
|
263
|
+
for (const r of results) {
|
|
264
|
+
printHuman(r, stdout);
|
|
265
|
+
if (opts.reconcile) {
|
|
266
|
+
const chk = reconcileByline.get(r.id);
|
|
267
|
+
if (chk)
|
|
268
|
+
printReconcile(chk, r, stdout);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
for (const id of skipped)
|
|
272
|
+
stdout(`\n=== ${id} === SKIP (source not found)\n`);
|
|
273
|
+
if (!opts.strict)
|
|
274
|
+
stdout("\n--- exit 0 (advisory). Use --strict to gate on un-triaged drift. ---\n");
|
|
275
|
+
}
|
|
276
|
+
if (opts.emitFinding) {
|
|
277
|
+
const runDate = opts.runDate ?? new Date().toISOString().slice(0, 10);
|
|
278
|
+
const path = await writeFindings(opts.emitFinding, results, runDate);
|
|
279
|
+
if (!opts.json)
|
|
280
|
+
stdout(`\n[OK] wrote conformance_finding catalogue: ${path}\n`);
|
|
281
|
+
}
|
|
282
|
+
const anyTriage = results.some((r) => r.needsTriage);
|
|
283
|
+
return { exitCode: opts.strict && anyTriage ? 1 : 0, results, skipped };
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/conformance/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../../src/verbs/conformance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAczC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+B1D"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { runConformance } from "../lib/conformance/index.js";
|
|
2
|
+
export function registerConformance(program) {
|
|
3
|
+
program
|
|
4
|
+
.command("conformance")
|
|
5
|
+
.description("Conformance-reverse: diff the declared surface (spec/binding/contract) against the observed " +
|
|
6
|
+
"surface (code) and report drift with PROVISIONAL verdicts (ADR 0180). Advisory by default — " +
|
|
7
|
+
"disposition (code-defect vs spec-stale vs divergence) is a triage step, not this verb's call. " +
|
|
8
|
+
"Checks are derived from the spec-implementation binding (.sdd/implementation-binding.yaml, " +
|
|
9
|
+
"ADR 0181) when present; else .sdd/conformance-checks.yaml.")
|
|
10
|
+
.option("--target-repo <dir>", "target SDD repo", process.cwd())
|
|
11
|
+
.option("--config <path>", "explicit checks file (overrides the binding)")
|
|
12
|
+
.option("--code-root <dir>", "checkout root for implementation member repos (resolves @code/ sources)")
|
|
13
|
+
.option("--check <id>", "run only the named check")
|
|
14
|
+
.option("--json", "machine-readable report (CI ingestion)")
|
|
15
|
+
.option("--reconcile", "for binding-vs-reality checks, emit the binding fragment regenerated from the observed-set (ADR 0181 §2.3)")
|
|
16
|
+
.option("--emit-finding <dir>", "write the conformance_finding catalogue CSV into <dir> (federates via aggregate)")
|
|
17
|
+
.option("--strict", "exit non-zero when any check needs triage (default: advisory, exit 0)")
|
|
18
|
+
.action(async (opts) => {
|
|
19
|
+
const { exitCode } = await runConformance({
|
|
20
|
+
targetRepo: opts.targetRepo,
|
|
21
|
+
...(opts.config ? { config: opts.config } : {}),
|
|
22
|
+
...(opts.codeRoot ? { codeRoot: opts.codeRoot } : {}),
|
|
23
|
+
...(opts.check ? { check: opts.check } : {}),
|
|
24
|
+
json: opts.json === true,
|
|
25
|
+
reconcile: opts.reconcile === true,
|
|
26
|
+
strict: opts.strict === true,
|
|
27
|
+
...(opts.emitFinding ? { emitFinding: opts.emitFinding } : {}),
|
|
28
|
+
});
|
|
29
|
+
if (exitCode !== 0)
|
|
30
|
+
process.exit(exitCode);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=conformance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conformance.js","sourceRoot":"","sources":["../../src/verbs/conformance.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAa7D,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,aAAa,CAAC;SACtB,WAAW,CACV,8FAA8F;QAC5F,8FAA8F;QAC9F,gGAAgG;QAChG,6FAA6F;QAC7F,4DAA4D,CAC/D;SACA,MAAM,CAAC,qBAAqB,EAAE,iBAAiB,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SAC/D,MAAM,CAAC,iBAAiB,EAAE,8CAA8C,CAAC;SACzE,MAAM,CAAC,mBAAmB,EAAE,yEAAyE,CAAC;SACtG,MAAM,CAAC,cAAc,EAAE,0BAA0B,CAAC;SAClD,MAAM,CAAC,QAAQ,EAAE,wCAAwC,CAAC;SAC1D,MAAM,CAAC,aAAa,EAAE,4GAA4G,CAAC;SACnI,MAAM,CAAC,sBAAsB,EAAE,kFAAkF,CAAC;SAClH,MAAM,CAAC,UAAU,EAAE,uEAAuE,CAAC;SAC3F,MAAM,CAAC,KAAK,EAAE,IAAiC,EAAE,EAAE;QAClD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,cAAc,CAAC;YACxC,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,IAAI;YACxB,SAAS,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI;YAClC,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,IAAI;YAC5B,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/D,CAAC,CAAC;QACH,IAAI,QAAQ,KAAK,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACP,CAAC"}
|