@sdd-method/maintain-cli 0.8.0 → 0.10.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 (105) hide show
  1. package/dist/lib/agent-harness.js +2 -2
  2. package/dist/lib/behaviour-store/archive.js +28 -1
  3. package/dist/lib/behaviour-store/schema.js +85 -0
  4. package/dist/lib/briefing/index.js +1 -1
  5. package/dist/lib/briefing/render.js +1 -1
  6. package/dist/lib/briefing/variables.js +1 -1
  7. package/dist/lib/bundle.js +1 -1
  8. package/dist/lib/catalogue/aggregate.js +7 -7
  9. package/dist/lib/catalogue/application-archetype/vocabulary.js +2 -2
  10. package/dist/lib/catalogue/archetype/maps/android.yaml +2 -2
  11. package/dist/lib/catalogue/archetype/maps/swiftui.yaml +2 -2
  12. package/dist/lib/catalogue/archetype/maps/uikit.yaml +2 -2
  13. package/dist/lib/catalogue/archetype/maps/web-generic.yaml +2 -2
  14. package/dist/lib/catalogue/archetype/openui-archetype-vocabulary.yaml +3 -3
  15. package/dist/lib/catalogue/archetype/resolver.js +4 -4
  16. package/dist/lib/catalogue/archetype/wireframe.js +1 -1
  17. package/dist/lib/catalogue/build.js +36 -33
  18. package/dist/lib/catalogue/builders/adr-supersedes.js +3 -3
  19. package/dist/lib/catalogue/builders/adrs.js +3 -3
  20. package/dist/lib/catalogue/builders/c4-containers.js +2 -2
  21. package/dist/lib/catalogue/builders/c4-entity-rollups.js +1 -1
  22. package/dist/lib/catalogue/builders/c4-external-systems.js +2 -2
  23. package/dist/lib/catalogue/builders/c4-systems.js +1 -1
  24. package/dist/lib/catalogue/builders/capabilities.js +1 -1
  25. package/dist/lib/catalogue/builders/capability-domain-model.js +1 -1
  26. package/dist/lib/catalogue/builders/capability-spec-walker.js +2 -2
  27. package/dist/lib/catalogue/builders/capability-spec.js +4 -4
  28. package/dist/lib/catalogue/builders/contracts.js +3 -3
  29. package/dist/lib/catalogue/builders/data-store-mapping.js +2 -2
  30. package/dist/lib/catalogue/builders/domain-models.js +2 -2
  31. package/dist/lib/catalogue/builders/domains.js +3 -3
  32. package/dist/lib/catalogue/builders/entities-manifest.js +8 -8
  33. package/dist/lib/catalogue/builders/entities-mermaid.js +4 -4
  34. package/dist/lib/catalogue/builders/entity-persistence.js +1 -1
  35. package/dist/lib/catalogue/builders/entity-slug.js +3 -3
  36. package/dist/lib/catalogue/builders/event-catalog-walker.js +6 -6
  37. package/dist/lib/catalogue/builders/event-edges.js +6 -6
  38. package/dist/lib/catalogue/builders/events.js +3 -3
  39. package/dist/lib/catalogue/builders/evidence-class.js +1 -1
  40. package/dist/lib/catalogue/builders/feature-domain-model.js +1 -1
  41. package/dist/lib/catalogue/builders/feature-grounding-walker.js +2 -2
  42. package/dist/lib/catalogue/builders/feature-grounding.js +5 -5
  43. package/dist/lib/catalogue/builders/feature-subscription-channels.js +3 -3
  44. package/dist/lib/catalogue/builders/features.js +1 -1
  45. package/dist/lib/catalogue/builders/glossary-xref.js +4 -4
  46. package/dist/lib/catalogue/builders/integrations.js +4 -4
  47. package/dist/lib/catalogue/builders/persona-c4system.js +1 -1
  48. package/dist/lib/catalogue/builders/product-edges.js +1 -1
  49. package/dist/lib/catalogue/builders/product-platform-dependencies.js +2 -2
  50. package/dist/lib/catalogue/builders/products.js +5 -5
  51. package/dist/lib/catalogue/builders/repo-edges.js +12 -12
  52. package/dist/lib/catalogue/builders/repositories.js +11 -7
  53. package/dist/lib/catalogue/builders/requirements.js +110 -11
  54. package/dist/lib/catalogue/builders/screen-tree.js +6 -6
  55. package/dist/lib/catalogue/builders/screens.js +18 -18
  56. package/dist/lib/catalogue/builders/service-contract-consumes.js +1 -1
  57. package/dist/lib/catalogue/builders/service-entity-tables.js +3 -3
  58. package/dist/lib/catalogue/builders/services.js +5 -5
  59. package/dist/lib/catalogue/builders/system-external-dependency.js +2 -2
  60. package/dist/lib/catalogue/canonical-schema.yaml +138 -2
  61. package/dist/lib/catalogue/coverage-render.js +15 -15
  62. package/dist/lib/catalogue/csv-writer.js +1 -1
  63. package/dist/lib/catalogue/feature-grounding-aliases-loader.js +1 -1
  64. package/dist/lib/catalogue/findings.js +1 -1
  65. package/dist/lib/catalogue/fk-validator.js +2 -2
  66. package/dist/lib/catalogue/manifest-loader.js +3 -3
  67. package/dist/lib/catalogue/rubric-coverage-map.yaml +28 -0
  68. package/dist/lib/catalogue/schema-compat.js +2 -2
  69. package/dist/lib/catalogue/schema-loader.js +1 -1
  70. package/dist/lib/catalogue/screen-validation-loader.js +2 -2
  71. package/dist/lib/catalogue/service-architecture-parser.js +1 -1
  72. package/dist/lib/catalogue/traceability-loader.js +6 -4
  73. package/dist/lib/ci-binding/module.js +4 -2
  74. package/dist/lib/generate-briefing/index.js +2 -2
  75. package/dist/lib/hooks-seed/entries.js +1 -1
  76. package/dist/lib/metamodel/tql-subset-parser.js +280 -0
  77. package/dist/lib/pack/builder.js +2 -2
  78. package/dist/lib/pack/index.js +1 -1
  79. package/dist/lib/pack/leakage.js +1 -1
  80. package/dist/lib/pack/publish-transform.js +2 -2
  81. package/dist/lib/pack/schema.js +2 -2
  82. package/dist/lib/pack/seed.js +2 -2
  83. package/dist/lib/pack/validate.js +1 -1
  84. package/dist/lib/repo-kind.js +4 -12
  85. package/dist/lib/scaffold/archetype-behaviour.js +173 -0
  86. package/dist/lib/scaffold/registry.js +136 -0
  87. package/dist/lib/sync/adr-transitions.js +4 -2
  88. package/dist/lib/sync/briefing-merge.js +2 -2
  89. package/dist/lib/sync/bundle-cache.js +4 -4
  90. package/dist/lib/sync/index.js +39 -12
  91. package/dist/lib/sync/settings-merge.js +1 -1
  92. package/dist/lib/sync/yaml-block-merge.js +1 -1
  93. package/dist/lib/validate/archetype-citations.js +169 -0
  94. package/dist/lib/validate/behaviour-store.js +161 -6
  95. package/dist/lib/validate/dispatch.js +8 -1
  96. package/dist/maintain-program.js +2 -2
  97. package/dist/maintain-version.json +2 -2
  98. package/dist/verbs/list.js +1 -1
  99. package/dist/verbs/pack-build.js +2 -2
  100. package/dist/verbs/render.js +1 -1
  101. package/dist/verify-program.js +2 -2
  102. package/dist/verify-version.json +2 -2
  103. package/package.json +2 -2
  104. package/scripts/validate-app-dependencies.sh +1 -1
  105. package/scripts/validate-integration-docs.sh +1 -1
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * Agent-harness identifiers — the value space of `--agent-harness` on
3
- * `sdd-cli init`, `sdd-cli sync` and `context pull` per ADR 0141 §4.6.
3
+ * `sdd-cli init`, `sdd-cli sync` and `context pull` per M-ADR 0141 §4.6.
4
4
  *
