@sdd-method/author-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 (203) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +17 -0
  3. package/README.md +6 -2
  4. package/dist/author-bin.js +8 -0
  5. package/dist/author-program.js +99 -0
  6. package/dist/lib/adr-origin.js +59 -0
  7. package/dist/lib/agent-harness.js +37 -0
  8. package/dist/lib/api-surface/__fixtures__/serverless-repo/serverless/serverless.yml +18 -0
  9. package/dist/lib/api-surface/analyzers/library.js +95 -0
  10. package/dist/lib/api-surface/analyzers/serverless.js +336 -0
  11. package/dist/lib/api-surface/analyzers/spring.js +237 -0
  12. package/dist/lib/api-surface/analyzers/terraform.js +109 -0
  13. package/dist/lib/api-surface/detect.js +25 -0
  14. package/dist/lib/api-surface/emit.js +109 -0
  15. package/dist/lib/api-surface/file-set.js +43 -0
  16. package/dist/lib/api-surface/index.js +134 -0
  17. package/dist/lib/api-surface/types.js +17 -0
  18. package/dist/lib/briefing/index.js +13 -0
  19. package/dist/lib/briefing/render.js +132 -0
  20. package/dist/lib/briefing/variables.js +92 -0
  21. package/dist/lib/catalogue/application-archetype/vocabulary.js +177 -0
  22. package/dist/lib/catalogue/archetype/maps/android.yaml +66 -0
  23. package/dist/lib/catalogue/archetype/maps/swiftui.yaml +58 -0
  24. package/dist/lib/catalogue/archetype/maps/uikit.yaml +48 -0
  25. package/dist/lib/catalogue/archetype/maps/web-generic.yaml +86 -0
  26. package/dist/lib/catalogue/archetype/openui-archetype-vocabulary.yaml +46 -0
  27. package/dist/lib/catalogue/archetype/resolver.js +103 -0
  28. package/dist/lib/catalogue/archetype/wireframe.js +418 -0
  29. package/dist/lib/catalogue/baseline-check.js +151 -0
  30. package/dist/lib/catalogue/build.js +1502 -0
  31. package/dist/lib/catalogue/builders/adr-supersedes.js +103 -0
  32. package/dist/lib/catalogue/builders/adrs.js +222 -0
  33. package/dist/lib/catalogue/builders/application-conformance-coverage.js +47 -0
  34. package/dist/lib/catalogue/builders/application-data-plane-bindings.js +115 -0
  35. package/dist/lib/catalogue/builders/c4-components.js +229 -0
  36. package/dist/lib/catalogue/builders/c4-containers.js +240 -0
  37. package/dist/lib/catalogue/builders/c4-entity-rollups.js +87 -0
  38. package/dist/lib/catalogue/builders/c4-external-systems.js +194 -0
  39. package/dist/lib/catalogue/builders/c4-l1-candidates.js +107 -0
  40. package/dist/lib/catalogue/builders/c4-systems.js +98 -0
  41. package/dist/lib/catalogue/builders/capabilities.js +488 -0
  42. package/dist/lib/catalogue/builders/capability-domain-model.js +74 -0
  43. package/dist/lib/catalogue/builders/capability-edges.js +256 -0
  44. package/dist/lib/catalogue/builders/capability-spec-walker.js +99 -0
  45. package/dist/lib/catalogue/builders/capability-spec.js +348 -0
  46. package/dist/lib/catalogue/builders/container-dependency.js +183 -0
  47. package/dist/lib/catalogue/builders/contracts.js +402 -0
  48. package/dist/lib/catalogue/builders/data-items.js +344 -0
  49. package/dist/lib/catalogue/builders/data-store-mapping.js +113 -0
  50. package/dist/lib/catalogue/builders/domain-models.js +175 -0
  51. package/dist/lib/catalogue/builders/domains.js +119 -0
  52. package/dist/lib/catalogue/builders/edge-label-merge.js +19 -0
  53. package/dist/lib/catalogue/builders/entities-manifest.js +160 -0
  54. package/dist/lib/catalogue/builders/entities-mermaid.js +189 -0
  55. package/dist/lib/catalogue/builders/entity-persistence.js +102 -0
  56. package/dist/lib/catalogue/builders/entity-slug.js +47 -0
  57. package/dist/lib/catalogue/builders/event-catalog-walker.js +186 -0
  58. package/dist/lib/catalogue/builders/event-edges.js +327 -0
  59. package/dist/lib/catalogue/builders/events.js +168 -0
  60. package/dist/lib/catalogue/builders/evidence-class.js +43 -0
  61. package/dist/lib/catalogue/builders/evidence-target-repo.js +67 -0
  62. package/dist/lib/catalogue/builders/external-system-exemption.js +120 -0
  63. package/dist/lib/catalogue/builders/feature-contract.js +77 -0
  64. package/dist/lib/catalogue/builders/feature-domain-model.js +50 -0
  65. package/dist/lib/catalogue/builders/feature-grounding-walker.js +254 -0
  66. package/dist/lib/catalogue/builders/feature-grounding.js +391 -0
  67. package/dist/lib/catalogue/builders/feature-groups.js +63 -0
  68. package/dist/lib/catalogue/builders/feature-subscription-channels.js +228 -0
  69. package/dist/lib/catalogue/builders/feature-tree-walker.js +295 -0
  70. package/dist/lib/catalogue/builders/features.js +300 -0
  71. package/dist/lib/catalogue/builders/glossary-xref.js +378 -0
  72. package/dist/lib/catalogue/builders/glossary.js +204 -0
  73. package/dist/lib/catalogue/builders/implementations.js +214 -0
  74. package/dist/lib/catalogue/builders/index.js +64 -0
  75. package/dist/lib/catalogue/builders/integration-components.js +344 -0
  76. package/dist/lib/catalogue/builders/integrations.js +181 -0
  77. package/dist/lib/catalogue/builders/persona-c4system.js +149 -0
  78. package/dist/lib/catalogue/builders/persona-container.js +133 -0
  79. package/dist/lib/catalogue/builders/persona-journey-edges.js +133 -0
  80. package/dist/lib/catalogue/builders/personas.js +152 -0
  81. package/dist/lib/catalogue/builders/product-edges.js +106 -0
  82. package/dist/lib/catalogue/builders/product-platform-dependencies.js +405 -0
  83. package/dist/lib/catalogue/builders/products.js +162 -0
  84. package/dist/lib/catalogue/builders/quality-scores.js +635 -0
  85. package/dist/lib/catalogue/builders/repo-capability-exemption.js +61 -0
  86. package/dist/lib/catalogue/builders/repo-dependency.js +127 -0
  87. package/dist/lib/catalogue/builders/repo-edges.js +340 -0
  88. package/dist/lib/catalogue/builders/repositories.js +458 -0
  89. package/dist/lib/catalogue/builders/scaffolds.js +197 -0
  90. package/dist/lib/catalogue/builders/screen-tree.js +222 -0
  91. package/dist/lib/catalogue/builders/screens.js +396 -0
  92. package/dist/lib/catalogue/builders/service-capability-exemption.js +63 -0
  93. package/dist/lib/catalogue/builders/service-contract-consumes.js +186 -0
  94. package/dist/lib/catalogue/builders/service-contract.js +74 -0
  95. package/dist/lib/catalogue/builders/service-entity-tables.js +187 -0
  96. package/dist/lib/catalogue/builders/services.js +232 -0
  97. package/dist/lib/catalogue/builders/system-external-dependency.js +115 -0
  98. package/dist/lib/catalogue/builders/user-journeys.js +253 -0
  99. package/dist/lib/catalogue/canonical-schema.yaml +4117 -0
  100. package/dist/lib/catalogue/cli-version.js +10 -0
  101. package/dist/lib/catalogue/contract-id.js +49 -0
  102. package/dist/lib/catalogue/coverage-predicates.js +603 -0
  103. package/dist/lib/catalogue/coverage-render.js +552 -0
  104. package/dist/lib/catalogue/coverage-run.js +115 -0
  105. package/dist/lib/catalogue/csv-reader.js +97 -0
  106. package/dist/lib/catalogue/csv-writer.js +96 -0
  107. package/dist/lib/catalogue/data-plane-coherence.js +77 -0
  108. package/dist/lib/catalogue/ddl-generator.js +233 -0
  109. package/dist/lib/catalogue/dedupe-keyed-tables.js +0 -0
  110. package/dist/lib/catalogue/engine-validator.js +239 -0
  111. package/dist/lib/catalogue/ext-id.js +76 -0
  112. package/dist/lib/catalogue/feature-grounding-aliases-loader.js +65 -0
  113. package/dist/lib/catalogue/feature-repo-zero-resolution-summary.js +31 -0
  114. package/dist/lib/catalogue/finding-identity.js +183 -0
  115. package/dist/lib/catalogue/findings.js +46 -0
  116. package/dist/lib/catalogue/fk-validator.js +136 -0
  117. package/dist/lib/catalogue/freshness.js +70 -0
  118. package/dist/lib/catalogue/gate-checks.js +338 -0
  119. package/dist/lib/catalogue/graph-projection.js +346 -0
  120. package/dist/lib/catalogue/impact-run.js +228 -0
  121. package/dist/lib/catalogue/manifest-loader.js +435 -0
  122. package/dist/lib/catalogue/platform-scope.js +7 -0
  123. package/dist/lib/catalogue/population-checks.js +87 -0
  124. package/dist/lib/catalogue/relationship-semantics.js +66 -0
  125. package/dist/lib/catalogue/reverse-product-quality.js +99 -0
  126. package/dist/lib/catalogue/rubric-coverage-map.yaml +871 -0
  127. package/dist/lib/catalogue/runway-vocabulary-loader.js +56 -0
  128. package/dist/lib/catalogue/scaffold-delta.js +261 -0
  129. package/dist/lib/catalogue/schema-compat.js +52 -0
  130. package/dist/lib/catalogue/schema-loader.js +87 -0
  131. package/dist/lib/catalogue/scores-coverage.js +573 -0
  132. package/dist/lib/catalogue/screen-validation-loader.js +89 -0
  133. package/dist/lib/catalogue/service-architecture-parser.js +193 -0
  134. package/dist/lib/catalogue/service-contract-aliases-loader.js +109 -0
  135. package/dist/lib/catalogue/staleness-verdicts.js +345 -0
  136. package/dist/lib/catalogue/traceability-loader.js +350 -0
  137. package/dist/lib/catalogue/validate.js +200 -0
  138. package/dist/lib/catalogue/version.js +18 -0
  139. package/dist/lib/conformance/binding.js +70 -0
  140. package/dist/lib/conformance/finding.js +69 -0
  141. package/dist/lib/conformance/index.js +578 -0
  142. package/dist/lib/context-pull/index.js +191 -0
  143. package/dist/lib/context-pull/resolve.js +70 -0
  144. package/dist/lib/context-pull/retired-mcp-setup.js +7 -0
  145. package/dist/lib/contracts-availability/index.js +267 -0
  146. package/dist/lib/generate-briefing/index.js +77 -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/pack/log.js +18 -0
  152. package/dist/lib/pack/schema.js +121 -0
  153. package/dist/lib/pack/seed.js +182 -0
  154. package/dist/lib/pack/validate.js +49 -0
  155. package/dist/lib/package-version.js +92 -0
  156. package/dist/lib/plan/index.js +69 -0
  157. package/dist/lib/plan/read-sdd.js +102 -0
  158. package/dist/lib/plan/render-template.js +84 -0
  159. package/dist/lib/repo-kind.js +129 -0
  160. package/dist/lib/scaffold/domain.js +234 -0
  161. package/dist/lib/scaffold/registry.js +136 -0
  162. package/dist/lib/scripts.js +7 -0
  163. package/dist/lib/sdd-index/repo-config.js +245 -0
  164. package/dist/lib/sdd-reader.js +91 -0
  165. package/dist/lib/snapshot/advance.js +454 -0
  166. package/dist/lib/snapshot/diff.js +190 -0
  167. package/dist/lib/snapshot/fold.js +208 -0
  168. package/dist/lib/snapshot/land.js +178 -0
  169. package/dist/lib/snapshot/manifest.js +206 -0
  170. package/dist/lib/snapshot/targets.js +169 -0
  171. package/dist/lib/snapshot/verify.js +91 -0
  172. package/dist/lib/sync/briefing-merge.js +106 -0
  173. package/dist/lib/sync/bundle-cache.js +109 -0
  174. package/dist/lib/sync/yaml-block-merge.js +120 -0
  175. package/dist/lib/validate/aggregate.js +51 -0
  176. package/dist/lib/validate/bundle-coherence.js +74 -0
  177. package/dist/lib/validate/dispatch.js +243 -0
  178. package/dist/lib/validate/index.js +110 -0
  179. package/dist/lib/validate/plan.js +54 -0
  180. package/dist/lib/validate/runner.js +85 -0
  181. package/dist/lib/validate/yaml-parse.js +112 -0
  182. package/dist/maintain-version.json +4 -0
  183. package/dist/verbs/api-surface.js +71 -0
  184. package/dist/verbs/catalogue-check.js +28 -0
  185. package/dist/verbs/catalogue-verify.js +114 -0
  186. package/dist/verbs/conformance.js +34 -0
  187. package/dist/verbs/context.js +39 -0
  188. package/dist/verbs/contracts.js +34 -0
  189. package/dist/verbs/generate-briefing.js +29 -0
  190. package/dist/verbs/list.js +45 -0
  191. package/dist/verbs/pack-validate.js +17 -0
  192. package/dist/verbs/path-option.js +25 -0
  193. package/dist/verbs/plan.js +42 -0
  194. package/dist/verbs/render.js +87 -0
  195. package/dist/verbs/scaffold.js +83 -0
  196. package/dist/verbs/snapshot.js +134 -0
  197. package/dist/verbs/validate.js +48 -0
  198. package/dist/verify-program.js +122 -0
  199. package/dist/verify-version.json +4 -0
  200. package/package.json +32 -4
  201. package/scripts/validate-app-dependencies.sh +664 -0
  202. package/scripts/validate-app-docs.sh +199 -0
  203. package/scripts/validate-integration-docs.sh +505 -0
