@sdd-method/sdd-cli 1.1.0 → 1.3.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.d.ts.map +1 -1
- package/dist/lib/catalogue/aggregate.js +5 -4
- package/dist/lib/catalogue/aggregate.js.map +1 -1
- package/dist/lib/catalogue/build.d.ts.map +1 -1
- package/dist/lib/catalogue/build.js +16 -7
- package/dist/lib/catalogue/build.js.map +1 -1
- package/dist/lib/catalogue/builders/capability-edges.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/capability-edges.js +10 -1
- package/dist/lib/catalogue/builders/capability-edges.js.map +1 -1
- package/dist/lib/catalogue/builders/capability-spec.d.ts +9 -3
- package/dist/lib/catalogue/builders/capability-spec.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/capability-spec.js +9 -3
- package/dist/lib/catalogue/builders/capability-spec.js.map +1 -1
- package/dist/lib/catalogue/builders/index.d.ts +2 -0
- package/dist/lib/catalogue/builders/index.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/index.js +1 -0
- package/dist/lib/catalogue/builders/index.js.map +1 -1
- package/dist/lib/catalogue/builders/quality-scores.d.ts +14 -0
- package/dist/lib/catalogue/builders/quality-scores.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/quality-scores.js +321 -0
- package/dist/lib/catalogue/builders/quality-scores.js.map +1 -0
- package/dist/lib/catalogue/builders/services.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/services.js +5 -1
- package/dist/lib/catalogue/builders/services.js.map +1 -1
- package/dist/lib/catalogue/canonical-schema.yaml +255 -6
- package/dist/lib/catalogue/coverage-predicates.d.ts +176 -0
- package/dist/lib/catalogue/coverage-predicates.d.ts.map +1 -0
- package/dist/lib/catalogue/coverage-predicates.js +603 -0
- package/dist/lib/catalogue/coverage-predicates.js.map +1 -0
- package/dist/lib/catalogue/coverage-render.d.ts +54 -0
- package/dist/lib/catalogue/coverage-render.d.ts.map +1 -0
- package/dist/lib/catalogue/coverage-render.js +432 -0
- package/dist/lib/catalogue/coverage-render.js.map +1 -0
- package/dist/lib/catalogue/coverage-run.d.ts +33 -0
- package/dist/lib/catalogue/coverage-run.d.ts.map +1 -0
- package/dist/lib/catalogue/coverage-run.js +97 -0
- package/dist/lib/catalogue/coverage-run.js.map +1 -0
- package/dist/lib/catalogue/ddl-generator.d.ts +80 -0
- package/dist/lib/catalogue/ddl-generator.d.ts.map +1 -0
- package/dist/lib/catalogue/ddl-generator.js +215 -0
- package/dist/lib/catalogue/ddl-generator.js.map +1 -0
- package/dist/lib/catalogue/engine-validator.d.ts +103 -0
- package/dist/lib/catalogue/engine-validator.d.ts.map +1 -0
- package/dist/lib/catalogue/engine-validator.js +221 -0
- package/dist/lib/catalogue/engine-validator.js.map +1 -0
- package/dist/lib/catalogue/enum-validator.d.ts.map +1 -1
- package/dist/lib/catalogue/enum-validator.js +15 -0
- package/dist/lib/catalogue/enum-validator.js.map +1 -1
- package/dist/lib/catalogue/fk-validator.d.ts +6 -0
- package/dist/lib/catalogue/fk-validator.d.ts.map +1 -1
- package/dist/lib/catalogue/fk-validator.js +6 -0
- package/dist/lib/catalogue/fk-validator.js.map +1 -1
- package/dist/lib/catalogue/gate-checks.d.ts +117 -0
- package/dist/lib/catalogue/gate-checks.d.ts.map +1 -0
- package/dist/lib/catalogue/gate-checks.js +261 -0
- package/dist/lib/catalogue/gate-checks.js.map +1 -0
- package/dist/lib/catalogue/parity-harness.d.ts +48 -0
- package/dist/lib/catalogue/parity-harness.d.ts.map +1 -0
- package/dist/lib/catalogue/parity-harness.js +76 -0
- package/dist/lib/catalogue/parity-harness.js.map +1 -0
- package/dist/lib/catalogue/schema-compat.d.ts +3 -3
- package/dist/lib/catalogue/schema-compat.js +3 -3
- package/dist/lib/catalogue/scores-coverage.d.ts +138 -0
- package/dist/lib/catalogue/scores-coverage.d.ts.map +1 -0
- package/dist/lib/catalogue/scores-coverage.js +346 -0
- package/dist/lib/catalogue/scores-coverage.js.map +1 -0
- package/dist/lib/catalogue/validate.d.ts.map +1 -1
- package/dist/lib/catalogue/validate.js +6 -11
- package/dist/lib/catalogue/validate.js.map +1 -1
- package/dist/lib/mcp/parse/gate-registry.d.ts +63 -4
- package/dist/lib/mcp/parse/gate-registry.d.ts.map +1 -1
- package/dist/lib/mcp/parse/gate-registry.js +127 -31
- package/dist/lib/mcp/parse/gate-registry.js.map +1 -1
- package/dist/lib/mcp/resources/gates.d.ts.map +1 -1
- package/dist/lib/mcp/resources/gates.js +13 -27
- package/dist/lib/mcp/resources/gates.js.map +1 -1
- package/dist/lib/mcp/tools/query-gate-status.d.ts.map +1 -1
- package/dist/lib/mcp/tools/query-gate-status.js +13 -27
- package/dist/lib/mcp/tools/query-gate-status.js.map +1 -1
- package/dist/verbs/catalogue.d.ts.map +1 -1
- package/dist/verbs/catalogue.js +24 -0
- package/dist/verbs/catalogue.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scores coverage — M-ADR 0205 §4.5's coverage instrument, the fourteenth
|
|
3
|
+
* engine check (Phase B, B2). SQL on the §4.1 engine, like every other
|
|
4
|
+
* catalogue-reading predicate; `check-repo-config-coverage.sh` remains the
|
|
5
|
+
* only shell survivor and is not the model for this.
|
|
6
|
+
*
|
|
7
|
+
* The claim: *every eligible artefact carries a current score*. Eligibility is
|
|
8
|
+
* computed per rubric against the catalogue that holds its targets, and the
|
|
9
|
+
* predicate reports BOTH directions, because the two say different things:
|
|
10
|
+
*
|
|
11
|
+
* - an eligible target with no score is a GAP — nobody has judged it;
|
|
12
|
+
* - a score whose target does not resolve is an ORPHANED SCORE — the
|
|
13
|
+
* assessment corpus has decayed away from the model it describes.
|
|
14
|
+
*
|
|
15
|
+
* The second direction is not decoration. Measured on the forward estate at
|
|
16
|
+
* introduction: 85 of 99 ADR scores point at ids that no longer exist, because
|
|
17
|
+
* a rename moved the ADR canon and the registry keys were never migrated. A
|
|
18
|
+
* one-directional predicate would have reported that estate as having 99
|
|
19
|
+
* scored ADRs while none of them resolved.
|
|
20
|
+
*
|
|
21
|
+
* THE JOIN VOCABULARY IS THE WHOLE DIFFICULTY, and it is declared rather than
|
|
22
|
+
* guessed. A registry's entry keys are not the catalogue's ids, and the
|
|
23
|
+
* mismatch differs per rubric — measured, not assumed:
|
|
24
|
+
*
|
|
25
|
+
* - contract-quality keys are SPEC PATHS (`contracts-avro/.../X.avsc`),
|
|
26
|
+
* joining `contracts.spec_path`; against `contracts.id` they score 0 of 55.
|
|
27
|
+
* - adr-quality keys carry a tier prefix (`M-ADR-0001`) the catalogue strips
|
|
28
|
+
* (`ADR-0001`); the raw join scores 0 of 99.
|
|
29
|
+
* - domain-architecture keys are plain domain slugs and join `domains.id`
|
|
30
|
+
* directly, 13 of 13.
|
|
31
|
+
*
|
|
32
|
+
* So each rubric declares its catalogue, its join column and its reference
|
|
33
|
+
* transform, and the predicate REPORTS the resolution rate it achieved. A join
|
|
34
|
+
* that silently resolves nothing looks exactly like an estate that has scored
|
|
35
|
+
* nothing — the confident-false-zero shape this whole phase exists to remove.
|
|
36
|
+
*
|
|
37
|
+
* Rubrics whose targets have NO catalogue (c4-diagram, strategic-doc,
|
|
38
|
+
* user-story, work-order) have no eligibility denominator to compute. They are
|
|
39
|
+
* reported as such by name and their scores are still resolution-checked as
|
|
40
|
+
* far as they can be — never silently omitted, because a rubric missing from
|
|
41
|
+
* the output reads as a rubric with nothing to say.
|
|
42
|
+
*
|
|
43
|
+
* Reporting-only at both tiers, per §4.5. Exemption vocabulary starts EMPTY
|
|
44
|
+
* (M-ADR 0199): there is no way to mark a target exempt yet, deliberately, so
|
|
45
|
+
* the first figure is the honest total.
|
|
46
|
+
*
|
|
47
|
+
* ADOPTION GATING — a rubric is measured only where its REGISTRY EXISTS. An SDD
|
|
48
|
+
* that carries no `<rubric>-scores.yaml` has not adopted that rubric, so it has
|
|
49
|
+
* no eligible population for it, and reporting its whole ADR/contract/capability
|
|
50
|
+
* corpus as unscored would be true-but-useless noise. This is the same n/a rule
|
|
51
|
+
* the repo-config predicate applies and the same rule the quality-scores builder
|
|
52
|
+
* applies to an absent registry directory: absence of the whole surface is not a
|
|
53
|
+
* gap in it. Measured before adopting it: without this rule ONE reverse-estate
|
|
54
|
+
* SDD emits 630 gap lines for rubrics it has never used, which across that
|
|
55
|
+
* estate would swamp the baseline re-take and bury the real signal.
|
|
56
|
+
*
|
|
57
|
+
* The distinction that must NOT be lost, and is not: a registry that EXISTS but
|
|
58
|
+
* is EMPTY reports its full population as gaps. That is the method repo's own
|
|
59
|
+
* state — fifteen deliberately-empty containers — and it is exactly the silence
|
|
60
|
+
* §4.5 exists to make loud. Absent surface and empty surface are different
|
|
61
|
+
* claims, and conflating them is the defect this whole phase is about.
|
|
62
|
+
*
|
|
63
|
+
* The n/a count is always printed. A rubric skipped silently reads as a rubric
|
|
64
|
+
* with nothing to report.
|
|
65
|
+
*/
|
|
66
|
+
import { existsSync } from "node:fs";
|
|
67
|
+
import { join } from "node:path";
|
|
68
|
+
/**
|
|
69
|
+
* The declared mapping. Three entries are EXERCISED against real estate data
|
|
70
|
+
* (adr-quality, contract-quality, domain-architecture); the rest are declared
|
|
71
|
+
* from the registry and rubric shapes and have no populated corpus to verify
|
|
72
|
+
* against yet — a distinction the metric line states rather than blurs.
|
|
73
|
+
*/
|
|
74
|
+
export const RUBRIC_ELIGIBILITY = [
|
|
75
|
+
{
|
|
76
|
+
rubricId: "adr-quality",
|
|
77
|
+
targetKind: "adr",
|
|
78
|
+
catalogue: "adrs",
|
|
79
|
+
joinColumn: "id",
|
|
80
|
+
// The catalogue strips the tier prefix (M-ADR 0186 §4.4); registries keep it.
|
|
81
|
+
refTransform: (r) => `regexp_replace(${r}, '^[A-Z]+-ADR-', 'ADR-')`,
|
|
82
|
+
eligibilityFilter: "status = 'Accepted'",
|
|
83
|
+
eligibilityNote: "Accepted only. A Proposed ADR is mid-decision and a Superseded one is history; requiring a current score on either would manufacture a gap nobody should close.",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
rubricId: "contract-quality",
|
|
87
|
+
targetKind: "contract",
|
|
88
|
+
catalogue: "contracts",
|
|
89
|
+
joinColumn: "spec_path",
|
|
90
|
+
refTransform: null,
|
|
91
|
+
eligibilityFilter: "status <> 'deprecated'",
|
|
92
|
+
eligibilityNote: "Every non-deprecated contract. Deprecated contracts are excluded for the same reason the contract-coverage predicate excludes them — they are on the way out, and scoring them is work with no consumer.",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
rubricId: "domain-architecture",
|
|
96
|
+
targetKind: "domain",
|
|
97
|
+
catalogue: "domains",
|
|
98
|
+
joinColumn: "id",
|
|
99
|
+
refTransform: null,
|
|
100
|
+
eligibilityFilter: null,
|
|
101
|
+
eligibilityNote: "Every domain on disk. A domain that exists is a domain that should be assessed.",
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
rubricId: "intent-quality",
|
|
105
|
+
targetKind: "domain",
|
|
106
|
+
catalogue: "domains",
|
|
107
|
+
joinColumn: "id",
|
|
108
|
+
refTransform: null,
|
|
109
|
+
eligibilityFilter: null,
|
|
110
|
+
eligibilityNote: "Every domain, same population as domain-architecture — the two rubrics judge different things about the same unit.",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
rubricId: "feature-grounding",
|
|
114
|
+
targetKind: "capability",
|
|
115
|
+
catalogue: "capabilities",
|
|
116
|
+
joinColumn: "id",
|
|
117
|
+
refTransform: null,
|
|
118
|
+
eligibilityFilter: null,
|
|
119
|
+
eligibilityNote: "Every capability.",
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
rubricId: "traceability-manifest",
|
|
123
|
+
targetKind: "capability",
|
|
124
|
+
catalogue: "capabilities",
|
|
125
|
+
joinColumn: "id",
|
|
126
|
+
refTransform: null,
|
|
127
|
+
eligibilityFilter: null,
|
|
128
|
+
eligibilityNote: "Every capability.",
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
rubricId: "glossary",
|
|
132
|
+
targetKind: "glossary",
|
|
133
|
+
catalogue: "domains",
|
|
134
|
+
joinColumn: "id",
|
|
135
|
+
refTransform: null,
|
|
136
|
+
eligibilityFilter: null,
|
|
137
|
+
eligibilityNote: "One glossary per domain — the registry keys by domain slug, so the eligible population is domains, not glossary_items (a glossary is scored whole, not term by term).",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
rubricId: "persona",
|
|
141
|
+
targetKind: "persona",
|
|
142
|
+
catalogue: "personas",
|
|
143
|
+
joinColumn: "id",
|
|
144
|
+
refTransform: null,
|
|
145
|
+
eligibilityFilter: null,
|
|
146
|
+
eligibilityNote: "Every persona.",
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
rubricId: "product-definition",
|
|
150
|
+
targetKind: "product",
|
|
151
|
+
catalogue: "products",
|
|
152
|
+
joinColumn: "id",
|
|
153
|
+
refTransform: null,
|
|
154
|
+
eligibilityFilter: null,
|
|
155
|
+
eligibilityNote: "Every product.",
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
rubricId: "screen-spec",
|
|
159
|
+
targetKind: "screen",
|
|
160
|
+
catalogue: "screens",
|
|
161
|
+
joinColumn: "id",
|
|
162
|
+
refTransform: null,
|
|
163
|
+
eligibilityFilter: null,
|
|
164
|
+
eligibilityNote: "Every screen.",
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
rubricId: "integration-sdd-quality",
|
|
168
|
+
targetKind: "integration",
|
|
169
|
+
catalogue: "integrations",
|
|
170
|
+
joinColumn: "id",
|
|
171
|
+
refTransform: null,
|
|
172
|
+
eligibilityFilter: null,
|
|
173
|
+
eligibilityNote: "Every integration.",
|
|
174
|
+
},
|
|
175
|
+
// ── No catalogued eligibility population ────────────────────────────────
|
|
176
|
+
// These rubrics score artefacts the catalogue model does not hold, so there
|
|
177
|
+
// is no denominator to compute. Declared explicitly so they appear in the
|
|
178
|
+
// output as "no denominator" rather than being absent — an absent rubric
|
|
179
|
+
// reads as a rubric with nothing to report.
|
|
180
|
+
{
|
|
181
|
+
rubricId: "c4-diagram",
|
|
182
|
+
targetKind: "c4_diagram",
|
|
183
|
+
catalogue: null,
|
|
184
|
+
joinColumn: "id",
|
|
185
|
+
refTransform: null,
|
|
186
|
+
eligibilityFilter: null,
|
|
187
|
+
eligibilityNote: "Diagrams are files, not catalogue rows.",
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
rubricId: "strategic-doc",
|
|
191
|
+
targetKind: "strategic_doc",
|
|
192
|
+
catalogue: null,
|
|
193
|
+
joinColumn: "id",
|
|
194
|
+
refTransform: null,
|
|
195
|
+
eligibilityFilter: null,
|
|
196
|
+
eligibilityNote: "Strategic documents are not catalogued.",
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
rubricId: "user-story",
|
|
200
|
+
targetKind: "user_story",
|
|
201
|
+
catalogue: null,
|
|
202
|
+
joinColumn: "id",
|
|
203
|
+
refTransform: null,
|
|
204
|
+
eligibilityFilter: null,
|
|
205
|
+
eligibilityNote: "User stories are not catalogued.",
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
rubricId: "work-order",
|
|
209
|
+
targetKind: "work_order",
|
|
210
|
+
catalogue: null,
|
|
211
|
+
joinColumn: "id",
|
|
212
|
+
refTransform: null,
|
|
213
|
+
eligibilityFilter: null,
|
|
214
|
+
eligibilityNote: "Work orders are not catalogued.",
|
|
215
|
+
},
|
|
216
|
+
];
|
|
217
|
+
const sqlStr = (s) => `'${s.replace(/'/g, "''")}'`;
|
|
218
|
+
async function rows(session, sql) {
|
|
219
|
+
const reader = await session.conn.runAndReadAll(sql);
|
|
220
|
+
return reader.getRows();
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Runs the predicate. `available` names the catalogues actually present, so a
|
|
224
|
+
* rubric whose population file is absent is skipped the way every other
|
|
225
|
+
* predicate skips an absent population — silently, because absence of the
|
|
226
|
+
* whole surface is not a gap in it — while a rubric whose population is
|
|
227
|
+
* PRESENT but empty still reports its zero.
|
|
228
|
+
*/
|
|
229
|
+
export async function runScoresCoverage(session, options) {
|
|
230
|
+
const findings = [];
|
|
231
|
+
const metrics = [];
|
|
232
|
+
if (!options.available.has("quality_scores")) {
|
|
233
|
+
return {
|
|
234
|
+
findings: [],
|
|
235
|
+
metrics: [],
|
|
236
|
+
undeclaredRubrics: [],
|
|
237
|
+
notAdopted: [],
|
|
238
|
+
stalenessBasis: { corpusRef: 0, scoredAt: 0, none: 0 },
|
|
239
|
+
totalScores: 0,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
const totalScores = Number((await rows(session, `SELECT COUNT(*) FROM "quality_scores";`))[0][0]);
|
|
243
|
+
const basis = await rows(session, `SELECT staleness_basis, COUNT(*) FROM "quality_scores" GROUP BY 1 ORDER BY 1;`);
|
|
244
|
+
const stalenessBasis = { corpusRef: 0, scoredAt: 0, none: 0 };
|
|
245
|
+
for (const [b, n] of basis) {
|
|
246
|
+
const c = Number(n);
|
|
247
|
+
if (b === "corpus_ref")
|
|
248
|
+
stalenessBasis.corpusRef = c;
|
|
249
|
+
else if (b === "scored_at")
|
|
250
|
+
stalenessBasis.scoredAt = c;
|
|
251
|
+
else
|
|
252
|
+
stalenessBasis.none = c;
|
|
253
|
+
}
|
|
254
|
+
// A row that can support no staleness verdict at all is its own finding.
|
|
255
|
+
// Without it the predicate would silently treat "unknown" as "fresh", which
|
|
256
|
+
// is the basis error this column exists to prevent.
|
|
257
|
+
if (stalenessBasis.none > 0) {
|
|
258
|
+
findings.push({
|
|
259
|
+
kind: "unresolvable-staleness",
|
|
260
|
+
rubricId: "(all)",
|
|
261
|
+
subject: `${stalenessBasis.none} score(s) carry neither corpus_ref nor a resolvable target_path — their currency is UNKNOWN, not fresh`,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
const declared = new Set(RUBRIC_ELIGIBILITY.map((r) => r.rubricId));
|
|
265
|
+
const present = await rows(session, `SELECT DISTINCT rubric_id FROM "quality_scores" ORDER BY 1;`);
|
|
266
|
+
const undeclaredRubrics = present
|
|
267
|
+
.map((r) => String(r[0]))
|
|
268
|
+
.filter((r) => !declared.has(r));
|
|
269
|
+
const adopted = (rubricId) => existsSync(join(options.sddRoot, "orchestration", "gate-registry", `${rubricId}-scores.yaml`));
|
|
270
|
+
const notAdopted = [];
|
|
271
|
+
for (const spec of RUBRIC_ELIGIBILITY) {
|
|
272
|
+
if (!adopted(spec.rubricId)) {
|
|
273
|
+
notAdopted.push(spec.rubricId);
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
const scored = Number((await rows(session, `SELECT COUNT(*) FROM "quality_scores" WHERE rubric_id = ${sqlStr(spec.rubricId)};`))[0][0]);
|
|
277
|
+
// No catalogued population: report the scores, state that there is no
|
|
278
|
+
// denominator, and do not invent one.
|
|
279
|
+
if (spec.catalogue === null) {
|
|
280
|
+
if (scored > 0) {
|
|
281
|
+
metrics.push({
|
|
282
|
+
rubricId: spec.rubricId,
|
|
283
|
+
targetKind: spec.targetKind,
|
|
284
|
+
eligible: null,
|
|
285
|
+
covered: scored,
|
|
286
|
+
scored,
|
|
287
|
+
orphaned: 0,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
if (!options.available.has(spec.catalogue))
|
|
293
|
+
continue;
|
|
294
|
+
if (scored === 0) {
|
|
295
|
+
// The population exists and nothing is scored — the loudest case, and
|
|
296
|
+
// exactly the silence M-ADR 0205 §4.5 names. Every eligible row is a gap.
|
|
297
|
+
const eligibleRows = await rows(session, `SELECT id FROM "${spec.catalogue}" WHERE (${spec.eligibilityFilter ?? "TRUE"}) ORDER BY id;`);
|
|
298
|
+
for (const [id] of eligibleRows) {
|
|
299
|
+
findings.push({ kind: "uncovered", rubricId: spec.rubricId, subject: String(id) });
|
|
300
|
+
}
|
|
301
|
+
metrics.push({
|
|
302
|
+
rubricId: spec.rubricId,
|
|
303
|
+
targetKind: spec.targetKind,
|
|
304
|
+
eligible: eligibleRows.length,
|
|
305
|
+
covered: 0,
|
|
306
|
+
scored: 0,
|
|
307
|
+
orphaned: 0,
|
|
308
|
+
});
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
const ref = spec.refTransform ? spec.refTransform("s.target_ref") : "s.target_ref";
|
|
312
|
+
// Eligibility is always a conjunct, so it composes with the not-exists
|
|
313
|
+
// clause without any string surgery on an assembled WHERE — `TRUE` for the
|
|
314
|
+
// unfiltered case keeps one query shape instead of two.
|
|
315
|
+
const eligibleWhere = spec.eligibilityFilter ?? "TRUE";
|
|
316
|
+
const scoreSet = `SELECT * FROM "quality_scores" WHERE rubric_id = ${sqlStr(spec.rubricId)}`;
|
|
317
|
+
// Direction 1 — eligible targets with no score.
|
|
318
|
+
const uncovered = await rows(session, `SELECT c.id FROM "${spec.catalogue}" c
|
|
319
|
+
WHERE (${eligibleWhere})
|
|
320
|
+
AND NOT EXISTS (SELECT 1 FROM (${scoreSet}) s WHERE ${ref} = c."${spec.joinColumn}")
|
|
321
|
+
ORDER BY c.id;`);
|
|
322
|
+
for (const [id] of uncovered) {
|
|
323
|
+
findings.push({ kind: "uncovered", rubricId: spec.rubricId, subject: String(id) });
|
|
324
|
+
}
|
|
325
|
+
// Direction 2 — scores whose target does not resolve.
|
|
326
|
+
const orphaned = await rows(session, `SELECT s.target_ref FROM (${scoreSet}) s
|
|
327
|
+
WHERE NOT EXISTS (
|
|
328
|
+
SELECT 1 FROM "${spec.catalogue}" c WHERE c."${spec.joinColumn}" = ${ref}
|
|
329
|
+
)
|
|
330
|
+
ORDER BY s.target_ref;`);
|
|
331
|
+
for (const [r] of orphaned) {
|
|
332
|
+
findings.push({ kind: "orphaned-score", rubricId: spec.rubricId, subject: String(r) });
|
|
333
|
+
}
|
|
334
|
+
const eligible = Number((await rows(session, `SELECT COUNT(*) FROM "${spec.catalogue}" WHERE (${eligibleWhere});`))[0][0]);
|
|
335
|
+
metrics.push({
|
|
336
|
+
rubricId: spec.rubricId,
|
|
337
|
+
targetKind: spec.targetKind,
|
|
338
|
+
eligible,
|
|
339
|
+
covered: eligible - uncovered.length,
|
|
340
|
+
scored,
|
|
341
|
+
orphaned: orphaned.length,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
return { findings, metrics, undeclaredRubrics, notAdopted, stalenessBasis, totalScores };
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=scores-coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scores-coverage.js","sourceRoot":"","sources":["../../../src/lib/catalogue/scores-coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/lib/catalogue/validate.ts"],"names":[],"mappings":"
|
|
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,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,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,CA0IzB"}
|
|
@@ -14,11 +14,10 @@
|
|
|
14
14
|
import { stat } from "node:fs/promises";
|
|
15
15
|
import { join, resolve } from "node:path";
|
|
16
16
|
import { CLI_VERSION } from "./cli-version.js";
|
|
17
|
-
import { validateColumnEnums } from "./enum-validator.js";
|
|
18
17
|
import { readCatalogueCsv } from "./csv-reader.js";
|
|
19
18
|
import { writeCatalogue } from "./csv-writer.js";
|
|
19
|
+
import { validateWithEngineToLog } from "./engine-validator.js";
|
|
20
20
|
import { FindingsLog } from "./findings.js";
|
|
21
|
-
import { validateForeignKeys } from "./fk-validator.js";
|
|
22
21
|
import { loadCanonicalSchema } from "./schema-loader.js";
|
|
23
22
|
export async function runCatalogueValidate(inputs, write) {
|
|
24
23
|
const sddPath = resolve(inputs.sddPath ?? process.cwd());
|
|
@@ -74,15 +73,11 @@ export async function runCatalogueValidate(inputs, write) {
|
|
|
74
73
|
// profiles → leave undefined, so those FKs validate as internal and MUST
|
|
75
74
|
// resolve (the merged platform domains are present to satisfy them).
|
|
76
75
|
const profile = singleProfile(rowsByCatalogue.get("products") ?? []);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
// legacy c4_containers.type rows (Infrastructure / External System) fail
|
|
83
|
-
// at 3.0.0: the catalogue predates the migration, and a rebuild with the
|
|
84
|
-
// rows' dispositions applied is the remedy (per M-ADR 0155's rule).
|
|
85
|
-
const enums = validateColumnEnums(schema, rowsByCatalogue, findings);
|
|
76
|
+
// FK + bound-enum validation on the embedded engine (M-ADR 0205 §4.4
|
|
77
|
+
// cutover; same semantics, findings text unchanged — the A2/A3 dual-run
|
|
78
|
+
// record is the evidence). Enum hard-fail behaviour per M-ADR 0203 §4.1
|
|
79
|
+
// is unchanged: an out-of-set value is an error-severity finding.
|
|
80
|
+
const { fk, enums } = await validateWithEngineToLog(schema, rowsByCatalogue, findings, { ...(profile !== undefined ? { profile } : {}) });
|
|
86
81
|
// Report.
|
|
87
82
|
const findingsText = findings.render();
|
|
88
83
|
if (findingsText)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/lib/catalogue/validate.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,uEAAuE;AACvE,EAAE;AACF,iEAAiE;AACjE,gEAAgE;AAChE,oEAAoE;AACpE,sEAAsE;AACtE,sEAAsE;AACtE,0CAA0C;AAC1C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,6BAA6B;AAE7B,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/lib/catalogue/validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* YAML reader for orchestration/gate-registry/<gate>-scores.yaml.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Registry shape: header fields (schema_version, description, pass_threshold,
|
|
5
|
+
* and the reverse family's registry_type / assessed_at / assessed_by) plus ONE
|
|
6
|
+
* container key holding the per-artefact entries. The container key is not a
|
|
7
|
+
* stable name — it drifts between the method template and live estate data,
|
|
8
|
+
* and is not unique across rubrics — so it is unwrapped rather than trusted.
|
|
9
|
+
*
|
|
10
|
+
* Three defects were found here by the M-ADR 0205 Phase-B survey (2026-08-06)
|
|
11
|
+
* and fixed together, since all three are the same mistake in different
|
|
12
|
+
* places: assuming the registry population looks like the reader's model of it.
|
|
13
|
+
*
|
|
14
|
+
* - `listGates` hard-coded ten names, so gate discovery was silently blind
|
|
15
|
+
* to nine of the nineteen rubric families now in existence (five newer
|
|
16
|
+
* method-side registries and four reverse-only ones). An unlisted gate
|
|
17
|
+
* read as absent. It now enumerates the directory.
|
|
18
|
+
* - `entries` returned the CONTAINER, not the artefacts, so the summary in
|
|
19
|
+
* `resources/gates.ts` reported `total: 1` for a registry holding 99
|
|
20
|
+
* scored ADRs — while its own description advertised "per-artefact
|
|
21
|
+
* entries". It now unwraps the single container.
|
|
22
|
+
* - `parseYaml` ran unguarded, so a malformed registry threw a raw
|
|
23
|
+
* YAMLParseError through two surfaces that otherwise honour the
|
|
24
|
+
* McpEnvelopeError contract. Measured: three of one estate's ten
|
|
25
|
+
* registries are unparseable. It now reports `parseError` and returns an
|
|
26
|
+
* empty-but-well-formed registry, leaving each caller to decide how to
|
|
27
|
+
* surface it — the reader's job is to report, not to throw.
|
|
7
28
|
*/
|
|
8
29
|
export interface GateRegistry {
|
|
9
30
|
readonly gate: string;
|
|
@@ -11,9 +32,47 @@ export interface GateRegistry {
|
|
|
11
32
|
readonly schemaVersion: string | null;
|
|
12
33
|
readonly description: string | null;
|
|
13
34
|
readonly passThreshold: unknown;
|
|
35
|
+
/** Per-artefact entries, unwrapped from the container key. */
|
|
14
36
|
readonly entries: Record<string, unknown>;
|
|
37
|
+
/** The container key the entries came from, when there was exactly one. */
|
|
38
|
+
readonly entryContainer: string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Parser message when the registry is malformed. Non-null means `entries` is
|
|
41
|
+
* empty because the file could not be read — NOT because nothing is scored.
|
|
42
|
+
* A caller that conflates the two reports an empty gate as a clean one.
|
|
43
|
+
*/
|
|
44
|
+
readonly parseError: string | null;
|
|
15
45
|
}
|
|
16
46
|
export declare function gateRegistryPath(sddRoot: string, gate: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Every gate this SDD actually carries, by enumeration — never a fixed list.
|
|
49
|
+
* A registry is any `<gate>-scores.yaml` in the gate-registry directory, so a
|
|
50
|
+
* newly-shipped rubric is discoverable the moment its registry exists.
|
|
51
|
+
*/
|
|
17
52
|
export declare function listGates(sddRoot: string): string[];
|
|
18
53
|
export declare function readGateRegistry(sddRoot: string, gate: string): GateRegistry | undefined;
|
|
54
|
+
export interface GateSummary {
|
|
55
|
+
readonly total: number;
|
|
56
|
+
readonly pass: number;
|
|
57
|
+
readonly conditional: number;
|
|
58
|
+
readonly fail: number;
|
|
59
|
+
readonly unscored: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Verdict tally over unwrapped entries. ONE implementation, deliberately: this
|
|
63
|
+
* existed identically in both MCP consumers, and a duplicated counter is a
|
|
64
|
+
* drift surface that only shows up as two surfaces disagreeing about the same
|
|
65
|
+
* registry.
|
|
66
|
+
*
|
|
67
|
+
* Reads BOTH authored dialects. The gate sits at `entry.current.gate` in the
|
|
68
|
+
* nested shape all fifteen method templates specify, and at `entry.gate` in
|
|
69
|
+
* the flat shape the live estate data overwhelmingly uses. Reading only the
|
|
70
|
+
* flat one reports every nested entry as `unscored` — a confident false zero
|
|
71
|
+
* of exactly the kind this arc keeps paying for.
|
|
72
|
+
*
|
|
73
|
+
* An out-of-vocabulary verdict counts as `unscored` rather than being dropped,
|
|
74
|
+
* so `pass + conditional + fail + unscored === total` always holds and the
|
|
75
|
+
* tally can never quietly lose a row.
|
|
76
|
+
*/
|
|
77
|
+
export declare function summariseGateEntries(entries: Record<string, unknown>): GateSummary;
|
|
19
78
|
//# sourceMappingURL=gate-registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-registry.d.ts","sourceRoot":"","sources":["../../../../src/lib/mcp/parse/gate-registry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"gate-registry.d.ts","sourceRoot":"","sources":["../../../../src/lib/mcp/parse/gate-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAiBH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,2EAA2E;IAC3E,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAanD;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACX,YAAY,GAAG,SAAS,CAmD1B;AAMD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAyBlF"}
|