5
5
  * Claude Code is the one supported harness (M-ADR 0220 §4.6) and the default. The GitHub Copilot
6
6
  * CLI value is retired: passing it fails, naming that record. Every SDD and code repository also
7
7
  * gets an AGENTS.md pointer to agent-instructions.md, with no flag; it is a pointer, not support
8
8
  * for another harness. Adopters binding any other harness implement the portable contracts
9
- * themselves (ADR 0141 §4.5).
9
+ * themselves (M-ADR 0141 §4.5).
10
10
  */
11
11
  export const AGENT_HARNESSES = ["claude-code"];
12
12
  export const DEFAULT_AGENT_HARNESS = "claude-code";
@@ -64,6 +64,33 @@ export function renamedFrom(text) {
64
64
  }
65
65
  return out;
66
66
  }
67
+ /** The FROM -> TO pairs of a RENAMED section, in file order. */
68
+ export function renamePairs(text) {
69
+ const out = [];
70
+ let op = null;
71
+ let from = null;
72
+ for (const line of text.split("\n")) {
73
+ const section = /^##\s+(ADDED|MODIFIED|REMOVED|RENAMED)\s+Requirements\b/.exec(line);
74
+ if (section) {
75
+ op = section[1];
76
+ from = null;
77
+ continue;
78
+ }
79
+ if (op !== "RENAMED")
80
+ continue;
81
+ const f = /^\s*-\s*FROM:\s*`?###\s+Requirement:\s*(.+?)`?\s*$/.exec(line);
82
+ if (f) {
83
+ from = f[1].trim();
84
+ continue;
85
+ }
86
+ const t = /^\s*-\s*TO:\s*`?###\s+Requirement:\s*(.+?)`?\s*$/.exec(line);
87
+ if (t && from !== null) {
88
+ out.push({ from, to: t[1].trim() });
89
+ from = null;
90
+ }
91
+ }
92
+ return out;
93
+ }
67
94
  /** Each archive directory's position in the SDD's history: the index of the first commit that added a file under it. */
68
95
  async function archiveHistory(sddPath, archiveRel) {
69
96
  let stdout;
@@ -100,7 +127,7 @@ export async function orderArchives(sddPath, archiveRel, names) {
100
127
  if (date(a) === date(b) && position(a) === position(b))
101
128
  ties.push([a, b]);
102
129
  }
103
- return { order, ties };
130
+ return { order, ties, history: history !== null };
104
131
  }
105
132
  /** The repositories a baseline was observed in: its evidence file's `**Observed in:** repo[@sha], repo[@sha]` line. */
