@sdd-method/sdd-cli 1.2.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.
Files changed (40) hide show
  1. package/dist/lib/catalogue/build.d.ts.map +1 -1
  2. package/dist/lib/catalogue/build.js +14 -1
  3. package/dist/lib/catalogue/build.js.map +1 -1
  4. package/dist/lib/catalogue/builders/capability-edges.d.ts.map +1 -1
  5. package/dist/lib/catalogue/builders/capability-edges.js +10 -1
  6. package/dist/lib/catalogue/builders/capability-edges.js.map +1 -1
  7. package/dist/lib/catalogue/builders/index.d.ts +2 -0
  8. package/dist/lib/catalogue/builders/index.d.ts.map +1 -1
  9. package/dist/lib/catalogue/builders/index.js +1 -0
  10. package/dist/lib/catalogue/builders/index.js.map +1 -1
  11. package/dist/lib/catalogue/builders/quality-scores.d.ts +14 -0
  12. package/dist/lib/catalogue/builders/quality-scores.d.ts.map +1 -0
  13. package/dist/lib/catalogue/builders/quality-scores.js +321 -0
  14. package/dist/lib/catalogue/builders/quality-scores.js.map +1 -0
  15. package/dist/lib/catalogue/builders/services.d.ts.map +1 -1
  16. package/dist/lib/catalogue/builders/services.js +5 -1
  17. package/dist/lib/catalogue/builders/services.js.map +1 -1
  18. package/dist/lib/catalogue/canonical-schema.yaml +199 -1
  19. package/dist/lib/catalogue/coverage-render.d.ts +15 -0
  20. package/dist/lib/catalogue/coverage-render.d.ts.map +1 -1
  21. package/dist/lib/catalogue/coverage-render.js +85 -0
  22. package/dist/lib/catalogue/coverage-render.js.map +1 -1
  23. package/dist/lib/catalogue/coverage-run.d.ts.map +1 -1
  24. package/dist/lib/catalogue/coverage-run.js +7 -1
  25. package/dist/lib/catalogue/coverage-run.js.map +1 -1
  26. package/dist/lib/catalogue/scores-coverage.d.ts +138 -0
  27. package/dist/lib/catalogue/scores-coverage.d.ts.map +1 -0
  28. package/dist/lib/catalogue/scores-coverage.js +346 -0
  29. package/dist/lib/catalogue/scores-coverage.js.map +1 -0
  30. package/dist/lib/mcp/parse/gate-registry.d.ts +63 -4
  31. package/dist/lib/mcp/parse/gate-registry.d.ts.map +1 -1
  32. package/dist/lib/mcp/parse/gate-registry.js +127 -31
  33. package/dist/lib/mcp/parse/gate-registry.js.map +1 -1
  34. package/dist/lib/mcp/resources/gates.d.ts.map +1 -1
  35. package/dist/lib/mcp/resources/gates.js +13 -27
  36. package/dist/lib/mcp/resources/gates.js.map +1 -1
  37. package/dist/lib/mcp/tools/query-gate-status.d.ts.map +1 -1
  38. package/dist/lib/mcp/tools/query-gate-status.js +13 -27
  39. package/dist/lib/mcp/tools/query-gate-status.js.map +1 -1
  40. package/package.json +1 -1