@@ -0,0 +1,83 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { isMethodDomainArchetype, METHOD_DOMAIN_ARCHETYPES, scaffoldDomain, } from "../lib/scaffold/domain.js";
4
+ import { resolveArchetype } from "../lib/scaffold/registry.js";
5
+ import { resolvePathOption } from "./path-option.js";
6
+ const DOMAIN_NAME = /^[a-z][a-z0-9-]*$/;
7
+ export function registerScaffold(program) {
8
+ const scaffold = program
9
+ .command("scaffold")
10
+ .description("Scaffold method-shaped artefacts into an existing SDD repo (ADR 0173)");
11
+ scaffold
12
+ .command("domain <name>")
13
+ .description("Scaffold a platform domain (docs/domains/<name>/) into a platform-root SDD. " +
14
+ "Writes the generic domain shape; --archetype overlays starter content.")
15
+ .option("--archetype <id>", `seed from a domain archetype: method tier (${METHOD_DOMAIN_ARCHETYPES.join(" | ")}) ` +
16
+ "or a registry archetype from a consumed bundle (e.g. core/identity, " +
17
+ "or bundle-qualified '<bundle>:<id>' — ADR 0176)")
18
+ .option("--with-contracts", "include a contracts/ subfolder")
19
+ .option("--target-repo <dir>", "platform-root SDD repo", resolvePathOption, process.cwd())
20
+ .option("--dry-run", "report planned files without writing")
21
+ .action(async (name, opts) => {
22
+ if (!DOMAIN_NAME.test(name)) {
23
+ fail(`domain name '${name}' must be kebab-case (lowercase, digits, hyphens)`);
24
+ }
25
+ const targetRepo = opts.targetRepo ?? process.cwd();
26
+ await assertPlatformRoot(targetRepo);
27
+ // Archetype resolution chain (ADR 0176 §4.4): method tier is
28
+ // built in; anything else resolves against cached bundle
29
+ // registries — with a helpful listing on miss.
30
+ let registryArchetype;
31
+ if (opts.archetype !== undefined && !isMethodDomainArchetype(opts.archetype)) {
32
+ const resolution = await resolveArchetype(targetRepo, opts.archetype);
33
+ if (!resolution.ok || !resolution.archetype) {
34
+ fail(`${resolution.error ?? "archetype resolution failed"} ` +
35
+ `(method-tier archetypes: ${METHOD_DOMAIN_ARCHETYPES.join(", ")})`);
36
+ }
37
+ registryArchetype = resolution.archetype;
38
+ }
39
+ if (opts.dryRun === true) {
40
+ const label = registryArchetype
41
+ ? `${registryArchetype.bundleName}:${registryArchetype.id}`
42
+ : (opts.archetype ?? "none");
43
+ process.stdout.write(`[DRY-RUN] would scaffold docs/domains/${name}/ ` +
44
+ `(archetype: ${label}${opts.withContracts ? ", +contracts" : ""})\n`);
45
+ return;
46
+ }
47
+ const { filesWritten } = await scaffoldDomain({
48
+ name,
49
+ targetRepo,
50
+ ...(opts.archetype && isMethodDomainArchetype(opts.archetype)
51
+ ? { archetype: opts.archetype }
52
+ : {}),
53
+ ...(registryArchetype ? { registryArchetype } : {}),
54
+ ...(opts.withContracts === true ? { withContracts: true } : {}),
55
+ });
56
+ if (registryArchetype) {
57
+ process.stdout.write(`[INFO] archetype ${registryArchetype.bundleName}:${registryArchetype.id} ` +
58
+ `(tier: ${registryArchetype.tier}) — seed files copied; the domain is adopter-owned from creation\n`);
59
+ }
60
+ process.stdout.write(`[PASS] scaffolded domain '${name}' (${filesWritten.length} files):\n`);
61
+ for (const f of filesWritten)
62
+ process.stdout.write(` ${f}\n`);
63
+ });
64
+ }
65
+ function fail(message) {
66
+ process.stderr.write(`[FAIL] scaffold domain: ${message}\n`);
67
+ process.exit(1);
68
+ }
69
+ async function assertPlatformRoot(targetRepo) {
70
+ let kind = "";
71
+ try {
72
+ kind = (await readFile(join(targetRepo, ".sdd-repo-kind"), "utf8")).trim();
73
+ }
74
+ catch {
75
+ fail(`not an SDD repo (no .sdd-repo-kind in ${targetRepo}). ` +
76
+ "Run inside a platform-root SDD, or pass --target-repo.");
77
+ }
78
+ if (kind !== "platform-product") {
79
+ fail(`domains are scaffolded into a platform-root SDD, but .sdd-repo-kind is '${kind}'. ` +
80
+ "Domains live in the platform-root, not in application/integration SDDs.");
81
+ }
82
+ }
83
+ //# sourceMappingURL=scaffold.js.map
@@ -0,0 +1,134 @@
1
+ import { resolve } from "node:path";
2
+ import { runSnapshotAdvance } from "../lib/snapshot/advance.js";
3
+ import { runSnapshotDiff } from "../lib/snapshot/diff.js";
4
+ import { runSnapshotFold } from "../lib/snapshot/fold.js";
5
+ import { runSnapshotLand } from "../lib/snapshot/land.js";
6
+ import { runSnapshotTargets } from "../lib/snapshot/targets.js";
7
+ import { runSnapshotVerify } from "../lib/snapshot/verify.js";
8
+ const out = (s) => process.stdout.write(s);
9
+ const exit = ({ exitCode }) => {
10
+ if (exitCode !== 0)
11
+ process.exit(exitCode);
12
+ };
13
+ /** Repeatable `key=value` option → Map. The value may itself contain `=`. */
14
+ function collectPairs(value, prior) {
15
+ const i = value.indexOf("=");
16
+ if (i <= 0)
17
+ throw new Error(`expected key=value, got '${value}'`);
18
+ prior.set(value.slice(0, i), value.slice(i + 1));
19
+ return prior;
20
+ }
21
+ function collectList(value, prior) {
22
+ prior.push(value);
23
+ return prior;
24
+ }
25
+ /**
26
+ * `a=1,b=2` → object (for records like the credential scan and a waiver). A comma
27
+ * splits only where the next part starts a new `key=`, so free text — a
28
+ * disposition, a waiver's reason — may contain commas without being cut short.
29
+ */
30
+ export function record(value) {
31
+ if (value === undefined)
32
+ return undefined;
33
+ const o = {};
34
+ for (const part of value.split(/,(?=\s*[A-Za-z_]+=)/)) {
35
+ const i = part.indexOf("=");
36
+ if (i > 0)
37
+ o[part.slice(0, i).trim()] = part.slice(i + 1).trim();
38
+ }
39
+ return o;
40
+ }
41
+ export function registerSnapshot(program) {
42
+ const snapshot = program
43
+ .command("snapshot")
44
+ .description("Implementation-set snapshots: the deterministic steps of delta-reverse (M-ADR 0180 §2.7, M-ADR 0181 §2.5), run by the reverse-snapshot-delta skill");
45
+ snapshot
46
+ .command("fold <area>")
47
+ .description("Move a flat <repo>@<rev>/ area into its first dated baseline, write its manifest, and list every reference to the old paths")
48
+ .option("--id <date>", "the date the flat exports were OBSERVED (YYYY-MM-DD); no default")
49
+ .option("--implementation <id>", "the durable system identity")
50
+ .option("--key <folder=key>", "canonical_repo_key for a folder (repeatable)", collectPairs, new Map())
51
+ .option("--scan <root>", "a root to search for references to the old paths — scan the estate, not only the SDD (repeatable)", collectList, [])
52
+ .option("--sdd-path <path>", "the owning SDD: re-point its evidence pins into the baseline, take keys and role_hint from them")
53
+ .action(async (area, o) => exit(await runSnapshotFold({
54
+ areaRoot: resolve(area),
55
+ ...(o.id !== undefined ? { id: o.id } : {}),
56
+ ...(o.implementation !== undefined ? { implementation: o.implementation } : {}),
57
+ keys: o.key,
58
+ scanRoots: o.scan.map((r) => resolve(r)),
59
+ ...(o.sddPath !== undefined ? { sddPath: resolve(o.sddPath) } : {}),
60
+ }, out)));
61
+ snapshot
62
+ .command("land <area>")
63
+ .description("Write a new baseline's manifest: every prior member re-observed, carried (with a reason) or removed (with a reason); refuses without a recorded credential scan")
64
+ .option("--id <date>", "the date the snapshot was OBSERVED (YYYY-MM-DD); no default, so the processing date cannot slip in")
65
+ .option("--prior <date>", "the baseline this supersedes (default: the latest earlier one)")
66
+ .option("--implementation <id>", "the durable system identity (default: the prior baseline's)")
67
+ .option("--member-date <key=date>", "a member observed on another day than the set (repeatable)", collectPairs, new Map())
68
+ .option("--carried <key=reason>", "a prior member not re-exported, and why (repeatable)", collectPairs, new Map())
69
+ .option("--removed <key=reason>", "a prior member that left the set, and why (repeatable)", collectPairs, new Map())
70
+ .option("--key <folder=key>", "canonical_repo_key for a new member's folder (repeatable)", collectPairs, new Map())
71
+ .option("--sdd-path <path>", "the owning SDD: a derived key for a new member must be one of its repository ids")
72
+ .option("--role-hint <key=role>", "role_hint for a member; continuing members otherwise keep the prior baseline's (repeatable)", collectPairs, new Map())
73
+ .option("--credential-scan <record>", "tool=…,version=…,date=YYYY-MM-DD,result=clean — or result=<findings>,disposition=<what, and why it stands>")
74
+ .option("--notes <text>", "coherence caveats for the manifest")
75
+ .action(async (area, o) => {
76
+ const scan = record(o.credentialScan);
77
+ exit(await runSnapshotLand({
78
+ areaRoot: resolve(area),
79
+ ...(o.id !== undefined ? { id: o.id } : {}),
80
+ ...(o.prior !== undefined ? { prior: o.prior } : {}),
81
+ ...(o.implementation !== undefined ? { implementation: o.implementation } : {}),
82
+ ...(o.sddPath !== undefined ? { sddPath: resolve(o.sddPath) } : {}),
83
+ memberDates: o.memberDate,
84
+ carried: o.carried,
85
+ removed: o.removed,
86
+ keys: o.key,
87
+ roleHints: o.roleHint,
88
+ ...(scan ? { credentialScan: scan } : {}),
89
+ ...(o.notes !== undefined ? { notes: o.notes } : {}),
90
+ }, out));
91
+ });
92
+ snapshot
93
+ .command("verify <area>")
94
+ .description("Check a baseline's provenance: local folder/revision consistency here, canonical-repo confirmation supplied per member or waived on the record; cannot-assert FAILS")
95
+ .requiredOption("--id <date>", "the baseline to verify (normally T0)")
96
+ .option("--confirmed <key=how>", "how a member's revision was confirmed on its canonical repo (repeatable)", collectPairs, new Map())
97
+ .option("--waiver <record>", "who=…,why=…,date=YYYY-MM-DD — recorded in provenance.yaml and printed on every run")
98
+ .action(async (area, o) => {
99
+ const w = record(o.waiver);
100
+ exit(await runSnapshotVerify({ areaRoot: resolve(area), id: o.id, confirmed: o.confirmed, ...(w ? { waiver: w } : {}) }, out));
101
+ });
102
+ snapshot
103
+ .command("diff <area>")
104
+ .description("Classify members from the two manifests and diff changed members by evidence class into delta.yaml (status: proposed); refuses once any finding carries judgement")
105
+ .requiredOption("--to <date>", "the new baseline (T1)")
106
+ .option("--from <date>", "the prior baseline (default: T1's prior_snapshot)")
107
+ .action(async (area, o) => exit(await runSnapshotDiff({ areaRoot: resolve(area), to: o.to, ...(o.from !== undefined ? { from: o.from } : {}) }, out)));
108
+ snapshot
109
+ .command("targets <area>")
110
+ .description("Route each delta.yaml finding to the SDD artefacts that cite it, recording the grain (file | repo) of each route")
111
+ .requiredOption("--id <date>", "the baseline whose delta.yaml to route")
112
+ .option("--sdd-path <path>", "the SDD repo root (defaults to cwd)")
113
+ .option("--derived <glob>", "SDD-relative glob of GENERATED artefacts (scores, reports, registries) — marked to regenerate, not re-derive (repeatable)", collectList, [])
114
+ .action(async (area, o) => exit(await runSnapshotTargets({ areaRoot: resolve(area), id: o.id, sddPath: resolve(o.sddPath ?? process.cwd()), derived: o.derived }, out)));
115
+ snapshot
116
+ .command("advance <area>")
117
+ .description("Advance each member's evidence pin to the baseline and append one history entry; refuses before delta.yaml, without impact, on legacy history or an unknown reverse_status")
118
+ .requiredOption("--to <date>", "the baseline to advance to (T1)")
119
+ .option("--sdd-path <path>", "the SDD repo root (defaults to cwd)")
120
+ .option("--member <key>", "limit to these members (repeatable)", collectList, [])
121
+ .option("--migrate-history", "convert legacy entries: histories to history[] first (phase: scan rows only)")
122
+ .option("--record-only", "for a pin already moved to --to by hand: write its history row, leave the pin")
123
+ .option("--notes <key=text>", "prose for a member's history row, beside the notes composed from its findings (repeatable)", collectPairs, new Map())
124
+ .action(async (area, o) => exit(await runSnapshotAdvance({
125
+ areaRoot: resolve(area),
126
+ to: o.to,
127
+ sddPath: resolve(o.sddPath ?? process.cwd()),
128
+ ...(o.member.length > 0 ? { members: o.member } : {}),
129
+ migrateHistory: o.migrateHistory === true,
130
+ recordOnly: o.recordOnly === true,
131
+ notes: o.notes,
132
+ }, out)));
133
+ }
134
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1,48 @@
1
+ import { runValidate } from "../lib/validate/index.js";
2
+ import { methodValidationPlan } from "../lib/validate/plan.js";
3
+ import { profileFromRepoKind, readRepoKind } from "../lib/repo-kind.js";
4
+ const LISTABLE = ["platform", "application", "integration"];
5
+ const isListable = (p) => LISTABLE.includes(p);
6
+ import { resolvePathOption } from "./path-option.js";
7
+ export function registerValidate(program) {
8
+ program
9
+ .command("validate")
10
+ .description("Run the method-level validation suite for this SDD repository")
11
+ .option("--target-repo <dir>", "target SDD repo", resolvePathOption, process.cwd())
12
+ .option("--platform-root <dir>", "path to the sdd-method (or platform) repo, required for app-dependencies", resolvePathOption)
13
+ .option("--validator <name>", "run only the named validator")
14
+ .option("--strict", "treat warnings as failures")
15
+ .option("--list", "print the method-managed validation job for this repo's profile as JSON (the plan every CI executor runs, the Dagger module included) and run nothing")
16
+ .option("--profile <profile>", "with --list: the profile to list, instead of reading .sdd-repo-kind (platform | application | integration)")
17
+ .action(async (opts) => {
18
+ if (opts.list === true) {
19
+ let profile;
20
+ if (opts.profile !== undefined) {
21
+ if (!isListable(opts.profile)) {
22
+ process.stderr.write(`--profile must be platform, application or integration (got: ${opts.profile})\n`);
23
+ process.exit(2);
24
+ }
25
+ profile = opts.profile;
26
+ }
27
+ else {
28
+ const kind = await readRepoKind(opts.targetRepo);
29
+ if (kind === null) {
30
+ process.stderr.write(`Not an SDD repo (no .sdd-repo-kind in ${opts.targetRepo}); pass --profile\n`);
31
+ process.exit(1);
32
+ }
33
+ profile = profileFromRepoKind(kind);
34
+ }
35
+ process.stdout.write(JSON.stringify({ profile, steps: methodValidationPlan(profile) }, null, 2) + "\n");
36
+ return;
37
+ }
38
+ const { exitCode } = await runValidate({
39
+ targetRepo: opts.targetRepo,
40
+ ...(opts.platformRoot ? { platformRoot: opts.platformRoot } : {}),
41
+ ...(opts.validator ? { validator: opts.validator } : {}),
42
+ strict: opts.strict === true,
43
+ });
44
+ if (exitCode !== 0)
45
+ process.exit(exitCode);
46
+ });
47
+ }
48
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1,122 @@
1
+ // Third entrypoint: the VERIFY surface — M-ADR 0212 §4.3b.
2
+ //
3
+ // A binary that CANNOT WRITE to the repository it is pointed at. That is the
4
+ // whole property, and it is the one a pipeline can rely on: whatever runs
5
+ // `sdd-verify` in CI can judge a repository and cannot change it.
6
+ //
7
+ // Two criteria admit a verb here, and both are required:
8
+ // 1. it does not write to the target repository — TESTED, not read from a
9
+ // description: the package acceptance check runs every verb in every mode
10
+ // against a clean checkout and requires `git status --porcelain` to be
11
+ // empty. Reading help text misfiled four verbs before that test existed
12
+ // (`sync`, `render`, `catalogue graph`, `metamodel roundtrip`).
13
+ // 2. it has something to act on in an adopter repository today. A read-only
14
+ // verb can fail this and pass (1): `metamodel roundtrip` is producer-only,
15
+ // `catalogue migration-map` serves a finished migration. Neither is here.
16
+ //
17
+ // ⚠ The boundary is ABSENCE, not a menu. The package ships only the import
18
+ // closure of this file, so an excluded verb's code is not present to be reached
19
+ // by any path — including `mcp serve`, which exposes the SDD as tools and would
20
+ // hand authoring back through a second door. That is why registration imports
21
+ // per-subcommand registrars (`catalogue-verify.ts`, `pack-validate.ts`) and never
22
+ // a barrel that re-exports a build path.
23
+ //
24
+ // Verbs are the SAME registrars the full CLI uses: one implementation, two
25
+ // surfaces, so behaviour cannot drift between them.
26
+ import { Command, CommanderError } from "commander";
27
+ import { getPackageVersion } from "./lib/package-version.js";
28
+ import { registerCatalogueBaselineCheck, registerCatalogueImpact, registerCatalogueValidate, registerCatalogueVersion, } from "./verbs/catalogue-verify.js";
29
+ import { registerList } from "./verbs/list.js";
30
+ import { registerPackValidate } from "./verbs/pack-validate.js";
31
+ import { registerValidate } from "./verbs/validate.js";
32
+ const SPEC_URL = "https://github.com/tomfosteruk/sdd-method/blob/main/docs/method/cli/sdd-cli-specification.md";
33
+ /** The full surface, as `<verb>` or `<verb> <subcommand>`. Asserted by test. */
34
+ export const VERIFY_SURFACE = [
35
+ "validate",
36
+ "list",
37
+ "pack validate",
38
+ "catalogue validate",
39
+ "catalogue impact",
40
+ "catalogue baseline-check",
41
+ "catalogue version",
42
+ ];
43
+ const OUTSIDE = "is not part of sdd-verify, which cannot write to the repository it is pointed at. " +
44
+ "Authoring and maintenance verbs are in @sdd-method/sdd-cli.";
45
+ /**
46
+ * Refuse anything outside the surface BEFORE commander parses it. Left to
47
+ * commander, `sdd-verify sync --help` prints top-level usage and exits 0 — in a
48
+ * pipeline that is a step that runs nothing and passes, which is the failure
49
+ * this binary exists to prevent. So an excluded verb fails, loudly, whatever
50
+ * flags accompany it.
51
+ */
52
+ export function rejectOutsideSurface(program, argv, outside = OUTSIDE) {
53
+ const words = argv.filter((a) => !a.startsWith("-"));
54
+ if (words.length === 0)
55
+ return;
56
+ const [verb, sub] = words;
57
+ if (verb === "help")
58
+ return;
59
+ const cmd = program.commands.find((c) => c.name() === verb);
60
+ if (!cmd)
61
+ throw new Error(`'${verb}' ${outside}`);
62
+ const subs = cmd.commands.map((c) => c.name()).filter((n) => n !== "help");
63
+ if (subs.length > 0 && sub !== undefined && sub !== "help" && !subs.includes(sub)) {
64
+ throw new Error(`'${verb} ${sub}' ${outside}`);
65
+ }
66
+ }
67
+ export async function runVerify(argv) {
68
+ const program = buildVerifyProgram();
69
+ if (argv.length === 0) {
70
+ program.outputHelp();
71
+ return;
72
+ }
73
+ rejectOutsideSurface(program, argv);
74
+ try {
75
+ await program.parseAsync([...argv], { from: "user" });
76
+ }
77
+ catch (err) {
78
+ if (err instanceof CommanderError) {
79
+ if (err.code === "commander.help" ||
80
+ err.code === "commander.helpDisplayed" ||
81
+ err.code === "commander.version") {
82
+ return;
83
+ }
84
+ }
85
+ throw err;
86
+ }
87
+ }
88
+ export function buildVerifyProgram() {
89
+ const program = new Command();
90
+ program
91
+ .name("sdd-verify")
92
+ .description("Verify an SDD repository without changing it — validate, list, and read-only catalogue and pack checks. Cannot write to the repository it is pointed at.")
93
+ .version(getPackageVersion(), "-v, --version")
94
+ .addHelpText("after", `\nSpec: ${SPEC_URL}\nAuthoring and maintenance verbs (sync, catalogue build, init, scaffold, …) are in @sdd-method/sdd-cli.`)
95
+ .exitOverride()
96
+ .configureOutput({
97
+ writeOut: (str) => process.stdout.write(str),
98
+ writeErr: (str) => process.stderr.write(str),
99
+ });
100
+ registerVerifySurface(program);
101
+ return program;
102
+ }
103
+ /**
104
+ * The verify verbs, registered onto any program. sdd-verify calls it; sdd-maintain calls it too,
105
+ * which is what makes the personas nest structurally: whatever verify ships, maintain ships.
106
+ */
107
+ export function registerVerifySurface(program) {
108
+ registerValidate(program);
109
+ registerList(program);
110
+ const pack = program
111
+ .command("pack")
112
+ .description("Validate adopter-shipped context-pack seeds (ADR 0151) — read-only");
113
+ registerPackValidate(pack);
114
+ const catalogue = program
115
+ .command("catalogue")
116
+ .description("Validate and query per-SDD catalogues (ADR 0134) — read-only, never rebuilds");
117
+ registerCatalogueValidate(catalogue);
118
+ registerCatalogueImpact(catalogue);
119
+ registerCatalogueBaselineCheck(catalogue);
120
+ registerCatalogueVersion(catalogue);
121
+ }
122
+ //# sourceMappingURL=verify-program.js.map
@@ -0,0 +1,4 @@
1
+ {
2
+ "version": "1.2.0",
3
+ "built_against_sdd_cli": "1.43.0"
4
+ }
package/package.json CHANGED
@@ -1,6 +1,34 @@
1
1
  {
2
2
  "name": "@sdd-method/author-cli",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "sddCliVersion": "1.43.0",
5
+ "description": "Re-author one SDD's content — scaffold, plan, contracts, conformance, api-surface, snapshots, briefings, catalogue check — plus every read-only verify verb. Ships only the code those verbs reach; it cannot sync the baseline or rebuild the catalogues. Maintenance is in @sdd-method/maintain-cli, administration in @sdd-method/sdd-cli.",
6
+ "license": "Apache-2.0",
7
+ "type": "module",
8
+ "bin": {
9
+ "sdd-author": "dist/author-bin.js"
10
+ },
11
+ "engines": {
12
+ "node": ">=20.0.0"
13
+ },
14
+ "dependencies": {
15
+ "commander": "^12.1.0",
16
+ "yaml": "^2.5.0",
17
+ "zod": "^4.3.6",
18
+ "@duckdb/node-api": "^1.5.5-r.3"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/tomfosteruk/sdd-cli.git"
23
+ },
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "scripts",
30
+ "README.md",
31
+ "LICENSE",
32
+ "NOTICE"
33
+ ]
34
+ }