106
133
  export function observedIn(evidence) {
@@ -0,0 +1,85 @@
1
+ // The method's OpenSpec change schema (M-ADR 0223 §4.2) and its copy in a behaviour store.
2
+ //
3
+ // The method ships the schema inert, at docs/method/foundations/openspec/sdd-change/, because
4
+ // sync writes an SDD's managed paths and a store is created only when its SDD first needs one
5
+ // (M-ADR 0221 §4.2): a managed path at openspec/ would create a store in every SDD.
6
+ // OpenSpec reads a project schema only from <store>/openspec/schemas/<name>/, so the store
7
+ // holds a copy. The copy is method-managed: sync refreshes it, scaffold writes it, and the
8
+ // behaviour-store validator fails when it differs. Adopter guidance goes in the store's
9
+ // config.yaml (`context:`, per-artifact `rules:`), never in the copy.
10
+ import { cp, mkdir, readdir, readFile, rm } from "node:fs/promises";
11
+ import { join, relative } from "node:path";
12
+ import { parseDocument } from "yaml";
13
+ export const SCHEMA_NAME = "sdd-change";
14
+ export const SHIPPED_SCHEMA_DIR = "docs/method/foundations/openspec/sdd-change";
15
+ export const SHIPPED_CONFIG_TEMPLATE = "docs/method/foundations/openspec/config-template.yaml";
16
+ export const STORE_SCHEMA_DIR = `openspec/schemas/${SCHEMA_NAME}`;
17
+ export const STORE_CONFIG = "openspec/config.yaml";
18
+ async function files(dir) {
19
+ const out = [];
20
+ async function walk(d) {
21
+ for (const e of await readdir(d, { withFileTypes: true })) {
22
+ const p = join(d, e.name);
23
+ if (e.isDirectory())
24
+ await walk(p);
25
+ else if (e.isFile())
26
+ out.push(relative(dir, p));
27
+ }
28
+ }
29
+ try {
30
+ await walk(dir);
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ return out.sort();
36
+ }
37
+ async function read(p) {
38
+ try {
39
+ return await readFile(p);
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ /** The schema the store's config.yaml selects: its name, null without a config, or "" without a `schema:` key. */
46
+ export async function storeSchemaName(repo) {
47
+ const text = await read(join(repo, STORE_CONFIG));
48
+ if (text === null)
49
+ return null;
50
+ const v = parseDocument(text.toString("utf8")).toJS()?.schema;
51
+ return typeof v === "string" ? v : "";
52
+ }
53
+ /** Compare the store's copy of the schema with the one the SDD's method bundle shipped, file by file. */
54
+ export async function compareStoreSchema(repo) {
55
+ const shipped = await files(join(repo, SHIPPED_SCHEMA_DIR));
56
+ if (shipped === null || shipped.length === 0)
57
+ return { shipped: false, missing: [], differing: [], extra: [] };
58
+ const store = (await files(join(repo, STORE_SCHEMA_DIR))) ?? [];
59
+ const missing = shipped.filter((f) => !store.includes(f));
60
+ const extra = store.filter((f) => !shipped.includes(f));
61
+ const differing = [];
62
+ for (const f of shipped.filter((x) => store.includes(x))) {
63
+ const a = await read(join(repo, SHIPPED_SCHEMA_DIR, f));
64
+ const b = await read(join(repo, STORE_SCHEMA_DIR, f));
65
+ if (a === null || b === null || !a.equals(b))
66
+ differing.push(f);
67
+ }
68
+ return { shipped: true, missing, differing, extra };
69
+ }
70
+ /**
71
+ * Replace the store's copy of the schema with the shipped one. Returns what changed, as a
72
+ * comparison taken before the write; a store already current returns empty lists.
73
+ */
74
+ export async function writeStoreSchema(repo) {
75
+ const before = await compareStoreSchema(repo);
76
+ if (!before.shipped)
77
+ return before;
78
+ if (before.missing.length + before.differing.length + before.extra.length === 0)
79
+ return before;
80
+ await rm(join(repo, STORE_SCHEMA_DIR), { recursive: true, force: true });
81
+ await mkdir(join(repo, STORE_SCHEMA_DIR), { recursive: true });
82
+ await cp(join(repo, SHIPPED_SCHEMA_DIR), join(repo, STORE_SCHEMA_DIR), { recursive: true });
83
+ return before;
84
+ }
85
+ //# sourceMappingURL=schema.js.map
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Public facade for the briefing layer (ADR 0148).
2
+ * Public facade for the briefing layer (M-ADR 0148).
3
3
  *
4
4
  * `agent-instructions.md` is the harness-neutral canonical briefing
5
5
  * (fully method-managed; sync overwrites unconditionally). Harness
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Renderer for the briefing-layer templates per ADR 0148.
2
+ * Renderer for the briefing-layer templates per M-ADR 0148.
3
3
  *
4
4
  * Templates ship via the method baseline bundle and land at
5
5
  * `<target>/orchestration/templates/briefing/...` after sync's
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Variable resolution for the briefing layer per ADR 0148 §4.1.
2
+ * Variable resolution for the briefing layer per M-ADR 0148 §4.1.
3
3
  *
4
4
  * The four variables are sourced from target-repo state:
5
5
  *
@@ -64,7 +64,7 @@ export function parseManifest(raw) {
64
64
  const isForwardBaseInferred = isForwardBaseRaw === null ? isForwardBase(bundleName) : isForwardBaseRaw;
65
65
  // Forward bases must use a known bundle name; adopter packs may use
66
66
  // any string. This enforces the closed enum where it matters and
67
- // opens it where ADR 0151 requires.
67
+ // opens it where M-ADR 0151 requires.
68
68
  if (isForwardBaseInferred && !isBundleName(bundleName)) {
69
69
  throw new Error(`Unknown bundle_name in manifest for forward base: ${JSON.stringify(bundleName)}`);
70
70
  }
@@ -161,7 +161,7 @@ export async function runCatalogueAggregate(inputs, write) {
161
161
  // capability_service.service_id, emitting one row per resolved
162
162
  // (consuming-product, platform-capability) pair. Per-SDD builders
163
163
  // emit nothing for this catalogue; the aggregator owns it entirely.
164
- // See ADR 0134.
164
+ // See M-ADR 0134.
165
165
  const crossSddRows = deriveCrossSddPlatformCapability(rowsByCatalogue.get("product_platform_dependencies") ?? [], rowsByCatalogue.get("capability_service") ?? [], findings, rowsByCatalogue.get("capabilities") ?? []);
166
166
  rowsByCatalogue.set("cross_sdd_platform_capability", crossSddRows);
167
167
  // @rule aggregate-feature-integration-support
@@ -389,12 +389,12 @@ export async function runCatalogueAggregate(inputs, write) {
389
389
  // integration builds emit screen_feature rows carrying the bare `realises:`
390
390
  // slug when the feature lives in another SDD (the platform). Rewrite those
391
391
  // to the resolved platform feature id by matching the slug against every
392
- // merged feature's slug. One slug vocabulary per capability (ADR 0177), so
392
+ // merged feature's slug. One slug vocabulary per capability (M-ADR 0177), so
393
393
  // a single match is authoritative; an ambiguous estate-wide match is refused
394
394
  // with a divergence finding (never guessed); no match is an orphan finding.
395
395
  rowsByCatalogue.set("screen_feature", resolveCrossSddScreenFeature(rowsByCatalogue.get("screen_feature") ?? [], rowsByCatalogue.get("features") ?? [], findings));
396
396
  // @rule aggregate-external-system-dedup
397
- // 5b. Dedup c4_external_systems by id (ADR 0155). External systems are
397
+ // 5b. Dedup c4_external_systems by id (M-ADR 0155). External systems are
398
398
  // inherently shared references — the same external (e.g. ext-google-maps)
399
399
  // may be declared by multiple SDDs. This is the one narrowly-scoped
400
400
  // exception to the duplicate-PK rule: identical rows merge (first-seen
@@ -413,7 +413,7 @@ export async function runCatalogueAggregate(inputs, write) {
413
413
  // / domain ADRs are NOT deduped — a collision there is a genuine error.
414
414
  await dedupMethodScopedAdrs(rowsByCatalogue, findings, sddRootsById);
415
415
  // @rule aggregate-federated-reverse-metadata-enrichment
416
- // 5c. Federated reverse-metadata enrichment (ADR 0163 P2). Both reference
416
+ // 5c. Federated reverse-metadata enrichment (M-ADR 0163 P2). Both reference
417
417
  // adopters centralise the service inventory in the platform-root, but for
418
418
  // reverse-method federations the per-service evidence (service-architecture.md)
419
419
  // lives one federation hop away, in member SDDs. The platform-root's own
@@ -598,7 +598,7 @@ export async function runCatalogueAggregate(inputs, write) {
598
598
  outDir,
599
599
  };
600
600
  }
601
- // ADR 0155: c4_external_systems rows dedup by id across SDDs rather than
601
+ // M-ADR 0155: c4_external_systems rows dedup by id across SDDs rather than
602
602
  // failing the duplicate-PK check. First-seen row wins; a `source_sdd_id`
603
603
  // already stamped is preserved. Conflicting name/technology/description on
604
604
  // the same id emits a `convention` finding so authors can reconcile.
@@ -781,7 +781,7 @@ async function dedupMethodScopedAdrs(rowsByCatalogue, findings, sddRootsById) {
781
781
  }
782
782
  rowsByCatalogue.set("adrs", out);
783
783
  }
784
- // ADR 0163 P2: the reverse-derived metadata columns that a member SDD's
784
+ // M-ADR 0163 P2: the reverse-derived metadata columns that a member SDD's
785
785
  // service-architecture.md can backfill onto a platform-root service row.
786
786
  const FEDERATED_META_COLS = [
787
787
  "runtime_type",
@@ -1259,7 +1259,7 @@ function featureSlugOf(row) {
1259
1259
  * the slug against every merged feature's recovered slug:
1260
1260
  * - exactly one match → rewrite feature_id (and the composite PK).
1261
1261
  * - >1 match → ambiguous; refuse (divergence finding), leave as-is
1262
- * so the FK pass surfaces it. ADR 0177 guarantees one
1262
+ * so the FK pass surfaces it. M-ADR 0177 guarantees one
1263
1263
  * slug per *capability*, not estate-wide, so cross-
1264
1264
  * capability slug clashes are possible and not guessed.
1265
1265
  * - 0 matches → orphan finding, leave as-is.
@@ -5,7 +5,7 @@
5
5
  * tiered vocabulary. This module resolves a declared value against the union
6
6
  * of:
7
7
  * - the **method tier** — `unclassified` only, built into sdd-cli (mirrors
8
- * how the ADR 0173/0176 method-tier scaffold archetypes are built in);
8
+ * how the M-ADR 0173/0176 method-tier scaffold archetypes are built in);
9
9
  * - the **reference-architecture / adopter bundle tiers** — seedless
10
10
  * vocabulary files (`application-archetypes.yaml`) shipped in consumed
11
11
  * bundles and extracted to the local bundle cache
@@ -13,7 +13,7 @@
13
13
  * - an optional **adopter-local** extension file at
14
14
  * `.sdd/application-archetypes.yaml` in the SDD repo.
15
15
  *
16
- * This deliberately does NOT reuse the ADR 0176 scaffold registry resolver
16
+ * This deliberately does NOT reuse the M-ADR 0176 scaffold registry resolver
17
17
  * (`scaffold/registry.ts`): that resolver is seed-oriented and drops any
18
18
  * entry with no `seeds[]`, whereas a classification archetype is seedless by
19
19
  * design. It DOES share the same bundle-cache distribution substrate — this
@@ -1,8 +1,8 @@
1
- # Default archetype map — android (ADR 0169 §4.2). Method-owned.
1
+ # Default archetype map — android (M-ADR 0169 §4.2). Method-owned.
2
2
  #
3
3
  # Android View + Material toolkit. These names are industry-standard (Google/AndroidX/Material)
4
4
  # and identical across every Android app — never an adopter's bespoke vocabulary.
5
- # Resolution order (ADR 0169 §4.3): adopter overlay override -> by_token -> by_suffix_heuristic -> default.
5
+ # Resolution order (M-ADR 0169 §4.3): adopter overlay override -> by_token -> by_suffix_heuristic -> default.
6
6
  # Selected per screen by `platform: android` frontmatter.
7
7
 
8
8
  map_version: "1.0.0"
@@ -1,8 +1,8 @@
1
- # Default archetype map — swiftui (ADR 0169 §4.2). Method-owned.
1
+ # Default archetype map — swiftui (M-ADR 0169 §4.2). Method-owned.
2
2
  #
3
3
  # Apple SwiftUI toolkit. Industry-standard Apple names, identical across every SwiftUI app —
4
4
  # never an adopter's bespoke vocabulary.
5
- # Resolution order (ADR 0169 §4.3): adopter overlay override -> by_token -> by_suffix_heuristic -> default.
5
+ # Resolution order (M-ADR 0169 §4.3): adopter overlay override -> by_token -> by_suffix_heuristic -> default.
6
6
  # Selected per screen by `platform: swiftui` frontmatter.
7
7
 
8
8
  map_version: "1.0.0"
@@ -1,8 +1,8 @@
1
- # Default archetype map — uikit (ADR 0169 §4.2). Method-owned.
1
+ # Default archetype map — uikit (M-ADR 0169 §4.2). Method-owned.
2
2
  #
3
3
  # Apple UIKit toolkit. Industry-standard Apple names (UI- prefixed), identical across every
4
4
  # UIKit app — never an adopter's bespoke vocabulary.
5
- # Resolution order (ADR 0169 §4.3): adopter overlay override -> by_token -> by_suffix_heuristic -> default.
5
+ # Resolution order (M-ADR 0169 §4.3): adopter overlay override -> by_token -> by_suffix_heuristic -> default.
6
6
  # Selected per screen by `platform: uikit` frontmatter.
7
7
 
8
8
  map_version: "1.0.0"
@@ -1,8 +1,8 @@
1
- # Default archetype map — web-generic (ADR 0169 §4.2). Method-owned.
1
+ # Default archetype map — web-generic (M-ADR 0169 §4.2). Method-owned.
2
2
  #
3
3
  # Keys off component NAMES (which the builder already parses), not design-system source.
4
4
  # Vendor-standard / common-DS tokens ONLY — never an adopter's bespoke vocabulary.
5
- # Resolution order (ADR 0169 §4.3): adopter overlay override -> by_token -> by_suffix_heuristic -> default.
5
+ # Resolution order (M-ADR 0169 §4.3): adopter overlay override -> by_token -> by_suffix_heuristic -> default.
6
6
  # Selected per screen by `platform: web-generic` (or web) frontmatter.
7
7
 
8
8
  map_version: "1.0.0"
@@ -1,12 +1,12 @@
1
- # OpenUI Archetype Vocabulary — method-owned (ADR 0169 §4.1)
1
+ # OpenUI Archetype Vocabulary — method-owned (M-ADR 0169 §4.1)
2
2
  #
3
3
  # A closed, platform-tagged superset of visual archetypes. An archetype assigns a
4
4
  # component a VISUAL SHAPE + slots/orientation — never geometry or styling (stays inside
5
- # the compose-only boundary, ADR 0166 §3). Default archetype maps
5
+ # the compose-only boundary, M-ADR 0166 §3). Default archetype maps
6
6
  # (archetype-maps/*.yaml) resolve adopter component NAMES to entries here; the
7
7
  # render-screen-wireframe skill lowers a resolved tree to SVG using `render`.
8
8
  #
9
- # `is_container` feeds ADR 0168 §4.1 isContainer when a resolved map is present.
9
+ # `is_container` feeds M-ADR 0168 §4.1 isContainer when a resolved map is present.
10
10
 
11
11
  vocabulary_version: "1.0.0"
12
12
 
@@ -1,12 +1,12 @@
1
- // OpenUI archetype resolver (per ADR 0169).
1
+ // OpenUI archetype resolver (per M-ADR 0169).
2
2
  //
3
3
  // Binds an adopter component NAME to a visual ARCHETYPE via a method-shipped
4
4
  // platform default map plus an optional adopter overlay. The binding is what
5
5
  // makes a shape-blind openui-lang block renderable as a wireframe, and it
6
- // supplies the container/leaf classification the ADR 0168 `screen-root-is-leaf`
6
+ // supplies the container/leaf classification the M-ADR 0168 `screen-root-is-leaf`
7
7
  // check consumes (isContainerArchetype).
8
8
  //
9
- // Resolution order (ADR 0169 §4.3): adopter override -> default by_token (after
9
+ // Resolution order (M-ADR 0169 §4.3): adopter override -> default by_token (after
10
10
  // stripping a vendor prefix) -> by_suffix_heuristic -> default (panel).
11
11
  //
12
12
  // The vocabulary + the four default maps are method-owned reference data,
@@ -74,7 +74,7 @@ export function resolveArchetype(name, platform, overlay) {
74
74
  }
75
75
  /**
76
76
  * Whether a component classifies as a container archetype for a platform.
77
- * Used by ADR 0168 §4.1 isContainer to refine the appears-with-children
77
+ * Used by M-ADR 0168 §4.1 isContainer to refine the appears-with-children
78
78
  * heuristic. Returns undefined when the platform has no map (caller falls back
79
79
  * to the heuristic) so an absent map never mis-classifies a known container.
80
80
  */
@@ -1,4 +1,4 @@
1
- // Deterministic structural-wireframe renderer (ADR 0169 §4.4).
1
+ // Deterministic structural-wireframe renderer (M-ADR 0169 §4.4).
2
2
  //
3
3
  // Lowers a screen's openui-lang block to an SVG wireframe: parse the block into
4
4
  // a composition tree, resolve each node to a visual archetype, and lay it out
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Per-SDD catalogue builder — `sdd-cli catalogue build` orchestrator.
3
3
  *
4
- * Per ADR 0134 §4.6, the canonical builder reads method-defined declarative
4
+ * Per M-ADR 0134 §4.6, the canonical builder reads method-defined declarative
5
5
  * inputs and emits `catalogues/*.csv` matching the canonical schema.
6
6
  *
7
7
  * The orchestrator provides:
@@ -119,7 +119,7 @@ export async function runCatalogueBuild(inputs, write) {
119
119
  }
120
120
  // 5. Internal FK validation (external FKs logged as findings). Pass the
121
121
  // SDD profile so profile-external FKs (schema 2.23.0, e.g. an app/integration
122
- // capability's platform-resident domain_id per ADR 0136) resolve at
122
+ // capability's platform-resident domain_id per M-ADR 0136) resolve at
123
123
  // aggregation instead of failing this local build.
124
124
  const { fk, enums } = await validateWithEngineToLog(schema, rowsByCatalogue, findings, { profile: manifest.profile });
125
125
  // 5b. Bound-enum validation (M-ADR 0203 §4.1): every column_enums-bound
@@ -172,7 +172,7 @@ export async function runCatalogueBuild(inputs, write) {
172
172
  // declared primary-key uniqueness — always a hard failure, like a dangling
173
173
  // internal FK. (The silent-union path is not a failure: it is the expected
174
174
  // outcome of two sources asserting the same fact.)
175
- // Error-severity findings (e.g. the ADR 0168 screen-spec status gate) fail the
175
+ // Error-severity findings (e.g. the M-ADR 0168 screen-spec status gate) fail the
176
176
  // build by default, independent of --strict.
177
177
  const exitCode = !fk.internalPass || dedupe.conflicts.length > 0 || findings.errorCount() > 0 || strictFail
178
178
  ? 1
@@ -312,7 +312,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
312
312
  })));
313
313
  }
314
314
  // 5. Services derived 1:1 from runtime-typed repositories.
315
- // Forward `description` source (ADR 0163 P1): repo-config `description:`,
315
+ // Forward `description` source (M-ADR 0163 P1): repo-config `description:`,
316
316
  // parsed but previously dropped by the repositories builder.
317
317
  const repoDescriptions = new Map();
318
318
  const declaredServicesByRepo = new Map();
@@ -503,18 +503,18 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
503
503
  contractIdByPath: mergedContractIdByPath,
504
504
  }));