@@ -0,0 +1,321 @@
1
+ // Quality-scores builder — emits the rubric-assessment catalogues (M-ADR 0205
2
+ // §4.5, schema 3.2.0):
3
+ // quality_scores, quality_score_dimensions
4
+ //
5
+ // Source: `orchestration/gate-registry/<rubric>-scores.yaml`. The authored
6
+ // surface stays YAML because a score is a judgment, authored where it asserts
7
+ // intent; these rows are DERIVED and never edited.
8
+ //
9
+ // Three shapes here are counter-intuitive enough that a builder written from
10
+ // the method's own registry TEMPLATES would get all three wrong. Each was
11
+ // measured across 15 method-side + 152 estate-side registry files (the Phase-B
12
+ // B0 survey, 2026-08-06), and each is guarded by a control:
13
+ //
14
+ // 1. TWO AUTHORED DIALECTS. All fifteen method templates specify a nested
15
+ // shape (`selection_policy` / `current` / `reviews`), but the live forward
16
+ // data is overwhelmingly FLAT — `gate` / `weighted_score` / `scored_at` /
17
+ // `scored_by` / `scores` / `flags` directly on the entry. Reading only the
18
+ // template shape would catalogue 6 entries out of 204. Both are legitimate:
19
+ // the templates were modernised, the data was not migrated.
20
+ // 2. THE CONTAINER KEY IDENTIFIES NOTHING. It drifts between template and
21
+ // estate in 4 of 10 files (`diagrams` vs `c4_diagram_scores`, `capabilities`
22
+ // vs `feature_grounding_scores`, ...) and is non-unique method-side
23
+ // (`domains` names BOTH domain-architecture and intent-quality;
24
+ // `capabilities` names BOTH feature-grounding and traceability-manifest).
25
+ // So `rubric_id` comes from the file's `registry_type` when declared, else
26
+ // the filename stem minus `-scores`. Never the key.
27
+ // 3. `corpus_ref` IS NEW AUTHORING. M-ADR 0205 §4.5 names it and the coverage
28
+ // instrument's staleness rule depends on it, but nothing authors it in
29
+ // either estate today. Rows therefore carry `staleness_basis` saying which
30
+ // anchor they can actually support, so no consumer can state a staleness
31
+ // verdict without its basis.
32
+ //
33
+ // LOUDNESS CONTRACT. Nothing here drops silently — that is the whole point of
34
+ // the class. An unparseable registry, an unknown rubric_id, an ambiguous
35
+ // container, a registry_type disagreeing with its filename, and an
36
+ // out-of-vocabulary gate value each produce a finding naming the file, the
37
+ // entry and the remedy. The one thing that is NOT a finding is a registry with
38
+ // an empty container: the method repo ships fifteen of those deliberately, and
39
+ // their emptiness is the signal the B2 coverage predicate reads, not an error
40
+ // here.
41
+ import { readdir, readFile } from "node:fs/promises";
42
+ import { basename, join } from "node:path";
43
+ import { parse as parseYaml } from "yaml";
44
+ const REGISTRY_DIR_REL = "orchestration/gate-registry";
45
+ /**
46
+ * File-level keys that are registry metadata rather than scored entries.
47
+ * Anything else at the top level is the entry container. The reverse family's
48
+ * `registry_type` / `assessed_at` / `assessed_by` are here too so that family
49
+ * parses with the same code path, even though only the weighted house form is
50
+ * emitted today (schema 3.2.0's `scoring_form` reserves the banded case).
51
+ */
52
+ const HEADER_KEYS = new Set([
53
+ "schema_version",
54
+ "description",
55
+ "pass_threshold",
56
+ "registry_type",
57
+ "assessed_at",
58
+ "assessed_by",
59
+ ]);
60
+ /**
61
+ * rubric_id -> target_kind. A CLOSED map on purpose: an unknown rubric is a
62
+ * loud finding, never a silently-dropped entry or a guessed kind. New rubrics
63
+ * ship with a row here (the R9 four-surface rule already requires the registry;
64
+ * this is the fifth touchpoint and the one that makes the rows appear).
65
+ */
66
+ const TARGET_KIND_BY_RUBRIC = new Map([
67
+ ["adr-quality", "adr"],
68
+ ["contract-quality", "contract"],
69
+ ["c4-diagram", "c4_diagram"],
70
+ ["domain-architecture", "domain"],
71
+ ["intent-quality", "domain"],
72
+ ["feature-grounding", "capability"],
73
+ ["traceability-manifest", "capability"],
74
+ ["glossary", "glossary"],
75
+ ["persona", "persona"],
76
+ ["product-definition", "product"],
77
+ ["screen-spec", "screen"],
78
+ ["strategic-doc", "strategic_doc"],
79
+ ["user-story", "user_story"],
80
+ ["work-order", "work_order"],
81
+ ["integration-sdd-quality", "integration"],
82
+ ]);
83
+ /** schema 3.2.0 `quality_gate`. Deliberately UNBOUND — see that enum's note. */
84
+ const GATE_VALUES = new Set(["pass", "conditional", "fail", "unscored"]);
85
+ const isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
86
+ const str = (v) => typeof v === "string" ? v : typeof v === "number" ? String(v) : null;
87
+ const num = (v) => {
88
+ if (typeof v === "number" && Number.isFinite(v))
89
+ return v;
90
+ if (typeof v === "string" && v.trim() !== "" && Number.isFinite(Number(v))) {
91
+ return Number(v);
92
+ }
93
+ return null;
94
+ };
95
+ /**
96
+ * Count raised flags across the two authored dialects:
97
+ * `flags: { over_scope_risk: true, ... }` -> count the true ones
98
+ * `flags_raised: [name, ...]` -> count the list
99
+ * A scalar `flags_raised: 0` also occurs in the wild (one estate authors it),
100
+ * and reads as zero rather than as a parse defect.
101
+ */
102
+ function countFlags(entry, current) {
103
+ const raised = current["flags_raised"] ?? entry["flags_raised"];
104
+ if (Array.isArray(raised))
105
+ return raised.length;
106
+ if (typeof raised === "number")
107
+ return raised;
108
+ const flags = current["flags"] ?? entry["flags"];
109
+ if (isRecord(flags))
110
+ return Object.values(flags).filter((v) => v === true).length;
111
+ return 0;
112
+ }
113
+ /**
114
+ * Hard-gate state across the two dialects:
115
+ * `hard_gates: { triggered: bool, reasons: [] }`
116
+ * `hard_gates_triggered: [reasons]` (empty list = not triggered)
117
+ */
118
+ function hardGateTriggered(entry, current) {
119
+ const list = current["hard_gates_triggered"] ?? entry["hard_gates_triggered"];
120
+ if (Array.isArray(list))
121
+ return list.length > 0;
122
+ const hg = current["hard_gates"] ?? entry["hard_gates"];
123
+ if (isRecord(hg))
124
+ return hg["triggered"] === true;
125
+ return false;
126
+ }
127
+ function requiredActionsCount(entry, current) {
128
+ const explicit = num(current["required_actions_count"] ?? entry["required_actions_count"]);
129
+ if (explicit !== null)
130
+ return explicit;
131
+ const list = current["required_actions"] ?? entry["required_actions"];
132
+ return Array.isArray(list) ? list.length : 0;
133
+ }
134
+ /**
135
+ * Scorer provenance across three dialects: the nested `scorer:` block, the flat
136
+ * `scored_by:` free-text field, and the reverse family's file-level
137
+ * `assessed_by:`. A flat-dialect row therefore lands its whole provenance in
138
+ * `scorer_model` as free text — expected, and documented in the schema, so it
139
+ * does not read as a parse defect to whoever queries it later.
140
+ */
141
+ function scorerFields(entry, current, fileAssessedBy) {
142
+ const scorer = current["scorer"] ?? entry["scorer"];
143
+ if (isRecord(scorer)) {
144
+ return {
145
+ scorer_provider: str(scorer["provider"]),
146
+ scorer_tool: str(scorer["tool"]),
147
+ scorer_model: str(scorer["model"]),
148
+ scorer_model_family: str(scorer["model_family"]),
149
+ scorer_prompt_version: str(scorer["prompt_version"]),
150
+ };
151
+ }
152
+ const flat = str(current["scored_by"] ?? entry["scored_by"]) ?? fileAssessedBy;
153
+ return {
154
+ scorer_provider: null,
155
+ scorer_tool: null,
156
+ scorer_model: flat,
157
+ scorer_model_family: null,
158
+ scorer_prompt_version: null,
159
+ };
160
+ }
161
+ /** Slug a target ref into a PK-safe token without collapsing distinct refs. */
162
+ const slugToken = (s) => s
163
+ .trim()
164
+ .replace(/[^A-Za-z0-9_.-]+/g, "-")
165
+ .replace(/^-+|-+$/g, "")
166
+ .toLowerCase();
167
+ export async function buildQualityScores(inputs) {
168
+ const { sddPath, findings, sddId } = inputs;
169
+ const dir = join(sddPath, REGISTRY_DIR_REL);
170
+ let files;
171
+ try {
172
+ files = (await readdir(dir))
173
+ .filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"))
174
+ .sort();
175
+ }
176
+ catch {
177
+ // No gate-registry directory. Headers-only, and NOT a finding: the surface
178
+ // is optional per profile, and absence of the whole surface is not an
179
+ // authoring gap in it (the repo-config predicate's n/a rule, same reasoning).
180
+ return { qualityScores: [], qualityScoreDimensions: [] };
181
+ }
182
+ const qualityScores = [];
183
+ const qualityScoreDimensions = [];
184
+ for (const file of files) {
185
+ const rel = `${REGISTRY_DIR_REL}/${file}`;
186
+ const raw = await readFile(join(dir, file), "utf8");
187
+ let doc;
188
+ try {
189
+ doc = parseYaml(raw);
190
+ }
191
+ catch (e) {
192
+ // Measured: 3 of one estate's 10 registries do not parse (two mixing
193
+ // mapping and sequence entries under one container, one with a duplicate
194
+ // key whose two blocks hold CONTRADICTORY verdicts for the same target).
195
+ // A parser that tolerates duplicate keys reports the flattering figure
196
+ // and hides it; this one refuses, and says so.
197
+ // WARN, not error, and the choice is deliberate. Score registries are
198
+ // scoring-run output, not a method-mandated authoring surface, and the
199
+ // same reasoning that leaves `quality_gate` unbound applies here: this
200
+ // class must not hard-fail an estate's whole catalogue build over data
201
+ // that predates it (measured: one estate carries three such files). The
202
+ // loudness comes from the findings baseline — a new unbaselined finding
203
+ // fails the gate — which is how this method makes things loud without
204
+ // making builds brittle.
205
+ findings.add("divergence", `${rel} is not parseable YAML (${String(e.message).split("\n")[0]}) — every score it holds is invisible to the catalogue; repair the file (a duplicate key silently discards one of two judgments, and a mapping/sequence mix is invalid in every parser)`);
206
+ continue;
207
+ }
208
+ if (!isRecord(doc))
209
+ continue;
210
+ // --- rubric_id: registry_type, else filename. Never the container key. ---
211
+ const stem = basename(file).replace(/\.(yaml|yml)$/, "");
212
+ const fromFilename = stem.replace(/-scores$/, "");
213
+ const declared = str(doc["registry_type"]);
214
+ const rubricId = declared ?? fromFilename;
215
+ if (declared !== null && declared !== fromFilename) {
216
+ findings.add("convention", `${rel} declares registry_type '${declared}' but its filename says '${fromFilename}' — rubric_id uses the declared value; rename the file or correct registry_type so the two agree`);
217
+ }
218
+ const targetKind = TARGET_KIND_BY_RUBRIC.get(rubricId);
219
+ if (targetKind === undefined) {
220
+ findings.add("coverage", `${rel} uses rubric '${rubricId}', which has no target-kind mapping — its scores are NOT catalogued; add the rubric to the quality-scores builder's TARGET_KIND_BY_RUBRIC map (a new rubric ships its registry, rubric, skill trio and seed rows; this is the fifth surface)`);
221
+ continue;
222
+ }
223
+ const fileAssessedBy = str(doc["assessed_by"]);
224
+ // --- the entry container: the single non-header mapping key ---
225
+ const containers = Object.entries(doc).filter(([k, v]) => !HEADER_KEYS.has(k) && isRecord(v));
226
+ if (containers.length === 0)
227
+ continue; // headers-only registry: deliberate, silent
228
+ if (containers.length > 1) {
229
+ findings.add("convention", `${rel} has ${containers.length} candidate entry containers (${containers.map(([k]) => k).join(", ")}) — a registry declares exactly one; no scores read from this file`);
230
+ continue;
231
+ }
232
+ const container = containers[0]?.[1];
233
+ if (!isRecord(container))
234
+ continue;
235
+ for (const [entryKey, entryVal] of Object.entries(container)) {
236
+ if (!isRecord(entryVal))
237
+ continue;
238
+ // --- dialect detection: nested (templates) vs flat (live estate data) ---
239
+ const nested = isRecord(entryVal["current"]);
240
+ const current = nested ? entryVal["current"] : entryVal;
241
+ const targetRef = str(entryVal["unit_id"]) ?? entryKey;
242
+ const targetPath = str(entryVal["file_path"]) ?? str(current["file_path"]);
243
+ // --- gate: unbound vocabulary, convention finding + empty cell ---
244
+ const rawGate = str(current["gate"]);
245
+ let gate = null;
246
+ if (rawGate !== null && rawGate.trim() !== "") {
247
+ if (GATE_VALUES.has(rawGate)) {
248
+ gate = rawGate;
249
+ }
250
+ else {
251
+ findings.add("convention", `${rel}: ${entryKey} has gate '${rawGate}', outside the quality_gate vocabulary (${[...GATE_VALUES].join(" | ")}) — the cell is left EMPTY rather than emitting a value no consumer can interpret; use an in-vocabulary value, or raise the extension as a method decision if the concept is real`);
252
+ }
253
+ }
254
+ const corpusRef = str(current["corpus_ref"]) ?? str(entryVal["corpus_ref"]);
255
+ const stalenessBasis = corpusRef !== null ? "corpus_ref" : targetPath !== null ? "scored_at" : "none";
256
+ const selectionPolicy = entryVal["selection_policy"];
257
+ const selectionMethod = isRecord(selectionPolicy)
258
+ ? str(selectionPolicy["method"])
259
+ : null;
260
+ const id = `${rubricId}__${targetKind}__${slugToken(targetRef)}`;
261
+ qualityScores.push({
262
+ id,
263
+ rubric_id: rubricId,
264
+ scoring_form: "weighted",
265
+ target_kind: targetKind,
266
+ target_ref: targetRef,
267
+ target_path: targetPath,
268
+ gate,
269
+ weighted_score: num(current["weighted_score"]),
270
+ score_denominator: num(entryVal["score_denominator"] ?? current["score_denominator"]),
271
+ scored_at: str(current["scored_at"]) ?? str(entryVal["scored_at"]),
272
+ corpus_ref: corpusRef,
273
+ staleness_basis: stalenessBasis,
274
+ review_run_id: str(current["review_run_id"]),
275
+ selection_method: selectionMethod,
276
+ ...scorerFields(entryVal, current, fileAssessedBy),
277
+ flag_count: countFlags(entryVal, current),
278
+ hard_gate_triggered: hardGateTriggered(entryVal, current),
279
+ required_actions_count: requiredActionsCount(entryVal, current),
280
+ sdd_id: sddId,
281
+ source_sdd_id: null,
282
+ });
283
+ // --- dimensions: the rubric's own keys, verbatim ---
284
+ const scores = current["scores"];
285
+ if (isRecord(scores)) {
286
+ for (const [dimKey, dimVal] of Object.entries(scores)) {
287
+ qualityScoreDimensions.push({
288
+ id: `${id}__${slugToken(dimKey)}`,
289
+ quality_score_id: id,
290
+ rubric_id: rubricId,
291
+ target_kind: targetKind,
292
+ target_ref: targetRef,
293
+ dimension_key: dimKey,
294
+ dimension_score: num(dimVal),
295
+ dimension_weight: null,
296
+ source_sdd_id: null,
297
+ });
298
+ }
299
+ }
300
+ }
301
+ }
302
+ // Total order, per M-ADR 0205 §4.2 — the committed CSV must be byte-stable.
303
+ qualityScores.sort((a, b) => String(a["id"]).localeCompare(String(b["id"])));
304
+ qualityScoreDimensions.sort((a, b) => String(a["id"]).localeCompare(String(b["id"])));
305
+ // Duplicate ids mean two entries scored the same target under one rubric.
306
+ // BOTH rows are emitted rather than one being dropped: dropping would pick a
307
+ // winner between two possibly-contradictory verdicts, which is precisely how
308
+ // that defect stayed invisible in an estate for a month. The builder
309
+ // diagnoses; the downstream pk-duplicate check owns fatality, which is where
310
+ // PK integrity belongs.
311
+ const seen = new Set();
312
+ for (const row of qualityScores) {
313
+ const id = String(row["id"]);
314
+ if (seen.has(id)) {
315
+ findings.add("divergence", `quality_scores: duplicate id '${id}' — two registry entries score the same target under the same rubric; both rows are emitted (the pk check fails on them) rather than one being silently preferred, because the two verdicts may disagree`);
316
+ }
317
+ seen.add(id);
318
+ }
319
+ return { qualityScores, qualityScoreDimensions };
320
+ }
321
+ //# sourceMappingURL=quality-scores.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality-scores.js","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/quality-scores.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/services.ts"],"names":[],"mappings":"AA8CA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,qBAAqB,CAAC;AAO7B,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,uDAAuD;IACvD,QAAQ,CAAC,YAAY,EAAE,SAAS,YAAY,EAAE,CAAC;IAC/C,qCAAqC;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxD;;;;;;OAMG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChE;AA8ED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAClD;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAoF9B"}
1
+ {"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/services.ts"],"names":[],"mappings":"AA8CA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,qBAAqB,CAAC;AAO7B,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,uDAAuD;IACvD,QAAQ,CAAC,YAAY,EAAE,SAAS,YAAY,EAAE,CAAC;IAC/C,qCAAqC;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxD;;;;;;OAMG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChE;AAiFD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAClD;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAoF9B"}
@@ -63,7 +63,11 @@ function parseDeclaredServices(raw, relPath, findings) {
63
63
  if (raw === undefined)
64
64
  return null;
65
65
  if (!Array.isArray(raw)) {
66
- findings.add("convention", `${relPath}: services: must be a list — block dropped, default single-service projection kept`);
66
+ findings.add("convention",
67
+ // Names the remedy, and specifically the `services: []` form: a BARE
68
+ // `services:` parses as null, which is not a list, so it lands here —
69
+ // and it is two characters away from the declaration an author meant.
70
+ `${relPath}: services: must be a list — block dropped, default single-service projection kept; write it as a list of entries (\`services:\` then \` - id: ...\`), or as \`services: []\` to declare that this repo deliberately emits no service row (M-ADR 0197). A bare \`services:\` with nothing after it is neither.`);
67
71
  return null;
68
72
  }
69
73
  const seen = new Set();
@@ -1 +1 @@
1
- {"version":3,"file":"services.js","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/services.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"services.js","sourceRoot":"","sources":["../../../../src/lib/catalogue/builders/services.ts"],"names":[],"mappings":"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"}
@@ -62,9 +62,50 @@
62
62
  # Builder contract: see docs/method/methods/guides/catalogue-builder-specification.md.
63
63
  # Category taxonomy: see docs/method/methods/standards/product-category-taxonomy.md.
64
64
 
65
- schema_version: "3.1.3"
65
+ schema_version: "3.2.0"
66
66
  schema_owner: "sdd-method"
67
67
  schema_status: "canonical"
68
+ # Bump rationale (3.2.0 — additive minor, 2026-08-06, per M-ADR 0205 §4.5):
69
+ # the rubric score registries join the catalogue metamodel. Two new catalogues
70
+ # and four new enums; no existing column, catalogue or enum is touched.
71
+ #
72
+ # 1. `quality_scores` — one row per (target, rubric), derived from
73
+ # `orchestration/gate-registry/<rubric>-scores.yaml`. The authored surface
74
+ # stays YAML (a score is a judgment, authored where it asserts intent);
75
+ # these rows are derived and never edited.
76
+ # 2. `quality_score_dimensions` — the per-dimension child. A child catalogue
77
+ # is FORCED, not stylistic: the fifteen rubrics carry fifteen disjoint
78
+ # dimension vocabularies (45 distinct keys measured in one estate), so no
79
+ # fixed column set can hold them.
80
+ # 3. Enums `quality_gate`, `score_selection_method`, `staleness_basis`,
81
+ # `scoring_form`. NONE is bound via column_enums — see quality_gate for
82
+ # the measured reason, which is the opposite lesson to 3.1.3's: there the
83
+ # defect was a binding that checked nothing, here the defect would be a
84
+ # binding that hard-fails an estate over a value it deliberately declared
85
+ # in its own registry header.
86
+ #
87
+ # Three shapes the survey behind this bump found, recorded because a builder
88
+ # written from the templates alone would get all three wrong (full record:
89
+ # the Phase-B B0 survey, 2026-08-06):
90
+ # - The live forward-estate data is FLAT, not the nested current/reviews
91
+ # shape all fifteen method templates specify. Reading only the template
92
+ # shape catalogues 6 entries out of 204.
93
+ # - The registry container key is unreliable (4 of 10 drift from the method
94
+ # template) and non-unique (`domains` and `capabilities` each name two
95
+ # different rubrics), so rubric_id comes from registry_type-or-filename.
96
+ # - `corpus_ref` — which M-ADR 0205 §4.5 names and the coverage instrument's
97
+ # staleness rule depends on — is authored NOWHERE today. It is introduced
98
+ # here as new authoring with a computed `scored_at` fallback, and
99
+ # `staleness_basis` records which of the two a row can actually use. A
100
+ # staleness verdict whose basis is unstated is not a measurement.
101
+ # `evidence_ref`, also named in §4.5, is deliberately NOT added: nothing
102
+ # authors it in any registry in either estate, and shipping it would create
103
+ # exactly the inert column that 2.48.0 deprecated `products.status` over.
104
+ # ACTIVATION NOTE (M-ADR 0200 §4.6): additive only — no existing row changes
105
+ # value and no existing check changes verdict. The new catalogues emit
106
+ # headers-only in any SDD without a gate-registry directory, which is every
107
+ # SDD in the method repo's own estate except the roots.
108
+ # Backward-compatible; SCHEMA_COMPAT "^3.0.0".
68
109
  # Bump rationale (3.1.3 — patch, 2026-08-05): `repositories.column_enums`
69
110
  # bound `service_type` — the AUTHORING field's name — but the catalogue
70
111
  # column that carries the value is `component_type` (the builder maps
@@ -565,6 +606,75 @@ schema_status: "canonical"
565
606
 
566
607
  enums:
567
608
 
609
+ quality_gate:
610
+ description: >
611
+ Gate verdict a rubric assessment records for a target, in
612
+ `quality_scores.gate` (per M-ADR 0205 §4.5). The vocabulary all fifteen
613
+ method-side gate registries declare.
614
+
615
+ DELIBERATELY NOT BOUND via `column_enums`, and the reason is measured
616
+ rather than assumed — do not "fix" this by binding it. These values come
617
+ from hand-authored score registries written by scoring runs, not from a
618
+ method-mandated authoring surface, and one estate's
619
+ `domain-architecture-scores.yaml` DECLARES AN EXTENDED VOCABULARY IN ITS
620
+ OWN FILE HEADER (`pass | pass-with-waiver | conditional | fail |
621
+ unscored`) and uses the extra value once. Binding would hard-fail that
622
+ estate's entire build over one deliberate, self-documented row. This
623
+ follows the `products.synthesis_band` precedent — the other column fed
624
+ from a rubric registry — where an out-of-vocabulary value is reported as
625
+ a convention finding and the cell left EMPTY, rather than emitting a
626
+ value no consumer can interpret. The builder names the file, the entry,
627
+ the value and the remedy, which is better diagnosis than a generic enum
628
+ violation could give. Contrast `service_type`, which IS bound: it comes
629
+ from repo-config, an authoring surface the method mandates.
630
+ values:
631
+ - { value: pass, description: "Meets the rubric's pass threshold with no hard gate triggered." }
632
+ - { value: conditional, description: "Below threshold or carrying flags — remediation required, not a failure." }
633
+ - { value: fail, description: "Below the fail threshold, or a hard gate triggered." }
634
+ - { value: unscored, description: "The entry exists but carries no assessment. Distinct from absent: an unscored row asserts that nothing has been judged, which is exactly the silence M-ADR 0205 §4.5's coverage instrument exists to make loud." }
635
+
636
+ score_selection_method:
637
+ description: >
638
+ How the effective review was chosen from a target's review history, in
639
+ `quality_scores.selection_method` — the `selection_policy.method` field
640
+ every gate registry carries. The catalogue models only the EFFECTIVE
641
+ score (one row per target/rubric); this column makes the row say WHICH
642
+ review it is rather than implying there was only one. Not bound, for the
643
+ same registry-authored reason as `quality_gate`.
644
+ values:
645
+ - { value: latest, description: "Most recent review by scored_at. The default and, at 2026-08-06, the only value in use across either estate." }
646
+ - { value: human-selected, description: "A human chose the effective review over the automatic pick." }
647
+ - { value: consensus, description: "Effective score reconciled across several reviews." }
648
+ - { value: highest-severity, description: "The most severe review wins — the conservative policy for gate-blocking rubrics." }
649
+
650
+ staleness_basis:
651
+ description: >
652
+ Which anchor a `quality_scores` row's staleness verdict can be computed
653
+ from, in `quality_scores.staleness_basis`. This column exists because a
654
+ staleness verdict whose basis is unstated is not a measurement — the
655
+ basis-error class that produced six wrong figures in a single day of this
656
+ method's own arc. The coverage predicate MUST NOT be able to emit a
657
+ staleness claim without naming which of these it used.
658
+ values:
659
+ - { value: corpus_ref, description: "The row carries the commit the assessment read — the precise anchor. Authored; introduced by the M-ADR 0205 §4.5 change-set, so absent from every score written before it." }
660
+ - { value: scored_at, description: "No corpus_ref; staleness computed from the assessment date against the target's last content change, resolved through target_path. Correct but coarser — it cannot distinguish a re-commit that changed nothing from a real edit." }
661
+ - { value: none, description: "Neither anchor available (no corpus_ref and no resolvable target_path). Staleness is UNKNOWN for this row and must be reported as unknown, never as fresh." }
662
+
663
+ scoring_form:
664
+ description: >
665
+ The scoring shape a rubric uses, in `quality_scores.scoring_form`.
666
+ Reserved by M-ADR 0205 §4.5 so the banded reverse family can arrive
667
+ additively without reshaping rows.
668
+
669
+ Only `weighted` is declared. The reverse estate's banded form (0-2 across
670
+ 5-6 dimensions with strong/working/weak/not-usable bands) is real and
671
+ measured — 142 registry files, 501 scored units — but is NOT modelled
672
+ yet, so its value is deliberately absent rather than declared-and-unemitted:
673
+ if a builder emits a banded row before that change-set lands, it should
674
+ fail loudly, not pass against a vocabulary entry nothing produces.
675
+ values:
676
+ - { value: weighted, description: "Weighted 1-5 dimensions rolled into a weighted_score against a pass threshold, with flags and hard gates. The forward house form; all fifteen method-side registries use it." }
677
+
568
678
  c4_system_kind:
569
679
  description: >
570
680
  Architectural kind of a C4 system. Derived 1:1 from the originating
@@ -1932,3 +2042,91 @@ catalogues:
1932
2042
  - { name: needs_triage, type: boolean, nullable: false, description: "True when any asymmetry exists. Triage, not auto-fail (M-ADR 0180 §2.3)." }
1933
2043
  - { name: run_date, type: string, nullable: false, description: "ISO date of the conformance run — the snapshot stamp enabling trend over time." }
1934
2044
  - { name: source_sdd_id, type: string, nullable: true, description: "Originating SDD slug. Populated by the aggregator per M-ADR 0134." }
2045
+
2046
+ quality_scores:
2047
+ primary_key: id
2048
+ description: >
2049
+ Rubric assessment of a target artefact, one row per (target, rubric), per
2050
+ M-ADR 0205 §4.5. Source: `orchestration/gate-registry/<rubric>-scores.yaml`
2051
+ — the authored surface stays YAML because a score is a judgment, authored
2052
+ where it asserts intent; these rows are DERIVED and never edited.
2053
+
2054
+ Models the EFFECTIVE score only — `current`, as chosen by the registry's
2055
+ `selection_policy`. The authored `reviews[]` history is deliberately not
2056
+ catalogued: variable-length history in a fixed-grain catalogue would give
2057
+ two answers to "what is the score". `review_run_id` and
2058
+ `selection_method` make each row name which review it is.
2059
+
2060
+ THE BUILDER MUST READ TWO AUTHORED DIALECTS. All fifteen method-side
2061
+ templates specify a nested shape (`selection_policy` / `current` /
2062
+ `reviews`), but the live forward-estate data is overwhelmingly FLAT —
2063
+ `gate`/`weighted_score`/`scored_at`/`scored_by`/`scores`/`flags` directly
2064
+ on the entry. Measured 2026-08-06: reading only the template shape would
2065
+ catalogue 6 entries out of 204. The templates were modernised; the data
2066
+ was not migrated, and both are legitimate.
2067
+
2068
+ `rubric_id` comes from the file's `registry_type` when declared, else the
2069
+ filename stem minus `-scores` — NEVER the container key, which is
2070
+ unreliable (4 of 10 forward registries drift from the method template)
2071
+ and non-unique (`domains` names both domain-architecture and
2072
+ intent-quality; `capabilities` names both feature-grounding and
2073
+ traceability-manifest).
2074
+
2075
+ Scope: the weighted house form only. The banded reverse family is
2076
+ additive later via `scoring_form` (see that enum).
2077
+ foreign_keys:
2078
+ - { column: sdd_id, references: products.id, nullable: true }
2079
+ columns:
2080
+ - { name: id, type: string, nullable: false, description: "PK: {rubric_id}__{target_kind}__{target_ref}. Composite in one slug because the natural key is a triple and the rest of this schema keys on a single `id`." }
2081
+ - { name: rubric_id, type: string, nullable: false, description: "The rubric that produced the assessment, e.g. adr-quality, contract-quality. From the registry's `registry_type` when declared, else the filename stem minus `-scores`. A `registry_type` disagreeing with its filename is a convention finding, never a silent preference." }
2082
+ - { name: scoring_form, type: string, nullable: false, description: "Scoring shape — see the scoring_form enum. `weighted` for every row the current builder emits." }
2083
+ - { name: target_kind, type: string, nullable: false, description: "What kind of thing was scored: adr | contract | c4_diagram | capability | domain | feature | product | repository | persona | screen | glossary | integration | user_story | work_order | strategic_doc. Polymorphic because scored units span catalogue entities and non-catalogued artefacts (M-ADR 0205 §4.5)." }
2084
+ - { name: target_ref, type: string, nullable: false, description: "Identifier of the scored target, in the vocabulary of its kind. For ADRs this is the prefix-stripped catalogue id (M-ADR 0186 §4.4), matching `adrs.id`." }
2085
+ - { name: target_path, type: string, nullable: true, description: "Repo-relative path to the scored artefact, from the entry's `file_path` where authored (7 of 15 registry shapes carry it). Doubles as the resolution anchor for `scored_at`-basis staleness — which is why its absence downgrades a row's staleness_basis to `none` rather than being cosmetic. Empty when the registry does not author it." }
2086
+ - { name: gate, type: string, nullable: true, description: "Verdict — see the quality_gate enum, which is deliberately UNBOUND. An out-of-vocabulary value leaves this cell EMPTY and raises a convention finding naming the file, entry and value (the products.synthesis_band precedent). Empty therefore means either unauthored or out-of-vocabulary, and the finding distinguishes them." }
2087
+ - { name: weighted_score, type: number, nullable: true, description: "The rubric's rolled-up weighted score. Empty for an unscored entry — which is a real state the registries author deliberately, not a gap." }
2088
+ - { name: score_denominator, type: number, nullable: true, description: "Denominator the weighted_score was computed against, where the rubric records one (contract-quality does). Present so a score is never reported without its basis." }
2089
+ - { name: scored_at, type: date, nullable: true, description: "Date of the effective assessment, from `scored_at` (the forward house form's field name — NOT `assessed_at`, which is the reverse family's file-level field). Date-typed: per the M-ADR 0205 §4.1 engine's TRY_CAST semantics, a prose value here is reported as a type nonconformance rather than aborting the load or being smoothed away — the `adrs.decision_date` case, which reverse practice already exercises." }
2090
+ - { name: corpus_ref, type: string, nullable: true, description: "The commit the assessment read — the precise staleness anchor. NEW AUTHORING introduced by this change-set: no score written before it carries one, so this column is empty across both estates at introduction and fills forward as registries are rewritten. The reverse family already has the idea under a different name (`snapshot.source_revision`)." }
2091
+ - { name: staleness_basis, type: string, nullable: false, description: "Which anchor this row's staleness can be computed from — see the staleness_basis enum. Emitted by the builder, never authored. Exists so no consumer can state a staleness verdict without its basis." }
2092
+ - { name: review_run_id, type: string, nullable: true, description: "Identifier of the effective review run. Empty in the flat dialect, which records no run ids." }
2093
+ - { name: selection_method, type: string, nullable: true, description: "How the effective review was chosen — see the score_selection_method enum. Empty in the flat dialect, which carries no selection_policy: absence means 'the only review', not 'policy unknown'." }
2094
+ - { name: scorer_provider, type: string, nullable: true, description: "Provider of the scoring agent (e.g. anthropic), from `current.scorer.provider`. Every score in this method is agent-produced, so which agent produced a judgment is part of the judgment, not metadata about it." }
2095
+ - { name: scorer_tool, type: string, nullable: true, description: "Tool the scoring agent ran in, from `current.scorer.tool`." }
2096
+ - { name: scorer_model, type: string, nullable: true, description: "Model that produced the assessment, from `current.scorer.model`. In the flat dialect the whole provenance block collapses to a free-text `scored_by:`, which lands here — so a value like 'intent-quality-review — rfms-connector-library' is expected and correct for flat-dialect rows, not a parse defect." }
2097
+ - { name: scorer_model_family, type: string, nullable: true, description: "Optional grouping field from `current.scorer.model_family`." }
2098
+ - { name: scorer_prompt_version, type: string, nullable: true, description: "Optional prompt-wrapper version from `current.scorer.prompt_version` — the input that makes a score reproducible." }
2099
+ - { name: flag_count, type: int, nullable: false, description: "Number of heuristic flags raised. Normalises two authored dialects: `flags: {name: bool}` (count the true ones) and `flags_raised: [names]` (count the list). A per-flag child catalogue is deliberately NOT built — it arrives when a named query needs to filter by flag name, not by accretion." }
2100
+ - { name: hard_gate_triggered, type: boolean, nullable: false, description: "Whether any hard gate fired. Normalises `hard_gates: {triggered, reasons}` and `hard_gates_triggered: [reasons]`." }
2101
+ - { name: required_actions_count, type: int, nullable: false, description: "Number of remediation actions the assessment recorded." }
2102
+ - { name: sdd_id, type: string, nullable: true, description: "SDD whose gate-registry authored this row. Soft FK to products.id — nullable because a registry can score targets in an SDD that emits no product row." }
2103
+ - { name: source_sdd_id, type: string, nullable: true, description: "Originating SDD slug. Populated by the aggregator per M-ADR 0134; left empty by per-SDD builders." }
2104
+
2105
+ quality_score_dimensions:
2106
+ primary_key: id
2107
+ description: >
2108
+ One row per (target, rubric, dimension) — the per-dimension detail behind
2109
+ a `quality_scores` row, per M-ADR 0205 §4.5.
2110
+
2111
+ A child catalogue rather than columns, and this is forced rather than
2112
+ stylistic: the fifteen rubrics carry FIFTEEN DISJOINT dimension
2113
+ vocabularies (`A1`-`A8`, `C1`-`C8`, `G1`-`G7`, `T1`-`T7`, `D1`-`D6`,
2114
+ `S1`-`S6`, `I1`-`I6`, plus five fully-named sets such as
2115
+ `definition_precision` and `intent_fidelity`) — 45 distinct keys measured
2116
+ in one estate alone. No fixed column set can hold them; serialised JSON in
2117
+ a cell would be unjoinable and break the relational metamodel; generic
2118
+ `d1..d8` columns would be lossy and re-create the positional-index failure
2119
+ class. A child table is what this metamodel already does for every
2120
+ one-to-many, and it joins natively on the M-ADR 0205 §4.1 engine.
2121
+ foreign_keys:
2122
+ - { column: quality_score_id, references: quality_scores.id, nullable: false }
2123
+ columns:
2124
+ - { name: id, type: string, nullable: false, description: "PK: {quality_score_id}__{dimension_key}." }
2125
+ - { name: quality_score_id, type: string, nullable: false, description: "The assessment this dimension belongs to." }
2126
+ - { name: rubric_id, type: string, nullable: false, description: "Denormalised from the parent so per-rubric dimension queries need no join." }
2127
+ - { name: target_kind, type: string, nullable: false, description: "Denormalised from the parent." }
2128
+ - { name: target_ref, type: string, nullable: false, description: "Denormalised from the parent." }
2129
+ - { name: dimension_key, type: string, nullable: false, description: "The rubric's own dimension identifier, verbatim — `A1` where the rubric uses codes, `definition_precision` where it uses names. NOT normalised into a method-wide vocabulary: the key is how the rubric and its registry refer to the dimension, and rewriting it here would make the row untraceable to the rubric that produced it." }
2130
+ - { name: dimension_score, type: number, nullable: true, description: "Score on that dimension. Empty for an unscored entry (the templates author explicit nulls)." }
2131
+ - { name: dimension_weight, type: number, nullable: true, description: "Weight the rubric assigns the dimension, where discoverable. Usually EMPTY: weights live in the rubric document and the registry header comment, not per entry — so this column is honest about the fact that a weighted_score cannot currently be recomputed from these rows alone." }
2132
+ - { name: source_sdd_id, type: string, nullable: true, description: "Originating SDD slug. Populated by the aggregator per M-ADR 0134." }