@sdd-method/author-cli 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +1 -1
- package/dist/author-program.js +1 -1
- package/dist/lib/catalogue/build.js +1 -1
- package/dist/lib/catalogue/builders/c4-components.js +1 -1
- package/dist/lib/catalogue/builders/c4-containers.js +1 -1
- package/dist/lib/catalogue/builders/c4-l1-candidates.js +1 -1
- package/dist/lib/catalogue/builders/container-dependency.js +1 -1
- package/dist/lib/catalogue/builders/data-store-mapping.js +1 -1
- package/dist/lib/catalogue/builders/screen-tree.js +1 -1
- package/dist/lib/catalogue/dedupe-keyed-tables.js +0 -0
- package/dist/lib/catalogue/scores-coverage.js +1 -1
- package/dist/lib/catalogue/service-contract-aliases-loader.js +1 -1
- package/dist/lib/lock-file.js +10 -0
- package/dist/lib/snapshot/targets.js +1 -1
- package/dist/lib/validate/plan.js +6 -3
- package/dist/maintain-version.json +2 -2
- package/dist/verbs/plan.js +1 -1
- package/dist/verbs/validate.js +6 -1
- package/dist/verify-program.js +1 -1
- package/dist/verify-version.json +2 -2
- package/package.json +2 -6
package/NOTICE
CHANGED
|
@@ -2,7 +2,7 @@ sdd-cli
|
|
|
2
2
|
Copyright 2026 Tom Foster
|
|
3
3
|
|
|
4
4
|
This product includes software developed as part of the SDD method
|
|
5
|
-
distribution
|
|
5
|
+
distribution.
|
|
6
6
|
|
|
7
7
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
8
|
you may not use this file except in compliance with the License.
|
package/dist/author-program.js
CHANGED
|
@@ -26,7 +26,7 @@ import { registerPlan } from "./verbs/plan.js";
|
|
|
26
26
|
import { registerRender } from "./verbs/render.js";
|
|
27
27
|
import { registerScaffold } from "./verbs/scaffold.js";
|
|
28
28
|
import { registerSnapshot } from "./verbs/snapshot.js";
|
|
29
|
-
const SPEC_URL = "
|
|
29
|
+
const SPEC_URL = "docs/method/cli/sdd-cli-specification.md (in the method distribution)";
|
|
30
30
|
/** The verbs the author adds to verify, as `<verb>` or `<verb> <subcommand>` (M-ADR 0220 §4.2). Asserted by test. */
|
|
31
31
|
export const AUTHOR_ONLY_SURFACE = [
|
|
32
32
|
"scaffold domain",
|
|
@@ -1158,7 +1158,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
|
|
|
1158
1158
|
out.set("repo_dependency", await buildRepoDependencies({ sddPath, configs: reposResult.configs, knownRepoIds: knownRepoIdsFinal, findings }));
|
|
1159
1159
|
// 15. C4 systems + containers + components (L1 + L2 + L3). The L3 walker
|
|
1160
1160
|
// shipped per `coordination/c4-l3-walker-and-path-convention-coordination.md`
|
|
1161
|
-
// (
|
|
1161
|
+
// (method governance, 2026-05-29) — forward-method authoring path reading
|
|
1162
1162
|
// `c4-l3-*.mermaid.md` files alongside the L2 layout. The earlier Path-B
|
|
1163
1163
|
// deferral assumed reverse-method code-walking; this walker is the
|
|
1164
1164
|
// forward-method analogue, granularity-agnostic (per-container or
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
//
|
|
7
7
|
// Mirrors c4-containers.ts at one level down. Source convention per
|
|
8
8
|
// `coordination/c4-l3-walker-and-path-convention-coordination.md`
|
|
9
|
-
// (
|
|
9
|
+
// (method governance, 2026-05-29). The walker is granularity-agnostic — both
|
|
10
10
|
// per-container files (one `Container_Boundary` block per file) and
|
|
11
11
|
// per-domain rollup files (multiple `Container_Boundary` blocks per file)
|
|
12
12
|
// produce identical row output. Adopters pick the file shape that suits
|
|
@@ -219,7 +219,7 @@ function slugify(s) {
|
|
|
219
219
|
}
|
|
220
220
|
/**
|
|
221
221
|
* F21: two technology strings flatly contradict when both are present and
|
|
222
|
-
* share no token — ".NET 6 (in
|
|
222
|
+
* share no token — ".NET 6 (in Kestrel)" vs "Java" needs no NLP. Absent or
|
|
223
223
|
* overlapping strings are NOT a contradiction (silence, not a guess).
|
|
224
224
|
*/
|
|
225
225
|
export function techContradicts(a, b) {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
// personas instead of the sibling's. c4-external-systems UNIONS every
|
|
21
21
|
// existing L1 file rather than picking one, so candidate order is irrelevant
|
|
22
22
|
// there; it shares these paths only to avoid a divergent copy.
|
|
23
|
-
// See
|
|
23
|
+
// See the method's coordination record persona-c4system-l1-priority-bug.
|
|
24
24
|
import { readdir, stat } from "node:fs/promises";
|
|
25
25
|
import { join } from "node:path";
|
|
26
26
|
/** Own-L1 candidates usable by ANY SDD, in priority order. */
|
|
@@ -121,7 +121,7 @@ export async function buildContainerDependency(inputs) {
|
|
|
121
121
|
* SAME referent and fired. The predicate was inverted on the two
|
|
122
122
|
* name-shapes the estate actually uses.
|
|
123
123
|
*
|
|
124
|
-
* The independent channel is the technology string: ".NET 6 (in
|
|
124
|
+
* The independent channel is the technology string: ".NET 6 (in Kestrel)"
|
|
125
125
|
* against "Java" is a flat contradiction and needs no NLP. A dual-use
|
|
126
126
|
* entry-id (Container + System_Ext in one SDD) whose technologies
|
|
127
127
|
* contradict draws the finding REGARDLESS of what the names say — name
|
|
@@ -71,7 +71,7 @@ export function collectTableLines(lines, startIdx) {
|
|
|
71
71
|
return null;
|
|
72
72
|
}
|
|
73
73
|
// ADR 0164: map a Data Store Mapping `Store` cell (a physical engine such as
|
|
74
|
-
// "MySQL (
|
|
74
|
+
// "MySQL (orders-db)", "MongoDB", "DynamoDB", "Kinesis") to the canonical
|
|
75
75
|
// `entities.persistence_kind` classification. This mirrors the services
|
|
76
76
|
// builder's deriveLanguage (a normalised token derived from a raw cell) —
|
|
77
77
|
// faithful classification, not a verbatim engine. The raw engine string is
|
|
@@ -35,7 +35,7 @@ const STRING_RE = /"[^"]*"|'[^']*'/g;
|
|
|
35
35
|
* line-structure-preserving) so call-head lexing can never fire on quoted
|
|
36
36
|
* content — `Table("Odometer (km)")` must not mint a phantom `Odometer`
|
|
37
37
|
* component, and `"total (sum)"` must not false-fire the lowercase-call-head
|
|
38
|
-
* finding (
|
|
38
|
+
* finding (sdd-cli issue 1). Quote characters are kept; newlines inside
|
|
39
39
|
* a span survive. The grammar defines no escape sequences (a quote always
|
|
40
40
|
* closes the literal), matching STRING_RE and stripLineComment.
|
|
41
41
|
*
|
|
Binary file
|
|
@@ -171,7 +171,7 @@ export const RUBRIC_ELIGIBILITY = [
|
|
|
171
171
|
joinColumn: "id",
|
|
172
172
|
refTransform: null,
|
|
173
173
|
eligibilityFilter: null,
|
|
174
|
-
eligibilityNote: "NO local population, measured rather than assumed. Refs are '<domain>-feature-grounding-<slug>' and the tails are SIBLING SDD SLUGS (app-shell,
|
|
174
|
+
eligibilityNote: "NO local population, measured rather than assumed. Refs are '<domain>-feature-grounding-<slug>' and the tails are SIBLING SDD SLUGS (app-shell, gift-cards, storefront-express), not rows in this SDD: 0/15 against products, applications, features and repositories, and 1/15 against capabilities — a coincidence, not a join. A cross-SDD reference the member tier cannot resolve, so its coverage is declared unmeasurable rather than given a transform that would produce plausible wrong numbers.",
|
|
175
175
|
},
|
|
176
176
|
{
|
|
177
177
|
rubricId: "reverse-contract-quality",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* # services). Use when the federated SDD lacks a services.csv to
|
|
28
28
|
* # gate emission and consumes rows would otherwise dangle at the
|
|
29
29
|
* # aggregator with unresolved service_id.
|
|
30
|
-
* - postman-
|
|
30
|
+
* - postman-stock
|
|
31
31
|
* - smoke-tests
|
|
32
32
|
*
|
|
33
33
|
* same_product_inference:
|
package/dist/lib/lock-file.js
CHANGED
|
@@ -66,6 +66,8 @@ export function serialiseLockFile(lock) {
|
|
|
66
66
|
...(lock.ciRunner !== undefined ? [`ci_runner: "${lock.ciRunner}"`] : []),
|
|
67
67
|
...(lock.ciWorkflowBlockSha256 !== undefined ? [`ci_workflow_block_sha256: "${lock.ciWorkflowBlockSha256}"`] : []),
|
|
68
68
|
...(lock.ciModuleSha256 !== undefined ? [`ci_module_sha256: "${lock.ciModuleSha256}"`] : []),
|
|
69
|
+
...(lock.cliSource !== undefined ? [`cli_source: ${lock.cliSource}`] : []),
|
|
70
|
+
...(lock.cliPackage !== undefined ? [`cli_package: "${lock.cliPackage}"`] : []),
|
|
69
71
|
"bundles:",
|
|
70
72
|
];
|
|
71
73
|
for (const b of lock.bundles) {
|
|
@@ -117,6 +119,8 @@ function parseVersioned(raw) {
|
|
|
117
119
|
let ciBinding;
|
|
118
120
|
let ciRunner;
|
|
119
121
|
let ciModuleSha256;
|
|
122
|
+
let cliSource;
|
|
123
|
+
let cliPackage;
|
|
120
124
|
const bundles = [];
|
|
121
125
|
let inBundles = false;
|
|
122
126
|
let inPaths = false;
|
|
@@ -186,6 +190,10 @@ function parseVersioned(raw) {
|
|
|
186
190
|
ciRunner = stripQuotes(value);
|
|
187
191
|
else if (key === "ci_module_sha256")
|
|
188
192
|
ciModuleSha256 = stripQuotes(value);
|
|
193
|
+
else if (key === "cli_source")
|
|
194
|
+
cliSource = stripQuotes(value);
|
|
195
|
+
else if (key === "cli_package")
|
|
196
|
+
cliPackage = stripQuotes(value);
|
|
189
197
|
}
|
|
190
198
|
continue;
|
|
191
199
|
}
|
|
@@ -313,6 +321,8 @@ function parseVersioned(raw) {
|
|
|
313
321
|
...(ciRunner !== undefined ? { ciRunner } : {}),
|
|
314
322
|
...(ciWorkflowBlockSha256 !== undefined ? { ciWorkflowBlockSha256 } : {}),
|
|
315
323
|
...(ciModuleSha256 !== undefined ? { ciModuleSha256 } : {}),
|
|
324
|
+
...(cliSource !== undefined ? { cliSource } : {}),
|
|
325
|
+
...(cliPackage !== undefined ? { cliPackage } : {}),
|
|
316
326
|
};
|
|
317
327
|
}
|
|
318
328
|
function migrateV1(raw, legacyBundleName) {
|
|
@@ -68,7 +68,7 @@ export function routeFinding(f, artefacts, shared = new Set()) {
|
|
|
68
68
|
const targets = new Map();
|
|
69
69
|
const paths = [...f.files.added, ...f.files.removed, ...f.files.modified].filter(citable);
|
|
70
70
|
// The key alone, or in export-folder form (`<key>-master@<rev>`): a hyphen may
|
|
71
|
-
// follow it only as a branch suffix, so `
|
|
71
|
+
// follow it only as a branch suffix, so `scanner` never matches inside `scanner-collector`.
|
|
72
72
|
const keyRe = new RegExp(`(^|[^A-Za-z0-9_-])${f.member.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(-(master|main|develop|trunk)@|[^A-Za-z0-9_-]|$)`);
|
|
73
73
|
const cites = (text, p) => shared.has(p) ? text.split("\n").some((line) => line.includes(p) && keyRe.test(line)) : text.includes(p);
|
|
74
74
|
// Folder-qualified — `<key>-<branch>@<rev>/<path>` — names the member AND the file,
|
|
@@ -25,7 +25,7 @@ const TITLES = {
|
|
|
25
25
|
// CI has no platform checkout, so this step runs the app-only checks; the met gate needs the platform beside it.
|
|
26
26
|
"app-dependencies": "Validate app dependencies (app-only checks; no platform checkout in CI)",
|
|
27
27
|
};
|
|
28
|
-
export function methodValidationPlan(profile) {
|
|
28
|
+
export function methodValidationPlan(profile, opts = {}) {
|
|
29
29
|
const steps = validatorsForProfile(profile)
|
|
30
30
|
.filter((v) => v.optional !== true)
|
|
31
31
|
.map((v) => ({
|
|
@@ -38,12 +38,15 @@ export function methodValidationPlan(profile) {
|
|
|
38
38
|
if (profile === "platform") {
|
|
39
39
|
steps.push({ id: "cascade-completeness", title: "Validate cascade completeness", tool: "bash", args: ["orchestration/scripts/validate-cascade-completeness.sh", "all"], advisory: false }, { id: "architecture-alignment", title: "Validate architecture alignment", tool: "bash", args: ["orchestration/scripts/validate-architecture-alignment.sh"], advisory: false });
|
|
40
40
|
}
|
|
41
|
+
const gating = opts.catalogueRebuild === true;
|
|
41
42
|
steps.push({
|
|
42
43
|
id: "catalogue-freshness",
|
|
43
|
-
title:
|
|
44
|
+
title: gating
|
|
45
|
+
? "Check catalogues reproduce from the specs (gating: the pipeline rebuilt them)"
|
|
46
|
+
: "Check catalogues reproduce from the specs (advisory)",
|
|
44
47
|
tool: "sdd-maintain",
|
|
45
48
|
args: ["catalogue", "build", "--check", "--sdd-path", "."],
|
|
46
|
-
advisory:
|
|
49
|
+
advisory: !gating,
|
|
47
50
|
});
|
|
48
51
|
return steps;
|
|
49
52
|
}
|
package/dist/verbs/plan.js
CHANGED
|
@@ -5,7 +5,7 @@ export function registerPlan(program) {
|
|
|
5
5
|
.command("plan")
|
|
6
6
|
.description("Scaffold a plan markdown file from a method-distributed template. Currently supports --pilot for pilot-kickoff plans; future subcommands may add --initiative / --migration.")
|
|
7
7
|
.option("--pilot", "scaffold a pilot-kickoff plan (requires --service, --capability, --domain)", false)
|
|
8
|
-
.option("--service <name>", "service / pilot name, e.g.
|
|
8
|
+
.option("--service <name>", "service / pilot name, e.g. customer-management")
|
|
9
9
|
.option("--capability <name>", "capability under test, e.g. organization-management")
|
|
10
10
|
.option("--domain <name>", "domain the capability belongs to, e.g. party")
|
|
11
11
|
.option("--workspace-root <path>", "SDD root (defaults to cwd)", resolvePathOption)
|
package/dist/verbs/validate.js
CHANGED
|
@@ -14,7 +14,12 @@ export function registerValidate(program) {
|
|
|
14
14
|
.option("--strict", "treat warnings as failures")
|
|
15
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
16
|
.option("--profile <profile>", "with --list: the profile to list, instead of reading .sdd-repo-kind (platform | application | integration)")
|
|
17
|
+
.option("--catalogue-rebuild", "with --list: the pipeline rebuilt the catalogues on this run (M-ADR 0220 §4.4), so the catalogue freshness step gates instead of advising")
|
|
17
18
|
.action(async (opts) => {
|
|
19
|
+
if (opts.catalogueRebuild === true && opts.list !== true) {
|
|
20
|
+
process.stderr.write("--catalogue-rebuild only applies with --list\n");
|
|
21
|
+
process.exit(2);
|
|
22
|
+
}
|
|
18
23
|
if (opts.list === true) {
|
|
19
24
|
let profile;
|
|
20
25
|
if (opts.profile !== undefined) {
|
|
@@ -32,7 +37,7 @@ export function registerValidate(program) {
|
|
|
32
37
|
}
|
|
33
38
|
profile = profileFromRepoKind(kind);
|
|
34
39
|
}
|
|
35
|
-
process.stdout.write(JSON.stringify({ profile, steps: methodValidationPlan(profile) }, null, 2) + "\n");
|
|
40
|
+
process.stdout.write(JSON.stringify({ profile, steps: methodValidationPlan(profile, { catalogueRebuild: opts.catalogueRebuild === true }) }, null, 2) + "\n");
|
|
36
41
|
return;
|
|
37
42
|
}
|
|
38
43
|
const { exitCode } = await runValidate({
|
package/dist/verify-program.js
CHANGED
|
@@ -29,7 +29,7 @@ import { registerCatalogueBaselineCheck, registerCatalogueImpact, registerCatalo
|
|
|
29
29
|
import { registerList } from "./verbs/list.js";
|
|
30
30
|
import { registerPackValidate } from "./verbs/pack-validate.js";
|
|
31
31
|
import { registerValidate } from "./verbs/validate.js";
|
|
32
|
-
const SPEC_URL = "
|
|
32
|
+
const SPEC_URL = "docs/method/cli/sdd-cli-specification.md (in the method distribution)";
|
|
33
33
|
/** The full surface, as `<verb>` or `<verb> <subcommand>`. Asserted by test. */
|
|
34
34
|
export const VERIFY_SURFACE = [
|
|
35
35
|
"validate",
|
package/dist/verify-version.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdd-method/author-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"sddCliVersion": "1.
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"sddCliVersion": "1.44.0",
|
|
5
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
6
|
"license": "Apache-2.0",
|
|
7
7
|
"type": "module",
|
|
@@ -17,10 +17,6 @@
|
|
|
17
17
|
"zod": "^4.3.6",
|
|
18
18
|
"@duckdb/node-api": "^1.5.5-r.3"
|
|
19
19
|
},
|
|
20
|
-
"repository": {
|
|
21
|
-
"type": "git",
|
|
22
|
-
"url": "git+https://github.com/tomfosteruk/sdd-cli.git"
|
|
23
|
-
},
|
|
24
20
|
"publishConfig": {
|
|
25
21
|
"access": "public"
|
|
26
22
|
},
|