505
505
  // 10. Repo edges — repo_capability, repo_contract (feature_repo empty
506
- // here; populated by feature-grounding extractor below per ADR 0143).
506
+ // here; populated by feature-grounding extractor below per M-ADR 0143).
507
507
  const capabilityIdByPath = new Map();
508
508
  for (const cap of capabilities) {
509
509
  const sp = String(cap["spec_path"] ?? "");
510
510
  if (sp !== "")
511
511
  capabilityIdByPath.set(sp, String(cap["id"]));
512
512
  }
513
- // Per ADR 0157, repo-edges has both forward-declared (additional_context,
513
+ // Per M-ADR 0157, repo-edges has both forward-declared (additional_context,
514
514
  // repo-config.contracts) and reverse-derived (capability_service ⋈
515
515
  // services.primary_repo_id, contracts.source_repo_id denorm) paths. Note
516
516
  // that the capability_feature ⋈ feature_repo path (Y) needs feature_repo
517
- // populated, which the ADR 0143 extractor below (10a) does — but repo-edges
517
+ // populated, which the M-ADR 0143 extractor below (10a) does — but repo-edges
518
518
  // runs first. So Path Y picks up zero rows here; the second pass after
519
519
  // grounding extracts (below) appends the missing edges.
520
520
  const knownRepoIds = new Set(repos.map((r) => String(r["id"])));
