@sdd-method/author-cli 0.7.0 → 0.9.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 (100) hide show
  1. package/dist/author-program.js +2 -1
  2. package/dist/lib/agent-harness.js +2 -2
  3. package/dist/lib/behaviour-store/archive.js +28 -1
  4. package/dist/lib/behaviour-store/schema.js +85 -0
  5. package/dist/lib/briefing/index.js +1 -1
  6. package/dist/lib/briefing/render.js +1 -1
  7. package/dist/lib/briefing/variables.js +1 -1
  8. package/dist/lib/catalogue/application-archetype/vocabulary.js +2 -2
  9. package/dist/lib/catalogue/archetype/maps/android.yaml +2 -2
  10. package/dist/lib/catalogue/archetype/maps/swiftui.yaml +2 -2
  11. package/dist/lib/catalogue/archetype/maps/uikit.yaml +2 -2
  12. package/dist/lib/catalogue/archetype/maps/web-generic.yaml +2 -2
  13. package/dist/lib/catalogue/archetype/openui-archetype-vocabulary.yaml +3 -3
  14. package/dist/lib/catalogue/archetype/resolver.js +4 -4
  15. package/dist/lib/catalogue/archetype/wireframe.js +1 -1
  16. package/dist/lib/catalogue/build.js +36 -33
  17. package/dist/lib/catalogue/builders/adr-supersedes.js +3 -3
  18. package/dist/lib/catalogue/builders/adrs.js +3 -3
  19. package/dist/lib/catalogue/builders/c4-containers.js +2 -2
  20. package/dist/lib/catalogue/builders/c4-entity-rollups.js +1 -1
  21. package/dist/lib/catalogue/builders/c4-external-systems.js +2 -2
  22. package/dist/lib/catalogue/builders/c4-systems.js +1 -1
  23. package/dist/lib/catalogue/builders/capabilities.js +1 -1
  24. package/dist/lib/catalogue/builders/capability-domain-model.js +1 -1
  25. package/dist/lib/catalogue/builders/capability-spec-walker.js +2 -2
  26. package/dist/lib/catalogue/builders/capability-spec.js +4 -4
  27. package/dist/lib/catalogue/builders/contracts.js +3 -3
  28. package/dist/lib/catalogue/builders/data-store-mapping.js +2 -2
  29. package/dist/lib/catalogue/builders/domain-models.js +2 -2
  30. package/dist/lib/catalogue/builders/domains.js +3 -3
  31. package/dist/lib/catalogue/builders/entities-manifest.js +8 -8
  32. package/dist/lib/catalogue/builders/entities-mermaid.js +4 -4
  33. package/dist/lib/catalogue/builders/entity-persistence.js +1 -1
  34. package/dist/lib/catalogue/builders/entity-slug.js +3 -3
  35. package/dist/lib/catalogue/builders/event-catalog-walker.js +6 -6
  36. package/dist/lib/catalogue/builders/event-edges.js +6 -6
  37. package/dist/lib/catalogue/builders/events.js +3 -3
  38. package/dist/lib/catalogue/builders/evidence-class.js +1 -1
  39. package/dist/lib/catalogue/builders/feature-domain-model.js +1 -1
  40. package/dist/lib/catalogue/builders/feature-grounding-walker.js +2 -2
  41. package/dist/lib/catalogue/builders/feature-grounding.js +5 -5
  42. package/dist/lib/catalogue/builders/feature-subscription-channels.js +3 -3
  43. package/dist/lib/catalogue/builders/features.js +1 -1
  44. package/dist/lib/catalogue/builders/glossary-xref.js +4 -4
  45. package/dist/lib/catalogue/builders/integrations.js +4 -4
  46. package/dist/lib/catalogue/builders/persona-c4system.js +1 -1
  47. package/dist/lib/catalogue/builders/product-edges.js +1 -1
  48. package/dist/lib/catalogue/builders/product-platform-dependencies.js +2 -2
  49. package/dist/lib/catalogue/builders/products.js +5 -5
  50. package/dist/lib/catalogue/builders/repo-edges.js +12 -12
  51. package/dist/lib/catalogue/builders/repositories.js +11 -7
  52. package/dist/lib/catalogue/builders/requirements.js +110 -11
  53. package/dist/lib/catalogue/builders/screen-tree.js +6 -6
  54. package/dist/lib/catalogue/builders/screens.js +18 -18
  55. package/dist/lib/catalogue/builders/service-contract-consumes.js +1 -1
  56. package/dist/lib/catalogue/builders/service-entity-tables.js +3 -3
  57. package/dist/lib/catalogue/builders/services.js +5 -5
  58. package/dist/lib/catalogue/builders/system-external-dependency.js +2 -2
  59. package/dist/lib/catalogue/canonical-schema.yaml +138 -2
  60. package/dist/lib/catalogue/coverage-render.js +15 -15
  61. package/dist/lib/catalogue/csv-writer.js +1 -1
  62. package/dist/lib/catalogue/feature-grounding-aliases-loader.js +1 -1
  63. package/dist/lib/catalogue/findings.js +1 -1
  64. package/dist/lib/catalogue/fk-validator.js +2 -2
  65. package/dist/lib/catalogue/manifest-loader.js +3 -3
  66. package/dist/lib/catalogue/rubric-coverage-map.yaml +28 -0
  67. package/dist/lib/catalogue/schema-compat.js +2 -2
  68. package/dist/lib/catalogue/schema-loader.js +1 -1
  69. package/dist/lib/catalogue/screen-validation-loader.js +2 -2
  70. package/dist/lib/catalogue/service-architecture-parser.js +1 -1
  71. package/dist/lib/catalogue/traceability-loader.js +6 -4
  72. package/dist/lib/conformance/finding.js +1 -1
  73. package/dist/lib/conformance/index.js +5 -5
  74. package/dist/lib/generate-briefing/index.js +2 -2
  75. package/dist/lib/metamodel/tql-subset-parser.js +280 -0
  76. package/dist/lib/pack/schema.js +2 -2
  77. package/dist/lib/pack/seed.js +2 -2
  78. package/dist/lib/pack/validate.js +1 -1
  79. package/dist/lib/plan/read-sdd.js +1 -1
  80. package/dist/lib/repo-kind.js +4 -12
  81. package/dist/lib/scaffold/archetype-behaviour.js +173 -0
  82. package/dist/lib/scaffold/behaviour-store.js +60 -0
  83. package/dist/lib/scaffold/domain.js +24 -6
  84. package/dist/lib/scaffold/registry.js +1 -1
  85. package/dist/lib/sync/briefing-merge.js +2 -2
  86. package/dist/lib/sync/bundle-cache.js +4 -4
  87. package/dist/lib/sync/yaml-block-merge.js +1 -1
  88. package/dist/lib/validate/archetype-citations.js +169 -0
  89. package/dist/lib/validate/behaviour-store.js +161 -6
  90. package/dist/lib/validate/dispatch.js +8 -1
  91. package/dist/maintain-version.json +2 -2
  92. package/dist/verbs/conformance.js +3 -3
  93. package/dist/verbs/list.js +1 -1
  94. package/dist/verbs/render.js +1 -1
  95. package/dist/verbs/scaffold.js +36 -4
  96. package/dist/verify-program.js +2 -2
  97. package/dist/verify-version.json +2 -2
  98. package/package.json +2 -2
  99. package/scripts/validate-app-dependencies.sh +1 -1
  100. package/scripts/validate-integration-docs.sh +1 -1
