@sdd-method/sdd-cli 1.46.0 → 2.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.
- package/dist/author-program.d.ts.map +1 -1
- package/dist/author-program.js +3 -0
- package/dist/author-program.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/behaviour-store/archive.d.ts +40 -0
- package/dist/lib/behaviour-store/archive.d.ts.map +1 -0
- package/dist/lib/behaviour-store/archive.js +180 -0
- package/dist/lib/behaviour-store/archive.js.map +1 -0
- package/dist/lib/catalogue/build.d.ts.map +1 -1
- package/dist/lib/catalogue/build.js +18 -1
- package/dist/lib/catalogue/build.js.map +1 -1
- package/dist/lib/catalogue/builders/capabilities.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/capabilities.js +4 -1
- package/dist/lib/catalogue/builders/capabilities.js.map +1 -1
- package/dist/lib/catalogue/builders/events.d.ts +1 -0
- package/dist/lib/catalogue/builders/events.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/events.js +12 -5
- package/dist/lib/catalogue/builders/events.js.map +1 -1
- package/dist/lib/catalogue/builders/product-edges.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/product-edges.js +3 -1
- package/dist/lib/catalogue/builders/product-edges.js.map +1 -1
- package/dist/lib/catalogue/builders/product-platform-dependencies.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/product-platform-dependencies.js +16 -1
- package/dist/lib/catalogue/builders/product-platform-dependencies.js.map +1 -1
- package/dist/lib/catalogue/builders/repo-edges.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/repo-edges.js +4 -3
- package/dist/lib/catalogue/builders/repo-edges.js.map +1 -1
- package/dist/lib/catalogue/builders/repositories.d.ts +2 -0
- package/dist/lib/catalogue/builders/repositories.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/repositories.js +6 -0
- package/dist/lib/catalogue/builders/repositories.js.map +1 -1
- package/dist/lib/catalogue/builders/requirements.d.ts +19 -0
- package/dist/lib/catalogue/builders/requirements.d.ts.map +1 -0
- package/dist/lib/catalogue/builders/requirements.js +208 -0
- package/dist/lib/catalogue/builders/requirements.js.map +1 -0
- package/dist/lib/catalogue/builders/service-contract.d.ts +1 -1
- package/dist/lib/catalogue/builders/service-contract.d.ts.map +1 -1
- package/dist/lib/catalogue/builders/service-contract.js +6 -9
- package/dist/lib/catalogue/builders/service-contract.js.map +1 -1
- package/dist/lib/catalogue/canonical-schema.yaml +160 -7
- package/dist/lib/catalogue/rubric-coverage-map.yaml +36 -0
- package/dist/lib/catalogue/schema-compat.d.ts +1 -1
- package/dist/lib/catalogue/schema-compat.js +1 -1
- package/dist/lib/init/app.js +2 -2
- package/dist/lib/sdd-index/repo-config.d.ts.map +1 -1
- package/dist/lib/sdd-index/repo-config.js +7 -2
- package/dist/lib/sdd-index/repo-config.js.map +1 -1
- package/dist/lib/sdd-index/types.d.ts +1 -1
- package/dist/lib/validate/behaviour-store.d.ts.map +1 -1
- package/dist/lib/validate/behaviour-store.js +112 -1
- package/dist/lib/validate/behaviour-store.js.map +1 -1
- package/dist/lib/vocabulary/migrate.d.ts +23 -0
- package/dist/lib/vocabulary/migrate.d.ts.map +1 -0
- package/dist/lib/vocabulary/migrate.js +237 -0
- package/dist/lib/vocabulary/migrate.js.map +1 -0
- package/dist/lib/vocabulary/renames.d.ts +20 -0
- package/dist/lib/vocabulary/renames.d.ts.map +1 -0
- package/dist/lib/vocabulary/renames.js +40 -0
- package/dist/lib/vocabulary/renames.js.map +1 -0
- package/dist/lib/vocabulary/vocabulary-renames.yaml +76 -0
- package/dist/maintain-version.json +2 -2
- package/dist/verbs/migrate.d.ts +9 -0
- package/dist/verbs/migrate.d.ts.map +1 -0
- package/dist/verbs/migrate.js +32 -0
- package/dist/verbs/migrate.js.map +1 -0
- package/dist/verify-version.json +2 -2
- package/package.json +1 -1
- package/scripts/author-acceptance.mjs +3 -1
- package/scripts/author-version.json +2 -2
- package/scripts/maintain-version.json +2 -2
- package/scripts/sync-vendored-script.sh +4 -1
- package/scripts/validate-app-dependencies.sh +29 -21
- package/scripts/verify-version.json +2 -2
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The method's vocabulary renames (M-ADR 0222 §4.1), loaded from the vendored copy of
|
|
3
|
+
* sdd-method's docs/method/foundations/vocabulary-renames.yaml (one-way, sdd-method ->
|
|
4
|
+
* vendored; scripts/sync-vendored-script.sh, drift-tested in tests/parity).
|
|
5
|
+
*
|
|
6
|
+
* For one major release every reader accepts a former value and reads it as the new one;
|
|
7
|
+
* from `removed_in` the former value is an error. Readers ask this module rather than
|
|
8
|
+
* keeping their own copy, so a rename has one definition here as it has one in the bundles.
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { parse } from "yaml";
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
export const VENDORED_RENAMES_PATH = join(__dirname, "vocabulary-renames.yaml");
|
|
16
|
+
let cached;
|
|
17
|
+
export function vocabularyRenames() {
|
|
18
|
+
if (cached === undefined) {
|
|
19
|
+
const doc = parse(readFileSync(VENDORED_RENAMES_PATH, "utf8"));
|
|
20
|
+
cached = { introduced_in: String(doc.introduced_in), removed_in: String(doc.removed_in), renames: doc.renames };
|
|
21
|
+
}
|
|
22
|
+
return cached;
|
|
23
|
+
}
|
|
24
|
+
/** The rename with this id; throws on an id the file does not hold, so a reader cannot silently lose its alias. */
|
|
25
|
+
export function rename(id) {
|
|
26
|
+
const r = vocabularyRenames().renames.find((x) => x.id === id);
|
|
27
|
+
if (r === undefined)
|
|
28
|
+
throw new Error(`vocabulary-renames.yaml has no rename "${id}"`);
|
|
29
|
+
return r;
|
|
30
|
+
}
|
|
31
|
+
/** The value as a reader should treat it: the new name for the former one, anything else unchanged. */
|
|
32
|
+
export function canonicalValue(id, value) {
|
|
33
|
+
const r = rename(id);
|
|
34
|
+
return value === r.old ? r.new : value;
|
|
35
|
+
}
|
|
36
|
+
/** Whether a value is the former name under this rename (for the reader's finding). */
|
|
37
|
+
export function isFormerValue(id, value) {
|
|
38
|
+
return value === rename(id).old;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=renames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renames.js","sourceRoot":"","sources":["../../../src/lib/vocabulary/renames.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAc7B,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC,SAAS,EAAE,yBAAyB,CAAC,CAAC;AAEhF,IAAI,MAA+B,CAAC;AAEpC,MAAM,UAAU,iBAAiB;IAC/B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAgB,CAAC;QAC9E,MAAM,GAAG,EAAE,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IAClH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mHAAmH;AACnH,MAAM,UAAU,MAAM,CAAC,EAAU;IAC/B,MAAM,CAAC,GAAG,iBAAiB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/D,IAAI,CAAC,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,EAAE,GAAG,CAAC,CAAC;IACtF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,cAAc,CAAC,EAAU,EAAE,KAAa;IACtD,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IACrB,OAAO,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;AACzC,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,aAAa,CAAC,EAAU,EAAE,KAAa;IACrD,OAAO,KAAK,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Vocabulary renames (M-ADR 0222 §4.1)
|
|
2
|
+
#
|
|
3
|
+
# The tool-read values the method renamed when "lock" left its vocabulary, as data:
|
|
4
|
+
# every reader that accepts a former value, and the migrate verb, follows this file.
|
|
5
|
+
# For one major release a reader accepts the former value, treats it as the new one
|
|
6
|
+
# and reports it; from removed_in the former value is an error.
|
|
7
|
+
#
|
|
8
|
+
# Each reader that aliases a former value marks the place with a comment line
|
|
9
|
+
# vocabulary-alias: <old> -> <new>
|
|
10
|
+
# and the correspondence registry holds the readers and this file to each other in
|
|
11
|
+
# both directions (orchestration/correspondence-registry.yaml, vocabulary-renames).
|
|
12
|
+
#
|
|
13
|
+
# Consumed by:
|
|
14
|
+
# - validate-spec-lifecycle.sh, validate-traceability.sh, validate-app-dependencies.sh,
|
|
15
|
+
# dispatch-release.sh (the bundled readers)
|
|
16
|
+
# - sdd-cli's catalogue build and repo-config reader
|
|
17
|
+
# - `sdd-cli migrate vocabulary` (rewrites an SDD's own files)
|
|
18
|
+
#
|
|
19
|
+
# Distribution: ships in every method baseline via the seed-file lists.
|
|
20
|
+
|
|
21
|
+
schema_version: "1.0.0"
|
|
22
|
+
introduced_in: "2.0.0" # the sdd-cli major that reads both names
|
|
23
|
+
removed_in: "3.0.0" # the sdd-cli major that rejects the former names
|
|
24
|
+
|
|
25
|
+
renames:
|
|
26
|
+
- id: authoring-status-detailed
|
|
27
|
+
old: detailed-pre-lock
|
|
28
|
+
new: detailed
|
|
29
|
+
positions:
|
|
30
|
+
- "spec `**Status:**` header (M-ADR 0201's authoring ladder)"
|
|
31
|
+
- "work-order status"
|
|
32
|
+
- "capability manifest `capability.status` (a spec-authoring stage on the wrong axis; reported, never translated)"
|
|
33
|
+
|
|
34
|
+
- id: stability-stable
|
|
35
|
+
old: locked
|
|
36
|
+
new: stable
|
|
37
|
+
positions:
|
|
38
|
+
- "`required_stability` (app and integration platform dependencies)"
|
|
39
|
+
- "`traceability.contracts.status` (the contract-set maturity ladder)"
|
|
40
|
+
- "repository config `stability` (a stability class)"
|
|
41
|
+
- "runtime-artefact `stability` and `template-stability`"
|
|
42
|
+
note: "Only where `locked` is a stability CLASS. A pinned version is a different thing (M-ADR 0222 §4.1)."
|
|
43
|
+
|
|
44
|
+
- id: agreement-tag
|
|
45
|
+
old: release-vMAJOR.MINOR-locked
|
|
46
|
+
new: release-vMAJOR.MINOR-agreed
|
|
47
|
+
positions:
|
|
48
|
+
- "the agreement tag on a release branch (M-ADRs 0072-0074)"
|
|
49
|
+
|
|
50
|
+
- id: agreement-tag-key
|
|
51
|
+
old: lock_in_tag
|
|
52
|
+
new: agreement_tag
|
|
53
|
+
positions:
|
|
54
|
+
- "a platform BASELINE.md record key (M-ADR 0073)"
|
|
55
|
+
|
|
56
|
+
- id: gate-registry-next-gate
|
|
57
|
+
old: lock-in
|
|
58
|
+
new: agreement
|
|
59
|
+
positions:
|
|
60
|
+
- "gate registry `next_gate` value (domain-architecture rubric)"
|
|
61
|
+
|
|
62
|
+
- id: gate-registry-remediation-key
|
|
63
|
+
old: remediation_before_lock_in
|
|
64
|
+
new: remediation_before_agreement
|
|
65
|
+
positions:
|
|
66
|
+
- "gate registry key (domain-architecture rubric)"
|
|
67
|
+
|
|
68
|
+
- id: journey-status-accepted
|
|
69
|
+
old: accepted-pre-lock
|
|
70
|
+
new: accepted
|
|
71
|
+
positions:
|
|
72
|
+
- "user-journey status (templates only; no reader)"
|
|
73
|
+
|
|
74
|
+
# An extension an adopter names itself (an `x-<adopter>-stability` contract extension,
|
|
75
|
+
# say) is the adopter's to rename; its values follow the method's (M-ADR 0222 §4.1). The migrate verb
|
|
76
|
+
# reports such extensions and never rewrites them.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* `migrate vocabulary` (M-ADR 0222 §4.1): rewrite the SDD's own files from the former tool-read values to the
|
|
4
|
+
* new ones, in known positions only, and report what it must not rewrite. Authored content, so the verb is the
|
|
5
|
+
* author's and the full CLI's (M-ADR 0218). Exit 0 when nothing is left to migrate, 1 when it rewrote values
|
|
6
|
+
* (or, with --dry-run, found values it would rewrite), so a wave can gate on "migrated".
|
|
7
|
+
*/
|
|
8
|
+
export declare function registerMigrate(program: Command): void;
|
|
9
|
+
//# sourceMappingURL=migrate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/verbs/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASzC;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuBtD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { migrateVocabulary } from "../lib/vocabulary/migrate.js";
|
|
3
|
+
/**
|
|
4
|
+
* `migrate vocabulary` (M-ADR 0222 §4.1): rewrite the SDD's own files from the former tool-read values to the
|
|
5
|
+
* new ones, in known positions only, and report what it must not rewrite. Authored content, so the verb is the
|
|
6
|
+
* author's and the full CLI's (M-ADR 0218). Exit 0 when nothing is left to migrate, 1 when it rewrote values
|
|
7
|
+
* (or, with --dry-run, found values it would rewrite), so a wave can gate on "migrated".
|
|
8
|
+
*/
|
|
9
|
+
export function registerMigrate(program) {
|
|
10
|
+
const migrate = program.command("migrate").description("Migrate an SDD's own files to the method's current vocabulary");
|
|
11
|
+
migrate
|
|
12
|
+
.command("vocabulary")
|
|
13
|
+
.description("Rewrite the SDD's own files from the former tool-read values (detailed-pre-lock, stability locked, release-vX.X-locked, lock_in_tag, next_gate lock-in, remediation_before_lock_in) to the new ones, in known positions only; method- and pack-managed files, .sdd/ and catalogues/ are untouched (exit 1 when anything was or would be rewritten)")
|
|
14
|
+
.option("--sdd-path <path>", "Path to the SDD repo root (defaults to cwd)")
|
|
15
|
+
.option("--dry-run", "List what would be rewritten; write nothing")
|
|
16
|
+
.action(async (opts) => {
|
|
17
|
+
const root = resolve(opts.sddPath ?? process.cwd());
|
|
18
|
+
const r = await migrateVocabulary(root, { dryRun: opts.dryRun === true });
|
|
19
|
+
const w = (s) => process.stdout.write(s);
|
|
20
|
+
for (const x of r.rewrites)
|
|
21
|
+
w(` ${opts.dryRun ? "would rewrite" : "rewrote"} ${x.file}:${x.line} ${x.from} -> ${x.to} (${x.rule})\n`);
|
|
22
|
+
for (const x of r.reported)
|
|
23
|
+
w(` reported ${x.file}:${x.line} ${x.text} — ${x.reason}\n`);
|
|
24
|
+
const verb = opts.dryRun ? "would rewrite" : "rewrote";
|
|
25
|
+
w(r.rewrites.length === 0
|
|
26
|
+
? `[PASS] migrate vocabulary: nothing to migrate in ${r.filesScanned} file(s) the SDD owns${r.reported.length ? `; ${r.reported.length} reported for the adopter` : ""}\n`
|
|
27
|
+
: `[INFO] migrate vocabulary: ${verb} ${r.rewrites.length} value(s) in ${r.filesChanged} file(s) of ${r.filesScanned}${r.reported.length ? `; ${r.reported.length} reported for the adopter` : ""}\n`);
|
|
28
|
+
if (r.rewrites.length > 0)
|
|
29
|
+
process.exit(1);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/verbs/migrate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAOjE;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,+DAA+D,CAAC,CAAC;IACxH,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CACV,oVAAoV,CACrV;SACA,MAAM,CAAC,mBAAmB,EAAE,6CAA6C,CAAC;SAC1E,MAAM,CAAC,WAAW,EAAE,6CAA6C,CAAC;SAClE,MAAM,CAAC,KAAK,EAAE,IAAoB,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACpD,MAAM,CAAC,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;QAC1E,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACjD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ;YAAE,CAAC,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC;QAC1I,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ;YAAE,CAAC,CAAC,eAAe,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;QAC7F,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC;QACvD,CAAC,CACC,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;YACrB,CAAC,CAAC,oDAAoD,CAAC,CAAC,YAAY,wBAAwB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,2BAA2B,CAAC,CAAC,CAAC,EAAE,IAAI;YAC1K,CAAC,CAAC,8BAA8B,IAAI,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,gBAAgB,CAAC,CAAC,YAAY,eAAe,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,2BAA2B,CAAC,CAAC,CAAC,EAAE,IAAI,CACxM,CAAC;QACF,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/verify-version.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdd-method/sdd-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "The full SDD method CLI (sdd-cli): init, sync, validate, catalogue build and aggregate, scaffold, plan, pack build and every other method verb for spec-driven-development repositories. The verify-only, author and maintain personas ship as @sdd-method/verify-cli, @sdd-method/author-cli and @sdd-method/maintain-cli.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sdd-method",
|
|
@@ -139,6 +139,8 @@ for (const repo of REPOS) {
|
|
|
139
139
|
check(`contracts attest @${name}`, repo, () => ["contracts", "attest", "--target-repo", ".", "--refresh"]);
|
|
140
140
|
check(`conformance @${name}`, repo, (_c, ws) => ["conformance", "--target-repo", ".", "--emit-finding", join(ws, "findings")]);
|
|
141
141
|
check(`api-surface @${name}`, repo, (_c, ws) => ["api-surface", "--source", ".", "--out", join(ws, "surface.yaml")]);
|
|
142
|
+
// Rewrites the SDD's own files to the current vocabulary: must never touch a maintain-only path (the lock, managed payload).
|
|
143
|
+
check(`migrate vocabulary @${name}`, repo, () => ["migrate", "vocabulary", "--sdd-path", "."]);
|
|
142
144
|
const screens = join(repo, "screens");
|
|
143
145
|
if (existsSync(screens)) {
|
|
144
146
|
const spec = readdirSync(screens).find((f) => f.endsWith(".md"));
|
|
@@ -161,7 +163,7 @@ for (const repo of REPOS) {
|
|
|
161
163
|
void kind;
|
|
162
164
|
}
|
|
163
165
|
|
|
164
|
-
const SURFACE = ["catalogue check", "generate-briefing", "scaffold domain", "plan", "contracts attest", "conformance", "api-surface", "render screen", "context pull",
|
|
166
|
+
const SURFACE = ["catalogue check", "generate-briefing", "scaffold domain", "plan", "contracts attest", "conformance", "api-surface", "render screen", "context pull", "migrate vocabulary",
|
|
165
167
|
"snapshot fold", "snapshot land", "snapshot verify", "snapshot diff", "snapshot targets", "snapshot advance"];
|
|
166
168
|
const missing = SURFACE.filter((v) => !exercised.has(v));
|
|
167
169
|
process.stdout.write(`COVERAGE exercised: ${[...exercised].join(", ")}\n`);
|
|
@@ -44,6 +44,9 @@ VENDORED=(
|
|
|
44
44
|
"validate-app-docs.sh:scripts"
|
|
45
45
|
"validate-app-dependencies.sh:scripts"
|
|
46
46
|
"validate-integration-docs.sh:scripts"
|
|
47
|
+
# A path with a slash is relative to the sdd-method root rather than its scripts directory.
|
|
48
|
+
# The vocabulary renames are data the TypeScript readers load (M-ADR 0222 §4.1).
|
|
49
|
+
"docs/method/foundations/vocabulary-renames.yaml:src/lib/vocabulary"
|
|
47
50
|
)
|
|
48
51
|
|
|
49
52
|
if [[ ! -d "$SRC_DIR" ]]; then
|
|
@@ -56,7 +59,7 @@ changed=0
|
|
|
56
59
|
for entry in "${VENDORED[@]}"; do
|
|
57
60
|
name="${entry%%:*}"
|
|
58
61
|
dest_dir="${entry#*:}"
|
|
59
|
-
src="$SRC_DIR/$name"
|
|
62
|
+
if [[ "$name" == */* ]]; then src="$SDD_METHOD_PATH/$name"; name="$(basename "$name")"; else src="$SRC_DIR/$name"; fi
|
|
60
63
|
dest="$HERE/../$dest_dir/$name"
|
|
61
64
|
|
|
62
65
|
if [[ ! -f "$src" ]]; then
|
|
@@ -11,23 +11,23 @@
|
|
|
11
11
|
#
|
|
12
12
|
# Checks (for each entry in app-platform-dependencies.yaml), split by whether they
|
|
13
13
|
# need a platform surface at all — LOCAL checks run wherever the app repo is:
|
|
14
|
-
# 1. (local) required_stability is a valid value (provisional |
|
|
14
|
+
# 1. (local) required_stability is a valid value (provisional | stable | unknown)
|
|
15
15
|
# 2a. (local) service_id is declared and non-empty
|
|
16
16
|
# 2b. (platform) service_id resolves against the platform source of truth:
|
|
17
17
|
# catalogues/services.csv (exact id match) when the catalogue exists,
|
|
18
18
|
# else docs/platform/service-architecture.md (word-anchored match)
|
|
19
|
-
# 3a. (local) a `
|
|
19
|
+
# 3a. (local) a `stable` dependency declares a contract_path at all
|
|
20
20
|
# 3b. (platform) that contract_path resolves to a file under the platform root
|
|
21
21
|
#
|
|
22
22
|
# Outputs a dependency status table.
|
|
23
|
-
# Used as the Stage
|
|
23
|
+
# Used as the Stage 9 agreement gate in the App Exploration Workflow.
|
|
24
24
|
#
|
|
25
25
|
# THE STABILITY VOCABULARY, AND WHY IT IS WHAT IT IS
|
|
26
26
|
# `required_stability` states the CONSUMING app's expectation of contract
|
|
27
27
|
# stability. Three values express that:
|
|
28
28
|
#
|
|
29
29
|
# provisional the contract may still change; the app tolerates it
|
|
30
|
-
#
|
|
30
|
+
# stable the contract is fixed; a contract_path must exist (check 3)
|
|
31
31
|
# unknown the expectation is not determined
|
|
32
32
|
#
|
|
33
33
|
# `unknown` is accepted because the canonical schema's
|
|
@@ -158,7 +158,7 @@ APP_DEPS_FILE="$APP_ROOT/app-platform-dependencies.yaml"
|
|
|
158
158
|
# This gate read only the forward file, so an entire equal-status source went
|
|
159
159
|
# ungated. Measured in one reverse estate: 15 evidence files declaring 65
|
|
160
160
|
# further dependencies, 38 of them `locked` — precisely the population
|
|
161
|
-
# a Stage
|
|
161
|
+
# a Stage 9 agreement gate exists to check — none of which this gate could see.
|
|
162
162
|
#
|
|
163
163
|
# A source that the catalogue reads and the gate does not is a coverage gap by
|
|
164
164
|
# construction, so the gate now reads both.
|
|
@@ -180,7 +180,7 @@ PLATFORM_SERVICES_CSV="$PLATFORM_ROOT/catalogues/services.csv"
|
|
|
180
180
|
# offer (instances app-dependency-stability-vocabulary-forward and -reverse).
|
|
181
181
|
VALID_STABILITY_VALUES=(
|
|
182
182
|
"provisional" # contract may still change; the app tolerates it
|
|
183
|
-
"
|
|
183
|
+
"stable" # contract is fixed; check 3 requires a resolvable contract_path
|
|
184
184
|
"unknown" # expectation not determined; no contract_path required
|
|
185
185
|
)
|
|
186
186
|
|
|
@@ -353,6 +353,13 @@ validate_dependency() {
|
|
|
353
353
|
service_id="$(yq e ".platform_dependencies[$index].service_id // \"\"" "$source_file")"
|
|
354
354
|
contract_type="$(yq e ".platform_dependencies[$index].contract_type // \"\"" "$source_file")"
|
|
355
355
|
required_stability="$(yq e ".platform_dependencies[$index].required_stability // \"\"" "$source_file")"
|
|
356
|
+
# vocabulary-alias: locked -> stable
|
|
357
|
+
# The fixed-contract stability class was `locked` (M-ADR 0222 §4.1; docs/method/foundations/vocabulary-renames.yaml).
|
|
358
|
+
# Read as `stable` for one major release and reported; from sdd-cli 3.0.0 it is invalid.
|
|
359
|
+
if [[ "$required_stability" == "locked" ]]; then
|
|
360
|
+
log_warn "$source_file: platform_dependencies[$index] uses the former required_stability 'locked', read as 'stable' (M-ADR 0222 §4.1). Run 'sdd-cli migrate vocabulary'; from sdd-cli 3.0.0 the former value is invalid."
|
|
361
|
+
required_stability="stable"
|
|
362
|
+
fi
|
|
356
363
|
contract_path="$(yq e ".platform_dependencies[$index].contract_path // \"\"" "$source_file")"
|
|
357
364
|
|
|
358
365
|
local dep_label="${service_id:-dep[$index]}"
|
|
@@ -403,7 +410,7 @@ validate_dependency() {
|
|
|
403
410
|
done
|
|
404
411
|
|
|
405
412
|
if [[ "$stability_deprecated" -eq 1 ]]; then
|
|
406
|
-
log_fail "$dep_label: required_stability '$required_stability' is not a stability value (M-ADR 0204 §4.4). Declare target_locus: '$required_stability' on the entry and give required_stability a real value (${VALID_STABILITY_VALUES[*]}) — a third-party contract can be
|
|
413
|
+
log_fail "$dep_label: required_stability '$required_stability' is not a stability value (M-ADR 0204 §4.4). Declare target_locus: '$required_stability' on the entry and give required_stability a real value (${VALID_STABILITY_VALUES[*]}) — a third-party contract can be stable."
|
|
407
414
|
((dep_errors++))
|
|
408
415
|
else
|
|
409
416
|
log_fail "$dep_label: invalid required_stability '$required_stability' (allowed: ${VALID_STABILITY_VALUES[*]})"
|
|
@@ -490,26 +497,26 @@ validate_dependency() {
|
|
|
490
497
|
((WARNINGS++))
|
|
491
498
|
fi
|
|
492
499
|
|
|
493
|
-
# Check 3: a
|
|
494
|
-
# resolves to a file (3b, needs the platform). Same split, same reason: "
|
|
500
|
+
# Check 3: a stable dependency declares a contract_path (3a, local) and that path
|
|
501
|
+
# resolves to a file (3b, needs the platform). Same split, same reason: "stable
|
|
495
502
|
# with no path at all" is an app-repo defect that needs nothing external to catch.
|
|
496
|
-
if [[ "$required_stability" == "
|
|
503
|
+
if [[ "$required_stability" == "stable" ]]; then
|
|
497
504
|
if [[ -z "$contract_path" || "$contract_path" == "null" ]]; then
|
|
498
|
-
log_fail "$dep_label: required_stability is '
|
|
505
|
+
log_fail "$dep_label: required_stability is 'stable' but contract_path is empty"
|
|
499
506
|
((dep_errors++))
|
|
500
507
|
elif [[ "$PLATFORM_AVAILABLE" -eq 0 ]]; then
|
|
501
508
|
((UNRESOLVED_CONTRACT_PATHS++))
|
|
502
509
|
else
|
|
503
510
|
local full_contract_path="$PLATFORM_ROOT/$contract_path"
|
|
504
511
|
if [[ ! -f "$full_contract_path" ]]; then
|
|
505
|
-
log_fail "$dep_label:
|
|
512
|
+
log_fail "$dep_label: stable contract_path '$contract_path' does not exist in platform repo"
|
|
506
513
|
((dep_errors++))
|
|
507
514
|
fi
|
|
508
515
|
fi
|
|
509
516
|
elif [[ "$required_stability" == "provisional" || "$required_stability" == "unknown" ]]; then
|
|
510
517
|
# Neither requires a contract_path. If one is declared it is still worth
|
|
511
518
|
# reporting when it does not resolve — silently accepting a path that
|
|
512
|
-
# points at nothing is how a
|
|
519
|
+
# points at nothing is how a stable dependency later inherits a dead path.
|
|
513
520
|
if [[ -n "$contract_path" && "$contract_path" != "null" && "$PLATFORM_AVAILABLE" -eq 1 ]]; then
|
|
514
521
|
local full_contract_path="$PLATFORM_ROOT/$contract_path"
|
|
515
522
|
if [[ ! -f "$full_contract_path" ]]; then
|
|
@@ -552,21 +559,22 @@ print_status_table() {
|
|
|
552
559
|
local service_id required_stability contract_type contract_path dep_status
|
|
553
560
|
service_id="$(yq e ".platform_dependencies[$i].service_id // \"(missing)\"" "$source_file")"
|
|
554
561
|
required_stability="$(yq e ".platform_dependencies[$i].required_stability // \"(missing)\"" "$source_file")"
|
|
562
|
+
if [[ "$required_stability" == "locked" ]]; then required_stability="stable"; fi # the former name, reported above
|
|
555
563
|
contract_type="$(yq e ".platform_dependencies[$i].contract_type // \"(missing)\"" "$source_file")"
|
|
556
564
|
contract_path="$(yq e ".platform_dependencies[$i].contract_path // \"\"" "$source_file")"
|
|
557
565
|
|
|
558
566
|
# Determine display status
|
|
559
|
-
if [[ "$required_stability" == "
|
|
567
|
+
if [[ "$required_stability" == "stable" ]]; then
|
|
560
568
|
if [[ -z "$contract_path" || "$contract_path" == "null" ]]; then
|
|
561
|
-
dep_status="${RED}
|
|
569
|
+
dep_status="${RED}STABLE UNMET${NC}"
|
|
562
570
|
elif [[ "$PLATFORM_AVAILABLE" -eq 0 ]]; then
|
|
563
571
|
# A declared path that was never resolved is not "OK" and not "UNMET".
|
|
564
572
|
# Reporting either would be a claim the run cannot support.
|
|
565
|
-
dep_status="${YELLOW}
|
|
573
|
+
dep_status="${YELLOW}STABLE UNRESOLVED${NC}"
|
|
566
574
|
elif [[ -f "$PLATFORM_ROOT/$contract_path" ]]; then
|
|
567
|
-
dep_status="${GREEN}
|
|
575
|
+
dep_status="${GREEN}STABLE OK${NC}"
|
|
568
576
|
else
|
|
569
|
-
dep_status="${RED}
|
|
577
|
+
dep_status="${RED}STABLE UNMET${NC}"
|
|
570
578
|
fi
|
|
571
579
|
elif [[ "$required_stability" == "provisional" ]]; then
|
|
572
580
|
dep_status="${YELLOW}PROVISIONAL${NC}"
|
|
@@ -637,7 +645,7 @@ main() {
|
|
|
637
645
|
fi
|
|
638
646
|
|
|
639
647
|
if [[ "$FAILURES" -gt 0 ]]; then
|
|
640
|
-
log_fail "$FAILURES dependency check(s) failed. Stage
|
|
648
|
+
log_fail "$FAILURES dependency check(s) failed. Stage 9 agreement gate NOT met."
|
|
641
649
|
exit 1
|
|
642
650
|
fi
|
|
643
651
|
|
|
@@ -648,7 +656,7 @@ main() {
|
|
|
648
656
|
# while never executing (M-ADR 0200 §4.3).
|
|
649
657
|
if [[ "$PLATFORM_AVAILABLE" -eq 0 ]]; then
|
|
650
658
|
log_warn "Ran check 1 (stability vocabulary) and the local halves of checks 2-3 over $TOTAL_DEPS dependency(ies): $FAILURES failure(s), $WARNINGS warning(s)."
|
|
651
|
-
log_warn "NOT RUN, for want of --platform-root: $UNRESOLVED_SERVICE_IDS service_id resolution(s) and $UNRESOLVED_CONTRACT_PATHS
|
|
659
|
+
log_warn "NOT RUN, for want of --platform-root: $UNRESOLVED_SERVICE_IDS service_id resolution(s) and $UNRESOLVED_CONTRACT_PATHS stable contract_path resolution(s)."
|
|
652
660
|
log_info "This is a partial run, not a met gate — pass --platform-root to complete it."
|
|
653
661
|
exit 0
|
|
654
662
|
fi
|
|
@@ -656,7 +664,7 @@ main() {
|
|
|
656
664
|
if [[ "$WARNINGS" -gt 0 ]]; then
|
|
657
665
|
log_warn "All required checks passed with $WARNINGS warning(s)."
|
|
658
666
|
else
|
|
659
|
-
log_pass "All dependency checks passed. Stage
|
|
667
|
+
log_pass "All dependency checks passed. Stage 9 agreement gate met."
|
|
660
668
|
fi
|
|
661
669
|
exit 0
|
|
662
670
|
}
|