@@ -558,7 +558,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
558
558
  knownServiceIds: knownServiceIdsForExemption,
559
559
  allowedReasons: serviceExemptionReasons,
560
560
  }));
561
- // 10a. Feature-grounding extractor per ADR 0143 (schema 2.5.0).
561
+ // 10a. Feature-grounding extractor per M-ADR 0143 (schema 2.5.0).
562
562
  // Walks docs/domains/*/design/*/feature-grounding.md (platform-profile)
563
563
  // or docs/design/integration/feature-grounding.md (integration-product)
564
564
  // and emits feature rows (source: feature-grounding) plus capability_feature,
@@ -588,7 +588,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
588
588
  ]);
589
589
  }
590
590
  // feature_repo + feature_service edges are stored unconditionally —
591
- // per ADR 0143 §2 they're grounding's unique contribution and must
591
+ // per M-ADR 0143 §2 they're grounding's unique contribution and must
592
592
  // emit even when every grounding row collides on feature id with an
593
593
  // earlier source (`feature-tree` / `feature-spec`). Pre-0.30.2 the
594
594
  // conditional above gated feature_repo on the row emission, dropping
@@ -599,13 +599,13 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
599
599
  ]);
600
600
  // feature_service starts here — earlier passes don't populate it.
601
601
  out.set("feature_service", grounding.featureServiceRows);