@@ -1,4 +1,4 @@
1
- // Phase 3 C4-to-entity roll-up walkers per ADR 0159 §4.8.
1
+ // Phase 3 C4-to-entity roll-up walkers per M-ADR 0159 §4.8.
2
2
  // Both are pure transitive joins over already-FK-enforced inputs.
3
3
  //
4
4
  // buildC4ContainerEntity:
@@ -1,5 +1,5 @@
1
1
  // C4 external software systems discoverer — emits `c4_external_systems.csv`
2
- // rows (per ADR 0155). External systems are C4 L1 peers the ecosystem
2
+ // rows (per M-ADR 0155). External systems are C4 L1 peers the ecosystem
3
3
  // integrates with but does not own; they are rendered `System_Ext(...)` on
4
4
  // L1/L2 diagrams (and occasionally `Container_Ext(...)` for an external
5
5
  // system's container). They are NOT c4_containers (not inside your system)
@@ -12,7 +12,7 @@
12
12
  // (schema 3.0.0, M-ADR 0203 §4.2) — so identity is the author's declared
13
13
  // assertion, the same identity the aggregator adjudicates (M-ADR 0189
14
14
  // §4.2). The same declared identity across SDDs collapses to one row at
15
- // aggregation (the dedup-by-PK exception to ADR 0134). Two entries whose
15
+ // aggregation (the dedup-by-PK exception to M-ADR 0134). Two entries whose
16
16
  // DISPLAY NAMES agree but whose entry ids differ are two rows — the
17
17
  // same-entity-two-labels case made visible instead of silently merged;
18
18
  // the 2.x name-slug ids map to these via the ext-id migration map.
@@ -1,6 +1,6 @@
1
1
  // C4 L1 systems discoverer — emits at most one `c4_systems.csv` row.
2
2
  //
3
- // Per ADR 0134's federation model, each SDD emits its OWN c4_systems
3
+ // Per M-ADR 0134's federation model, each SDD emits its OWN c4_systems
4
4
  // row when its manifest category is architectural. Categories map to
5
5
  // the c4_system_kind enum (canonical-schema.yaml):
6
6
  // platform-root → platform
@@ -2,7 +2,7 @@
2
2
  // traceability YAMLs (authoritative) plus capability spec files
3
3
  // (fallback for specs not covered by a traceability).
4
4
  //
5
- // Per ADR 0134 and the catalogue-builder-specification §"Inputs":
5
+ // Per M-ADR 0134 and the catalogue-builder-specification §"Inputs":
6
6
  // - Authoritative source: docs/domains/<domain>/product/<cap>.traceability.yaml
7
7
  // declares capability.id (canonical), domain, capability_spec, runway.
8
8
  // - Fallback: capability spec markdown files at
@@ -14,7 +14,7 @@
14
14
  // Domain model ids follow the `{domain_id}-data-model` convention from
15
15
  // the domain-models builder.
16
16
  //
