@sdd-method/maintain-cli 0.0.0-stage → 0.1.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 (206) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +17 -0
  3. package/README.md +6 -2
  4. package/dist/lib/adr-origin.js +59 -0
  5. package/dist/lib/agent-harness.js +28 -0
  6. package/dist/lib/briefing/index.js +13 -0
  7. package/dist/lib/briefing/render.js +123 -0
  8. package/dist/lib/briefing/variables.js +92 -0
  9. package/dist/lib/bundle.js +123 -0
  10. package/dist/lib/catalogue/aggregate.js +2404 -0
  11. package/dist/lib/catalogue/aggregation-manifest-loader.js +173 -0
  12. package/dist/lib/catalogue/application-archetype/expectations.js +119 -0
  13. package/dist/lib/catalogue/application-archetype/vocabulary.js +177 -0
  14. package/dist/lib/catalogue/archetype/maps/android.yaml +66 -0
  15. package/dist/lib/catalogue/archetype/maps/swiftui.yaml +58 -0
  16. package/dist/lib/catalogue/archetype/maps/uikit.yaml +48 -0
  17. package/dist/lib/catalogue/archetype/maps/web-generic.yaml +86 -0
  18. package/dist/lib/catalogue/archetype/openui-archetype-vocabulary.yaml +46 -0
  19. package/dist/lib/catalogue/archetype/resolver.js +103 -0
  20. package/dist/lib/catalogue/archetype/wireframe.js +418 -0
  21. package/dist/lib/catalogue/baseline-check.js +151 -0
  22. package/dist/lib/catalogue/build.js +1502 -0
  23. package/dist/lib/catalogue/builders/adr-supersedes.js +103 -0
  24. package/dist/lib/catalogue/builders/adrs.js +222 -0
  25. package/dist/lib/catalogue/builders/application-conformance-coverage.js +47 -0
  26. package/dist/lib/catalogue/builders/application-data-plane-bindings.js +115 -0
  27. package/dist/lib/catalogue/builders/c4-components.js +229 -0
  28. package/dist/lib/catalogue/builders/c4-containers.js +240 -0
  29. package/dist/lib/catalogue/builders/c4-entity-rollups.js +87 -0
  30. package/dist/lib/catalogue/builders/c4-external-systems.js +194 -0
  31. package/dist/lib/catalogue/builders/c4-l1-candidates.js +107 -0
  32. package/dist/lib/catalogue/builders/c4-systems.js +98 -0
  33. package/dist/lib/catalogue/builders/capabilities.js +488 -0
  34. package/dist/lib/catalogue/builders/capability-domain-model.js +74 -0
  35. package/dist/lib/catalogue/builders/capability-edges.js +256 -0
  36. package/dist/lib/catalogue/builders/capability-spec-walker.js +99 -0
  37. package/dist/lib/catalogue/builders/capability-spec.js +348 -0
  38. package/dist/lib/catalogue/builders/container-dependency.js +183 -0
  39. package/dist/lib/catalogue/builders/contracts.js +402 -0
  40. package/dist/lib/catalogue/builders/data-items.js +344 -0
  41. package/dist/lib/catalogue/builders/data-store-mapping.js +113 -0
  42. package/dist/lib/catalogue/builders/domain-models.js +175 -0
  43. package/dist/lib/catalogue/builders/domains.js +119 -0
  44. package/dist/lib/catalogue/builders/edge-label-merge.js +19 -0
  45. package/dist/lib/catalogue/builders/entities-manifest.js +160 -0
  46. package/dist/lib/catalogue/builders/entities-mermaid.js +189 -0
  47. package/dist/lib/catalogue/builders/entity-persistence.js +102 -0
  48. package/dist/lib/catalogue/builders/entity-slug.js +47 -0
  49. package/dist/lib/catalogue/builders/event-catalog-walker.js +186 -0
  50. package/dist/lib/catalogue/builders/event-edges.js +327 -0
  51. package/dist/lib/catalogue/builders/events.js +168 -0
  52. package/dist/lib/catalogue/builders/evidence-class.js +43 -0
  53. package/dist/lib/catalogue/builders/evidence-target-repo.js +67 -0
  54. package/dist/lib/catalogue/builders/external-system-exemption.js +120 -0
  55. package/dist/lib/catalogue/builders/feature-contract.js +77 -0
  56. package/dist/lib/catalogue/builders/feature-domain-model.js +50 -0
  57. package/dist/lib/catalogue/builders/feature-grounding-walker.js +254 -0
  58. package/dist/lib/catalogue/builders/feature-grounding.js +391 -0
  59. package/dist/lib/catalogue/builders/feature-groups.js +63 -0
  60. package/dist/lib/catalogue/builders/feature-subscription-channels.js +228 -0
  61. package/dist/lib/catalogue/builders/feature-tree-walker.js +295 -0
  62. package/dist/lib/catalogue/builders/features.js +300 -0
  63. package/dist/lib/catalogue/builders/glossary-xref.js +378 -0
  64. package/dist/lib/catalogue/builders/glossary.js +204 -0
  65. package/dist/lib/catalogue/builders/implementations.js +214 -0
  66. package/dist/lib/catalogue/builders/index.js +64 -0
  67. package/dist/lib/catalogue/builders/integration-components.js +344 -0
  68. package/dist/lib/catalogue/builders/integrations.js +181 -0
  69. package/dist/lib/catalogue/builders/persona-c4system.js +149 -0
  70. package/dist/lib/catalogue/builders/persona-container.js +133 -0
  71. package/dist/lib/catalogue/builders/persona-journey-edges.js +133 -0
  72. package/dist/lib/catalogue/builders/personas.js +152 -0
  73. package/dist/lib/catalogue/builders/product-edges.js +106 -0
  74. package/dist/lib/catalogue/builders/product-platform-dependencies.js +405 -0
  75. package/dist/lib/catalogue/builders/products.js +162 -0
  76. package/dist/lib/catalogue/builders/quality-scores.js +635 -0
  77. package/dist/lib/catalogue/builders/repo-capability-exemption.js +61 -0
  78. package/dist/lib/catalogue/builders/repo-dependency.js +127 -0
  79. package/dist/lib/catalogue/builders/repo-edges.js +340 -0
  80. package/dist/lib/catalogue/builders/repositories.js +458 -0
  81. package/dist/lib/catalogue/builders/scaffolds.js +197 -0
  82. package/dist/lib/catalogue/builders/screen-tree.js +222 -0
  83. package/dist/lib/catalogue/builders/screens.js +396 -0
  84. package/dist/lib/catalogue/builders/service-capability-exemption.js +63 -0
  85. package/dist/lib/catalogue/builders/service-contract-consumes.js +186 -0
  86. package/dist/lib/catalogue/builders/service-contract.js +74 -0
  87. package/dist/lib/catalogue/builders/service-entity-tables.js +187 -0
  88. package/dist/lib/catalogue/builders/services.js +232 -0
  89. package/dist/lib/catalogue/builders/system-external-dependency.js +115 -0
  90. package/dist/lib/catalogue/builders/user-journeys.js +253 -0
  91. package/dist/lib/catalogue/canonical-schema.yaml +4117 -0
  92. package/dist/lib/catalogue/cli-version.js +10 -0
  93. package/dist/lib/catalogue/contract-id.js +49 -0
  94. package/dist/lib/catalogue/contract-path-resolution.js +149 -0
  95. package/dist/lib/catalogue/coverage-predicates.js +603 -0
  96. package/dist/lib/catalogue/coverage-render.js +552 -0
  97. package/dist/lib/catalogue/coverage-run.js +115 -0
  98. package/dist/lib/catalogue/csv-reader.js +97 -0
  99. package/dist/lib/catalogue/csv-writer.js +96 -0
  100. package/dist/lib/catalogue/data-item-coverage.js +142 -0
  101. package/dist/lib/catalogue/data-plane-coherence.js +77 -0
  102. package/dist/lib/catalogue/ddl-generator.js +233 -0
  103. package/dist/lib/catalogue/dedupe-keyed-tables.js +0 -0
  104. package/dist/lib/catalogue/engine-validator.js +239 -0
  105. package/dist/lib/catalogue/ext-id.js +76 -0
  106. package/dist/lib/catalogue/feature-grounding-aliases-loader.js +65 -0
  107. package/dist/lib/catalogue/feature-repo-zero-resolution-summary.js +31 -0
  108. package/dist/lib/catalogue/finding-identity.js +183 -0
  109. package/dist/lib/catalogue/findings.js +46 -0
  110. package/dist/lib/catalogue/fk-validator.js +136 -0
  111. package/dist/lib/catalogue/freshness.js +69 -0
  112. package/dist/lib/catalogue/gate-checks.js +338 -0
  113. package/dist/lib/catalogue/graph-projection.js +346 -0
  114. package/dist/lib/catalogue/graph-run.js +64 -0
  115. package/dist/lib/catalogue/impact-run.js +228 -0
  116. package/dist/lib/catalogue/manifest-loader.js +435 -0
  117. package/dist/lib/catalogue/platform-scope.js +7 -0
  118. package/dist/lib/catalogue/population-checks.js +87 -0
  119. package/dist/lib/catalogue/relationship-semantics.js +66 -0
  120. package/dist/lib/catalogue/reverse-product-quality.js +99 -0
  121. package/dist/lib/catalogue/rubric-coverage-map.yaml +871 -0
  122. package/dist/lib/catalogue/runway-vocabulary-loader.js +56 -0
  123. package/dist/lib/catalogue/scaffold-delta.js +261 -0
  124. package/dist/lib/catalogue/schema-compat.js +52 -0
  125. package/dist/lib/catalogue/schema-loader.js +87 -0
  126. package/dist/lib/catalogue/scores-coverage.js +573 -0
  127. package/dist/lib/catalogue/screen-validation-loader.js +89 -0
  128. package/dist/lib/catalogue/service-architecture-parser.js +193 -0
  129. package/dist/lib/catalogue/service-contract-aliases-loader.js +109 -0
  130. package/dist/lib/catalogue/staleness-verdicts.js +345 -0
  131. package/dist/lib/catalogue/traceability-loader.js +350 -0
  132. package/dist/lib/catalogue/validate.js +200 -0
  133. package/dist/lib/catalogue/version.js +18 -0
  134. package/dist/lib/ci-binding/index.js +220 -0
  135. package/dist/lib/ci-binding/module.js +204 -0
  136. package/dist/lib/conformance/binding.js +70 -0
  137. package/dist/lib/context-pull/index.js +151 -0
  138. package/dist/lib/context-pull/resolve.js +70 -0
  139. package/dist/lib/generate-briefing/index.js +77 -0
  140. package/dist/lib/hooks-seed/copilot.js +167 -0
  141. package/dist/lib/hooks-seed/entries.js +47 -0
  142. package/dist/lib/hooks-seed/index.js +17 -0
  143. package/dist/lib/hooks-seed/lifecycle-mapping.js +28 -0
  144. package/dist/lib/hooks-seed/merge.js +128 -0
  145. package/dist/lib/hooks-seed/types.js +20 -0
  146. package/dist/lib/init/ci-workflow.js +98 -0
  147. package/dist/lib/list/discover.js +100 -0
  148. package/dist/lib/list/format.js +84 -0
  149. package/dist/lib/list/index.js +16 -0
  150. package/dist/lib/lock-file.js +437 -0
  151. package/dist/lib/mcp-seed/entries.js +14 -0
  152. package/dist/lib/mcp-seed/index.js +28 -0
  153. package/dist/lib/mcp-seed/merge.js +99 -0
  154. package/dist/lib/mcp-seed/types.js +13 -0
  155. package/dist/lib/pack/builder.js +303 -0
  156. package/dist/lib/pack/index.js +87 -0
  157. package/dist/lib/pack/leakage.js +144 -0
  158. package/dist/lib/pack/log.js +18 -0
  159. package/dist/lib/pack/publish-transform.js +233 -0
  160. package/dist/lib/pack/reference-closure.js +125 -0
  161. package/dist/lib/pack/schema.js +121 -0
  162. package/dist/lib/pack/seed.js +182 -0
  163. package/dist/lib/pack/validate.js +49 -0
  164. package/dist/lib/package-version.js +92 -0
  165. package/dist/lib/repo-kind.js +129 -0
  166. package/dist/lib/scripts.js +7 -0
  167. package/dist/lib/snapshot/catalogue-diff.js +219 -0
  168. package/dist/lib/snapshot/manifest.js +206 -0
  169. package/dist/lib/sync/adr-transitions.js +250 -0
  170. package/dist/lib/sync/apply.js +91 -0
  171. package/dist/lib/sync/briefing-merge.js +90 -0
  172. package/dist/lib/sync/bundle-cache.js +109 -0
  173. package/dist/lib/sync/bundle-source.js +61 -0
  174. package/dist/lib/sync/config.js +72 -0
  175. package/dist/lib/sync/copilot-hooks-merge.js +108 -0
  176. package/dist/lib/sync/diff.js +251 -0
  177. package/dist/lib/sync/index.js +818 -0
  178. package/dist/lib/sync/settings-merge.js +216 -0
  179. package/dist/lib/sync/yaml-block-merge.js +120 -0
  180. package/dist/lib/validate/aggregate.js +51 -0
  181. package/dist/lib/validate/bundle-coherence.js +74 -0
  182. package/dist/lib/validate/dispatch.js +243 -0
  183. package/dist/lib/validate/index.js +110 -0
  184. package/dist/lib/validate/plan.js +54 -0
  185. package/dist/lib/validate/runner.js +85 -0
  186. package/dist/lib/validate/yaml-parse.js +112 -0
  187. package/dist/maintain-bin.js +8 -0
  188. package/dist/maintain-program.js +91 -0
  189. package/dist/maintain-version.json +4 -0
  190. package/dist/verbs/catalogue-maintain.js +110 -0
  191. package/dist/verbs/catalogue-verify.js +114 -0
  192. package/dist/verbs/context.js +39 -0
  193. package/dist/verbs/generate-briefing.js +29 -0
  194. package/dist/verbs/list.js +45 -0
  195. package/dist/verbs/pack-build.js +31 -0
  196. package/dist/verbs/pack-validate.js +17 -0
  197. package/dist/verbs/path-option.js +25 -0
  198. package/dist/verbs/render.js +87 -0
  199. package/dist/verbs/sync.js +110 -0
  200. package/dist/verbs/validate.js +48 -0
  201. package/dist/verify-program.js +122 -0
  202. package/dist/verify-version.json +4 -0
  203. package/package.json +32 -4
  204. package/scripts/validate-app-dependencies.sh +664 -0
  205. package/scripts/validate-app-docs.sh +199 -0
  206. package/scripts/validate-integration-docs.sh +505 -0