602
- // 10b. Capability-spec extractor per ADR 0145 (schema 2.7.0).
602
+ // 10b. Capability-spec extractor per M-ADR 0145 (schema 2.7.0).
603
603
  // Walks docs/domains/*/product/*.md (platform-profile only) and emits
604
604
  // feature rows (source: capability-spec) plus capability_feature,
605
605
  // feature_repo, feature_service edges from the
606
606
  // `## Feature Grounding (code-path trace)` table. Runs after the
607
607
  // feature-grounding extractor so precedence (feature-grounding wins
608
- // on id collision) is enforced. Reuses ADR 0143's alias map for
608
+ // on id collision) is enforced. Reuses M-ADR 0143's alias map for
609
609
  // service / repo resolution.
610
610
  const existingFeatureIdsAfterGrounding = new Set((out.get("features") ?? []).map((r) => String(r["id"])));
611
611
  const capabilitySpec = await buildCapabilitySpec({
@@ -629,7 +629,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
629
629
  ]);
630
630
  }
631
631
  // feature_repo + feature_service edges are stored unconditionally —
632
- // per ADR 0145 they're capability-spec's unique contribution and must
632
+ // per M-ADR 0145 they're capability-spec's unique contribution and must
633
633
  // emit even when every capability-spec row collides on feature id with an