17
- // Added in schema 2.4.0 per ADR 0142.
17
+ // Added in schema 2.4.0 per M-ADR 0142.
18
18
  export function buildCapabilityDomainModel(inputs) {
19
19
  if (inputs.manifest.profile !== "platform-profile") {
20
20
  return [];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Walker for capability spec markdown files per ADR 0145 (schema 2.7.0).
2
+ * Walker for capability spec markdown files per M-ADR 0145 (schema 2.7.0).
3
3
  *
4
4
  * Reads `## Feature Grounding (code-path trace)` markdown tables of the
5
5
  * canonical shape:
@@ -8,7 +8,7 @@
8
8
  * |---|---|---|
9
9
  * | `banners-module` | `banners` store module + `src/components/banners` | docs/.../feature-grounding.md |
10
10
  *
11
- * Path convention (per ADR 0145 §4.3):
11
+ * Path convention (per M-ADR 0145 §4.3):
12
12
  * - platform-profile: `docs/domains/<dom>/product/<capability>.md`
13
13
  *
14
14
  * Capability id resolves from the filename stem. Tolerant of column
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Capability-spec feature extractor per ADR 0145 (schema 2.7.0).
2
+ * Capability-spec feature extractor per M-ADR 0145 (schema 2.7.0).
3
3
  *
4
4
  * Walks `docs/domains/<dom>/product/<capability>.md` (platform-profile),
5
5
  * parses the `## Feature Grounding (code-path trace)` markdown table,
@@ -12,7 +12,7 @@
12
12
  * - `feature_service.csv` rows derived from class names / file
13
13
  * basenames / route fragments in the Implementation column,
14
14
  * resolved via `services.csv` + the optional per-SDD alias map
15
- * introduced by ADR 0143.
15
+ * introduced by M-ADR 0143.
16
16
  *
17
17
  * Resolution is best-effort and never breaks FK validation — only
18
18
  * confidently-resolved rows are emitted. Unresolved CAPABILITY ids emit
@@ -25,7 +25,7 @@
25
25
  * coverage finding per row plus one summary line (M-ADR 0143 §4.4 as
26
26
  * amended); it measures resolution coverage, never correctness.
27
27
  *
28
- * Precedence per ADR 0145 §4.7: feature-tree, feature-spec, and
28
+ * Precedence per M-ADR 0145 §4.7: feature-tree, feature-spec, and
29
29
  * feature-grounding rows win on id collision (they are more specific
30
30
  * sources); capability-spec rows are skipped with a divergence finding
31
31
  * when their id is already taken.
@@ -105,7 +105,7 @@ export async function buildCapabilitySpec(inputs) {
105
105
  // When the earlier source DID also emit the edge, the ids are identical
106
106
  // (`${cap}__${feature}` in every emitter) and keyed-table dedup unions
107
107
  // them — dedup rows, keep edges. feature_repo / feature_service remain
108
- // this source's unique contribution (ADR 0145) as before.
108
+ // this source's unique contribution (M-ADR 0145) as before.
109
109
  if (seenFeatures.has(featureId)) {
110
110
  // Same one-check-two-meanings split as feature-grounding.ts: a hit on
111
111
  // an id seeded from an EARLIER SOURCE is the documented precedence rule
@@ -8,7 +8,7 @@
8
8
  // - openapi/*.yaml → rest
9
9
  // - proto/*.proto → rpc
10
10
  // - avro/*.avsc → event
11
- // - service_id and source_repo_id are nullable; per ADR 0110 the real
11
+ // - service_id and source_repo_id are nullable; per M-ADR 0110 the real
12
12
  // contract sources may live in sibling contracts-* repos. The
13
13
  // canonical builder leaves these empty by default; an OpenAPI
14
14
  // `x-source-repo` extension is honoured as a hint when present
@@ -64,7 +64,7 @@ export async function buildContracts(inputs) {
64
64
  const idByPath = new Map();
65
65
  const seen = new Set();
66
66
  // Contract deprecation source (schema 2.22.0): BASELINE.md deprecation-
67
- // runway entries per ADR 0073 §4.8 — the same source
67
+ // runway entries per M-ADR 0073 §4.8 — the same source
68
68
  // validate-deprecation-runway.sh enforces. Absent file = no deprecations.
69
69
  const deprecatedPaths = await readBaselineDeprecations(inputs.sddPath, inputs.findings);
70
70
  const discovered = [];
@@ -173,7 +173,7 @@ export async function buildContracts(inputs) {
173
173
  /**
174
174
  * Read deprecated contract paths from BASELINE.md at the SDD root.
175
175
  *
176
- * Shape per ADR 0073 §4.8 (the deprecation-runway gate's source):
176
+ * Shape per M-ADR 0073 §4.8 (the deprecation-runway gate's source):
177
177
  * contracts:
178
178
  * openapi: [ { path, status, sunset_date? }, ... ]
179
179
  * proto: [ ... ]
@@ -2,7 +2,7 @@
2
2
  // that reverse-method adopters author in
3
3
  // `docs/domains/<domain>/architecture/data-model.mermaid.md`.
4
4
  //
5
- // Extracted so two consumers share one parser (ADR 0164):
5
+ // Extracted so two consumers share one parser (M-ADR 0164):
6
6
  // - service-entity-tables.ts — emits service_entity edges from the
7
7
  // Entity + Owning Service columns (relation=owns).
8
8
  // - entity-persistence.ts — backfills entities.persistence_kind from the
@@ -70,7 +70,7 @@ export function collectTableLines(lines, startIdx) {
70
70
  }
71
71
  return null;
72
72
  }
73
- // ADR 0164: map a Data Store Mapping `Store` cell (a physical engine such as
73
+ // M-ADR 0164: map a Data Store Mapping `Store` cell (a physical engine such as
74
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) —
@@ -21,7 +21,7 @@
21
21
  // is the declarative source) and the reverse check is silent unless the
22
22
  // paths disagree, in which case a `[finding] divergence` is emitted.
23
23
  //
24
- // Added in schema 2.4.0 per ADR 0142.
24
+ // Added in schema 2.4.0 per M-ADR 0142.
25
25
  import { readdir, readFile, stat } from "node:fs/promises";
26
26
  import { join } from "node:path";
27
27
  import { extractFileEvidenceClass } from "./evidence-class.js";
@@ -83,7 +83,7 @@ export async function buildDomainModels(inputs) {
83
83
  }
84
84
  // Step 4: Emit rows sorted by id for determinism. `evidence_class` reads
85
85
  // from the model file's leading ```yaml fence (`evidence-class:`) per the
86
- // documentation-reverse anchor convention (ADR 0175); absent file or
86
+ // documentation-reverse anchor convention (M-ADR 0175); absent file or
87
87
  // declaration → "".
88
88
  const rows = [];
89
89
  for (const [domainId, model] of declaredByDomain) {
@@ -1,6 +1,6 @@
1
1
  // Domain discoverer — emits `domains.csv` rows from `docs/domains/<slug>/`.
2
2
  //
3
- // Per ADR 0134 and catalogue-builder-specification.md:
3
+ // Per M-ADR 0134 and catalogue-builder-specification.md:
4
4
  // - Domains are method-defined: each subdirectory under docs/domains/
5
5
  // is one domain, named by its slug.
6
6
  // - method_profile reflects the SDD's profile (the domain belongs to
@@ -8,7 +8,7 @@
8
8
  // - repo_count is computed by the build orchestrator after repositories
9
9
  // are discovered, since this builder runs first.
10
10
  //
11
- // Per ADR 0136 ("App and Integration Products Do Not Belong to a Primary
11
+ // Per M-ADR 0136 ("App and Integration Products Do Not Belong to a Primary
12
12
  // Domain"), only platform-profile SDDs own domains. Application-product
13
13
  // and integration-product SDDs may have a `docs/domains/<umbrella>/`
14
14
  // subdirectory as a structural-organisation convention (where their
@@ -27,7 +27,7 @@ import { readdir, readFile, stat } from "node:fs/promises";
27
27
  import { join } from "node:path";
28
28
  const DOMAINS_DIR_REL = join("docs", "domains");
29
29
  export async function buildDomains(inputs) {
30
- // Per ADR 0136: only platform-profile SDDs own domains. Non-platform
30
+ // Per M-ADR 0136: only platform-profile SDDs own domains. Non-platform
31
31
  // SDDs return an empty list to avoid duplicate-PK collisions at
32
32
  // aggregation against the canonical platform-profile contribution.
33
33
  if (inputs.manifest.profile !== "platform-profile") {
@@ -1,23 +1,23 @@
1
- // Forward-method walker for the entities catalogue per ADR 0159 §4.2.
1
+ // Forward-method walker for the entities catalogue per M-ADR 0159 §4.2.
2
2
  // Reads `models[].entities[]` from `docs/platform/reference/glossary-alignment-manifest.yaml`.
3
3
  //
4
- // Same input file ADR 0158's entity_glossary walker reads — this walker
4
+ // Same input file M-ADR 0158's entity_glossary walker reads — this walker
5
5
  // promotes the entity entries to first-class entity rows; entity_glossary
6
6
  // continues to emit a separate edge per (domain, entity, glossary_term).
7
7
  //
8
- // **Profile-gated to platform-profile only (per ADR 0159 §4.2 amendment,
8
+ // **Profile-gated to platform-profile only (per M-ADR 0159 §4.2 amendment,
9
9
  // schema 2.13.0 patch).** The manifest is platform-owned ecosystem-wide
10
10
  // content; adopters who syndicate it to sibling application-product /
11
11
  // integration-product SDDs would otherwise see siblings re-emit the entire
12
12
  // entity registry locally with unresolved-domain PKs, then collide en masse
13
13
  // at aggregation. Profile-gating mirrors the precedent set by
14
- // domain-models.ts per ADR 0142 (same scope, same syndication shape).
14
+ // domain-models.ts per M-ADR 0142 (same scope, same syndication shape).
15
15
  //
16
- // Behaviour (ADR 0159 acceptance):
16
+ // Behaviour (M-ADR 0159 acceptance):
17
17
  // - For each models[] entry, derive domain_id from its `domain` field.
18
18
  // `platform-wide` and other non-canonical hints map to empty domain_id
19
19
  // and the entity PK uses the `_platform-wide-{slug}` sentinel prefix
20
- // (per ADR 0159 §4.2 amendment, schema 2.13.0 patch). The underscore
20
+ // (per M-ADR 0159 §4.2 amendment, schema 2.13.0 patch). The underscore
21
21
  // prefix is unreachable via entitySlug (slugify strips underscores), so
22
22
  // the sentinel can't collide with any real domain id including
23
23
  // ecosystem-named domains. A [finding] convention surfaces the choice.
@@ -37,7 +37,7 @@ const MANIFEST_REL_PATH = join("docs", "platform", "reference", "glossary-alignm
37
37
  const NON_CANONICAL_DOMAINS = new Set(["platform-wide", "", "platform_wide"]);
38
38
  const PLATFORM_WIDE_PK_PREFIX = "_platform-wide";
39
39
  export async function buildEntitiesFromManifest(inputs) {
40
- // Profile gate per ADR 0159 §4.2 amendment: only platform-profile SDDs
40
+ // Profile gate per M-ADR 0159 §4.2 amendment: only platform-profile SDDs
41
41
  // read the manifest. Sibling profiles (application-product, integration-
42
42
  // product, support-repo, organisation) emit 0 rows even when the file is
43
43
  // present via syndication.
@@ -114,7 +114,7 @@ export async function buildEntitiesFromManifest(inputs) {
114
114
  glossary_term: glossaryTerm,
115
115
  notes: noteParts.join(";"),
116
116
  // The glossary-alignment manifest's entities[] shape has no evidence
117
- // slot — manifest-sourced rows stay empty (ADR 0175; schema 2.20.0).
117
+ // slot — manifest-sourced rows stay empty (M-ADR 0175; schema 2.20.0).
118
118
  evidence_class: "",
119
119
  source_sdd_id: "",
120
120
  };
@@ -1,8 +1,8 @@
1
- // Reverse-method walker for the entities catalogue per ADR 0159 §4.3.
1
+ // Reverse-method walker for the entities catalogue per M-ADR 0159 §4.3.
2
2
  // Parses `erDiagram` blocks in `docs/domains/{domain}/architecture/data-model.mermaid.md`
3
3
  // (or whatever file domain_models.csv references for that domain).
4
4
  //
5
- // Prototype findings (per ADR 0159 — mermaid authoring quirks):
5
+ // Prototype findings (per M-ADR 0159 — mermaid authoring quirks):
6
6
  // - Multi-erDiagram-per-file is the norm (asset has 7 blocks; identity has 4).
7
7
  // Walker merges entities across all `erDiagram` fences in the file.
8
8
  // - Naming style varies within a single file: UPPER_SNAKE_CASE, PascalCase,
@@ -43,7 +43,7 @@ export async function buildEntitiesFromMermaid(inputs) {
43
43
  }
44
44
  const parsed = parseFile(text, dm, inputs.findings);
45
45
  // File-level evidence class (leading ```yaml fence's `evidence-class:`,
46
- // per the documentation-reverse anchor convention / ADR 0175). Every
46
+ // per the documentation-reverse anchor convention / M-ADR 0175). Every
47
47
  // entity extracted from this file inherits it; absence → "".
48
48
  const fileEvidenceClass = extractFileEvidenceClass(text);
49
49
  // Within-file dedup by id is enforced inside parseFile via seen-set;
@@ -168,7 +168,7 @@ function resolveGlossaryTermBySlug(entityName, domainId, knownGlossaryIds) {
168
168
  if (id === slug || id.endsWith(`-${slug}`))
169
169
  return id;
170
170
  }
171
- // ADR 0165 follow-on: the glossary builder collapses multi-word term slugs
171
+ // M-ADR 0165 follow-on: the glossary builder collapses multi-word term slugs
172
172
  // (BASKET_MESSAGE → "...-basketmessage"), while entitySlug
173
173
  // hyphenates ("basket-message"), so multi-word terms miss the suffix
174
174
  // match above. Reconcile boundary-insensitively (compare hyphen-stripped
@@ -1,4 +1,4 @@
1
- // ADR 0164: backfill `entities.persistence_kind` from the reverse-method
1
+ // M-ADR 0164: backfill `entities.persistence_kind` from the reverse-method
2
2
  // `## Data Store Mapping` table's `Store` column.
3
3
  //
4
4
  // persistence_kind is a reverse-only column (the services parity arc, ADR
@@ -1,5 +1,5 @@
1
1
  // Entity-aware slug helper used by the data-model-entity walkers
2
- // (entities-manifest, entities-mermaid, service-entity-tables) per ADR 0159 §4.6.
2
+ // (entities-manifest, entities-mermaid, service-entity-tables) per M-ADR 0159 §4.6.
3
3
  //
4
4
  // Differs from the base `slugify` in events / capabilities / contracts: adds
5
5
  // an ALLCAPS-then-Pascal split rule so naming-style variation across
@@ -19,7 +19,7 @@
19
19
  // (`POS_TERMINAL_CONFIG`), breaking ~50% of expected service_entity
20
20
  // edges in one reference estate.
21
21
  //
22
- // Acronym-run rule (ADR 0164 wave-2 follow-on): the first replace requires the
22
+ // Acronym-run rule (M-ADR 0164 wave-2 follow-on): the first replace requires the
23
23
  // leading uppercase run to be >=2 chars (`[A-Z]{2,}`). A *single* leading
24
24
  // capital before a capitalised word is NOT split off, so a PascalCase form
25
25
  // reconciles with its boundary-free UPPER_SNAKE form:
@@ -34,7 +34,7 @@
34
34
  //
35
35
  // Kept local to the entity walkers to avoid affecting events / contracts /
36
36
  // capability id generation. Promote to a shared module only if a fourth
37
- // walker needs it (per ADR 0159 §4.6 deferred decision).
37
+ // walker needs it (per M-ADR 0159 §4.6 deferred decision).
38
38
  export function entitySlug(s) {
39
39
  return s
40
40
  .replace(/([A-Z]{2,})([A-Z][a-z])/g, "$1-$2")
@@ -1,5 +1,5 @@
1
1
  // Walker for `docs/domains/<domain>/contracts/events/event-catalog.yaml` —
2
- // the reverse-method canonical source for events per ADR 0156.
2
+ // the reverse-method canonical source for events per M-ADR 0156.
3
3
  //
4
4
  // One file per domain. Each `events[]` entry encodes the event's name,
5
5
  // publisher_service_id, transport, schema_path, version, and consumers[].
@@ -8,7 +8,7 @@
8
8
  //
9
9
  // Merges with the avsc-sourced forward path in events.ts: YAML wins on
10
10
  // name/domain/publisher/transport/consumers; avsc augments schema_path/
11
- // version when the YAML row leaves them null. See ADR 0156 §4 and the
11
+ // version when the YAML row leaves them null. See M-ADR 0156 §4 and the
12
12
  // metamodel's §"Event sources" subsection for the precedence rules.
13
13
  import { readdir, readFile } from "node:fs/promises";
14
14
  import { join } from "node:path";
@@ -69,7 +69,7 @@ export async function walkEventCatalogs(inputs) {
69
69
  if (!Array.isArray(events))
70
70
  continue;
71
71
  // File-level evidence-class fallback for events that don't declare
72
- // their own (ADR 0175). Both key spellings accepted.
72
+ // their own (M-ADR 0175). Both key spellings accepted.
73
73
  const fileEvidenceClass = String(rawObj["evidence_class"] ?? rawObj["evidence-class"] ?? "").trim();
74
74
  // Track slugs derived within this domain so we can flag duplicates.
75
75
  const slugsInDomain = new Set();
@@ -80,7 +80,7 @@ export async function walkEventCatalogs(inputs) {
80
80
  const explicitId = String(e["id"] ?? "").trim();
81
81
  const name = String(e["name"] ?? "").trim();
82
82
  // Derive id: explicit id wins when present (allows future override);
83
- // otherwise slug from name, per ADR 0156: "derive `id` from `name`
83
+ // otherwise slug from name, per M-ADR 0156: "derive `id` from `name`
84
84
  // (slugged)". Some adopters' authoring uses
85
85
  // `name:` only (no `id:` field).
86
86
  let id;
@@ -117,7 +117,7 @@ export async function walkEventCatalogs(inputs) {
117
117
  }
118
118
  }
119
119
  if (transport !== "" && !RECOMMENDED_TRANSPORTS.has(transport)) {
120
- inputs.findings.add("convention", `docs/domains/${domain}/contracts/events/event-catalog.yaml: event ${id} transport "${transport}" outside recommended set (per ADR 0156)`);
120
+ inputs.findings.add("convention", `docs/domains/${domain}/contracts/events/event-catalog.yaml: event ${id} transport "${transport}" outside recommended set (per M-ADR 0156)`);
121
121
  }
122
122
  if (byId.has(id)) {
123
123
  inputs.findings.add("divergence", `event ${id} declared in multiple event-catalog.yaml files — first-seen kept`);
@@ -158,7 +158,7 @@ function slugify(s) {
158
158
  }
159
159
  /**
160
160
  * Merge a YAML-parsed event with the equivalent avsc-derived row. YAML wins
161
- * on name/domain/publisher/transport per ADR 0156 §4.1; avsc augments
161
+ * on name/domain/publisher/transport per M-ADR 0156 §4.1; avsc augments
162
162
  * schema_path/version only when the YAML row leaves them empty.
163
163
  *
164
164
  * Returns a fresh CatalogueRow ready to write into events.csv.
@@ -1,6 +1,6 @@
1
1
  // service_event + capability_event edge builders.
2
2
  //
3
- // service_event sources (per ADR 0156):
3
+ // service_event sources (per M-ADR 0156):
4
4
  // - Forward-method canonical: repo-config `events.produces[].schema`
5
5
  // (role=publishes) and `events.consumes[].schema` (role=consumes).
6
6
  // Each schema is resolved against the contracts.avro index → event id.
@@ -12,7 +12,7 @@
12
12
  // (for code-gen / validation) that consumers commonly declare too. Only
13
13
  // the events block + event-catalog.yaml are authoritative for edges.
14
14
  //
15
- // capability_event sources (per ADR 0160, schema 2.14.0):
15
+ // capability_event sources (per M-ADR 0160, schema 2.14.0):
16
16
  // - Forward shape A — `traceability.events[{id, role}]` (legacy
17
17
  // aspirational shape; unauthored across observed adopters, kept for
18
18
  // compatibility). Emits with source=authored.
@@ -23,7 +23,7 @@
23
23
  // fire `[finding] orphan`. Emits with source=authored.
24
24
  // - Derived — `capability_service ⋈ service_event` join on service_id.
25
25
  // Zero-authoring associative path; emits role from service_event.
26
- // Per ADR 0160, the over-attribution fan-out is intrinsic to services
26
+ // Per M-ADR 0160, the over-attribution fan-out is intrinsic to services
27
27
  // that own multiple primary capabilities, so a role filter has no
28
28
  // useful effect (verified on a real corpus: 144 → 144 with primary
29
29
  // filter). The `source=derived` column distinguishes these from
@@ -31,7 +31,7 @@
31
31
  // - Merge by PK `{capability_id}__{event_id}__{role}`: authored wins;
32
32
  // conflicting authored sources fire `[finding] divergence`.
33
33
  //
34
- // feature_event sources (per ADR 0161, schema 2.15.0):
34
+ // feature_event sources (per M-ADR 0161, schema 2.15.0):
35
35
  // - Derived only — `feature_service ⋈ service_event` join on service_id.
36
36
  // Completes the capability/feature/service trio of materialised event
37
37
  // edges. There is no authored shape; the authored signal lives at the
@@ -177,7 +177,7 @@ export function buildCapabilityEvent(inputs) {
177
177
  }
178
178
  }
179
179
  // ---- Derived: capability_service ⋈ service_event --------------------
180
- // Pure associative coupling. Per ADR 0160, no role filter — Phase Pre
180
+ // Pure associative coupling. Per M-ADR 0160, no role filter — Phase Pre
181
181
  // verified that role=primary filtering gives no reduction in practice
182
182
  // (services that emit events legitimately own multiple primary caps).
183
183
  // Provenance distinguishes derived from authored for governance queries.
@@ -230,7 +230,7 @@ export function buildCapabilityEvent(inputs) {
230
230
  return [...authored.values(), ...derived];
231
231
  }
232
232
  export function buildFeatureEvent(inputs) {
233
- // Derived-only edge per ADR 0161. Mirrors capability_event's derived path
233
+ // Derived-only edge per M-ADR 0161. Mirrors capability_event's derived path
234
234
  // one rung lower in the hierarchy. PK uses three components so the same
235
235
  // feature can hold both publishes + consumes rows for the same event.
236
236
  const rows = [];
@@ -1,5 +1,5 @@
1
1
  // Events discoverer — emits `events.csv` from two canonical sources per
2
- // ADR 0156 (multi-source ingestion):
2
+ // M-ADR 0156 (multi-source ingestion):
3
3
  //
4
4
  // Forward-method canonical: `contracts/avro/*.avsc` files (existing path).
5
5
  // The avsc id becomes the event id; publisher_service_id reads from
@@ -15,7 +15,7 @@
15
15
  // - Events declared only in avsc → forward-only row (existing behaviour)
16
16
  // - Events declared only in YAML → reverse-only row (new)
17
17
  //
18
- // Transport: open string per ADR 0156 (no hardcoded default). When the
18
+ // Transport: open string per M-ADR 0156 (no hardcoded default). When the
19
19
  // source is avsc-only with no `repo-config.events` declaration, transport
20
20
  // may be empty.
21
21
  import { sep } from "node:path";
@@ -70,7 +70,7 @@ export async function buildEvents(inputs) {
70
70
  transport: "",
71
71
  schema_path: specPath,
72
72
  version: String(c["version"] ?? ""),
73
- // avsc has no evidence slot — avsc-only events stay empty (ADR 0175).
73
+ // avsc has no evidence slot — avsc-only events stay empty (M-ADR 0175).
74
74
  evidence_class: "",
75
75
  source_sdd_id: "",
76
76
  });
@@ -1,5 +1,5 @@
1
1
  // File-level evidence-class extraction for data-model markdown, per the
2
- // documentation-reverse anchor convention (ADR 0175 / sdd-method
2
+ // documentation-reverse anchor convention (M-ADR 0175 / sdd-method
3
3
  // `docs/method/methods/reverse/documentation-reverse-anchor-schema.md`).
4
4
  //
5
5
  // Documentation-reversed data models open with a fenced ```yaml block near
@@ -11,7 +11,7 @@
11
11
  // model, both pairs are emitted. If multiple capabilities link to the
12
12
  // SAME domain model, the duplicate is silently dropped.
13
13
  //
14
- // Added in schema 2.4.0 per ADR 0142.
14
+ // Added in schema 2.4.0 per M-ADR 0142.
15
15
  export function buildFeatureDomainModel(inputs) {
16
16
  if (inputs.manifest.profile !== "platform-profile") {
17
17
  return [];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Walker for `feature-grounding.md` files per ADR 0143 (schema 2.5.0).
2
+ * Walker for `feature-grounding.md` files per M-ADR 0143 (schema 2.5.0).
3
3
  *
4
4
  * Reads markdown tables of the canonical shape:
5
5
  *
@@ -7,7 +7,7 @@
7
7
  * |---|---|---|---|---|---|
8
8
  * | `oauth2-login` | ... | BFF `GET /login` | `AuthHandler.handle...()` | Token | `auth-handler.ts` |
9
9
  *
10
- * Path conventions (per ADR 0143 §4.3):
10
+ * Path conventions (per M-ADR 0143 §4.3):
11
11
  * - platform-profile: `docs/domains/<dom>/design/<capability>/feature-grounding.md`
12
12
  * - integration-product: `docs/design/integration/feature-grounding.md`
13
13
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Feature-grounding extractor per ADR 0143 (schema 2.5.0).
2
+ * Feature-grounding extractor per M-ADR 0143 (schema 2.5.0).
3
3
  *
4
4
  * Walks `docs/domains/<dom>/design/<capability>/feature-grounding.md`
5
5
  * (platform-profile) and `docs/design/integration/feature-grounding.md`
@@ -19,7 +19,7 @@
19
19
  * findings but never break FK validation — only confidently-resolved
20
20
  * rows are emitted.
21
21
  *
22
- * Precedence per ADR 0143 §4.4: feature-tree and feature-spec rows
22
+ * Precedence per M-ADR 0143 §4.4: feature-tree and feature-spec rows
23
23
  * win on id collision; grounding rows are skipped with a divergence
24
24
  * finding.
25
25
  */
@@ -105,7 +105,7 @@ export async function buildFeatureGrounding(inputs) {
105
105
  // capability_feature row on the spec source path.
106
106
  //
107
107
  // feature_repo and feature_service edges: emit unconditionally per
108
- // ADR 0143 §2 (these are the source's unique contribution; nothing
108
+ // M-ADR 0143 §2 (these are the source's unique contribution; nothing
109
109
  // else carries per-row code-mapping). Pre-0.30.2 the collision skip
110
110
  // dropped these edges too — bug fixed.
111
111
  if (featureRowCollides) {
@@ -114,7 +114,7 @@ export async function buildFeatureGrounding(inputs) {
114
114
  //
115
115
  // `seenFeatures` is seeded from earlier sources AND grows during this
116
116
  // walk, so a hit means either:
117
- // - an earlier SOURCE emitted this id. That is ADR 0143 §2's
117
+ // - an earlier SOURCE emitted this id. That is M-ADR 0143 §2's
118
118
  // documented precedence rule working exactly as specified: the
119
119
  // grounding pass re-declares ids that feature-tree/feature-spec
120
120
  // already own. It happens for essentially every grounded feature,
@@ -133,7 +133,7 @@ export async function buildFeatureGrounding(inputs) {
133
133
  // of 1,545 accepted ones, so the whole category was unusable as a
134
134
  // signal and unbaselineable as a backlog.
135
135
  if (fromEarlierSource.has(featureId)) {
136
- inputs.findings.add("inferred", `${relPath}:${row.lineNumber}: feature id "${featureId}" already emitted by an earlier source (feature-tree / feature-spec wins for the row; feature_repo + feature_service edges still emitted per ADR 0143 §2)`);
136
+ inputs.findings.add("inferred", `${relPath}:${row.lineNumber}: feature id "${featureId}" already emitted by an earlier source (feature-tree / feature-spec wins for the row; feature_repo + feature_service edges still emitted per M-ADR 0143 §2)`);
137
137
  }
138
138
  else {
139
139
  inputs.findings.add("divergence", `${relPath}:${row.lineNumber}: feature id "${featureId}" already emitted by another file in this same feature-grounding pass — two files under one capability declare the same slug (first occurrence wins)`);
@@ -46,7 +46,7 @@ export async function buildFeatureSubscriptionChannels(inputs) {
46
46
  const relPath = relative(inputs.sddPath, file);
47
47
  // The per-design-dir `feature-grounding-evidence.yaml` is this builder's
48
48
  // dedicated contract — read/parse failures are its findings. The
49
- // per-domain `<domain>-feature-grounding.yaml` files (ADR 0164) are
49
+ // per-domain `<domain>-feature-grounding.yaml` files (M-ADR 0164) are
50
50
  // primarily authored for other tooling and only opportunistically scanned
51
51
  // for a `feature_subscription_channels:` key; they may not be strict YAML,
52
52
  // so their read/parse failures are skipped silently (not this builder's
@@ -77,7 +77,7 @@ export async function buildFeatureSubscriptionChannels(inputs) {
77
77
  continue;
78
78
  // Per-feature subscription_channels live under `features:` (per-design-dir
79
79
  // layout) or a top-level `feature_subscription_channels:` list (per-domain
80
- // layout, ADR 0164). Both are lists of { feature_slug, subscription_channels }.
80
+ // layout, M-ADR 0164). Both are lists of { feature_slug, subscription_channels }.
81
81
  const obj = parsed;
82
82
  const featureEntries = [];
83
83
  if (Array.isArray(obj["features"]))
@@ -192,7 +192,7 @@ async function walk(root, current, out) {
192
192
  if (e.isDirectory()) {
193
193
  // Check whether this is the reverse-evidence dir; if so, look for the file directly.
194
194
  if (e.name === "reverse-evidence") {
195
- // Two reverse-evidence layouts are read (ADR 0164):
195
+ // Two reverse-evidence layouts are read (M-ADR 0164):
196
196
  // - per-design-dir: `reverse-evidence/feature-grounding-evidence.yaml`
197
197
  // (features: → per-feature subscription_channels:).
198
198
  // - per-domain: `reverse-evidence/<domain>-feature-grounding.yaml`
@@ -30,7 +30,7 @@
30
30
  import { readdir, readFile } from "node:fs/promises";
31
31
  import { basename, join, relative, sep } from "node:path";
32
32
  import { featureGroupId, findFeatureTreeFile, walkFeatureTree, } from "./feature-tree-walker.js";
33
- // ADR 0165: the standard, cross-SDD-comparable `features.maturity` vocabulary
33
+ // M-ADR 0165: the standard, cross-SDD-comparable `features.maturity` vocabulary
34
34
  // (canonical-schema §features). Feature-tree `[runway: X]` markers whose value
35
35
  // is in this set ARE the maturity signal — wire them to `maturity` (comparable)
36
36
  // while `runway` keeps the full marker (adopter-owned, incl. non-standard values
@@ -1,7 +1,7 @@
1
1
  // glossary_xref + entity_glossary edge builders — emit cross-domain glossary
2
2
  // relationships from `docs/platform/reference/glossary-alignment-manifest.yaml`.
3
3
  //
4
- // Per ADR 0158 (Glossary Cross-Reference Multi-Source Ingestion, schema 2.12.0),
4
+ // Per M-ADR 0158 (Glossary Cross-Reference Multi-Source Ingestion, schema 2.12.0),
5
5
  // the builder ingests from FIVE walkers:
6
6
  //
7
7
  // 1. Forward declared pair-form (existing).
@@ -42,7 +42,7 @@ import { join } from "node:path";
42
42
  import { parse as parseYaml } from "yaml";
43
43
  const MANIFEST_REL_PATH = join("docs", "platform", "reference", "glossary-alignment-manifest.yaml");
44
44
  export async function buildGlossaryXref(inputs) {
45
- // Profile gate per ADR 0158 §amendment: the manifest is platform-owned;
45
+ // Profile gate per M-ADR 0158 §amendment: the manifest is platform-owned;
46
46
  // sibling SDDs that syndicate it for documentation accessibility should
47
47
  // not re-emit rows. Mirrors the entities-manifest profile gate.
48
48
  if (inputs.profile !== "platform-profile") {
@@ -292,7 +292,7 @@ export async function buildGlossaryXref(inputs) {
292
292
  status: winner,
293
293
  });
294
294
  }
295
- inputs.findings.add("divergence", `${MANIFEST_REL_PATH}: entity ${name} in domain ${domain} has conflicting statuses across models (${existingStatus} vs ${status}) — keeping ${winner} (per ADR 0158)`);
295
+ inputs.findings.add("divergence", `${MANIFEST_REL_PATH}: entity ${name} in domain ${domain} has conflicting statuses across models (${existingStatus} vs ${status}) — keeping ${winner} (per M-ADR 0158)`);
296
296
  continue;
297
297
  }
298
298
  const row = {
@@ -321,7 +321,7 @@ export async function buildGlossaryXref(inputs) {
321
321
  || "cross_domain_terms" in obj
322
322
  || "models" in obj;
323
323
  if (!hasAnyKnownKey) {
324
- inputs.findings.add("convention", `${MANIFEST_REL_PATH}: present but no recognised top-level keys (aliases/conflicts/cross_domain_terms/models) — emitting 0 xref rows (per ADR 0158)`);
324
+ inputs.findings.add("convention", `${MANIFEST_REL_PATH}: present but no recognised top-level keys (aliases/conflicts/cross_domain_terms/models) — emitting 0 xref rows (per M-ADR 0158)`);
325
325
  }
326
326
  }
327
327
  return { glossaryXref: xrefRows, entityGlossary: entityRows };
@@ -1,10 +1,10 @@
1
1
  // Integrations discoverer — emits `integrations.csv` rows from an
2
2
  // integration-product SDD's `integration-manifest.yaml`.
3
3
  //
4
- // Per ADR 0134 federation: each integration-provider SDD owns one row
4
+ // Per M-ADR 0134 federation: each integration-provider SDD owns one row
5
5
  // in the granular integrations.csv. The aggregator merges siblings.
6
6
  //
7
- // Per ADR 0144 (schema 2.6.0): if the manifest declares an optional
7
+ // Per M-ADR 0144 (schema 2.6.0): if the manifest declares an optional
8
8
  // `sub_integrations:` array (multi-provider monolith pattern), emit
9
9
  // one additional row per entry with parent_product_id set to the
10
10
  // SDD's integrationId. The umbrella SDD row stays unchanged.
@@ -29,7 +29,7 @@
29
29
  // doc_path = SDD's doc_path
30
30
  // repo_count = 0 (repo ownership stays with the umbrella)
31
31
  //
32
- // domain_id is always empty per ADR 0136.
32
+ // domain_id is always empty per M-ADR 0136.
33
33
  import { readFile } from "node:fs/promises";
34
34
  import { join } from "node:path";
35
35
  import { parse as parseYaml } from "yaml";
@@ -111,7 +111,7 @@ export async function buildIntegrations(inputs) {
111
111
  source_sdd_id: "",
112
112
  },
113
113
  ];
114
- // Per ADR 0144 (schema 2.6.0): emit one row per sub_integration with
114
+ // Per M-ADR 0144 (schema 2.6.0): emit one row per sub_integration with
115
115
  // parent_product_id = the umbrella SDD's id.
116
116
  const subs = parsed.data.sub_integrations ?? [];
117
117
  const seenSubIds = new Set([id]); // umbrella id is reserved
@@ -1,5 +1,5 @@
1
1
  // persona_c4system edge builder — emits one row per `Person(...)` actor on
2
- // the L1 context diagram that maps to a known persona (per ADR 0155). This
2
+ // the L1 context diagram that maps to a known persona (per M-ADR 0155). This
3
3
  // captures the C4 "Person uses System" relationship; the C4 Person
4
4
  // abstraction reuses the existing Persona entity rather than a parallel one.
5
5
  //