@@ -0,0 +1,151 @@
1
+ /**
2
+ * `catalogue baseline-check` — compares emitted findings against a repo's
3
+ * findings baseline BY IDENTITY (M-ADR 0132 §9), and reports the four outcomes
4
+ * a re-take needs to be reviewable: unbaselined, reworded, closed, unchanged.
5
+ *
6
+ * WHY THIS IS A COMMAND AND NOT A DISCIPLINE. The comparison was previously
7
+ * described in prose and performed per repo, which is why the rewording class
8
+ * (§9.1) went undetected twice on the same finding family: every repo
9
+ * implemented "is this line in the file" independently and correctly, and the
10
+ * defect was in the question, not the implementations.
11
+ *
12
+ * It reads findings rather than producing them, so it composes with whatever
13
+ * produced them and cannot disagree with a separate run of the builder:
14
+ *
15
+ * sdd-cli catalogue validate --coverage > findings.txt
16
+ * sdd-cli catalogue baseline-check --findings findings.txt
17
+ *
18
+ * ONLY GATE-ACTING CATEGORIES ARE COMPARED (`orphan`, `divergence` — M-ADR 0132
19
+ * §4.3). Filtering happens here, visibly, and the count of what was filtered is
20
+ * printed: a comparator that silently dropped categories would make an empty
21
+ * result ambiguous between "nothing gate-acting" and "nothing at all".
22
+ */
23
+ import { readFile } from "node:fs/promises";
24
+ import { join } from "node:path";
25
+ import { compareToBaseline } from "./finding-identity.js";
26
+ /** The categories a baseline governs, per M-ADR 0132 §4.3. */
27
+ const GATE_ACTING = new Set(["orphan", "divergence"]);
28
+ export const DEFAULT_BASELINE_REL = join("orchestration", "catalogue-findings-baseline.txt");
29
+ const FINDING_LINE = /^\[finding\] (\w+)(?: \[error\])?[ (:]/;
30
+ /**
31
+ * Findings from a stream of mixed output. Non-finding lines (metrics, headers,
32
+ * blank lines, a baseline file's `#` provenance) are not findings and are
33
+ * dropped without comment; a `[finding]` line of a non-gate-acting category is
34
+ * dropped and COUNTED, because that number is the difference between "nothing
35
+ * to compare" and "nothing was comparable".
36
+ */
37
+ export function extractGateActing(text) {
38
+ const lines = [];
39
+ let nonGateActing = 0;
40
+ for (const raw of text.split("\n")) {
41
+ const line = raw.trimEnd();
42
+ const m = FINDING_LINE.exec(line);
43
+ if (!m)
44
+ continue;
45
+ if (GATE_ACTING.has(m[1]))
46
+ lines.push(line);
47
+ else
48
+ nonGateActing++;
49
+ }
50
+ return { lines, nonGateActing };
51
+ }
52
+ export async function runBaselineCheck(options, write) {
53
+ const root = options.sddPath ?? process.cwd();
54
+ const baselinePath = options.baseline ?? join(root, DEFAULT_BASELINE_REL);
55
+ let findingsText;
56
+ if (options.findings !== undefined) {
57
+ findingsText = await readFile(options.findings, "utf-8");
58
+ }
59
+ else if (options.stdin) {
60
+ findingsText = await options.stdin();
61
+ }
62
+ else {
63
+ write("[error] baseline-check: no findings source (--findings <path>, or pipe them in)\n");
64
+ return { exitCode: 2 };
65
+ }
66
+ // An input with no lines at all is not "zero findings": every real findings
67
+ // stream (build, coverage, validate output) carries at least its own metric
68
+ // and verdict lines. The default source is stdin, so an empty pipe arrives
69
+ // here as nothing — refused, never compared (empty-set sweep, R2).
70
+ if (findingsText.trim() === "") {
71
+ write(`[error] baseline-check: the findings stream is EMPTY — no lines of any kind. ` +
72
+ `This is not zero findings; it is no measurement (an empty pipe, or the wrong ` +
73
+ `file). Pass --findings <path> to the captured stream\n`);
74
+ return { exitCode: 2 };
75
+ }
76
+ let baselineText;
77
+ try {
78
+ baselineText = await readFile(baselinePath, "utf-8");
79
+ }
80
+ catch (err) {
81
+ if (err.code !== "ENOENT")
82
+ throw err;
83
+ // A MISSING baseline is not an empty one. Under §9.3 the canonical zero is
84
+ // an empty-but-present file, precisely so that "measured, and there were
85
+ // none" is distinguishable from "never measured" — so this reports rather
86
+ // than treating every live finding as unbaselined.
87
+ write(`[error] baseline-check: no baseline at ${baselinePath} — a missing file is not a ` +
88
+ `recorded zero (M-ADR 0132 §9.3); create it empty, with its provenance header, ` +
89
+ `to record that findings were measured and there were none\n`);
90
+ return { exitCode: 2 };
91
+ }
92
+ const live = extractGateActing(findingsText);
93
+ const base = extractGateActing(baselineText);
94
+ const cmp = compareToBaseline(live.lines, base.lines);
95
+ write(`[metric] baseline_check: ${live.lines.length} gate-acting finding(s) against ` +
96
+ `${base.lines.length} baseline entr(ies) — ${cmp.unchanged} unchanged, ` +
97
+ `${cmp.reworded.length} reworded, ${cmp.unbaselined.length} unbaselined, ` +
98
+ `${cmp.stale.length} closed; ${live.nonGateActing} non-gate-acting finding(s) not compared\n`);
99
+ // ⚠ THE WHOLE-BASELINE-CLOSED GUARD. An all-closed result against a non-empty
100
+ // baseline is far more likely to mean the comparison read the WRONG STREAM than
101
+ // that an estate fixed everything at once, and until now it rendered as a clean
102
+ // green number: "0 gate-acting findings, 215 closed" reads as success and is
103
+ // indistinguishable from a gate comparing against nothing.
104
+ //
105
+ // Raised by an adopter estate that hit it on a 215-entry baseline: its
106
+ // baseline had been captured from one stream/tier and was being compared
107
+ // against another, so every entry reported closed and the regression gate
108
+ // passed unconditionally. The `--findings` default is stdin, so an empty pipe
109
+ // reaches here as legitimately-zero findings — the same estate had already
110
+ // been caught once by a bare invocation reporting 832 closed.
111
+ //
112
+ // The condition is deliberately narrow: live gate-acting findings ZERO, baseline
113
+ // non-empty, and EVERY entry closed. That triple cannot arise from ordinary
114
+ // remediation without also being worth a human look.
115
+ const allClosed = live.lines.length === 0 && base.lines.length > 0 && cmp.stale.length === base.lines.length;
116
+ if (allClosed) {
117
+ write(`[finding] divergence: baseline_check compared ZERO live gate-acting findings ` +
118
+ `against ${base.lines.length} baseline entr(ies) and reported ALL of them closed. ` +
119
+ `This is reported as a DEFECT rather than a pass: an all-closed baseline is far ` +
120
+ `more likely to mean the findings stream was empty or was the wrong one than that ` +
121
+ `every finding was fixed at once. Check that --findings received the stream the ` +
122
+ `baseline was CAPTURED from (note the default is stdin, so an empty pipe arrives ` +
123
+ `here as zero findings), and that --tier matches. Re-taking the baseline against ` +
124
+ `this comparison would bake the empty stream in as the new truth and destroy the ` +
125
+ `${base.lines.length}-entry record.\n`);
126
+ }
127
+ // Reported even at zero. While it is above zero those entries are matched on
128
+ // whole text and remain exposed to the rewording class; silence here would
129
+ // imply a protection the repo has not got.
130
+ write(`[metric] baseline_check.legacy_keyed: ${cmp.legacyKeyed} baseline entr(ies) carry no ` +
131
+ `identity and are matched on their whole line — re-take them as their emission ` +
132
+ `sites migrate (M-ADR 0132 §9.2)\n`);
133
+ for (const r of cmp.reworded) {
134
+ // Named, not counted only: a re-take must be able to show which line
135
+ // replaced which, and "N reworded" is not reviewable evidence.
136
+ write(`[reworded] ${r.baseline}\n[reworded] -> ${r.live}\n`);
137
+ }
138
+ for (const s of cmp.stale)
139
+ write(`[closed] ${s}\n`);
140
+ for (const u of cmp.unbaselined)
141
+ write(`[unbaselined] ${u}\n`);
142
+ // Only genuinely unbaselined findings fail. A reworded finding is the case
143
+ // this whole mechanism exists to stop failing, and a closed one is good news
144
+ // that a re-take tidies — neither is a regression.
145
+ // The all-closed guard FAILS the gate (empty-set sweep, R2, ruled 2026-09-29):
146
+ // it used to print "a DEFECT rather than a pass" and exit 0, so the regression
147
+ // gate still passed on exactly the empty/wrong stream it was written to catch.
148
+ // A genuinely all-fixed estate re-takes its baseline once, deliberately.
149
+ return { exitCode: cmp.unbaselined.length > 0 || allClosed ? 1 : 0 };
150
+ }
151
+ //# sourceMappingURL=baseline-check.js.map