634
634
  // earlier source. Pre-fix the conditional above gated these edges on the
635
635
  // row emission, dropping them in the all-collide case (same two-level bug
@@ -714,7 +714,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
714
714
  out.set("feature_repo", [...existingFeatureRepo, ...derived]);
715
715
  }
716
716
  }
717
- // 10b-bis. Second pass on repo_capability Path Y (per ADR 0157 §4.3) —
717
+ // 10b-bis. Second pass on repo_capability Path Y (per M-ADR 0157 §4.3) —
718
718
  // capability_feature ⋈ feature_repo. The initial repo-edges pass (step 10)
719
719
  // ran before the feature-grounding extractor populated feature_repo, so
720
720
  // Path Y picked up zero rows there. Now that feature_repo is fully built,
@@ -821,7 +821,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
821
821
  }
822
822
  }
823
823
  // 11. Events + service_event + capability_event.
824
- // Per ADR 0156 (schema 2.12.0), events ingest from both the forward-method
824
+ // Per M-ADR 0156 (schema 2.12.0), events ingest from both the forward-method
825
825
  // avsc path and the reverse-method `event-catalog.yaml` path. YAML wins on
826
826
  // name/domain/publisher/transport; avsc augments schema_path/version.
827
827
  // service_event edges populate from both repo-config events.produces/consumes
@@ -863,7 +863,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
863
863
  // repos/<service>/docs/service-architecture.md External Interfaces table.
864
864
  // The consumes-emission path is gated on an adopter-supplied
865
865
  // .sdd/service-contract-aliases.yaml mapping interface display text to
866
- // canonical contract names. Pattern documented in ADR 0147.
866
+ // canonical contract names. Pattern documented in M-ADR 0147.
867
867
  const exposesRows = buildServiceContract({
868
868
  findings,
869
869
  configs: reposResult.configs,
@@ -900,7 +900,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
900
900
  }
901
901
  }
902
902
  }
903
- // 12-bis. Second pass on repo_contract Path X (per ADR 0157 §4.2 amendment) —
903
+ // 12-bis. Second pass on repo_contract Path X (per M-ADR 0157 §4.2 amendment) —
904
904
  // service_contract ⋈ services.primary_repo_id. The initial repo-edges pass
905
905
  // (step 10) ran before service_contract was built, so Path X picked up zero
906
906
  // rows there. Now that service_contract is fully populated, derive the
@@ -947,9 +947,9 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
947
947
  featureServiceRows: out.get("feature_service") ?? [],
948
948
  serviceContractRows: out.get("service_contract") ?? [],
949
949
  }));
950
- // 12a-bis. feature_event — derived edge per schema 2.15.0 / ADR 0161.
950
+ // 12a-bis. feature_event — derived edge per schema 2.15.0 / M-ADR 0161.
951
951
  // Pure join of feature_service ⋈ service_event; no authored shape. Mirrors
952
- // ADR 0160's capability_event derived path one rung lower in the hierarchy.
952
+ // M-ADR 0160's capability_event derived path one rung lower in the hierarchy.
953
953
  out.set("feature_event", buildFeatureEvent({
954
954
  knownFeatureIds: featureIdsAfterAllSources,
955
955
  knownEventIds,
@@ -957,7 +957,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
957
957
  serviceEventRows: out.get("service_event") ?? [],
958
958
  }));
959
959
  // 12b. domain_models + capability_domain_model + feature_domain_model
960
- // per schema 2.4.0 / ADR 0142. Platform-profile only — non-platform
960
+ // per schema 2.4.0 / M-ADR 0142. Platform-profile only — non-platform
961
961
  // builds emit headers-only. domain_models runs first; the edges depend
962
962
  // on its known-id set.
963
963
  const domainModels = await buildDomainModels({
@@ -984,8 +984,8 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
984
984
  capabilityDomainModelRows: out.get("capability_domain_model") ?? [],
985
985
  }));
986
986
  // 13. App-product profile builders (personas, journeys, persona/journey
987
- // edges, product-edges). Per ADR 0134, app-product SDDs emit these
988
- // catalogues; other profiles emit zero rows. Per ADR 0136, product_*
987
+ // edges, product-edges). Per M-ADR 0134, app-product SDDs emit these
988
+ // catalogues; other profiles emit zero rows. Per M-ADR 0136, product_*
989
989
  // edges' capability_id and service_id are external FKs validated by
990
990
  // the aggregator, not here.
991
991
  const featureIdByPath = featuresResult.idByPath;
@@ -1024,12 +1024,12 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
1024
1024
  featureIdByPath,
1025
1025
  featureIdBySlug,
1026
1026
  }));
1027
- // UI screens family (per ADR 0166). Application-product profile; the walker
1027
+ // UI screens family (per M-ADR 0166). Application-product profile; the walker
1028
1028
  // reads `screens/*.md` screen-spec artefacts (frontmatter + ```openui-lang
1029
1029
  // block) and emits the six catalogues. Other profiles have no screens/ dir →
1030
1030
  // empty. FK resolution uses the feature + persona id maps already built.
1031
- // Optional adopter-tunable screen-validation parameters (ADR 0168 §4.5 /
1032
- // ADR 0169 §4.3); absent → method defaults (the vocabulary-free checks run).
1031
+ // Optional adopter-tunable screen-validation parameters (M-ADR 0168 §4.5 /
1032
+ // M-ADR 0169 §4.3); absent → method defaults (the vocabulary-free checks run).
1033
1033
  const screenValidation = await loadScreenValidationConfig(sddPath);
1034
1034
  const screensResult = await buildScreens({
1035
1035
  sddPath,
@@ -1091,7 +1091,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
1091
1091
  });
