@sdd-method/sdd-cli 1.36.1 → 1.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/catalogue/aggregate.js +2 -2
- package/dist/lib/catalogue/aggregate.js.map +1 -1
- package/dist/lib/catalogue/baseline-check.d.ts.map +1 -1
- package/dist/lib/catalogue/baseline-check.js +17 -2
- package/dist/lib/catalogue/baseline-check.js.map +1 -1
- package/dist/lib/catalogue/build.js +23 -3
- package/dist/lib/catalogue/build.js.map +1 -1
- package/dist/lib/catalogue/builders/feature-tree-walker.d.ts +7 -0
- package/dist/lib/catalogue/builders/feature-tree-walker.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/feature-tree-walker.js +16 -4
- package/dist/lib/catalogue/builders/feature-tree-walker.js.map +1 -1
- package/dist/lib/catalogue/builders/repositories.js +48 -13
- package/dist/lib/catalogue/builders/repositories.js.map +1 -1
- package/dist/lib/catalogue/canonical-schema.yaml +6 -3
- package/dist/lib/catalogue/coverage-render.d.ts.map +1 -1
- package/dist/lib/catalogue/coverage-render.js +30 -0
- package/dist/lib/catalogue/coverage-render.js.map +1 -1
- package/dist/lib/catalogue/engine-validator.d.ts +6 -0
- package/dist/lib/catalogue/engine-validator.d.ts.map +1 -1
- package/dist/lib/catalogue/engine-validator.js +17 -0
- package/dist/lib/catalogue/engine-validator.js.map +1 -1
- package/dist/lib/catalogue/graph-projection.d.ts +8 -0
- package/dist/lib/catalogue/graph-projection.d.ts.map +1 -1
- package/dist/lib/catalogue/graph-projection.js +10 -0
- package/dist/lib/catalogue/graph-projection.js.map +1 -1
- package/dist/lib/catalogue/graph-run.d.ts +2 -9
- package/dist/lib/catalogue/graph-run.d.ts.map +1 -1
- package/dist/lib/catalogue/graph-run.js +6 -11
- package/dist/lib/catalogue/graph-run.js.map +1 -1
- package/dist/lib/catalogue/impact-run.d.ts.map +1 -1
- package/dist/lib/catalogue/impact-run.js +1 -2
- package/dist/lib/catalogue/impact-run.js.map +1 -1
- package/dist/lib/catalogue/manifest-loader.d.ts +2 -0
- package/dist/lib/catalogue/manifest-loader.d.ts.map +1 -1
- package/dist/lib/catalogue/manifest-loader.js +9 -0
- package/dist/lib/catalogue/manifest-loader.js.map +1 -1
- package/dist/lib/catalogue/scores-coverage.d.ts +26 -1
- package/dist/lib/catalogue/scores-coverage.d.ts.map +1 -1
- package/dist/lib/catalogue/scores-coverage.js +38 -0
- package/dist/lib/catalogue/scores-coverage.js.map +1 -1
- package/dist/lib/catalogue/validate.js +4 -4
- package/dist/lib/catalogue/validate.js.map +1 -1
- package/dist/lib/conformance/index.d.ts.map +1 -1
- package/dist/lib/conformance/index.js +28 -3
- package/dist/lib/conformance/index.js.map +1 -1
- package/dist/lib/snapshot/catalogue-diff.d.ts.map +1 -1
- package/dist/lib/snapshot/catalogue-diff.js +15 -1
- package/dist/lib/snapshot/catalogue-diff.js.map +1 -1
- package/dist/lib/snapshot/fold.d.ts.map +1 -1
- package/dist/lib/snapshot/fold.js +3 -1
- package/dist/lib/snapshot/fold.js.map +1 -1
- package/dist/lib/snapshot/verify.d.ts.map +1 -1
- package/dist/lib/snapshot/verify.js +6 -0
- package/dist/lib/snapshot/verify.js.map +1 -1
- package/dist/lib/sync/adr-transitions.d.ts +25 -1
- package/dist/lib/sync/adr-transitions.d.ts.map +1 -1
- package/dist/lib/sync/adr-transitions.js +59 -5
- package/dist/lib/sync/adr-transitions.js.map +1 -1
- package/dist/lib/sync/index.d.ts.map +1 -1
- package/dist/lib/sync/index.js +31 -1
- package/dist/lib/sync/index.js.map +1 -1
- package/dist/lib/validate/aggregate.d.ts +4 -0
- package/dist/lib/validate/aggregate.d.ts.map +1 -1
- package/dist/lib/validate/aggregate.js +31 -15
- package/dist/lib/validate/aggregate.js.map +1 -1
- package/dist/lib/validate/bundle-coherence.d.ts.map +1 -1
- package/dist/lib/validate/bundle-coherence.js +7 -2
- package/dist/lib/validate/bundle-coherence.js.map +1 -1
- package/dist/lib/validate/dispatch.d.ts.map +1 -1
- package/dist/lib/validate/dispatch.js +25 -0
- package/dist/lib/validate/dispatch.js.map +1 -1
- package/dist/lib/validate/index.d.ts.map +1 -1
- package/dist/lib/validate/index.js +32 -10
- package/dist/lib/validate/index.js.map +1 -1
- package/dist/lib/validate/yaml-parse.d.ts +17 -0
- package/dist/lib/validate/yaml-parse.d.ts.map +1 -0
- package/dist/lib/validate/yaml-parse.js +112 -0
- package/dist/lib/validate/yaml-parse.js.map +1 -0
- package/package.json +2 -2
- package/scripts/validate-app-dependencies.sh +24 -4
- package/scripts/validate-app-docs.sh +18 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { profileFromRepoKind, readRepoKind } from "../repo-kind.js";
|
|
2
|
-
import { aggregateResults } from "./aggregate.js";
|
|
2
|
+
import { aggregateResults, classifyResult } from "./aggregate.js";
|
|
3
3
|
import { selectValidators } from "./dispatch.js";
|
|
4
4
|
import { runValidator } from "./runner.js";
|
|
5
5
|
const SECTION_RULE = "═".repeat(59);
|
|
@@ -35,13 +35,17 @@ export async function runValidate(opts, stdout = (line) => process.stdout.write(
|
|
|
35
35
|
stdout(result.stdout);
|
|
36
36
|
if (result.stderr)
|
|
37
37
|
stdout(result.stderr);
|
|
38
|
-
if (result.exitCode
|
|
39
|
-
stdout(pass(`${cfg.name}: ok`));
|
|
40
|
-
else
|
|
38
|
+
if (result.exitCode !== 0)
|
|
41
39
|
stdout(fail(`${cfg.name}: exit ${result.exitCode}`));
|
|
40
|
+
else if (classifyResult(result, { strict: opts.strict }) === "not-measured") {
|
|
41
|
+
stdout(na(`${cfg.name}: nothing measured — its population is empty`));
|
|
42
|
+
}
|
|
43
|
+
else
|
|
44
|
+
stdout(pass(`${cfg.name}: ok`));
|
|
42
45
|
}
|
|
43
46
|
const summary = aggregateResults(results, { strict: opts.strict });
|
|
44
|
-
stdout(info(`Summary: passed=${summary.passed} failed=${summary.failed} skipped=${summary.skipped}
|
|
47
|
+
stdout(info(`Summary: passed=${summary.passed} failed=${summary.failed} skipped=${summary.skipped} ` +
|
|
48
|
+
`not-measured=${summary.notMeasured} warned=${summary.warned}${opts.strict ? " (strict)" : ""}`));
|
|
45
49
|
stdout(verdict(summary, validators.length));
|
|
46
50
|
return { exitCode: summary.exitCode, summary };
|
|
47
51
|
}
|
|
@@ -55,14 +59,29 @@ function verdict(summary, selected) {
|
|
|
55
59
|
if (summary.exitCode !== 0)
|
|
56
60
|
return fail("One or more validators failed");
|
|
57
61
|
const ran = summary.passed + summary.failed;
|
|
58
|
-
|
|
62
|
+
const nm = summary.notMeasured;
|
|
63
|
+
if (summary.skipped === 0 && nm === 0)
|
|
59
64
|
return pass("All validators passed");
|
|
60
|
-
if (ran === 0) {
|
|
65
|
+
if (ran === 0 && nm === 0) {
|
|
61
66
|
return warn(`0 of ${selected} validators ran — all ${summary.skipped} skipped. ` +
|
|
62
67
|
`This is an absence of evidence, not a pass.`);
|
|
63
68
|
}
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
if (nm === 0) {
|
|
70
|
+
return warn(`${ran} of ${selected} validators passed — ${summary.skipped} skipped, ` +
|
|
71
|
+
`and a skipped validator is not covered by this verdict.`);
|
|
72
|
+
}
|
|
73
|
+
const uncovered = [
|
|
74
|
+
summary.skipped > 0 ? `${summary.skipped} skipped` : "",
|
|
75
|
+
nm > 0 ? `${nm} measured nothing (an empty population)` : "",
|
|
76
|
+
]
|
|
77
|
+
.filter(Boolean)
|
|
78
|
+
.join(", ");
|
|
79
|
+
if (ran === 0) {
|
|
80
|
+
return warn(`0 of ${selected} validators measured anything — ${uncovered}. ` +
|
|
81
|
+
`This is an absence of evidence, not a pass.`);
|
|
82
|
+
}
|
|
83
|
+
return warn(`${ran} of ${selected} validators passed — ${uncovered}; ` +
|
|
84
|
+
`neither is covered by this verdict.`);
|
|
66
85
|
}
|
|
67
86
|
function section(title) {
|
|
68
87
|
return `\n${SECTION_RULE}\n ${title}\n${SECTION_RULE}\n\n`;
|
|
@@ -79,10 +98,13 @@ function fail(msg) {
|
|
|
79
98
|
function skip(msg) {
|
|
80
99
|
return `[SKIP] ${msg}\n`;
|
|
81
100
|
}
|
|
101
|
+
function na(msg) {
|
|
102
|
+
return `[N/A] ${msg}\n`;
|
|
103
|
+
}
|
|
82
104
|
function warn(msg) {
|
|
83
105
|
return `[WARN] ${msg}\n`;
|
|
84
106
|
}
|
|
85
107
|
function emptySummary() {
|
|
86
|
-
return { exitCode: 1, passed: 0, failed: 0, skipped: 0, warned: 0 };
|
|
108
|
+
return { exitCode: 1, passed: 0, failed: 0, skipped: 0, warned: 0, notMeasured: 0 };
|
|
87
109
|
}
|
|
88
110
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/validate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAyB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/validate/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface YamlParseResult {
|
|
2
|
+
exitCode: number;
|
|
3
|
+
stdout: string;
|
|
4
|
+
skipped?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface YamlParseError {
|
|
7
|
+
readonly file: string;
|
|
8
|
+
readonly code: string;
|
|
9
|
+
readonly message: string;
|
|
10
|
+
}
|
|
11
|
+
/** Strict-parse one YAML text; returns the errors (empty = parses). */
|
|
12
|
+
export declare function strictYamlErrors(text: string): Array<{
|
|
13
|
+
code: string;
|
|
14
|
+
message: string;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function checkYamlParse(targetRepo: string): Promise<YamlParseResult>;
|
|
17
|
+
//# sourceMappingURL=yaml-parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml-parse.d.ts","sourceRoot":"","sources":["../../../src/lib/validate/yaml-parse.ts"],"names":[],"mappings":"AAgCA,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAOvF;AAeD,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAsEjF"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// YAML parse gate — every tracked YAML source must parse STRICTLY.
|
|
2
|
+
//
|
|
3
|
+
// The catalogue builders read YAML file by file and, for most sources, log
|
|
4
|
+
// `invalid YAML` and move on: the file becomes wholly invisible to the
|
|
5
|
+
// catalogue and nothing ever fails. Measured: 19 unparseable files across 4
|
|
6
|
+
// SDDs, 16 in one repo, accumulated that way.
|
|
7
|
+
//
|
|
8
|
+
// THE LOADER IS THE GATE. PyYAML (and any last-key-wins loader) accepts a
|
|
9
|
+
// duplicate key and silently keeps the second value, so a parse-only check
|
|
10
|
+
// with it certifies exactly the corruption a line-surgery transformer
|
|
11
|
+
// produces. `yaml` v2 refuses duplicate keys (DUPLICATE_KEY) and the other
|
|
12
|
+
// malformations a lenient parse glosses — e.g. a `: ` inside an unquoted
|
|
13
|
+
// scalar (`path: (none — tel: URL)`), which no pattern rule catches.
|
|
14
|
+
//
|
|
15
|
+
// Scope: the YAML files git TRACKS (`*.yaml`, `*.yml`) — the repo's sources,
|
|
16
|
+
// not build output or dependencies. Outside a git work tree there is no
|
|
17
|
+
// honest scope, so the check reports a SKIP rather than a pass.
|
|
18
|
+
//
|
|
19
|
+
// A TEMPLATE is not YAML until rendered (Helm/Go `{{- … -}}`, Handlebars).
|
|
20
|
+
// A file that fails to parse AND carries a template directive is listed as
|
|
21
|
+
// templated and not failed — UNLESS one of its errors is a duplicate key: a
|
|
22
|
+
// duplicate key is a duplicate however the file is produced, and exempting it
|
|
23
|
+
// would let any `{{ }}` in a value hide exactly the defect this gate exists for.
|
|
24
|
+
import { execFile } from "node:child_process";
|
|
25
|
+
import { readFile } from "node:fs/promises";
|
|
26
|
+
import { join } from "node:path";
|
|
27
|
+
import { promisify } from "node:util";
|
|
28
|
+
import { parseAllDocuments } from "yaml";
|
|
29
|
+
const execFileAsync = promisify(execFile);
|
|
30
|
+
const TEMPLATE_DIRECTIVE_RE = /\{\{[\s\S]*?\}\}/;
|
|
31
|
+
/** Strict-parse one YAML text; returns the errors (empty = parses). */
|
|
32
|
+
export function strictYamlErrors(text) {
|
|
33
|
+
return parseAllDocuments(text).flatMap((doc) => doc.errors.map((e) => ({
|
|
34
|
+
code: e.code,
|
|
35
|
+
message: e.message.split("\n")[0] ?? e.message,
|
|
36
|
+
})));
|
|
37
|
+
}
|
|
38
|
+
async function trackedYamlFiles(repo) {
|
|
39
|
+
try {
|
|
40
|
+
const { stdout } = await execFileAsync("git", ["-C", repo, "ls-files", "-z", "--", "*.yaml", "*.yml"], { maxBuffer: 64 * 1024 * 1024 });
|
|
41
|
+
return stdout.split("\0").filter((p) => p !== "");
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export async function checkYamlParse(targetRepo) {
|
|
48
|
+
const files = await trackedYamlFiles(targetRepo);
|
|
49
|
+
if (files === null) {
|
|
50
|
+
return {
|
|
51
|
+
exitCode: 0,
|
|
52
|
+
stdout: "",
|
|
53
|
+
skipped: "not a git work tree — no tracked-file scope to check",
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const failures = [];
|
|
57
|
+
const templated = [];
|
|
58
|
+
let read = 0;
|
|
59
|
+
for (const file of files) {
|
|
60
|
+
let text;
|
|
61
|
+
try {
|
|
62
|
+
text = await readFile(join(targetRepo, file), "utf-8");
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
continue; // tracked but deleted in the work tree: not a parse question
|
|
66
|
+
}
|
|
67
|
+
read += 1;
|
|
68
|
+
const errors = strictYamlErrors(text);
|
|
69
|
+
if (errors.length > 0 &&
|
|
70
|
+
!errors.some((e) => e.code === "DUPLICATE_KEY") &&
|
|
71
|
+
TEMPLATE_DIRECTIVE_RE.test(text)) {
|
|
72
|
+
templated.push(file);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
for (const e of errors) {
|
|
76
|
+
failures.push({ file, code: e.code, message: e.message });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const checked = read - templated.length;
|
|
80
|
+
const templatedNote = templated.length === 0
|
|
81
|
+
? ""
|
|
82
|
+
: `[INFO] yaml-parse: ${templated.length} templated file(s) not checked — they do not parse ` +
|
|
83
|
+
`until rendered and carry a {{ … }} directive: ${templated.join(", ")}\n`;
|
|
84
|
+
if (failures.length === 0 && checked === 0) {
|
|
85
|
+
// Zero files checked is absence of evidence, never a pass.
|
|
86
|
+
return {
|
|
87
|
+
exitCode: 0,
|
|
88
|
+
stdout: templatedNote,
|
|
89
|
+
skipped: "no tracked YAML files to parse — nothing to check",
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (failures.length === 0) {
|
|
93
|
+
return {
|
|
94
|
+
exitCode: 0,
|
|
95
|
+
stdout: templatedNote +
|
|
96
|
+
`[PASS] yaml-parse: ${checked} tracked YAML file(s) parse strictly (duplicate keys refused)\n`,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const failedFiles = new Set(failures.map((f) => f.file)).size;
|
|
100
|
+
const byCode = new Map();
|
|
101
|
+
for (const f of failures)
|
|
102
|
+
byCode.set(f.code, (byCode.get(f.code) ?? 0) + 1);
|
|
103
|
+
const lines = failures.map((f) => `[FAIL] yaml-parse: ${f.file}: ${f.code}: ${f.message}\n`);
|
|
104
|
+
if (templatedNote !== "")
|
|
105
|
+
lines.unshift(templatedNote);
|
|
106
|
+
lines.push(`[FAIL] yaml-parse: ${failedFiles} of ${checked} tracked YAML file(s) do not parse strictly ` +
|
|
107
|
+
`(${[...byCode].map(([c, n]) => `${c} ×${n}`).join(", ")}). ` +
|
|
108
|
+
`A file that does not parse is invisible to the catalogue; a duplicate key keeps only one ` +
|
|
109
|
+
`of its values under a lenient loader. Fix the file — do not relax the loader.\n`);
|
|
110
|
+
return { exitCode: 1, stdout: lines.join("") };
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=yaml-parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml-parse.js","sourceRoot":"","sources":["../../../src/lib/validate/yaml-parse.ts"],"names":[],"mappings":"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"}
|