1092
1092
  out.set("scaffolds", scaffoldsResult.scaffolds);
1093
1093
  out.set("scaffold_items", scaffoldsResult.scaffoldItems);
1094
- // Screen↔capability context cross-check (ADR 0170 §4.6, schema 2.21.0):
1094
+ // Screen↔capability context cross-check (M-ADR 0170 §4.6, schema 2.21.0):
1095
1095
  // a screen's `context:` should equal the context of the capability it
1096
1096
  // realises (screen → screen_feature → feature.capability_id →
1097
1097
  // capability.context). Convention finding, never an FK failure — the
@@ -1167,6 +1167,9 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
1167
1167
  out.set("requirements", r.requirements);
1168
1168
  out.set("requirement_lineage", r.lineage);
1169
1169
  out.set("requirement_status", r.status);
1170
+ out.set("changes", r.changes);
1171
+ out.set("change_work_order", r.workOrders);
1172
+ out.set("change_work_item", r.workItems);
1170
1173
  }
1171
1174
  // 15. C4 systems + containers + components (L1 + L2 + L3). The L3 walker
1172
1175
  // is the forward-method authoring path reading
@@ -1203,7 +1206,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
1203
1206
  c4ContainerRows: c4Containers,
1204
1207
  });
1205
1208
  out.set("c4_components", c4Components);
1206
- // 15b. C4 L1 context elements (ADR 0155): external systems + the
1209
+ // 15b. C4 L1 context elements (M-ADR 0155): external systems + the
1207
1210
  // persona→system and system→external edges, extracted from System_Ext /
1208
1211
  // Person / Rel macros on the L1/L2 diagrams. (The rows were computed at
1209
1212
  // step 7, where capability_service consults them — see above.)
@@ -1274,7 +1277,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
1274
1277
  });
1275
1278
  out.set("glossary_items", glossaryResult.rows);
1276
1279
  const knownGlossaryIds = new Set(glossaryResult.rows.map((r) => String(r["id"])));
1277
- // Per ADR 0158 (schema 2.12.0), the glossary-xref builder ingests from
1280
+ // Per M-ADR 0158 (schema 2.12.0), the glossary-xref builder ingests from
1278
1281
  // five walkers and emits two catalogues: glossary_xref (term-to-term
1279
1282
  // relations) and entity_glossary (new sibling — data-model entity to
1280
1283
  // canonical term mappings).
@@ -1291,7 +1294,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
1291
1294
  // Backfill canonical_term_id + aliases onto glossary_items from the xref
1292
1295
  // edges (same alignment manifest, resolved downstream).
1293
1296
  out.set("glossary_items", backfillGlossaryRelations(glossaryResult.rows, xref.glossaryXref));
1294
- // 17. Data-model entities + service_entity + C4 roll-ups per ADR 0159
1297
+ // 17. Data-model entities + service_entity + C4 roll-ups per M-ADR 0159
1295
1298
  // (schema 2.13.0). Four new catalogues, five walkers:
1296
1299
  //
1297
1300
  // - entities-manifest: forward path, reads models[].entities[] from
@@ -1322,7 +1325,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
1322
1325
  knownGlossaryIds,
1323
1326
  });
1324
1327
  // Forward wins on attribute conflicts (matches per-adopter authoring intent
1325
- // per ADR 0159 §4.4). Reverse rows seed the map; forward overwrites.
1328
+ // per M-ADR 0159 §4.4). Reverse rows seed the map; forward overwrites.
1326
1329
  const entitiesById = new Map();
1327
1330
  for (const r of entitiesFromMermaid)
1328
1331
  entitiesById.set(String(r["id"]), r);
@@ -1330,9 +1333,9 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
1330
1333
  entitiesById.set(String(r["id"]), r);
1331
1334
  const entityRows = [...entitiesById.values()];
1332
1335
  out.set("entities", entityRows);
1333
- // Per ADR 0159 §4.9: now that entities.csv exists, append entity_glossary
1336
+ // Per M-ADR 0159 §4.9: now that entities.csv exists, append entity_glossary
1334
1337
  // rows for the reverse-method side. The forward-method emission via
1335
- // glossary-xref's models[].entities[] walker (ADR 0158) is already in
1338
+ // glossary-xref's models[].entities[] walker (M-ADR 0158) is already in
1336
1339
  // xref.entityGlossary; here we extend with rows derived from
1337
1340
  // entities-mermaid's slug-matched glossary_term FKs.
1338
1341
  const existingEntityGlossaryPks = new Set(xref.entityGlossary.map((r) => String(r["id"])));
@@ -1370,7 +1373,7 @@ async function collectRows(schema, manifest, findings, sddPath, snapshotStore) {
1370
1373
  if (!entityIdBySlug.has(slug))
1371
1374
  entityIdBySlug.set(slug, id);
1372
1375
  }
1373
- // ADR 0164: backfill entities.persistence_kind from the Data Store Mapping
1376
+ // M-ADR 0164: backfill entities.persistence_kind from the Data Store Mapping
1374
1377
  // Store column (reverse-only; forward store-less tables leave it empty).
1375
1378
  const enrichedEntityRows = await enrichEntityPersistenceKind({
1376
1379
  sddPath,
@@ -1466,7 +1469,7 @@ function checkScreenCapabilityContext(args) {
1466
1469
  if (sCtx !== cCtx) {
1467
1470
  args.findings.add("convention", `screen-capability context mismatch: screen "${screenId}" ` +
1468
1471
  `(context=${sCtx}) realises capability "${capId}" ` +
1469
- `(context=${cCtx}) — a seam screen or a mistag (ADR 0170 §4.6)`);
1472
+ `(context=${cCtx}) — a seam screen or a mistag (M-ADR 0170 §4.6)`);
1470
1473
  }
1471
1474
  }
1472
1475
  }