@sdd-method/sdd-cli 1.23.1 → 1.24.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.
@@ -1,22 +1,17 @@
1
1
  # GENERATED — DO NOT EDIT. This file is a projection of the authored model (M-ADR 0210 §4.6, flip 1):
2
2
  # docs/method/foundations/schemas/catalogue-schema.tql (the type system; header carries the bump log)
3
3
  # docs/method/foundations/schemas/catalogue-schema-meta.tql (what a type system cannot say)
4
- # Regenerate: python3 orchestration/scripts/check-catalogue-schema-roundtrip.py --write
5
- # Guard: python3 orchestration/scripts/check-catalogue-schema-roundtrip.py (any difference fails the build)
4
+ # Regenerate: sdd-cli metamodel roundtrip --write
5
+ # Guard: sdd-cli metamodel roundtrip (any difference fails the build)
6
6
  # Direction of truth: authored .tql -> this projection (round-trip gate) -> vendored copies (digest hook).
7
- # Emitted with PyYAML safe_dump(sort_keys=False, allow_unicode=True, width=1000000); the three header scalars
8
- # are quoted for the textual readers downstream. The one deliberate
9
- # difference from the authored form is schema_status: the authored form says canonical; a projection never does.
7
+ # Emitted by sdd-cli's YAML emitter with no line folding; the three header scalars are quoted for the
8
+ # textual readers downstream. The one deliberate difference from the authored form is schema_status:
9
+ # the authored form says canonical; a projection never does.
10
10
  schema_version: "3.10.0"
11
11
  schema_owner: "sdd-method"
12
12
  schema_status: "generated"
13
13
  enums:
14
14
  quality_gate:
15
- description: 'Gate verdict a rubric assessment records for a target, in `quality_scores.gate` (per M-ADR 0205 §4.5). The vocabulary all fifteen method-side gate registries declare.
16
-
17
- DELIBERATELY NOT BOUND via `column_enums`, and the reason is measured rather than assumed — do not "fix" this by binding it. These values come from hand-authored score registries written by scoring runs, not from a method-mandated authoring surface, and one estate''s `domain-architecture-scores.yaml` declared `pass-with-waiver` before the method did, and uses it — the extension was RULED INTO this vocabulary (2026-08-07); the next estate extension would meet the same choice, and binding would hard-fail a build over a deliberate, self-documented row. This follows the `products.synthesis_band` precedent — the other column fed from a rubric registry — where an out-of-vocabulary value is reported as a convention finding and the cell left EMPTY, rather than emitting a value no consumer can interpret. The builder names the file, the entry, the value and the remedy, which is better diagnosis than a generic enum violation could give. Contrast `service_type`, which IS bound: it comes from repo-config, an authoring surface the method mandates.
18
-
19
- '
20
15
  values:
21
16
  - value: pass
22
17
  description: Meets the rubric's pass threshold with no hard gate triggered.
@@ -27,11 +22,11 @@ enums:
27
22
  - value: fail
28
23
  description: Below the fail threshold, or a hard gate triggered.
29
24
  - value: unscored
30
- description: 'The entry exists but carries no assessment. Distinct from absent: an unscored row asserts that nothing has been judged, which is exactly the silence M-ADR 0205 §4.5''s coverage instrument exists to make loud.'
25
+ description: "The entry exists but carries no assessment. Distinct from absent: an unscored row asserts that nothing has been judged, which is exactly the silence M-ADR 0205 §4.5's coverage instrument exists to make loud."
26
+ description: |
27
+ Gate verdict a rubric assessment records for a target, in `quality_scores.gate` (per M-ADR 0205 §4.5). The vocabulary all fifteen method-side gate registries declare.
28
+ DELIBERATELY NOT BOUND via `column_enums`, and the reason is measured rather than assumed — do not "fix" this by binding it. These values come from hand-authored score registries written by scoring runs, not from a method-mandated authoring surface, and one estate's `domain-architecture-scores.yaml` declared `pass-with-waiver` before the method did, and uses it — the extension was RULED INTO this vocabulary (2026-08-07); the next estate extension would meet the same choice, and binding would hard-fail a build over a deliberate, self-documented row. This follows the `products.synthesis_band` precedent — the other column fed from a rubric registry — where an out-of-vocabulary value is reported as a convention finding and the cell left EMPTY, rather than emitting a value no consumer can interpret. The builder names the file, the entry, the value and the remedy, which is better diagnosis than a generic enum violation could give. Contrast `service_type`, which IS bound: it comes from repo-config, an authoring surface the method mandates.
31
29
  score_selection_method:
32
- description: 'How the effective review was chosen from a target''s review history, in `quality_scores.selection_method` — the `selection_policy.method` field every gate registry carries. The catalogue models only the EFFECTIVE score (one row per target/rubric); this column makes the row say WHICH review it is rather than implying there was only one. Not bound, for the same registry-authored reason as `quality_gate`.
33
-
34
- '
35
30
  values:
36
31
  - value: latest
37
32
  description: Most recent review by scored_at. The default and, at 2026-08-06, the only value in use across either estate.
@@ -41,10 +36,9 @@ enums:
41
36
  description: Effective score reconciled across several reviews.
42
37
  - value: highest-severity
43
38
  description: The most severe review wins — the conservative policy for gate-blocking rubrics.
39
+ description: |
40
+ How the effective review was chosen from a target's review history, in `quality_scores.selection_method` — the `selection_policy.method` field every gate registry carries. The catalogue models only the EFFECTIVE score (one row per target/rubric); this column makes the row say WHICH review it is rather than implying there was only one. Not bound, for the same registry-authored reason as `quality_gate`.
44
41
  staleness_basis:
45
- description: 'Which anchor a `quality_scores` row''s staleness verdict can be computed from, in `quality_scores.staleness_basis`. This column exists because a staleness verdict whose basis is unstated is not a measurement — the basis-error class that produced six wrong figures in a single day of this method''s own arc. The coverage predicate MUST NOT be able to emit a staleness claim without naming which of these it used.
46
-
47
- '
48
42
  values:
49
43
  - value: corpus_ref
50
44
  description: The row carries the commit the assessment read — the precise anchor. Authored; introduced by the M-ADR 0205 §4.5 change-set, so absent from every score written before it.
@@ -52,23 +46,19 @@ enums:
52
46
  description: No corpus_ref; staleness computed from the assessment date against the target's last content change, resolved through target_path. Correct but coarser — it cannot distinguish a re-commit that changed nothing from a real edit.
53
47
  - value: none
54
48
  description: Neither anchor available (no corpus_ref and no resolvable target_path). Staleness is UNKNOWN for this row and must be reported as unknown, never as fresh.
49
+ description: |
50
+ Which anchor a `quality_scores` row's staleness verdict can be computed from, in `quality_scores.staleness_basis`. This column exists because a staleness verdict whose basis is unstated is not a measurement — the basis-error class that produced six wrong figures in a single day of this method's own arc. The coverage predicate MUST NOT be able to emit a staleness claim without naming which of these it used.
55
51
  scoring_form:
56
- description: 'The scoring shape a rubric uses, in `quality_scores.scoring_form`. Reserved by M-ADR 0205 §4.5 so the banded reverse family can arrive additively without reshaping rows.
57
-
58
- Both forms are now declared. `banded` was added in 3.3.0 once the reverse family was modelled; before that it was deliberately absent so a premature banded row would fail loudly rather than pass against an unemitted value.
59
-
60
- The two forms are NOT interchangeable and must not be averaged together — which is why they never share a score column. A weighted row carries `weighted_score` (1-5) and leaves `band`/`band_total` empty; a banded row carries `band` + `band_total` and leaves `weighted_score` empty. Any aggregate over `weighted_score` is therefore correct by construction rather than by the caller remembering to filter.
61
-
62
- '
63
52
  values:
64
53
  - value: weighted
65
54
  description: Weighted 1-5 dimensions rolled into a weighted_score against a pass threshold, with flags and hard gates. The forward house form; all fifteen method-side registries use it.
66
55
  - value: banded
67
56
  description: Dimensions summed to an integer total and mapped to a named band. The reverse family's form. Added in 3.3.0. The band vocabulary is PER-RUBRIC and deliberately unbound — see the band column.
57
+ description: |
58
+ The scoring shape a rubric uses, in `quality_scores.scoring_form`. Reserved by M-ADR 0205 §4.5 so the banded reverse family can arrive additively without reshaping rows.
59
+ Both forms are now declared. `banded` was added in 3.3.0 once the reverse family was modelled; before that it was deliberately absent so a premature banded row would fail loudly rather than pass against an unemitted value.
60
+ The two forms are NOT interchangeable and must not be averaged together — which is why they never share a score column. A weighted row carries `weighted_score` (1-5) and leaves `band`/`band_total` empty; a banded row carries `band` + `band_total` and leaves `weighted_score` empty. Any aggregate over `weighted_score` is therefore correct by construction rather than by the caller remembering to filter.
68
61
  capability_service_role:
69
- description: 'The part a service plays in delivering ONE capability. A property of the capability↔service RELATIONSHIP, never of the service: the same service is legitimately `primary` for capabilities in its own domain and `backend-gateway` for capabilities elsewhere. Authored in the capability traceability manifest services[].role (see the capability-traceability-manifest-template). Bound in 3.8.0; the values and their meanings are the template''s, unchanged. Consumers deriving "which repos realise this capability" MUST read this column or use repo_capability, which excludes `dependency` (M-ADR 0157 §4.3 as amended) — a repo_capability row is a contribution claim.
70
-
71
- '
72
62
  values:
73
63
  - value: primary
74
64
  description: Realises this capability.
@@ -78,8 +68,9 @@ enums:
78
68
  description: This capability DEPENDS ON the service — the inverse direction of contribution. The relationship is real and catalogued here; it does NOT produce a repo_capability row.
79
69
  - value: backend-gateway
80
70
  description: Owned by ANOTHER domain and the sanctioned entry point into that domain's data for this capability — not merely a dependency, the door in. Expect it on cross-domain rows only. Contributes; kept in repo_capability.
71
+ description: |
72
+ The part a service plays in delivering ONE capability. A property of the capability↔service RELATIONSHIP, never of the service: the same service is legitimately `primary` for capabilities in its own domain and `backend-gateway` for capabilities elsewhere. Authored in the capability traceability manifest services[].role (see the capability-traceability-manifest-template). Bound in 3.8.0; the values and their meanings are the template's, unchanged. Consumers deriving "which repos realise this capability" MUST read this column or use repo_capability, which excludes `dependency` (M-ADR 0157 §4.3 as amended) — a repo_capability row is a contribution claim.
81
73
  c4_system_kind:
82
- description: "Architectural kind of a C4 system. Derived 1:1 from the originating SDD manifest's category — every architectural product (the only ones that get a c4_systems row) maps to exactly one of these four kinds. Non-architectural categories (integration-umbrella, support-repo) emit no c4_systems row — and the builder MUST say so with a coverage finding, never silently (M-ADR 0133 §4.2c). Mapping table:\n platform-root → platform\n platform-subsystem → subsystem\n application-product → application\n integration-provider → integration\n"
83
74
  values:
84
75
  - value: platform
85
76
  description: A platform-root system — the one system that identifies a platform (M-ADR 0208 §4.1; 'platform-ecosystem' is the long form, 1:1 with the root). Exactly one per PLATFORM; an organisation-tier aggregate legitimately carries one per constituent platform, keyed by platform_sdd_id (0208 §4.2). An invariant `subsystem` exists to protect — do not reuse `platform` for subsystem rows.
@@ -89,21 +80,22 @@ enums:
89
80
  description: An application-product system, consumes platform services and contracts.
90
81
  - value: integration
91
82
  description: An integration-provider system, bridges an external provider into the platform.
83
+ description: |
84
+ Architectural kind of a C4 system. Derived 1:1 from the originating SDD manifest's category — every architectural product (the only ones that get a c4_systems row) maps to exactly one of these four kinds. Non-architectural categories (integration-umbrella, support-repo) emit no c4_systems row — and the builder MUST say so with a coverage finding, never silently (M-ADR 0133 §4.2c). Mapping table:
85
+ platform-root → platform
86
+ platform-subsystem → subsystem
87
+ application-product → application
88
+ integration-provider → integration
92
89
  c4_container_type:
93
- description: 'Canonical C4 container kind for `c4_containers.type`, aligned with c4model.com/abstractions (per M-ADR 0155). A C4 container is something that must be running for the system to work — an application or a data store.
94
-
95
- BOUND via `c4_containers.column_enums` since 3.0.0 (M-ADR 0203 §4.1, completing 0155''s staged enforcement): a non-member value hard-fails build and validate. The 2.x-era legacy values are removed; their migration rule (0155''s own): `External System` boxes belong in `c4_external_systems` (C4 L1 peer systems, not L2 containers); running infrastructure (broker, gateway, cache) retypes to Application or Data Store; pure deployment infrastructure (load balancer, DNS) leaves the container catalogue (it belongs in a C4 deployment diagram, which is not catalogued).
96
-
97
- '
98
90
  values:
99
91
  - value: Application
100
92
  description: A separately deployable/runnable application — a service, BFF, UI, consumer, worker, etc.
101
93
  - value: Data Store
102
94
  description: A database or persistence layer (also covers running stores like a message broker when modelled as a container).
95
+ description: |
96
+ Canonical C4 container kind for `c4_containers.type`, aligned with c4model.com/abstractions (per M-ADR 0155). A C4 container is something that must be running for the system to work — an application or a data store.
97
+ BOUND via `c4_containers.column_enums` since 3.0.0 (M-ADR 0203 §4.1, completing 0155's staged enforcement): a non-member value hard-fails build and validate. The 2.x-era legacy values are removed; their migration rule (0155's own): `External System` boxes belong in `c4_external_systems` (C4 L1 peer systems, not L2 containers); running infrastructure (broker, gateway, cache) retypes to Application or Data Store; pure deployment infrastructure (load balancer, DNS) leaves the container catalogue (it belongs in a C4 deployment diagram, which is not catalogued).
103
98
  service_type:
104
- description: 'Type of repository, declared in `orchestration/repo-config/*.yaml` as `service_type` and surfaced in `repositories.component_type` and `services.component_type`. The canonical builder uses this to decide which repos are runtime services (api_service, worker, gateway, frontend, mobile) and which are non-runtime (library, infrastructure, documentation). Whether a repo is a vertical-domain application is conveyed by its SDD manifest''s `profile: application-product`, not by a service_type tag — this enum is strictly about runtime artefact shape (per resolution of adopt-canonical-catalogue-builder.md §7.1).
105
-
106
- '
107
99
  values:
108
100
  - value: api_service
109
101
  description: REST/GraphQL/RPC service exposing an API.
@@ -137,12 +129,9 @@ enums:
137
129
  description: Docs-only repo.
138
130
  runtime: false
139
131
  emits_service_row: false
132
+ description: |
133
+ Type of repository, declared in `orchestration/repo-config/*.yaml` as `service_type` and surfaced in `repositories.component_type` and `services.component_type`. The canonical builder uses this to decide which repos are runtime services (api_service, worker, gateway, frontend, mobile) and which are non-runtime (library, infrastructure, documentation). Whether a repo is a vertical-domain application is conveyed by its SDD manifest's `profile: application-product`, not by a service_type tag — this enum is strictly about runtime artefact shape (per resolution of adopt-canonical-catalogue-builder.md §7.1).
140
134
  capability_exemption_reason:
141
- description: 'Why a catalogued repository deliberately bears no capability, per M-ADR 0188 §4.2. Closed vocabulary: reason codes make exemptions countable and trendable (a growing `prototype` or `archived` population is itself an estate signal), where free text would bury them. Extensions are method-owned and proceed by ADR amendment, so that adopters cannot locally widen the exemption surface to silence findings.
142
-
143
- ENFORCED, not advisory. The builder drops a `repo_capability_exemption` row whose reason is outside this vocabulary and emits a `convention` finding. The repository then resolves to nothing and is reported as an orphan — which is the point. If an unrecognised reason still exempted the repo, `reason: whatever` would be a universal silencer.
144
-
145
- '
146
135
  values:
147
136
  - value: infrastructure
148
137
  description: Provisions or operates the estate; realises no product capability.
@@ -156,23 +145,19 @@ enums:
156
145
  description: Exploratory; not part of the product model.
157
146
  - value: archived
158
147
  description: Retained for reference; no longer live.
148
+ description: |
149
+ Why a catalogued repository deliberately bears no capability, per M-ADR 0188 §4.2. Closed vocabulary: reason codes make exemptions countable and trendable (a growing `prototype` or `archived` population is itself an estate signal), where free text would bury them. Extensions are method-owned and proceed by ADR amendment, so that adopters cannot locally widen the exemption surface to silence findings.
150
+ ENFORCED, not advisory. The builder drops a `repo_capability_exemption` row whose reason is outside this vocabulary and emits a `convention` finding. The repository then resolves to nothing and is reported as an orphan — which is the point. If an unrecognised reason still exempted the repo, `reason: whatever` would be a universal silencer.
159
151
  service_capability_exemption_reason:
160
- description: 'Why a catalogued service deliberately bears no capability, per M-ADR 0133 §4.2b. Closed vocabulary — narrower than `capability_exemption_reason` by design: a repository can be exempt for six reasons (packaging, tooling, provenance), but a SERVICE, by definition, already runs something — the repository-tier distinctions that don''t reproduce at the service tier (pure IaC, build tooling, test scaffolding, vendored code) fold into `platform-internal`, since a service that exists at all is doing platform-internal work if it isn''t product-facing.
161
-
162
- ENFORCED, not advisory. The builder drops a `service_capability_exemption` row whose reason is outside this vocabulary and emits a `convention` finding. The service then resolves to nothing and is reported per the coverage predicate''s tier-scoped verdict set — which is the point.
163
-
164
- '
165
152
  values:
166
153
  - value: platform-internal
167
154
  description: Runs, but serves the platform's own operation rather than a product capability (e.g. an internal control-plane or ops service).
168
155
  - value: deprecated
169
156
  description: No longer live; retained for reference or wind-down.
157
+ description: |
158
+ Why a catalogued service deliberately bears no capability, per M-ADR 0133 §4.2b. Closed vocabulary — narrower than `capability_exemption_reason` by design: a repository can be exempt for six reasons (packaging, tooling, provenance), but a SERVICE, by definition, already runs something — the repository-tier distinctions that don't reproduce at the service tier (pure IaC, build tooling, test scaffolding, vendored code) fold into `platform-internal`, since a service that exists at all is doing platform-internal work if it isn't product-facing.
159
+ ENFORCED, not advisory. The builder drops a `service_capability_exemption` row whose reason is outside this vocabulary and emits a `convention` finding. The service then resolves to nothing and is reported per the coverage predicate's tier-scoped verdict set — which is the point.
170
160
  external_system_exemption_reason:
171
- description: 'Why an external-system candidate is ACCOUNTED FOR at the estate boundary, per M-ADR 0189 §4.6 (WS15; wording corrected by F16, 2.32.0): five values assert another party owns the system, and two assert the estate/organisation owns it but it has no model home yet — forcing the latter through the former would demand a false reason, and a false reason is worse than silence. The adjudicator can prove a candidate internal; it cannot prove one accounted-for — that is an assertion the author is accountable for, in the shape M-ADR 0188 ratified for repositories. Closed vocabulary, method-owned, extended only by ADR amendment, so adopters cannot locally widen the exemption surface to silence the unverified-candidate coverage finding.
172
-
173
- ENFORCED, not advisory: the builder drops a row whose reason is outside this vocabulary (convention finding) and the candidate stays unverified — which is the point. An unrecognised reason must not succeed at the one thing an exemption does.
174
-
175
- '
176
161
  values:
177
162
  - value: third-party-saas
178
163
  description: An operated vendor service the estate consumes (billing, auth, maps, email…).
@@ -185,22 +170,21 @@ enums:
185
170
  - value: public-infrastructure
186
171
  description: Public networks, registries, or services no party in the estate operates.
187
172
  - value: estate-owned-unmodelled
188
- description: 'Operated by this estate but with no SDD or container home yet — the row is an accounted-for stand-in, and this population is the estate''s modelling backlog, countable (F16, 2.32.0). Not an assertion of externality: an assertion of accountability for a boundary row.'
173
+ description: "Operated by this estate but with no SDD or container home yet — the row is an accounted-for stand-in, and this population is the estate's modelling backlog, countable (F16, 2.32.0). Not an assertion of externality: an assertion of accountability for a boundary row."
189
174
  - value: organisation-internal
190
175
  description: Owned elsewhere in the same organisation, outside this estate's modelling boundary (F16, 2.32.0).
176
+ description: |
177
+ Why an external-system candidate is ACCOUNTED FOR at the estate boundary, per M-ADR 0189 §4.6 (WS15; wording corrected by F16, 2.32.0): five values assert another party owns the system, and two assert the estate/organisation owns it but it has no model home yet — forcing the latter through the former would demand a false reason, and a false reason is worse than silence. The adjudicator can prove a candidate internal; it cannot prove one accounted-for — that is an assertion the author is accountable for, in the shape M-ADR 0188 ratified for repositories. Closed vocabulary, method-owned, extended only by ADR amendment, so adopters cannot locally widen the exemption surface to silence the unverified-candidate coverage finding.
178
+ ENFORCED, not advisory: the builder drops a row whose reason is outside this vocabulary (convention finding) and the candidate stays unverified — which is the point. An unrecognised reason must not succeed at the one thing an exemption does.
191
179
  scaffold_status:
192
- description: 'Lifecycle of a scaffold declaration, in `scaffolds.status`. AUTHORED in the manifest, copied by the builder: closing a scaffold is a recorded act of the unit of work finishing (M-ADR 0207 §4.3), not a computed consequence — the delta instrument reports a closed scaffold whose delta is not zero as a finding, it never closes one itself.
193
-
194
- '
195
180
  values:
196
181
  - value: open
197
182
  description: The unit of work is in flight. `declared` items are a state, not a defect (M-ADR 0207 §4.2).
198
183
  - value: closed
199
184
  description: The author has recorded the unit of work as done. A `declared` item under a closed scaffold presumes the scaffold right — the work is incomplete — and is reported (M-ADR 0207 §4.3).
185
+ description: |
186
+ Lifecycle of a scaffold declaration, in `scaffolds.status`. AUTHORED in the manifest, copied by the builder: closing a scaffold is a recorded act of the unit of work finishing (M-ADR 0207 §4.3), not a computed consequence — the delta instrument reports a closed scaffold whose delta is not zero as a finding, it never closes one itself.
200
187
  scaffold_item_kind:
201
- description: 'The grain of a scaffold declaration item, in `scaffold_items.item_kind`. Declares which family of catalogue surface the item promises; `target_kind` names the specific catalogue.
202
-
203
- '
204
188
  values:
205
189
  - value: entity
206
190
  description: A node catalogue row the work will add (a service, capability, feature, screen, …). target_ref is the declared id in that catalogue's vocabulary.
@@ -208,17 +192,17 @@ enums:
208
192
  description: An edge catalogue row the work will add. Endpoints are declared in edge_source_ref/edge_target_ref, mapped to the edge catalogue's FK columns in schema declaration order.
209
193
  - value: contract
210
194
  description: A contract artefact the work will introduce or amend. target_ref is the repo-relative spec path, matching `contracts.spec_path`.
195
+ description: |
196
+ The grain of a scaffold declaration item, in `scaffold_items.item_kind`. Declares which family of catalogue surface the item promises; `target_kind` names the specific catalogue.
211
197
  scaffold_item_state:
212
- description: 'Realisation state of a scaffold item, in `scaffold_items.state`. DERIVED by the builder''s resolution pass against the same build''s catalogue rows — never authored. The manifest declares intent; this column records whether the intent is realised in the corpus the build read. Staleness is deliberately NOT a value here: it is a coverage-time verdict against `scaffolds.corpus_ref` (M-ADR 0207 §4.6), because a git-derived value in a derived row would break rebuild determinism against unchanged authored inputs.
213
-
214
- '
215
198
  values:
216
199
  - value: declared
217
200
  description: The target does not (yet) resolve in the built catalogues. Under an open scaffold this is the computable backlog; under a closed one it is a reported finding (M-ADR 0207 §4.2/§4.3).
218
201
  - value: realised
219
202
  description: The target resolves in the built catalogues. The declaration is met for this item.
203
+ description: |
204
+ Realisation state of a scaffold item, in `scaffold_items.state`. DERIVED by the builder's resolution pass against the same build's catalogue rows — never authored. The manifest declares intent; this column records whether the intent is realised in the corpus the build read. Staleness is deliberately NOT a value here: it is a coverage-time verdict against `scaffolds.corpus_ref` (M-ADR 0207 §4.6), because a git-derived value in a derived row would break rebuild determinism against unchanged authored inputs.
220
205
  interaction_pattern:
221
- description: 'How a capability''s declared dependency on a service is coupled at RUNTIME — M-ADR 0171''s closed interaction-pattern vocabulary (the union of its ingestion and invocation sets), reused on `capability_service.interaction_pattern` per M-ADR 0211 §4.1 and not widened. BOUND because the value comes from the traceability manifest, a method-mandated authoring surface (M-ADR 0210 §4.5). A NON-RUNTIME coupling — build-time code generation, a load-time singleton, packaging, an authoring sequence — leaves the column EMPTY and states its kind in the manifest''s dependency_notes; that is T4''s excluded-by-class case and reaches no band 5. An entry declares ONE coupling: two tokens in one entry is two entries. Measured at two estates before binding: 17 of 18 runtime couplings mapped onto exactly one token; none needed a token the vocabulary lacks.'
222
206
  values:
223
207
  - value: event-stream-consume
224
208
  description: Subscribe to and drain a broker / stream / feed the provider produces; the consumer drains a durable, ordered channel (Event-Driven / Polling Consumer over a Message Channel).
@@ -234,27 +218,27 @@ enums:
234
218
  description: Submit a request; the result returns later via a separate channel, correlated by identifier (Request-Reply, asynchronous + Correlation Identifier).
235
219
  - value: publish
236
220
  description: Fire-and-forget write to a broker / queue / endpoint with no awaited response (Publish-Subscribe / fire-and-forget Message).
221
+ description: "How a capability's declared dependency on a service is coupled at RUNTIME — M-ADR 0171's closed interaction-pattern vocabulary (the union of its ingestion and invocation sets), reused on `capability_service.interaction_pattern` per M-ADR 0211 §4.1 and not widened. BOUND because the value comes from the traceability manifest, a method-mandated authoring surface (M-ADR 0210 §4.5). A NON-RUNTIME coupling — build-time code generation, a load-time singleton, packaging, an authoring sequence — leaves the column EMPTY and states its kind in the manifest's dependency_notes; that is T4's excluded-by-class case and reaches no band 5. An entry declares ONE coupling: two tokens in one entry is two entries. Measured at two estates before binding: 17 of 18 runtime couplings mapped onto exactly one token; none needed a token the vocabulary lacks."
237
222
  event_participation:
238
- description: 'The part a service, capability or feature plays toward an event, in `service_event.role`, `capability_event.role` and `feature_event.role`. `service_event.role` is also M-ADR 0206 §4.2''s role-conditional impact flow (publishes → toward-target, consumes → toward-source). Bound at 3.9.0 (M-ADR 0210 §4.5): the values come from repo-config and derived edges, method-mandated surfaces; every row at both adopter estates'' committed aggregates was in-vocabulary when bound.'
239
223
  values:
240
224
  - value: publishes
241
225
  description: The participant emits the event.
242
226
  - value: consumes
243
227
  description: The participant receives the event.
228
+ description: "The part a service, capability or feature plays toward an event, in `service_event.role`, `capability_event.role` and `feature_event.role`. `service_event.role` is also M-ADR 0206 §4.2's role-conditional impact flow (publishes → toward-target, consumes → toward-source). Bound at 3.9.0 (M-ADR 0210 §4.5): the values come from repo-config and derived edges, method-mandated surfaces; every row at both adopter estates' committed aggregates was in-vocabulary when bound."
244
229
  contract_participation:
245
- description: The part a service plays toward a contract, in `service_contract.role`. Bound at 3.9.0 (M-ADR 0210 §4.5); one estate's rows were all `exposes`, the other's all `consumes` — the union is the vocabulary, and each estate's usage was in it.
246
230
  values:
247
231
  - value: exposes
248
232
  description: The service publishes the contract as its own surface.
249
233
  - value: consumes
250
234
  description: The service depends on a contract another service exposes.
235
+ description: The part a service plays toward a contract, in `service_contract.role`. Bound at 3.9.0 (M-ADR 0210 §4.5); one estate's rows were all `exposes`, the other's all `consumes` — the union is the vocabulary, and each estate's usage was in it.
251
236
  consumption_role:
252
- description: 'The part a product plays toward a capability or service it depends on, in `product_capability.role` and `product_service.role`. EXACTLY ONE VALUE, deliberately: every row at both estates carries `consumes`, and a column with one value is a population of one (M-ADR 0200 §4.10). Bound so the constant is DECLARED rather than accidental — a second value arriving is then a vocabulary decision with a finding, not a silent widening.'
253
237
  values:
254
238
  - value: consumes
255
239
  description: The product depends on / consumes the target.
240
+ description: "The part a product plays toward a capability or service it depends on, in `product_capability.role` and `product_service.role`. EXACTLY ONE VALUE, deliberately: every row at both estates carries `consumes`, and a column with one value is a population of one (M-ADR 0200 §4.10). Bound so the constant is DECLARED rather than accidental — a second value arriving is then a vocabulary decision with a finding, not a silent widening."
256
241
  journey_participation:
257
- description: 'The kind of participation a persona has in a user journey, in `persona_journey.role` — the ADR 0210 worked example''s `participation`. Bound at 3.9.0 (M-ADR 0210 §4.5): parsed from the persona spec''s declared `Roles:` line, a method template surface; every row at both estates was in-vocabulary when bound.'
258
242
  values:
259
243
  - value: primary
260
244
  description: The persona the journey is designed around.
@@ -262,6 +246,7 @@ enums:
262
246
  description: A persona the journey passes to or from.
263
247
  - value: supporting
264
248
  description: A persona present in the journey without owning it.
249
+ description: "The kind of participation a persona has in a user journey, in `persona_journey.role` — the ADR 0210 worked example's `participation`. Bound at 3.9.0 (M-ADR 0210 §4.5): parsed from the persona spec's declared `Roles:` line, a method template surface; every row at both estates was in-vocabulary when bound."
265
250
  catalogues:
266
251
  domains:
267
252
  primary_key: id
@@ -320,7 +305,7 @@ catalogues:
320
305
  - name: category
321
306
  type: string
322
307
  nullable: true
323
- description: 'Architectural classification per docs/method/methods/standards/product-category-taxonomy.md. Values: platform-root | platform-subsystem | application-product | integration-provider | integration-umbrella | support-repo. Determines whether the Product gets a c4_systems row.'
308
+ description: "Architectural classification per docs/method/methods/standards/product-category-taxonomy.md. Values: platform-root | platform-subsystem | application-product | integration-provider | integration-umbrella | support-repo. Determines whether the Product gets a c4_systems row."
324
309
  - name: doc_path
325
310
  type: string
326
311
  nullable: false
@@ -328,7 +313,7 @@ catalogues:
328
313
  - name: lifecycle
329
314
  type: string
330
315
  nullable: true
331
- description: 'planned | active | deprecated (default active when empty). Owner-declared product lifecycle from the SDD manifest''s lifecycle: field (sdd-manifest-schema 1.1.0; `planned` added 1.9.0 / catalogue 2.47.0). `planned` = the product is real and intended but does not exist yet, which is the normal opening state of a forward-authored product — so a forward estate that has generated nothing should read `planned`, not the `active` the empty default implies. Distinct from status (documentation maturity): lifecycle is a fact about the PRODUCT, status about the DOCUMENT, and both can hold at once — a product can be reviewed AND deprecated, or planned AND thinly documented. Added in 2.22.0.'
316
+ description: "planned | active | deprecated (default active when empty). Owner-declared product lifecycle from the SDD manifest's lifecycle: field (sdd-manifest-schema 1.1.0; `planned` added 1.9.0 / catalogue 2.47.0). `planned` = the product is real and intended but does not exist yet, which is the normal opening state of a forward-authored product — so a forward estate that has generated nothing should read `planned`, not the `active` the empty default implies. Distinct from status (documentation maturity): lifecycle is a fact about the PRODUCT, status about the DOCUMENT, and both can hold at once — a product can be reviewed AND deprecated, or planned AND thinly documented. Added in 2.22.0."
332
317
  - name: deprecated_date
333
318
  type: date
334
319
  nullable: true
@@ -336,31 +321,31 @@ catalogues:
336
321
  - name: successor_sdd_id
337
322
  type: string
338
323
  nullable: true
339
- description: 'For deprecated products: sdd_id of the superseding SDD. Same vocabulary as sdd_id/source_sdd_id (NOT products.id). Soft reference — the aggregator orphan-checks it against contributing sdd_ids ([finding] orphan when unresolved), never a hard FK: the successor may live outside the aggregation scope. Added in 2.22.0.'
324
+ description: "For deprecated products: sdd_id of the superseding SDD. Same vocabulary as sdd_id/source_sdd_id (NOT products.id). Soft reference — the aggregator orphan-checks it against contributing sdd_ids ([finding] orphan when unresolved), never a hard FK: the successor may live outside the aggregation scope. Added in 2.22.0."
340
325
  - name: exemplar
341
326
  type: string
342
327
  nullable: true
343
- description: '`true` when this SDD is a reference exemplar — it demonstrates a profile shape rather than modelling a real product or provider relationship. Empty otherwise, which is the unmarked norm (absent in the manifest = a real SDD, no finding). From the manifest''s `exemplar:` field (sdd-manifest-schema 1.8.0). PROFILE-AGNOSTIC, unlike surface/packaging/application_archetype which are application-product-only — the first exemplar cohort found was integration-products. DERIVED, not authorable: this column and `integrations.exemplar` both come from the one manifest field, so they cannot disagree; two independently authored copies could, which is the failure mode the trait exists to remove. No builder branches on it — it is emitted to be filterable and nothing consumes it, because an implicit exclusion inside a rollup is much harder to remove than to add. Added in 2.46.0.'
328
+ description: "`true` when this SDD is a reference exemplar — it demonstrates a profile shape rather than modelling a real product or provider relationship. Empty otherwise, which is the unmarked norm (absent in the manifest = a real SDD, no finding). From the manifest's `exemplar:` field (sdd-manifest-schema 1.8.0). PROFILE-AGNOSTIC, unlike surface/packaging/application_archetype which are application-product-only — the first exemplar cohort found was integration-products. DERIVED, not authorable: this column and `integrations.exemplar` both come from the one manifest field, so they cannot disagree; two independently authored copies could, which is the failure mode the trait exists to remove. No builder branches on it — it is emitted to be filterable and nothing consumes it, because an implicit exclusion inside a rollup is much harder to remove than to add. Added in 2.46.0."
344
329
  - name: surface
345
330
  type: string
346
331
  nullable: true
347
- description: 'ui | api (empty for non-application-product). Application-product surface trait from the manifest''s surface: field (M-ADR 0167, sdd-manifest-schema 1.2.0). Empty on non-application products. Added in 2.35.0.'
332
+ description: "ui | api (empty for non-application-product). Application-product surface trait from the manifest's surface: field (M-ADR 0167, sdd-manifest-schema 1.2.0). Empty on non-application products. Added in 2.35.0."
348
333
  - name: packaging
349
334
  type: string
350
335
  nullable: true
351
- description: 'vendor-saas | self-operated (empty for non-application-product). Application-product packaging trait from the manifest''s packaging: field (M-ADR 0175, sdd-manifest-schema 1.7.0). `vendor-saas` marks a packaged-SaaS product — vendor-operated runtime (no own deployment evidence) and a vendor-versioned base capability set. Absent in the manifest resolves to `self-operated`, the unmarked norm. Per M-ADR 0175 §4 no builder may branch on this trait beyond evidence/deployment handling. Column position follows the M-ADR 0194 §3.1 canonical axis order (surface, packaging, application_archetype). Added in 2.41.0.'
336
+ description: "vendor-saas | self-operated (empty for non-application-product). Application-product packaging trait from the manifest's packaging: field (M-ADR 0175, sdd-manifest-schema 1.7.0). `vendor-saas` marks a packaged-SaaS product — vendor-operated runtime (no own deployment evidence) and a vendor-versioned base capability set. Absent in the manifest resolves to `self-operated`, the unmarked norm. Per M-ADR 0175 §4 no builder may branch on this trait beyond evidence/deployment handling. Column position follows the M-ADR 0194 §3.1 canonical axis order (surface, packaging, application_archetype). Added in 2.41.0."
352
337
  - name: application_archetype
353
338
  type: string
354
339
  nullable: true
355
- description: 'Application-product shape classification from the manifest''s application_archetype: field (M-ADR 0191, sdd-manifest-schema 1.2.0). Resolved-enum over a tiered vocabulary (method: unclassified; reference-architecture bundle; adopter). Defaults to ''unclassified'' for application-product (with a coverage finding), empty for other profiles. Distinct from the M-ADR 0173 domain archetype and M-ADR 0169 openui archetype. Added in 2.35.0.'
340
+ description: "Application-product shape classification from the manifest's application_archetype: field (M-ADR 0191, sdd-manifest-schema 1.2.0). Resolved-enum over a tiered vocabulary (method: unclassified; reference-architecture bundle; adopter). Defaults to 'unclassified' for application-product (with a coverage finding), empty for other profiles. Distinct from the M-ADR 0173 domain archetype and M-ADR 0169 openui archetype. Added in 2.35.0."
356
341
  - name: synthesis_quality
357
342
  type: int
358
343
  nullable: true
359
- description: 'DEPRECATED at 3.3.0, for removal at 4.0.0 — superseded by `quality_scores` (rubric_id `reverse-product-quality.product_synthesis_quality`). Score 0-10 from the product-synthesis rubric (reverse method only). WIRED in 2.47.0 from `orchestration/gate-registry/reverse-product-quality-scores.yaml` — the registry family at product granularity — via the SELF-PRODUCT rule: the unit whose `product_path` is ''.'' AND whose key equals the SDD''s sdd_id. Both conditions are required; product_path alone admits synthetic gate fixtures, key-matching alone admits covered sub-products. Backfill only: it fills an empty cell and never overwrites an emitted value. Empty on a forward estate by design — a forward-authored product has no reverse rubric score, and residue-based authoring signals deliberately do NOT write here (see status).'
344
+ description: "DEPRECATED at 3.3.0, for removal at 4.0.0 — superseded by `quality_scores` (rubric_id `reverse-product-quality.product_synthesis_quality`). Score 0-10 from the product-synthesis rubric (reverse method only). WIRED in 2.47.0 from `orchestration/gate-registry/reverse-product-quality-scores.yaml` — the registry family at product granularity — via the SELF-PRODUCT rule: the unit whose `product_path` is '.' AND whose key equals the SDD's sdd_id. Both conditions are required; product_path alone admits synthetic gate fixtures, key-matching alone admits covered sub-products. Backfill only: it fills an empty cell and never overwrites an emitted value. Empty on a forward estate by design — a forward-authored product has no reverse rubric score, and residue-based authoring signals deliberately do NOT write here (see status)."
360
345
  - name: synthesis_band
361
346
  type: string
362
347
  nullable: true
363
- description: 'DEPRECATED at 3.3.0, for removal at 4.0.0 — superseded by `quality_scores.band`, which is UNBOUND because the vocabulary is per-rubric. This column''s closed set accepts only three of the SEVEN band values the reverse estate actually authors (measured 3.3.0: strong, working, weak, moderate, easy, hard, very-hard), silently emptying the rest. developing | working | strong — a CLOSED vocabulary; a band outside it is reported as a convention finding and the cell left empty rather than emitting a value no consumer can interpret. Wired in 2.47.0 alongside synthesis_quality.'
348
+ description: "DEPRECATED at 3.3.0, for removal at 4.0.0 — superseded by `quality_scores.band`, which is UNBOUND because the vocabulary is per-rubric. This column's closed set accepts only three of the SEVEN band values the reverse estate actually authors (measured 3.3.0: strong, working, weak, moderate, easy, hard, very-hard), silently emptying the rest. developing | working | strong — a CLOSED vocabulary; a band outside it is reported as a convention finding and the cell left empty rather than emitting a value no consumer can interpret. Wired in 2.47.0 alongside synthesis_quality."
364
349
  - name: last_assessed
365
350
  type: date
366
351
  nullable: true
@@ -385,7 +370,6 @@ catalogues:
385
370
  nullable: true
386
371
  applications:
387
372
  primary_key: id
388
- description: Filtered view of products where profile = application-product.
389
373
  columns:
390
374
  - name: id
391
375
  type: string
@@ -405,7 +389,7 @@ catalogues:
405
389
  - name: category
406
390
  type: string
407
391
  nullable: true
408
- description: 'Architectural classification per docs/method/methods/standards/product-category-taxonomy.md. Values: platform-root | platform-subsystem | application-product | integration-provider | integration-umbrella | support-repo. Determines whether the Product gets a c4_systems row.'
392
+ description: "Architectural classification per docs/method/methods/standards/product-category-taxonomy.md. Values: platform-root | platform-subsystem | application-product | integration-provider | integration-umbrella | support-repo. Determines whether the Product gets a c4_systems row."
409
393
  - name: doc_path
410
394
  type: string
411
395
  nullable: false
@@ -413,7 +397,7 @@ catalogues:
413
397
  - name: lifecycle
414
398
  type: string
415
399
  nullable: true
416
- description: 'planned | active | deprecated (default active when empty). Owner-declared product lifecycle from the SDD manifest''s lifecycle: field (sdd-manifest-schema 1.1.0; `planned` added 1.9.0 / catalogue 2.47.0). `planned` = the product is real and intended but does not exist yet, which is the normal opening state of a forward-authored product — so a forward estate that has generated nothing should read `planned`, not the `active` the empty default implies. Distinct from status (documentation maturity): lifecycle is a fact about the PRODUCT, status about the DOCUMENT, and both can hold at once — a product can be reviewed AND deprecated, or planned AND thinly documented. Added in 2.22.0.'
400
+ description: "planned | active | deprecated (default active when empty). Owner-declared product lifecycle from the SDD manifest's lifecycle: field (sdd-manifest-schema 1.1.0; `planned` added 1.9.0 / catalogue 2.47.0). `planned` = the product is real and intended but does not exist yet, which is the normal opening state of a forward-authored product — so a forward estate that has generated nothing should read `planned`, not the `active` the empty default implies. Distinct from status (documentation maturity): lifecycle is a fact about the PRODUCT, status about the DOCUMENT, and both can hold at once — a product can be reviewed AND deprecated, or planned AND thinly documented. Added in 2.22.0."
417
401
  - name: deprecated_date
418
402
  type: date
419
403
  nullable: true
@@ -421,31 +405,31 @@ catalogues:
421
405
  - name: successor_sdd_id
422
406
  type: string
423
407
  nullable: true
424
- description: 'For deprecated products: sdd_id of the superseding SDD. Same vocabulary as sdd_id/source_sdd_id (NOT products.id). Soft reference — the aggregator orphan-checks it against contributing sdd_ids ([finding] orphan when unresolved), never a hard FK: the successor may live outside the aggregation scope. Added in 2.22.0.'
408
+ description: "For deprecated products: sdd_id of the superseding SDD. Same vocabulary as sdd_id/source_sdd_id (NOT products.id). Soft reference — the aggregator orphan-checks it against contributing sdd_ids ([finding] orphan when unresolved), never a hard FK: the successor may live outside the aggregation scope. Added in 2.22.0."
425
409
  - name: exemplar
426
410
  type: string
427
411
  nullable: true
428
- description: '`true` when this SDD is a reference exemplar — it demonstrates a profile shape rather than modelling a real product or provider relationship. Empty otherwise, which is the unmarked norm (absent in the manifest = a real SDD, no finding). From the manifest''s `exemplar:` field (sdd-manifest-schema 1.8.0). PROFILE-AGNOSTIC, unlike surface/packaging/application_archetype which are application-product-only — the first exemplar cohort found was integration-products. DERIVED, not authorable: this column and `integrations.exemplar` both come from the one manifest field, so they cannot disagree; two independently authored copies could, which is the failure mode the trait exists to remove. No builder branches on it — it is emitted to be filterable and nothing consumes it, because an implicit exclusion inside a rollup is much harder to remove than to add. Added in 2.46.0.'
412
+ description: "`true` when this SDD is a reference exemplar — it demonstrates a profile shape rather than modelling a real product or provider relationship. Empty otherwise, which is the unmarked norm (absent in the manifest = a real SDD, no finding). From the manifest's `exemplar:` field (sdd-manifest-schema 1.8.0). PROFILE-AGNOSTIC, unlike surface/packaging/application_archetype which are application-product-only — the first exemplar cohort found was integration-products. DERIVED, not authorable: this column and `integrations.exemplar` both come from the one manifest field, so they cannot disagree; two independently authored copies could, which is the failure mode the trait exists to remove. No builder branches on it — it is emitted to be filterable and nothing consumes it, because an implicit exclusion inside a rollup is much harder to remove than to add. Added in 2.46.0."
429
413
  - name: surface
430
414
  type: string
431
415
  nullable: true
432
- description: 'ui | api (empty for non-application-product). Application-product surface trait from the manifest''s surface: field (M-ADR 0167, sdd-manifest-schema 1.2.0). Empty on non-application products. Added in 2.35.0.'
416
+ description: "ui | api (empty for non-application-product). Application-product surface trait from the manifest's surface: field (M-ADR 0167, sdd-manifest-schema 1.2.0). Empty on non-application products. Added in 2.35.0."
433
417
  - name: packaging
434
418
  type: string
435
419
  nullable: true
436
- description: 'vendor-saas | self-operated (empty for non-application-product). Application-product packaging trait from the manifest''s packaging: field (M-ADR 0175, sdd-manifest-schema 1.7.0). `vendor-saas` marks a packaged-SaaS product — vendor-operated runtime (no own deployment evidence) and a vendor-versioned base capability set. Absent in the manifest resolves to `self-operated`, the unmarked norm. Per M-ADR 0175 §4 no builder may branch on this trait beyond evidence/deployment handling. Column position follows the M-ADR 0194 §3.1 canonical axis order (surface, packaging, application_archetype). Added in 2.41.0.'
420
+ description: "vendor-saas | self-operated (empty for non-application-product). Application-product packaging trait from the manifest's packaging: field (M-ADR 0175, sdd-manifest-schema 1.7.0). `vendor-saas` marks a packaged-SaaS product — vendor-operated runtime (no own deployment evidence) and a vendor-versioned base capability set. Absent in the manifest resolves to `self-operated`, the unmarked norm. Per M-ADR 0175 §4 no builder may branch on this trait beyond evidence/deployment handling. Column position follows the M-ADR 0194 §3.1 canonical axis order (surface, packaging, application_archetype). Added in 2.41.0."
437
421
  - name: application_archetype
438
422
  type: string
439
423
  nullable: true
440
- description: 'Application-product shape classification from the manifest''s application_archetype: field (M-ADR 0191, sdd-manifest-schema 1.2.0). Resolved-enum over a tiered vocabulary (method: unclassified; reference-architecture bundle; adopter). Defaults to ''unclassified'' for application-product (with a coverage finding), empty for other profiles. Distinct from the M-ADR 0173 domain archetype and M-ADR 0169 openui archetype. Added in 2.35.0.'
424
+ description: "Application-product shape classification from the manifest's application_archetype: field (M-ADR 0191, sdd-manifest-schema 1.2.0). Resolved-enum over a tiered vocabulary (method: unclassified; reference-architecture bundle; adopter). Defaults to 'unclassified' for application-product (with a coverage finding), empty for other profiles. Distinct from the M-ADR 0173 domain archetype and M-ADR 0169 openui archetype. Added in 2.35.0."
441
425
  - name: synthesis_quality
442
426
  type: int
443
427
  nullable: true
444
- description: 'DEPRECATED at 3.3.0, for removal at 4.0.0 — superseded by `quality_scores` (rubric_id `reverse-product-quality.product_synthesis_quality`). Score 0-10 from the product-synthesis rubric (reverse method only). WIRED in 2.47.0 from `orchestration/gate-registry/reverse-product-quality-scores.yaml` — the registry family at product granularity — via the SELF-PRODUCT rule: the unit whose `product_path` is ''.'' AND whose key equals the SDD''s sdd_id. Both conditions are required; product_path alone admits synthetic gate fixtures, key-matching alone admits covered sub-products. Backfill only: it fills an empty cell and never overwrites an emitted value. Empty on a forward estate by design — a forward-authored product has no reverse rubric score, and residue-based authoring signals deliberately do NOT write here (see status).'
428
+ description: "DEPRECATED at 3.3.0, for removal at 4.0.0 — superseded by `quality_scores` (rubric_id `reverse-product-quality.product_synthesis_quality`). Score 0-10 from the product-synthesis rubric (reverse method only). WIRED in 2.47.0 from `orchestration/gate-registry/reverse-product-quality-scores.yaml` — the registry family at product granularity — via the SELF-PRODUCT rule: the unit whose `product_path` is '.' AND whose key equals the SDD's sdd_id. Both conditions are required; product_path alone admits synthetic gate fixtures, key-matching alone admits covered sub-products. Backfill only: it fills an empty cell and never overwrites an emitted value. Empty on a forward estate by design — a forward-authored product has no reverse rubric score, and residue-based authoring signals deliberately do NOT write here (see status)."
445
429
  - name: synthesis_band
446
430
  type: string
447
431
  nullable: true
448
- description: 'DEPRECATED at 3.3.0, for removal at 4.0.0 — superseded by `quality_scores.band`, which is UNBOUND because the vocabulary is per-rubric. This column''s closed set accepts only three of the SEVEN band values the reverse estate actually authors (measured 3.3.0: strong, working, weak, moderate, easy, hard, very-hard), silently emptying the rest. developing | working | strong — a CLOSED vocabulary; a band outside it is reported as a convention finding and the cell left empty rather than emitting a value no consumer can interpret. Wired in 2.47.0 alongside synthesis_quality.'
432
+ description: "DEPRECATED at 3.3.0, for removal at 4.0.0 — superseded by `quality_scores.band`, which is UNBOUND because the vocabulary is per-rubric. This column's closed set accepts only three of the SEVEN band values the reverse estate actually authors (measured 3.3.0: strong, working, weak, moderate, easy, hard, very-hard), silently emptying the rest. developing | working | strong — a CLOSED vocabulary; a band outside it is reported as a convention finding and the cell left empty rather than emitting a value no consumer can interpret. Wired in 2.47.0 alongside synthesis_quality."
449
433
  - name: last_assessed
450
434
  type: date
451
435
  nullable: true
@@ -464,13 +448,13 @@ catalogues:
464
448
  type: string
465
449
  nullable: true
466
450
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
451
+ description: Filtered view of products where profile = application-product.
467
452
  foreign_keys:
468
453
  - column: domain_id
469
454
  references: domains.id
470
455
  nullable: true
471
456
  integrations:
472
457
  primary_key: id
473
- description: Granular provider adapters. Each row is either (a) an integration-product SDD's own row (one per SDD; parent_product_id empty), or (b) a manifest-declared sub-integration of a multi-provider monolith (parent_product_id = umbrella SDD's id). Per M-ADR 0144 (schema 2.6.0), sub-integrations are declared via the optional `sub_integrations:` array in `integration-manifest.yaml`.
474
458
  columns:
475
459
  - name: id
476
460
  type: string
@@ -500,7 +484,7 @@ catalogues:
500
484
  - name: ingestion_pattern
501
485
  type: string
502
486
  nullable: true
503
- description: 'Closed method-tier enum (event-stream-consume | webhook | socket-listen | poll) from the manifest''s SDD-level `ingestionPattern` — HOW the integration acquires data (M-ADR 0171 §4.2). SCALAR: §9.3''s multi-valued allowance was withdrawn in §10.5. Empty when undeclared or on an outbound-only integration. Empty on `sub_integrations` rows — the patterns are declared once at SDD level and are not per-provider. Added in 2.45.0.'
487
+ description: "Closed method-tier enum (event-stream-consume | webhook | socket-listen | poll) from the manifest's SDD-level `ingestionPattern` — HOW the integration acquires data (M-ADR 0171 §4.2). SCALAR: §9.3's multi-valued allowance was withdrawn in §10.5. Empty when undeclared or on an outbound-only integration. Empty on `sub_integrations` rows — the patterns are declared once at SDD level and are not per-provider. Added in 2.45.0."
504
488
  - name: invocation_pattern
505
489
  type: string
506
490
  nullable: true
@@ -512,7 +496,7 @@ catalogues:
512
496
  - name: exemplar
513
497
  type: string
514
498
  nullable: true
515
- description: '`true` when the emitting SDD is a reference exemplar (demonstrates a profile shape rather than modelling a real provider relationship); empty otherwise. Derived from the SDD manifest''s `exemplar:` field (sdd-manifest-schema 1.8.0), same source as `products.exemplar` — neither column is independently authorable. Carried on `sub_integrations` rows too, INHERITED from the emitting SDD. That deliberately differs from `ingestion_pattern`/`invocation_pattern`, which are empty on sub rows, and the difference is the point: a pattern is a MECHANISM (how this integration acquires data), genuinely one per SDD, whereas `exemplar` is a REALITY STATUS that propagates to everything the SDD emits — if the SDD is a demonstration then every provider relationship it declares is a demonstration. Leaving sub rows empty would flag the umbrella and count its demonstration sub-providers as real, reproducing the rollup overcount this column exists to fix one level down. Do not normalise it to match the pattern columns. The trade accepted: a real SDD with one demonstration sub-provider is unexpressible — a state that should not exist. Added in 2.46.0.'
499
+ description: "`true` when the emitting SDD is a reference exemplar (demonstrates a profile shape rather than modelling a real provider relationship); empty otherwise. Derived from the SDD manifest's `exemplar:` field (sdd-manifest-schema 1.8.0), same source as `products.exemplar` — neither column is independently authorable. Carried on `sub_integrations` rows too, INHERITED from the emitting SDD. That deliberately differs from `ingestion_pattern`/`invocation_pattern`, which are empty on sub rows, and the difference is the point: a pattern is a MECHANISM (how this integration acquires data), genuinely one per SDD, whereas `exemplar` is a REALITY STATUS that propagates to everything the SDD emits — if the SDD is a demonstration then every provider relationship it declares is a demonstration. Leaving sub rows empty would flag the umbrella and count its demonstration sub-providers as real, reproducing the rollup overcount this column exists to fix one level down. Do not normalise it to match the pattern columns. The trade accepted: a real SDD with one demonstration sub-provider is unexpressible — a state that should not exist. Added in 2.46.0."
516
500
  - name: source_sdd_id
517
501
  type: string
518
502
  nullable: true
@@ -521,6 +505,7 @@ catalogues:
521
505
  type: string
522
506
  nullable: true
523
507
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
508
+ description: Granular provider adapters. Each row is either (a) an integration-product SDD's own row (one per SDD; parent_product_id empty), or (b) a manifest-declared sub-integration of a multi-provider monolith (parent_product_id = umbrella SDD's id). Per M-ADR 0144 (schema 2.6.0), sub-integrations are declared via the optional `sub_integrations:` array in `integration-manifest.yaml`.
524
509
  foreign_keys:
525
510
  - column: domain_id
526
511
  references: domains.id
@@ -530,18 +515,11 @@ catalogues:
530
515
  nullable: true
531
516
  integration_component:
532
517
  primary_key: id
533
- description: 'Integration-product edge (M-ADR 0171 §9, catalogued per §10.1): one row per component declared in the SDD''s `integration-manifest.yaml` `components:` array. A component is one of the integration''s component code repos (M-ADR 0106) — an integration SDD is a one-to-many spec→code unit — and the tier is the source of truth for the interaction pattern, with the SDD-level `ingestionPattern`/`invocationPattern` as its aggregate (§9.3).
534
-
535
- Built per-SDD, integration-product only (other profiles emit headers-only). A component id is unique within its manifest and names an **interaction surface** — commonly one provider feed — which is NOT necessarily a deployable (§10.2). The optional `component_repo` carries an explicit code linkage; when declared it MUST resolve to a `repositories.id` or `services.id` of the same SDD, and a declared-but-unresolvable linkage is a **coverage finding, not a load failure**. `resolution` records the outcome inline, including `undeclared` for the normal feed-level case, so a consumer filters on it rather than inferring from a join miss.
536
-
537
- The method deliberately does NOT enumerate `component_type` — that is the adopter''s own framework-role label (§9.1/§9.5), carried so an adopter''s role→pattern mapping stays machine-traceable. `transport`/`format`/`auth` are open strings for the same reason: they describe the wire, and the portable semantic is the pattern. Added in schema 2.43.0.
538
-
539
- '
540
518
  columns:
541
519
  - name: id
542
520
  type: string
543
521
  nullable: false
544
- description: '{integration_id}__{component_id}. A duplicate emits a divergence finding and is dropped — two components of one integration cannot share an id.'
522
+ description: "{integration_id}__{component_id}. A duplicate emits a divergence finding and is dropped — two components of one integration cannot share an id."
545
523
  - name: integration_id
546
524
  type: string
547
525
  nullable: false
@@ -553,7 +531,7 @@ catalogues:
553
531
  - name: component_repo
554
532
  type: string
555
533
  nullable: true
556
- description: 'OPTIONAL explicit code linkage from `components[].componentRepo` — the deployable (repositories.id / services.id) that realises this component. Empty is the normal case for a feed-level component: the tier is at interaction-surface granularity, not deployable granularity, and the method does not require a component to name a deployable (M-ADR 0171 §10.2). When declared it MUST resolve, since a declared link is a positive assertion the method can check. Added in 2.44.0.'
534
+ description: "OPTIONAL explicit code linkage from `components[].componentRepo` — the deployable (repositories.id / services.id) that realises this component. Empty is the normal case for a feed-level component: the tier is at interaction-surface granularity, not deployable granularity, and the method does not require a component to name a deployable (M-ADR 0171 §10.2). When declared it MUST resolve, since a declared link is a positive assertion the method can check. Added in 2.44.0."
557
535
  - name: resolution
558
536
  type: string
559
537
  nullable: false
@@ -565,7 +543,7 @@ catalogues:
565
543
  - name: direction
566
544
  type: string
567
545
  nullable: true
568
- description: 'inbound | outbound | bidirectional, from `dataFlow.direction`. Determines which pattern field is meaningful: inbound → ingestion_pattern, outbound → invocation_pattern, internal components declare neither (M-ADR 0171 §9.1).'
546
+ description: "inbound | outbound | bidirectional, from `dataFlow.direction`. Determines which pattern field is meaningful: inbound → ingestion_pattern, outbound → invocation_pattern, internal components declare neither (M-ADR 0171 §9.1)."
569
547
  - name: frequency
570
548
  type: string
571
549
  nullable: true
@@ -601,7 +579,7 @@ catalogues:
601
579
  - name: declared_in
602
580
  type: string
603
581
  nullable: false
604
- description: 'components-array | component-manifest — WHICH of M-ADR 0171 §9.1''s two homes declared this component. Added in 2.49.0, when the second home became catalogued. Required because §10.1 states that any coverage reasoning MUST say which form it counts, and once one table holds both, a consumer cannot tell them apart: merging them without this recreates the reference-exemplar problem — well-formed rows that do not mean what a consumer assumes. Measured at the time of wiring: the array form was 15 components across 5 SDDs, the per-component form 86 across 21, and the two are DISJOINT (no id collision, no SDD using both). `resolution` also reads differently by form — for the array form `componentRepo` is an optional declaration (0 of 15 declared it); for the per-component form the containing `repos/<component>/` directory IS the repo, so linkage is structural rather than declared.'
582
+ description: "components-array | component-manifest — WHICH of M-ADR 0171 §9.1's two homes declared this component. Added in 2.49.0, when the second home became catalogued. Required because §10.1 states that any coverage reasoning MUST say which form it counts, and once one table holds both, a consumer cannot tell them apart: merging them without this recreates the reference-exemplar problem — well-formed rows that do not mean what a consumer assumes. Measured at the time of wiring: the array form was 15 components across 5 SDDs, the per-component form 86 across 21, and the two are DISJOINT (no id collision, no SDD using both). `resolution` also reads differently by form — for the array form `componentRepo` is an optional declaration (0 of 15 declared it); for the per-component form the containing `repos/<component>/` directory IS the repo, so linkage is structural rather than declared."
605
583
  - name: source_sdd_id
606
584
  type: string
607
585
  nullable: true
@@ -610,6 +588,10 @@ catalogues:
610
588
  type: string
611
589
  nullable: true
612
590
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
591
+ description: |
592
+ Integration-product edge (M-ADR 0171 §9, catalogued per §10.1): one row per component declared in the SDD's `integration-manifest.yaml` `components:` array. A component is one of the integration's component code repos (M-ADR 0106) — an integration SDD is a one-to-many spec→code unit — and the tier is the source of truth for the interaction pattern, with the SDD-level `ingestionPattern`/`invocationPattern` as its aggregate (§9.3).
593
+ Built per-SDD, integration-product only (other profiles emit headers-only). A component id is unique within its manifest and names an **interaction surface** — commonly one provider feed — which is NOT necessarily a deployable (§10.2). The optional `component_repo` carries an explicit code linkage; when declared it MUST resolve to a `repositories.id` or `services.id` of the same SDD, and a declared-but-unresolvable linkage is a **coverage finding, not a load failure**. `resolution` records the outcome inline, including `undeclared` for the normal feed-level case, so a consumer filters on it rather than inferring from a join miss.
594
+ The method deliberately does NOT enumerate `component_type` — that is the adopter's own framework-role label (§9.1/§9.5), carried so an adopter's role→pattern mapping stays machine-traceable. `transport`/`format`/`auth` are open strings for the same reason: they describe the wire, and the portable semantic is the pattern. Added in schema 2.43.0.
613
595
  foreign_keys:
614
596
  - column: integration_id
615
597
  references: integrations.id
@@ -631,7 +613,7 @@ catalogues:
631
613
  - name: domain_id
632
614
  type: string
633
615
  nullable: true
634
- description: 'Domain slug for a domain-scoped ADR (docs/domains/<slug>/…); ''platform'' for a platform-scoped ADR (docs/platform/adr/), whose owner has that domain by construction; EMPTY for a method-scoped ADR (docs/method/adr/, docs/method/platform-adr/) — method ADRs are cross-cutting governance and belong to no domain. Nullable since 3.10.0 (M-ADR 0136 §4.3 amendment): before it, method ADRs were pinned to ''platform'' and dangled in every platform-root without a domain of that name.'
616
+ description: "Domain slug for a domain-scoped ADR (docs/domains/<slug>/…); 'platform' for a platform-scoped ADR (docs/platform/adr/), whose owner has that domain by construction; EMPTY for a method-scoped ADR (docs/method/adr/, docs/method/platform-adr/) — method ADRs are cross-cutting governance and belong to no domain. Nullable since 3.10.0 (M-ADR 0136 §4.3 amendment): before it, method ADRs were pinned to 'platform' and dangled in every platform-root without a domain of that name."
635
617
  - name: decision_date
636
618
  type: date
637
619
  nullable: true
@@ -670,7 +652,7 @@ catalogues:
670
652
  - name: id
671
653
  type: string
672
654
  nullable: false
673
- description: 'Slug: {domain}-{term-slug} for uniqueness.'
655
+ description: "Slug: {domain}-{term-slug} for uniqueness."
674
656
  - name: term
675
657
  type: string
676
658
  nullable: false
@@ -688,7 +670,7 @@ catalogues:
688
670
  - name: aliases
689
671
  type: string
690
672
  nullable: true
691
- description: ''';''-separated list.'
673
+ description: "';'-separated list."
692
674
  - name: evidence
693
675
  type: string
694
676
  nullable: true
@@ -712,12 +694,11 @@ catalogues:
712
694
  nullable: true
713
695
  glossary_xref:
714
696
  primary_key: id
715
- description: 'Edge: cross-domain glossary relationships from glossary-alignment-manifest.yaml. Per M-ADR 0158, four walkers ingest into this catalogue: (a) forward declared pair-form {source, target} entries under aliases/conflicts, (b) reverse-method cross_domain_terms (emits references edges per referencer→owner), (c) reverse-method multi-domain conflicts (pair-wise expansion across domains[]), (d) forward-method supersedes (status: superseded entries with superseded_by back-link).'
716
697
  columns:
717
698
  - name: id
718
699
  type: string
719
700
  nullable: false
720
- description: 'Composite: {source_id}__{relation}__{target_id}.'
701
+ description: "Composite: {source_id}__{relation}__{target_id}."
721
702
  - name: source_id
722
703
  type: string
723
704
  nullable: false
@@ -728,6 +709,7 @@ catalogues:
728
709
  type: string
729
710
  nullable: false
730
711
  description: alias-of | conflicts-with | references | supersedes (extended in schema 2.12.0 per M-ADR 0158).
712
+ description: "Edge: cross-domain glossary relationships from glossary-alignment-manifest.yaml. Per M-ADR 0158, four walkers ingest into this catalogue: (a) forward declared pair-form {source, target} entries under aliases/conflicts, (b) reverse-method cross_domain_terms (emits references edges per referencer→owner), (c) reverse-method multi-domain conflicts (pair-wise expansion across domains[]), (d) forward-method supersedes (status: superseded entries with superseded_by back-link)."
731
713
  foreign_keys:
732
714
  - column: source_id
733
715
  references: glossary_items.id
@@ -737,12 +719,11 @@ catalogues:
737
719
  nullable: false
738
720
  entity_glossary:
739
721
  primary_key: id
740
- description: 'Edge: data-model entity → canonical glossary term. Added in schema 2.12.0 per M-ADR 0158. Source: glossary-alignment-manifest.yaml `models[].entities[]` with status ∈ {aligned, matched_direct} and non-empty glossary_term. PK derives from (domain, entity_name, glossary_item) so same-domain multi-diagram entries collapse to one row; cross-domain entries (e.g. platform-wide conceptual model + domain-specific model) emit one row per domain — legitimate cross-level cataloguing.'
741
722
  columns:
742
723
  - name: id
743
724
  type: string
744
725
  nullable: false
745
- description: 'Composite: {domain_id}__{entity_name_slug}__{glossary_item_id}.'
726
+ description: "Composite: {domain_id}__{entity_name_slug}__{glossary_item_id}."
746
727
  - name: domain_id
747
728
  type: string
748
729
  nullable: false
@@ -768,6 +749,7 @@ catalogues:
768
749
  type: string
769
750
  nullable: true
770
751
  description: The data-model entity this glossary mapping is about — an entities.id. The edge was always emitted per (domain, entity, glossary_term) and this end was missing from its keys (found at M-ADR 0210 flip 2; added at 3.9.0). Nullable until every builder populates it.
752
+ description: "Edge: data-model entity → canonical glossary term. Added in schema 2.12.0 per M-ADR 0158. Source: glossary-alignment-manifest.yaml `models[].entities[]` with status ∈ {aligned, matched_direct} and non-empty glossary_term. PK derives from (domain, entity_name, glossary_item) so same-domain multi-diagram entries collapse to one row; cross-domain entries (e.g. platform-wide conceptual model + domain-specific model) emit one row per domain — legitimate cross-level cataloguing."
771
753
  foreign_keys:
772
754
  - column: domain_id
773
755
  references: domains.id
@@ -879,7 +861,7 @@ catalogues:
879
861
  - name: status
880
862
  type: string
881
863
  nullable: false
882
- description: 'Capability LIFECYCLE phase — this column carries ONE axis and the reader may rely on that. active | planned | exploration | deprecated. Default ''active''. History, because the shape of the mistake is the useful part: the prior three-member set (active|planned|deprecated) could not express what estates authored, so 3.5.0 widened it to six on measured evidence — 44 of one estate''s 78 manifests were outside it (exploration 26, placeholder 11, detailed-pre-lock 6, first-draft 1), each recurring value varying WITHIN a domain, which is the ruled discriminator for a genuine phase over an authoring convention. But 3.6.0 RETRACTED `placeholder` and `detailed-pre-lock`: per M-ADR 0201 §1 those are rungs on the SPEC-AUTHORING ladder (`placeholder | first-draft | detailed-pre-lock`, plus §4.1''s `reverse-derived`), declared in each spec''s own `**Status:**` header and gated there by the spec-lifecycle gate. Admitting them here made one column carry two orthogonal axes, so a reader could not tell whether `placeholder` described the capability or its document. **Where the other axis lives: the spec header. Do not re-import it here.** `exploration` stays and is NOT authoring vocabulary — it is absent from 0201''s ladder, has M-ADR 0089''s workflow and named gates behind it, and describes the capability rather than its spec; a capability declaring it must carry a populated `traceability.exploration` block, and one that does not is a loud contradiction (validate-traceability enforces this; measured 0 of 26 violations). ⚠ A rule this column deliberately does NOT carry: `placeholder`''s. The obvious one (no authored features) was MEASURED FALSE — 4 of 11 carried features, one of them 9 — and the deeper reason no rule fit is that `placeholder` was never making a claim about the capability at all. That unwritable rule was the first symptom of the axis error, before anyone had named it. ⚠ DELIBERATELY NOT BOUND via column_enums, and this is staged rather than permanent: binding carries hard-fail teeth, and at 3.5.0 one out-of-vocabulary row remains (forward estate, `first-draft`, n=1, referred to that estate; the reverse estate measures ZERO across 180 manifests). An out-of-vocabulary value is CARRIED, not emptied and not rejected, and is reported as a convention finding by validate-traceability — nullable stays false and no cell is ever emptied, so the empty-means-unauthored-or-rejected ambiguity of the products.synthesis_band / quality_scores.gate precedents does not arise here. Bind only once that count is ZERO at both estates; binding a set not proven to cover what estates author is how synthesis_band earned its deprecation. On drift and enforcement, stated with its confound rather than as a slogan: the enforced sibling `contracts.status` drifted 1.2% (2 of 172) while this unenforced field drifted 56% (44 of 78) at the SAME estate — but the other estate''s copy of this same unenforced field drifted 0% of 180, so enforcement is not the only variable. The difference is authoring shape: the forward estate hand-authors per capability across 13 domains and explores vocabulary doing it, while the reverse estate''s manifests come from one largely uniform extraction process. That uniformity is itself the phase-vs-convention discriminator firing — a value uniform across a whole estate is tracking the process that wrote it.'
864
+ description: "Capability LIFECYCLE phase — this column carries ONE axis and the reader may rely on that. active | planned | exploration | deprecated. Default 'active'. History, because the shape of the mistake is the useful part: the prior three-member set (active|planned|deprecated) could not express what estates authored, so 3.5.0 widened it to six on measured evidence — 44 of one estate's 78 manifests were outside it (exploration 26, placeholder 11, detailed-pre-lock 6, first-draft 1), each recurring value varying WITHIN a domain, which is the ruled discriminator for a genuine phase over an authoring convention. But 3.6.0 RETRACTED `placeholder` and `detailed-pre-lock`: per M-ADR 0201 §1 those are rungs on the SPEC-AUTHORING ladder (`placeholder | first-draft | detailed-pre-lock`, plus §4.1's `reverse-derived`), declared in each spec's own `**Status:**` header and gated there by the spec-lifecycle gate. Admitting them here made one column carry two orthogonal axes, so a reader could not tell whether `placeholder` described the capability or its document. **Where the other axis lives: the spec header. Do not re-import it here.** `exploration` stays and is NOT authoring vocabulary — it is absent from 0201's ladder, has M-ADR 0089's workflow and named gates behind it, and describes the capability rather than its spec; a capability declaring it must carry a populated `traceability.exploration` block, and one that does not is a loud contradiction (validate-traceability enforces this; measured 0 of 26 violations). ⚠ A rule this column deliberately does NOT carry: `placeholder`'s. The obvious one (no authored features) was MEASURED FALSE — 4 of 11 carried features, one of them 9 — and the deeper reason no rule fit is that `placeholder` was never making a claim about the capability at all. That unwritable rule was the first symptom of the axis error, before anyone had named it. ⚠ DELIBERATELY NOT BOUND via column_enums, and this is staged rather than permanent: binding carries hard-fail teeth, and at 3.5.0 one out-of-vocabulary row remains (forward estate, `first-draft`, n=1, referred to that estate; the reverse estate measures ZERO across 180 manifests). An out-of-vocabulary value is CARRIED, not emptied and not rejected, and is reported as a convention finding by validate-traceability — nullable stays false and no cell is ever emptied, so the empty-means-unauthored-or-rejected ambiguity of the products.synthesis_band / quality_scores.gate precedents does not arise here. Bind only once that count is ZERO at both estates; binding a set not proven to cover what estates author is how synthesis_band earned its deprecation. On drift and enforcement, stated with its confound rather than as a slogan: the enforced sibling `contracts.status` drifted 1.2% (2 of 172) while this unenforced field drifted 56% (44 of 78) at the SAME estate — but the other estate's copy of this same unenforced field drifted 0% of 180, so enforcement is not the only variable. The difference is authoring shape: the forward estate hand-authors per capability across 13 domains and explores vocabulary doing it, while the reverse estate's manifests come from one largely uniform extraction process. That uniformity is itself the phase-vs-convention discriminator firing — a value uniform across a whole estate is tracking the process that wrote it."
883
865
  - name: spec_path
884
866
  type: string
885
867
  nullable: true
@@ -887,7 +869,7 @@ catalogues:
887
869
  - name: contract_provenance
888
870
  type: string
889
871
  nullable: true
890
- description: 'How this capability''s declared contract SET was produced, from `traceability.contracts.provenance`. hand-authored | reverse-extracted | generated — the vocabulary the method already ships for `authoring-mode`, reused deliberately so provenance has one vocabulary and not two. Empty means undeclared, and undeclared reads as `hand-authored` by convention. Added at 3.5.0. ⚠ STRICTLY ORTHOGONAL to the contract-set maturity ladder (`traceability.contracts.status`: planned | provisional | partial | complete | locked | none): provenance never constrains status and status never constrains provenance, and `reverse-extracted` + `complete` is the legitimate pair that motivated the field. Evidence: 2 reverse-estate manifests had written `reverse-extracted` INTO contracts.status, where it is invalid, because a complete reverse-derived contract surface had no way to say both true things at once and the author picked the provenance one. A rule here that constrained maturity would re-create exactly that defect. ⚠ Note the asymmetry this column exposes and does not fix: the maturity ladder it is orthogonal to has NO catalogue column at all — `traceability.contracts.status` is validator-enforced but uncatalogued, so it is queryable by no consumer. That is the authored-but-uncatalogued class (a block with no column has no automated reader, so nothing can notice when it is absent or wrong); this column is given one precisely so the provenance half does not join it. Giving the ladder a column is a candidate follow-on, not done here.'
872
+ description: "How this capability's declared contract SET was produced, from `traceability.contracts.provenance`. hand-authored | reverse-extracted | generated — the vocabulary the method already ships for `authoring-mode`, reused deliberately so provenance has one vocabulary and not two. Empty means undeclared, and undeclared reads as `hand-authored` by convention. Added at 3.5.0. ⚠ STRICTLY ORTHOGONAL to the contract-set maturity ladder (`traceability.contracts.status`: planned | provisional | partial | complete | locked | none): provenance never constrains status and status never constrains provenance, and `reverse-extracted` + `complete` is the legitimate pair that motivated the field. Evidence: 2 reverse-estate manifests had written `reverse-extracted` INTO contracts.status, where it is invalid, because a complete reverse-derived contract surface had no way to say both true things at once and the author picked the provenance one. A rule here that constrained maturity would re-create exactly that defect. ⚠ Note the asymmetry this column exposes and does not fix: the maturity ladder it is orthogonal to has NO catalogue column at all — `traceability.contracts.status` is validator-enforced but uncatalogued, so it is queryable by no consumer. That is the authored-but-uncatalogued class (a block with no column has no automated reader, so nothing can notice when it is absent or wrong); this column is given one precisely so the provenance half does not join it. Giving the ladder a column is a candidate follow-on, not done here."
891
873
  - name: source
892
874
  type: string
893
875
  nullable: false
@@ -903,7 +885,7 @@ catalogues:
903
885
  - name: slice_scope
904
886
  type: string
905
887
  nullable: true
906
- description: 'Per-slice marker when one capability legitimately covers multiple app groups or data subsets (e.g. a compliance capability spanning several regulated-fleet sub-groups). Same capability_id may appear across multiple rows when sliced; row identity is then `(id, slice_scope)`. Empty when the capability is not sliced. Per-slice AC numbering convention: AC1-ACN unsuffixed for the first slice; subsequent slices use AC numbering suffixed by slice. See `docs/method/methods/reverse/rubrics/reverse-platform-evidence-quality.md` §`slice_scope:` and `docs/method/methods/capability-spec-template.md` Guideline 9. Added in schema 2.9.0.'
888
+ description: "Per-slice marker when one capability legitimately covers multiple app groups or data subsets (e.g. a compliance capability spanning several regulated-fleet sub-groups). Same capability_id may appear across multiple rows when sliced; row identity is then `(id, slice_scope)`. Empty when the capability is not sliced. Per-slice AC numbering convention: AC1-ACN unsuffixed for the first slice; subsequent slices use AC numbering suffixed by slice. See `docs/method/methods/reverse/rubrics/reverse-platform-evidence-quality.md` §`slice_scope:` and `docs/method/methods/capability-spec-template.md` Guideline 9. Added in schema 2.9.0."
907
889
  - name: source_sdd_id
908
890
  type: string
909
891
  nullable: true
@@ -924,14 +906,11 @@ catalogues:
924
906
  nullable: true
925
907
  feature_groups:
926
908
  primary_key: id
927
- description: 'Hierarchical grouping for features. First-class entity per resolution of adopt-canonical-catalogue-builder.md §7.2 — replaces the previous reverse-only synthetic `feature-tree-group` rows in features.csv. Both forward and reverse can use feature_groups: forward application-product SDDs whose `feature-tree.md` has H2/H3 structure, reverse SDDs whose extracted feature trees are inherently hierarchical, and any SDD that promotes groups to first-class with authored metadata. Groups can nest via `parent_group_id`.
928
-
929
- '
930
909
  columns:
931
910
  - name: id
932
911
  type: string
933
912
  nullable: false
934
- description: '{product_id|capability_id}-group-{slug}[-{nested-slug}].'
913
+ description: "{product_id|capability_id}-group-{slug}[-{nested-slug}]."
935
914
  - name: name
936
915
  type: string
937
916
  nullable: false
@@ -964,6 +943,8 @@ catalogues:
964
943
  type: string
965
944
  nullable: true
966
945
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
946
+ description: |
947
+ Hierarchical grouping for features. First-class entity per resolution of adopt-canonical-catalogue-builder.md §7.2 — replaces the previous reverse-only synthetic `feature-tree-group` rows in features.csv. Both forward and reverse can use feature_groups: forward application-product SDDs whose `feature-tree.md` has H2/H3 structure, reverse SDDs whose extracted feature trees are inherently hierarchical, and any SDD that promotes groups to first-class with authored metadata. Groups can nest via `parent_group_id`.
967
948
  foreign_keys:
968
949
  - column: product_id
969
950
  references: products.id
@@ -980,7 +961,7 @@ catalogues:
980
961
  - name: id
981
962
  type: string
982
963
  nullable: false
983
- description: '{product_id|capability_id}-{feature-slug}.'
964
+ description: "{product_id|capability_id}-{feature-slug}."
984
965
  - name: name
985
966
  type: string
986
967
  nullable: false
@@ -1005,7 +986,7 @@ catalogues:
1005
986
  - name: maturity
1006
987
  type: string
1007
988
  nullable: true
1008
- description: 'Standard: working | provisional | unknown | absent. Ecosystem-specific values may be added with parser awareness.'
989
+ description: "Standard: working | provisional | unknown | absent. Ecosystem-specific values may be added with parser awareness."
1009
990
  - name: status
1010
991
  type: string
1011
992
  nullable: false
@@ -1013,7 +994,7 @@ catalogues:
1013
994
  - name: source
1014
995
  type: string
1015
996
  nullable: false
1016
- description: 'feature-tree | feature-set | capability-spec | feature-spec | feature-grounding. NOTE: feature-tree-group source removed in 1.3.0 — groups are now first-class in feature_groups.csv. As of schema 2.2.0, source: feature-tree is emitted by the canonical builder for rows derived from feature-tree.md bullets. As of schema 2.5.0, source: feature-grounding is emitted for rows derived from `docs/domains/<dom>/design/<capability>/feature-grounding.md` markdown tables (per M-ADR 0143). As of schema 2.7.0, source: capability-spec is emitted by the canonical builder for rows derived from `## Feature Grounding (code-path trace)` tables in `docs/domains/<dom>/product/<capability>.md` capability spec markdown (per M-ADR 0145). Feature-grounding and capability-spec rows are both capability-owned: product_id is empty; capability_id resolves from the file path.'
997
+ description: "feature-tree | feature-set | capability-spec | feature-spec | feature-grounding. NOTE: feature-tree-group source removed in 1.3.0 — groups are now first-class in feature_groups.csv. As of schema 2.2.0, source: feature-tree is emitted by the canonical builder for rows derived from feature-tree.md bullets. As of schema 2.5.0, source: feature-grounding is emitted for rows derived from `docs/domains/<dom>/design/<capability>/feature-grounding.md` markdown tables (per M-ADR 0143). As of schema 2.7.0, source: capability-spec is emitted by the canonical builder for rows derived from `## Feature Grounding (code-path trace)` tables in `docs/domains/<dom>/product/<capability>.md` capability spec markdown (per M-ADR 0145). Feature-grounding and capability-spec rows are both capability-owned: product_id is empty; capability_id resolves from the file path."
1017
998
  - name: runway
1018
999
  type: string
1019
1000
  nullable: true
@@ -1045,7 +1026,7 @@ catalogues:
1045
1026
  - name: id
1046
1027
  type: string
1047
1028
  nullable: false
1048
- description: '{product_id}-{persona-slug}.'
1029
+ description: "{product_id}-{persona-slug}."
1049
1030
  - name: name
1050
1031
  type: string
1051
1032
  nullable: false
@@ -1076,7 +1057,7 @@ catalogues:
1076
1057
  - name: id
1077
1058
  type: string
1078
1059
  nullable: false
1079
- description: '{product_id}-{journey-slug}.'
1060
+ description: "{product_id}-{journey-slug}."
1080
1061
  - name: name
1081
1062
  type: string
1082
1063
  nullable: false
@@ -1114,7 +1095,7 @@ catalogues:
1114
1095
  - name: id
1115
1096
  type: string
1116
1097
  nullable: false
1117
- description: '{domain}-{stem}-{kind} — the kind component joined the id at schema 3.0.0 (M-ADR 0203 §4.4), ending the kindless collision class where one service published as two contract families (openapi + proto) minted one id (measured cost: 1 row + 2 edges permanently unrepresentable, plus legitimate shared-contract citation flagged as divergence). Mechanical migration: new id = old id + ''-'' + kind; `sdd-cli catalogue migration-map` emits the pairs, and authored alias targets (M-ADR 0147) re-key automatically during the cut window.'
1098
+ description: "{domain}-{stem}-{kind} — the kind component joined the id at schema 3.0.0 (M-ADR 0203 §4.4), ending the kindless collision class where one service published as two contract families (openapi + proto) minted one id (measured cost: 1 row + 2 edges permanently unrepresentable, plus legitimate shared-contract citation flagged as divergence). Mechanical migration: new id = old id + '-' + kind; `sdd-cli catalogue migration-map` emits the pairs, and authored alias targets (M-ADR 0147) re-key automatically during the cut window."
1118
1099
  - name: name
1119
1100
  type: string
1120
1101
  nullable: false
@@ -1177,7 +1158,6 @@ catalogues:
1177
1158
  nullable: true
1178
1159
  events:
1179
1160
  primary_key: id
1180
- description: 'Asynchronous messages. Cross-domain events (e.g. shared envelopes) leave domain_id empty. Per M-ADR 0156 (multi-source ingestion, schema 2.12.0): forward-method canonical source is `contracts/avro/*.avsc` files; reverse-method canonical source is `docs/domains/{domain}/contracts/events/event-catalog.yaml`. YAML wins on name/domain/publisher/transport/consumers; avsc augments schema_path/version. Both paths run and merge by id slug.'
1181
1161
  columns:
1182
1162
  - name: id
1183
1163
  type: string
@@ -1194,11 +1174,11 @@ catalogues:
1194
1174
  - name: transport
1195
1175
  type: string
1196
1176
  nullable: true
1197
- description: 'Open string per M-ADR 0156. Recommended values: kafka | sns | sqs | kinesis | eventbridge | mongodb-change-stream | nats | activemq | rabbitmq | jms | other. Values outside the recommended set emit [finding] convention.'
1177
+ description: "Open string per M-ADR 0156. Recommended values: kafka | sns | sqs | kinesis | eventbridge | mongodb-change-stream | nats | activemq | rabbitmq | jms | other. Values outside the recommended set emit [finding] convention."
1198
1178
  - name: schema_path
1199
1179
  type: string
1200
1180
  nullable: true
1201
- description: 'Path to event schema (Avro .avsc or JSON-Schema .json/.schema.json). Nullable — leave empty for loosely-typed events (e.g. ActiveMQ JMS, NATS with payload_schema: {type: object}). Per M-ADR 0156.'
1181
+ description: "Path to event schema (Avro .avsc or JSON-Schema .json/.schema.json). Nullable — leave empty for loosely-typed events (e.g. ActiveMQ JMS, NATS with payload_schema: {type: object}). Per M-ADR 0156."
1202
1182
  - name: version
1203
1183
  type: string
1204
1184
  nullable: true
@@ -1214,6 +1194,7 @@ catalogues:
1214
1194
  type: string
1215
1195
  nullable: true
1216
1196
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1197
+ description: "Asynchronous messages. Cross-domain events (e.g. shared envelopes) leave domain_id empty. Per M-ADR 0156 (multi-source ingestion, schema 2.12.0): forward-method canonical source is `contracts/avro/*.avsc` files; reverse-method canonical source is `docs/domains/{domain}/contracts/events/event-catalog.yaml`. YAML wins on name/domain/publisher/transport/consumers; avsc augments schema_path/version. Both paths run and merge by id slug."
1217
1198
  foreign_keys:
1218
1199
  - column: publisher_service_id
1219
1200
  references: services.id
@@ -1234,7 +1215,7 @@ catalogues:
1234
1215
  - name: product_id
1235
1216
  type: string
1236
1217
  nullable: true
1237
- description: 'Owning product, when the system corresponds to one. Nullable: every product is a system, but not every system is a product (external/SaaS systems have no owning product). Architectural products only (per category taxonomy). Relaxed to nullable in schema 2.11.0.'
1218
+ description: "Owning product, when the system corresponds to one. Nullable: every product is a system, but not every system is a product (external/SaaS systems have no owning product). Architectural products only (per category taxonomy). Relaxed to nullable in schema 2.11.0."
1238
1219
  - name: kind
1239
1220
  type: string
1240
1221
  nullable: false
@@ -1262,14 +1243,11 @@ catalogues:
1262
1243
  kind: enums.c4_system_kind
1263
1244
  c4_containers:
1264
1245
  primary_key: id
1265
- description: 'C4 L2. Each container belongs to exactly one C4 system. `domain_id` is a denormalised organisational tag, not a C4-structural attribute — multi-domain ecosystems use it for filtering/reporting. `service_id` is the optional "may represent" link to a runtime service when the container is a deployable application.
1266
-
1267
- '
1268
1246
  columns:
1269
1247
  - name: id
1270
1248
  type: string
1271
1249
  nullable: false
1272
- description: '{system_id}-{container-slug}.'
1250
+ description: "{system_id}-{container-slug}."
1273
1251
  - name: name
1274
1252
  type: string
1275
1253
  nullable: false
@@ -1288,7 +1266,7 @@ catalogues:
1288
1266
  - name: type
1289
1267
  type: string
1290
1268
  nullable: true
1291
- description: 'Canonical C4 container kind — bound to enums.c4_container_type (Application | Data Store) since 3.0.0, hard-fail (M-ADR 0203 §4.1 completing M-ADR 0155). The 2.x legacy values are removed: External System boxes belong in c4_external_systems; running infrastructure retypes; deployment infrastructure leaves the catalogue.'
1269
+ description: "Canonical C4 container kind — bound to enums.c4_container_type (Application | Data Store) since 3.0.0, hard-fail (M-ADR 0203 §4.1 completing M-ADR 0155). The 2.x legacy values are removed: External System boxes belong in c4_external_systems; running infrastructure retypes; deployment infrastructure leaves the catalogue."
1292
1270
  - name: technology
1293
1271
  type: string
1294
1272
  nullable: true
@@ -1303,6 +1281,8 @@ catalogues:
1303
1281
  type: string
1304
1282
  nullable: true
1305
1283
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1284
+ description: |
1285
+ C4 L2. Each container belongs to exactly one C4 system. `domain_id` is a denormalised organisational tag, not a C4-structural attribute — multi-domain ecosystems use it for filtering/reporting. `service_id` is the optional "may represent" link to a runtime service when the container is a deployable application.
1306
1286
  foreign_keys:
1307
1287
  - column: system_id
1308
1288
  references: c4_systems.id
@@ -1317,14 +1297,11 @@ catalogues:
1317
1297
  type: enums.c4_container_type
1318
1298
  c4_components:
1319
1299
  primary_key: id
1320
- description: 'C4 L3. Each component belongs to exactly one C4 container. `service_id` is denormalised from `c4_containers.service_id` for query convenience — populated when the parent container represents a runtime service.
1321
-
1322
- '
1323
1300
  columns:
1324
1301
  - name: id
1325
1302
  type: string
1326
1303
  nullable: false
1327
- description: '{container_id}-{component-slug}.'
1304
+ description: "{container_id}-{component-slug}."
1328
1305
  - name: name
1329
1306
  type: string
1330
1307
  nullable: false
@@ -1335,7 +1312,7 @@ catalogues:
1335
1312
  - name: service_id
1336
1313
  type: string
1337
1314
  nullable: true
1338
- description: 'Denormalised: the service the parent container represents, when applicable.'
1315
+ description: "Denormalised: the service the parent container represents, when applicable."
1339
1316
  - name: path
1340
1317
  type: string
1341
1318
  nullable: true
@@ -1350,6 +1327,8 @@ catalogues:
1350
1327
  type: string
1351
1328
  nullable: true
1352
1329
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1330
+ description: |
1331
+ C4 L3. Each component belongs to exactly one C4 container. `service_id` is denormalised from `c4_containers.service_id` for query convenience — populated when the parent container represents a runtime service.
1353
1332
  foreign_keys:
1354
1333
  - column: container_id
1355
1334
  references: c4_containers.id
@@ -1359,9 +1338,6 @@ catalogues:
1359
1338
  nullable: true
1360
1339
  c4_external_systems:
1361
1340
  primary_key: id
1362
- description: 'C4 external software systems — peer systems at the L1 context level that the ecosystem integrates with but does not own (per M-ADR 0155). Rendered `System_Ext(...)` on L1/L2 diagrams. NOT a c4_container (external systems are not inside your system) and NOT a c4_system (they have no owning Product). External systems are inherently shared references: the same external system may be declared by multiple SDDs, so the aggregator dedups identical rows by PK rather than failing on duplicate (the one narrowly-scoped exception to M-ADR 0134''s duplicate-PK rule); conflicting attributes on the same id surface as a `convention` finding.
1363
-
1364
- '
1365
1341
  columns:
1366
1342
  - name: id
1367
1343
  type: string
@@ -1386,7 +1362,7 @@ catalogues:
1386
1362
  - name: source_scope
1387
1363
  type: string
1388
1364
  nullable: true
1389
- description: 'Scope of the first-seen declaration: l1 (context diagram) or l2 (container diagram — scope-relative per M-ADR 0189 §4.1). Added 2.30.0.'
1365
+ description: "Scope of the first-seen declaration: l1 (context diagram) or l2 (container diagram — scope-relative per M-ADR 0189 §4.1). Added 2.30.0."
1390
1366
  - name: source_sdd_id
1391
1367
  type: string
1392
1368
  nullable: true
@@ -1395,6 +1371,8 @@ catalogues:
1395
1371
  type: string
1396
1372
  nullable: true
1397
1373
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1374
+ description: |
1375
+ C4 external software systems — peer systems at the L1 context level that the ecosystem integrates with but does not own (per M-ADR 0155). Rendered `System_Ext(...)` on L1/L2 diagrams. NOT a c4_container (external systems are not inside your system) and NOT a c4_system (they have no owning Product). External systems are inherently shared references: the same external system may be declared by multiple SDDs, so the aggregator dedups identical rows by PK rather than failing on duplicate (the one narrowly-scoped exception to M-ADR 0134's duplicate-PK rule); conflicting attributes on the same id surface as a `convention` finding.
1398
1376
  repositories:
1399
1377
  primary_key: id
1400
1378
  columns:
@@ -1446,7 +1424,7 @@ catalogues:
1446
1424
  - name: languages
1447
1425
  type: string
1448
1426
  nullable: true
1449
- description: ''';''-separated.'
1427
+ description: "';'-separated."
1450
1428
  - name: doc_path
1451
1429
  type: string
1452
1430
  nullable: false
@@ -1469,12 +1447,11 @@ catalogues:
1469
1447
  component_type: enums.service_type
1470
1448
  domain_models:
1471
1449
  primary_key: id
1472
- description: 'Per-domain ER diagram modelling the domain''s aggregates, entities, and domain events. Platform-profile only — application and integration profiles emit headers-only. Forward source: `traceability.domain_model.path` in capability traceability manifests. Reverse source: file-system scan of `docs/domains/*/architecture/data-model.mermaid.md`. Added in schema 2.4.0; see M-ADR 0142.'
1473
1450
  columns:
1474
1451
  - name: id
1475
1452
  type: string
1476
1453
  nullable: false
1477
- description: '{domain_id}-data-model.'
1454
+ description: "{domain_id}-data-model."
1478
1455
  - name: name
1479
1456
  type: string
1480
1457
  nullable: false
@@ -1501,18 +1478,18 @@ catalogues:
1501
1478
  type: string
1502
1479
  nullable: true
1503
1480
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1481
+ description: "Per-domain ER diagram modelling the domain's aggregates, entities, and domain events. Platform-profile only — application and integration profiles emit headers-only. Forward source: `traceability.domain_model.path` in capability traceability manifests. Reverse source: file-system scan of `docs/domains/*/architecture/data-model.mermaid.md`. Added in schema 2.4.0; see M-ADR 0142."
1504
1482
  foreign_keys:
1505
1483
  - column: domain_id
1506
1484
  references: domains.id
1507
1485
  nullable: false
1508
1486
  entities:
1509
1487
  primary_key: id
1510
- description: 'Data-model entity (a structural realisation of a concept inside a domain''s data model). Distinct from glossary_items (vocabulary-level) and from domain_models (file-level). Added in schema 2.13.0 per M-ADR 0159. Forward source: `models[].entities[]` in glossary-alignment-manifest.yaml. Reverse source: `EntityName { ... }` declarations inside `erDiagram` fences in `docs/domains/{domain}/architecture/data-model.mermaid.md`. PK uses an entity-aware slug that normalises across UPPER_SNAKE and PascalCase authoring styles.'
1511
1488
  columns:
1512
1489
  - name: id
1513
1490
  type: string
1514
1491
  nullable: false
1515
- description: 'Slugged PK: {domain_id}-{entitySlug(name)}. For manifest-sourced rows with domain=platform-wide, the leading domain segment is empty (`-{entitySlug(name)}`) and the row carries a [finding] convention.'
1492
+ description: "Slugged PK: {domain_id}-{entitySlug(name)}. For manifest-sourced rows with domain=platform-wide, the leading domain segment is empty (`-{entitySlug(name)}`) and the row carries a [finding] convention."
1516
1493
  - name: name
1517
1494
  type: string
1518
1495
  nullable: false
@@ -1528,7 +1505,7 @@ catalogues:
1528
1505
  - name: persistence_kind
1529
1506
  type: string
1530
1507
  nullable: true
1531
- description: 'Open string; recommended values: relational-table | document-collection | event-payload | dto | view | other. Values outside the recommended set fire `[finding] convention`.'
1508
+ description: "Open string; recommended values: relational-table | document-collection | event-payload | dto | view | other. Values outside the recommended set fire `[finding] convention`."
1532
1509
  - name: context
1533
1510
  type: string
1534
1511
  nullable: true
@@ -1553,6 +1530,7 @@ catalogues:
1553
1530
  type: string
1554
1531
  nullable: true
1555
1532
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1533
+ description: "Data-model entity (a structural realisation of a concept inside a domain's data model). Distinct from glossary_items (vocabulary-level) and from domain_models (file-level). Added in schema 2.13.0 per M-ADR 0159. Forward source: `models[].entities[]` in glossary-alignment-manifest.yaml. Reverse source: `EntityName { ... }` declarations inside `erDiagram` fences in `docs/domains/{domain}/architecture/data-model.mermaid.md`. PK uses an entity-aware slug that normalises across UPPER_SNAKE and PascalCase authoring styles."
1556
1534
  foreign_keys:
1557
1535
  - column: domain_id
1558
1536
  references: domains.id
@@ -1565,7 +1543,6 @@ catalogues:
1565
1543
  nullable: true
1566
1544
  repo_capability:
1567
1545
  primary_key: id
1568
- description: 'Edge: repo contributes to capability. Forward-declared via repo-config `capabilities[]` (M-ADR 0188 §6.1) or the legacy multi-purpose `additional_context[]`; reverse-derived via capability_service ⋈ services.primary_repo_id and capability_feature ⋈ feature_repo.'
1569
1546
  columns:
1570
1547
  - name: id
1571
1548
  type: string
@@ -1576,6 +1553,7 @@ catalogues:
1576
1553
  - name: capability_id
1577
1554
  type: string
1578
1555
  nullable: false
1556
+ description: "Edge: repo contributes to capability. Forward-declared via repo-config `capabilities[]` (M-ADR 0188 §6.1) or the legacy multi-purpose `additional_context[]`; reverse-derived via capability_service ⋈ services.primary_repo_id and capability_feature ⋈ feature_repo."
1579
1557
  foreign_keys:
1580
1558
  - column: repo_id
1581
1559
  references: repositories.id
@@ -1585,13 +1563,6 @@ catalogues:
1585
1563
  nullable: false
1586
1564
  repo_capability_exemption:
1587
1565
  primary_key: id
1588
- description: 'A repository''s declared, reasoned statement that it bears no product capability (M-ADR 0188 §4.3). Emitted from the repo-config `capability_exemption:` block.
1589
-
1590
- This is deliberately a catalogue row rather than an inert YAML aside. An exemption is a modelling assertion and belongs in the model: it is then queryable at the aggregate tier, reviewable in the same surface as the capabilities it stands in for, and countable — so that a reviewer watching the exemption population grow can see it happen. Never net exemptions off against orphans in a metric.
1591
-
1592
- The invariant it participates in (M-ADR 0188 §4.1): every `repositories` row must resolve, either by carrying a `repo_capability` edge or by declaring an exemption here. A row satisfying both is a declaration conflict, reported as a `divergence` finding.
1593
-
1594
- '
1595
1566
  columns:
1596
1567
  - name: id
1597
1568
  type: string
@@ -1606,6 +1577,10 @@ catalogues:
1606
1577
  type: string
1607
1578
  nullable: false
1608
1579
  description: Mandatory, non-empty. The reason code makes exemptions countable; the note makes them reviewable. A row with an empty note is dropped with a `convention` finding.
1580
+ description: |
1581
+ A repository's declared, reasoned statement that it bears no product capability (M-ADR 0188 §4.3). Emitted from the repo-config `capability_exemption:` block.
1582
+ This is deliberately a catalogue row rather than an inert YAML aside. An exemption is a modelling assertion and belongs in the model: it is then queryable at the aggregate tier, reviewable in the same surface as the capabilities it stands in for, and countable — so that a reviewer watching the exemption population grow can see it happen. Never net exemptions off against orphans in a metric.
1583
+ The invariant it participates in (M-ADR 0188 §4.1): every `repositories` row must resolve, either by carrying a `repo_capability` edge or by declaring an exemption here. A row satisfying both is a declaration conflict, reported as a `divergence` finding.
1609
1584
  foreign_keys:
1610
1585
  - column: repo_id
1611
1586
  references: repositories.id
@@ -1614,13 +1589,6 @@ catalogues:
1614
1589
  reason: enums.capability_exemption_reason
1615
1590
  service_capability_exemption:
1616
1591
  primary_key: id
1617
- description: 'A service''s declared, reasoned statement that it bears no product capability (M-ADR 0133 §4.2b). The services-tier equivalent of `repo_capability_exemption`, one tier down: `repo_capability_exemption` exists because M-ADR 0197 gave a repository a `services:` block, so a repository resolving under M-ADR 0188 no longer implies its services do. Emitted from the repo-config `service_capability_exemption:` block, keyed to the repo''s own default/primary service id — a declared, non-primary `services:` entry has no per-entry authoring surface yet (M-ADR 0197 §4.7, design-only) and cannot be exempted through this block.
1618
-
1619
- Two reasons only (`enums.service_capability_exemption_reason`): `platform-internal` and `deprecated`. Narrower than the repository vocabulary by design — a service, by definition, already runs something, so the repository-tier packaging/tooling/provenance distinctions don''t reproduce here.
1620
-
1621
- The invariant it participates in: every catalogued `services` row must resolve, either by carrying a `capability_service` edge or by declaring an exemption here — checked by a coverage predicate whose verdict set is tier-scoped (member tier cannot assert an unclaimed service is genuinely orphaned, only that it is unresolved locally; a cross-SDD claim on the service may exist in a sibling SDD''s own capability_service.csv, invisible to this SDD''s own build).
1622
-
1623
- '
1624
1592
  columns:
1625
1593
  - name: id
1626
1594
  type: string
@@ -1635,6 +1603,10 @@ catalogues:
1635
1603
  type: string
1636
1604
  nullable: false
1637
1605
  description: Mandatory, non-empty. The reason code makes exemptions countable; the note makes them reviewable. A row with an empty note is dropped with a `convention` finding.
1606
+ description: |
1607
+ A service's declared, reasoned statement that it bears no product capability (M-ADR 0133 §4.2b). The services-tier equivalent of `repo_capability_exemption`, one tier down: `repo_capability_exemption` exists because M-ADR 0197 gave a repository a `services:` block, so a repository resolving under M-ADR 0188 no longer implies its services do. Emitted from the repo-config `service_capability_exemption:` block, keyed to the repo's own default/primary service id — a declared, non-primary `services:` entry has no per-entry authoring surface yet (M-ADR 0197 §4.7, design-only) and cannot be exempted through this block.
1608
+ Two reasons only (`enums.service_capability_exemption_reason`): `platform-internal` and `deprecated`. Narrower than the repository vocabulary by design — a service, by definition, already runs something, so the repository-tier packaging/tooling/provenance distinctions don't reproduce here.
1609
+ The invariant it participates in: every catalogued `services` row must resolve, either by carrying a `capability_service` edge or by declaring an exemption here — checked by a coverage predicate whose verdict set is tier-scoped (member tier cannot assert an unclaimed service is genuinely orphaned, only that it is unresolved locally; a cross-SDD claim on the service may exist in a sibling SDD's own capability_service.csv, invisible to this SDD's own build).
1638
1610
  foreign_keys:
1639
1611
  - column: service_id
1640
1612
  references: services.id
@@ -1643,11 +1615,6 @@ catalogues:
1643
1615
  reason: enums.service_capability_exemption_reason
1644
1616
  external_system_exemption:
1645
1617
  primary_key: id
1646
- description: 'A declared, reasoned assertion that an external-system candidate is GENUINELY external (M-ADR 0189 §4.6 / WS15). Annotation catalogue (M-ADR 0133 §4.2b): one FK, declared never derived, closed reason enum. Sourced from `orchestration/external-system-exemptions.yaml`.
1647
-
1648
- The invariant it completes: c4_external_systems was the one catalogue family with no coverage predicate — a candidate producing no adjudication outcome was silent, and that silence hid a 28% dependency -graph distortion (ledger L4). Every candidate now either resolves at adjudication, or carries an exemption here, or is reported unverified. An exemption retires only the unverified finding — never an adjudication outcome (a converted candidate''s exemption is a contradiction, reported and dropped). Shared entities may be exempted by multiple SDDs: identical rows dedup at aggregation (same exception class as c4_external_systems); conflicting rows keep first-seen with a convention finding.
1649
-
1650
- '
1651
1618
  columns:
1652
1619
  - name: id
1653
1620
  type: string
@@ -1663,6 +1630,9 @@ catalogues:
1663
1630
  type: string
1664
1631
  nullable: false
1665
1632
  description: Mandatory, non-empty. The reason makes exemptions countable; the note makes them reviewable (M-ADR 0188 §4.2 pattern).
1633
+ description: |
1634
+ A declared, reasoned assertion that an external-system candidate is GENUINELY external (M-ADR 0189 §4.6 / WS15). Annotation catalogue (M-ADR 0133 §4.2b): one FK, declared never derived, closed reason enum. Sourced from `orchestration/external-system-exemptions.yaml`.
1635
+ The invariant it completes: c4_external_systems was the one catalogue family with no coverage predicate — a candidate producing no adjudication outcome was silent, and that silence hid a 28% dependency -graph distortion (ledger L4). Every candidate now either resolves at adjudication, or carries an exemption here, or is reported unverified. An exemption retires only the unverified finding — never an adjudication outcome (a converted candidate's exemption is a contradiction, reported and dropped). Shared entities may be exempted by multiple SDDs: identical rows dedup at aggregation (same exception class as c4_external_systems); conflicting rows keep first-seen with a convention finding.
1666
1636
  foreign_keys:
1667
1637
  - column: external_system_id
1668
1638
  references: c4_external_systems.id
@@ -1671,7 +1641,6 @@ catalogues:
1671
1641
  reason: enums.external_system_exemption_reason
1672
1642
  repo_contract:
1673
1643
  primary_key: id
1674
- description: 'Edge: repo is bound to a contract — implements or consumes; the source (contributes_to.artifact_type=contract-surface) does not distinguish, so this description asserts no direction (M-ADR 0211 §1). From contributes_to.artifact_type=contract-surface. Per M-ADR 0147 service-architecture external interfaces are a contract-consumes source; contract_id is external_for_profiles app/integration because their repos reference platform-resident (or platform-held BFF) contracts — resolved at aggregation, staying internal for platform-profile.'
1675
1644
  columns:
1676
1645
  - name: id
1677
1646
  type: string
@@ -1682,6 +1651,7 @@ catalogues:
1682
1651
  - name: contract_id
1683
1652
  type: string
1684
1653
  nullable: false
1654
+ description: "Edge: repo is bound to a contract — implements or consumes; the source (contributes_to.artifact_type=contract-surface) does not distinguish, so this description asserts no direction (M-ADR 0211 §1). From contributes_to.artifact_type=contract-surface. Per M-ADR 0147 service-architecture external interfaces are a contract-consumes source; contract_id is external_for_profiles app/integration because their repos reference platform-resident (or platform-held BFF) contracts — resolved at aggregation, staying internal for platform-profile."
1685
1655
  foreign_keys:
1686
1656
  - column: repo_id
1687
1657
  references: repositories.id
@@ -1694,7 +1664,6 @@ catalogues:
1694
1664
  - integration-product
1695
1665
  product_capability:
1696
1666
  primary_key: id
1697
- description: 'Edge: product depends on / consumes capability. Forward sources from app-platform-dependencies.yaml. capability_id is external because the consuming product (an application-product SDD) references a capability owned by the platform SDD.'
1698
1667
  columns:
1699
1668
  - name: id
1700
1669
  type: string
@@ -1712,6 +1681,7 @@ catalogues:
1712
1681
  - name: notes
1713
1682
  type: string
1714
1683
  nullable: true
1684
+ description: "Edge: product depends on / consumes capability. Forward sources from app-platform-dependencies.yaml. capability_id is external because the consuming product (an application-product SDD) references a capability owned by the platform SDD."
1715
1685
  foreign_keys:
1716
1686
  - column: product_id
1717
1687
  references: products.id
@@ -1724,7 +1694,6 @@ catalogues:
1724
1694
  role: enums.consumption_role
1725
1695
  product_service:
1726
1696
  primary_key: id
1727
- description: 'Edge: product depends on / consumes service. Forward sources from app-platform-dependencies.yaml. service_id is external because the consuming product (an application-product SDD) references a service owned by the platform SDD.'
1728
1697
  columns:
1729
1698
  - name: id
1730
1699
  type: string
@@ -1742,7 +1711,8 @@ catalogues:
1742
1711
  - name: required_stability
1743
1712
  type: string
1744
1713
  nullable: true
1745
- description: 'provisional | locked | unknown. The consuming SDD''s expectation of contract stability, carried verbatim from app-platform-dependencies.yaml. Not a bound enum: an out-of-vocabulary value is carried, not rejected, and is reported by validate-app-dependencies.sh.'
1714
+ description: "provisional | locked | unknown. The consuming SDD's expectation of contract stability, carried verbatim from app-platform-dependencies.yaml. Not a bound enum: an out-of-vocabulary value is carried, not rejected, and is reported by validate-app-dependencies.sh."
1715
+ description: "Edge: product depends on / consumes service. Forward sources from app-platform-dependencies.yaml. service_id is external because the consuming product (an application-product SDD) references a service owned by the platform SDD."
1746
1716
  foreign_keys:
1747
1717
  - column: product_id
1748
1718
  references: products.id
@@ -1755,12 +1725,11 @@ catalogues:
1755
1725
  role: enums.consumption_role
1756
1726
  service_contract:
1757
1727
  primary_key: id
1758
- description: 'Edge: service exposes or consumes contract. Both FKs are external (per M-ADR 0147): federated SDDs that walk per-repo service-architecture tables emit consumes rows where service_id resolves to the platform-root catalogue''s services.csv (post-aggregation) and contract_id resolves to the platform-root contracts.csv. Internal builds (e.g. connect-mono) still optimistically validate locally. Schema 2.8.0.'
1759
1728
  columns:
1760
1729
  - name: id
1761
1730
  type: string
1762
1731
  nullable: false
1763
- description: '{service_id}__{contract_id}__{role}.'
1732
+ description: "{service_id}__{contract_id}__{role}."
1764
1733
  - name: service_id
1765
1734
  type: string
1766
1735
  nullable: false
@@ -1771,6 +1740,7 @@ catalogues:
1771
1740
  type: string
1772
1741
  nullable: false
1773
1742
  description: exposes | consumes.
1743
+ description: "Edge: service exposes or consumes contract. Both FKs are external (per M-ADR 0147): federated SDDs that walk per-repo service-architecture tables emit consumes rows where service_id resolves to the platform-root catalogue's services.csv (post-aggregation) and contract_id resolves to the platform-root contracts.csv. Internal builds (e.g. connect-mono) still optimistically validate locally. Schema 2.8.0."
1774
1744
  foreign_keys:
1775
1745
  - column: service_id
1776
1746
  references: services.id
@@ -1784,12 +1754,11 @@ catalogues:
1784
1754
  role: enums.contract_participation
1785
1755
  service_event:
1786
1756
  primary_key: id
1787
- description: 'Edge: service publishes or consumes event.'
1788
1757
  columns:
1789
1758
  - name: id
1790
1759
  type: string
1791
1760
  nullable: false
1792
- description: '{service_id}__{event_id}__{role}.'
1761
+ description: "{service_id}__{event_id}__{role}."
1793
1762
  - name: service_id
1794
1763
  type: string
1795
1764
  nullable: false
@@ -1800,6 +1769,7 @@ catalogues:
1800
1769
  type: string
1801
1770
  nullable: false
1802
1771
  description: publishes | consumes.
1772
+ description: "Edge: service publishes or consumes event."
1803
1773
  foreign_keys:
1804
1774
  - column: service_id
1805
1775
  references: services.id
@@ -1811,12 +1781,11 @@ catalogues:
1811
1781
  role: enums.event_participation
1812
1782
  service_entity:
1813
1783
  primary_key: id
1814
- description: 'Edge: service touches data-model entity. Added in schema 2.13.0 per M-ADR 0159. Primary source: per-domain `## Data Store Mapping` markdown table in `docs/domains/{domain}/architecture/data-model.mermaid.md` (relation=owns). Optional forward source (Phase 5 deferred): `entities:` block in `orchestration/repo-config/<repo>.yaml`. Service names resolve via heuristic (slug-of-name; trailing-id-segment) with optional adopter-authored alias map at `docs/platform/reference/service-name-aliases.yaml`.'
1815
1784
  columns:
1816
1785
  - name: id
1817
1786
  type: string
1818
1787
  nullable: false
1819
- description: 'Composite PK: {service_id}__{entity_id}__{relation}.'
1788
+ description: "Composite PK: {service_id}__{entity_id}__{relation}."
1820
1789
  - name: service_id
1821
1790
  type: string
1822
1791
  nullable: false
@@ -1826,7 +1795,7 @@ catalogues:
1826
1795
  - name: relation
1827
1796
  type: string
1828
1797
  nullable: false
1829
- description: 'Open string; recommended values: owns | reads | writes | references. Data Store Mapping table source emits `owns`. Values outside the recommended set fire `[finding] convention`.'
1798
+ description: "Open string; recommended values: owns | reads | writes | references. Data Store Mapping table source emits `owns`. Values outside the recommended set fire `[finding] convention`."
1830
1799
  - name: evidence_path
1831
1800
  type: string
1832
1801
  nullable: true
@@ -1839,6 +1808,7 @@ catalogues:
1839
1808
  type: string
1840
1809
  nullable: true
1841
1810
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1811
+ description: "Edge: service touches data-model entity. Added in schema 2.13.0 per M-ADR 0159. Primary source: per-domain `## Data Store Mapping` markdown table in `docs/domains/{domain}/architecture/data-model.mermaid.md` (relation=owns). Optional forward source (Phase 5 deferred): `entities:` block in `orchestration/repo-config/<repo>.yaml`. Service names resolve via heuristic (slug-of-name; trailing-id-segment) with optional adopter-authored alias map at `docs/platform/reference/service-name-aliases.yaml`."
1842
1812
  foreign_keys:
1843
1813
  - column: service_id
1844
1814
  references: services.id
@@ -1848,7 +1818,6 @@ catalogues:
1848
1818
  nullable: false
1849
1819
  capability_feature:
1850
1820
  primary_key: id
1851
- description: 'Edge: capability decomposes into features. Forward: traceability.runway.enables. Reverse: parsed from spec Feature Grounding.'
1852
1821
  columns:
1853
1822
  - name: id
1854
1823
  type: string
@@ -1859,6 +1828,7 @@ catalogues:
1859
1828
  - name: feature_id
1860
1829
  type: string
1861
1830
  nullable: false
1831
+ description: "Edge: capability decomposes into features. Forward: traceability.runway.enables. Reverse: parsed from spec Feature Grounding."
1862
1832
  foreign_keys:
1863
1833
  - column: capability_id
1864
1834
  references: capabilities.id
@@ -1868,9 +1838,6 @@ catalogues:
1868
1838
  nullable: false
1869
1839
  capability_service:
1870
1840
  primary_key: id
1871
- description: 'Edge: capability is realised by services. Sourced from the capability traceability manifest services[] block. service_id is an external FK (schema 2.29.0, F4): a traceability entry marked `owner_sdd:` declares a cross-SDD reference (e.g. the service moved to a sibling SDD at an M-ADR 0170 §4.2 carve) — the per-SDD builder emits the edge, logs it `[finding] external`, and aggregation validates it hard against the owning sibling''s rows. An UNMARKED id that does not resolve locally is NOT emitted — it stays a member-tier orphan finding (or convention, when it names a known external system).
1872
-
1873
- '
1874
1841
  columns:
1875
1842
  - name: id
1876
1843
  type: string
@@ -1884,11 +1851,11 @@ catalogues:
1884
1851
  - name: role
1885
1852
  type: string
1886
1853
  nullable: true
1887
- description: 'The part the service plays in delivering THIS capability — a property of the relationship, not of the service (capability-traceability-manifest-template). Closed enum, see enums.capability_service_role. Nullable: legacy rows may carry no role; the enum validator checks values, not presence. `dependency` rows are excluded from repo_capability Path X (M-ADR 0157 §4.3 as amended). Enum bound in 3.8.0.'
1854
+ description: "The part the service plays in delivering THIS capability — a property of the relationship, not of the service (capability-traceability-manifest-template). Closed enum, see enums.capability_service_role. Nullable: legacy rows may carry no role; the enum validator checks values, not presence. `dependency` rows are excluded from repo_capability Path X (M-ADR 0157 §4.3 as amended). Enum bound in 3.8.0."
1888
1855
  - name: contract_id
1889
1856
  type: string
1890
1857
  nullable: true
1891
- description: 'The contract this dependency is against — a contracts.id declared as `contract:` on the services[] entry (M-ADR 0211 §4.1). External FK on the pattern of feature_contract: resolved at aggregation. Empty when the entry declares none; a `dependency`-role entry that reaches T4 band 5 carries it.'
1858
+ description: "The contract this dependency is against — a contracts.id declared as `contract:` on the services[] entry (M-ADR 0211 §4.1). External FK on the pattern of feature_contract: resolved at aggregation. Empty when the entry declares none; a `dependency`-role entry that reaches T4 band 5 carries it."
1892
1859
  - name: interaction_pattern
1893
1860
  type: string
1894
1861
  nullable: true
@@ -1901,6 +1868,8 @@ catalogues:
1901
1868
  type: string
1902
1869
  nullable: true
1903
1870
  description: Where the coupling is evidenced — a path or anchor in the SDD, from `evidence:` on the services[] entry. Prose about the coupling stays in dependency_notes; this is the pointer a reviewer follows.
1871
+ description: |
1872
+ Edge: capability is realised by services. Sourced from the capability traceability manifest services[] block. service_id is an external FK (schema 2.29.0, F4): a traceability entry marked `owner_sdd:` declares a cross-SDD reference (e.g. the service moved to a sibling SDD at an M-ADR 0170 §4.2 carve) — the per-SDD builder emits the edge, logs it `[finding] external`, and aggregation validates it hard against the owning sibling's rows. An UNMARKED id that does not resolve locally is NOT emitted — it stays a member-tier orphan finding (or convention, when it names a known external system).
1904
1873
  foreign_keys:
1905
1874
  - column: capability_id
1906
1875
  references: capabilities.id
@@ -1918,7 +1887,6 @@ catalogues:
1918
1887
  interaction_pattern: enums.interaction_pattern
1919
1888
  capability_event:
1920
1889
  primary_key: id
1921
- description: 'Edge: capability publishes or consumes event. Schema 2.14.0 (per M-ADR 0160) multi-source ingestion: (1) forward shape A — `traceability.events[{id, role}]` (legacy aspirational shape, unauthored across observed adopters); (2) forward shape B — `traceability.contracts.published_events[]` / `consumed_events[]` with `{event, status, notes}` (the observed forward-method shape; event name slug-resolves against events.csv); (3) derived — `capability_service ⋈ service_event` join (zero authoring; associative not authoritative). Authored rows win on PK conflict with derived. The `source` column distinguishes the two so governance queries can filter to authoritative ownership. The earlier `## Related Events` capability-spec heading is retired (no adopter authored it; the template never carried the section).'
1922
1890
  columns:
1923
1891
  - name: id
1924
1892
  type: string
@@ -1937,6 +1905,7 @@ catalogues:
1937
1905
  type: string
1938
1906
  nullable: false
1939
1907
  description: authored | derived. `authored` rows come from a traceability declaration (shape A or shape B); `derived` rows come from `capability_service ⋈ service_event` and represent associative coupling, not ownership. Schema 2.14.0 per M-ADR 0160.
1908
+ description: "Edge: capability publishes or consumes event. Schema 2.14.0 (per M-ADR 0160) multi-source ingestion: (1) forward shape A — `traceability.events[{id, role}]` (legacy aspirational shape, unauthored across observed adopters); (2) forward shape B — `traceability.contracts.published_events[]` / `consumed_events[]` with `{event, status, notes}` (the observed forward-method shape; event name slug-resolves against events.csv); (3) derived — `capability_service ⋈ service_event` join (zero authoring; associative not authoritative). Authored rows win on PK conflict with derived. The `source` column distinguishes the two so governance queries can filter to authoritative ownership. The earlier `## Related Events` capability-spec heading is retired (no adopter authored it; the template never carried the section)."
1940
1909
  foreign_keys:
1941
1910
  - column: capability_id
1942
1911
  references: capabilities.id
@@ -1948,7 +1917,6 @@ catalogues:
1948
1917
  role: enums.event_participation
1949
1918
  capability_contract:
1950
1919
  primary_key: id
1951
- description: 'Edge: capability is bound to a contract. Whether the capability exposes or depends on it is not stated by the source (traceability.contracts), so this description asserts no direction (M-ADR 0211 §1). Forward-declared only. Forward-declared only (traceability.contracts). The reverse derivation this description long claimed (service_contract ⋈ capability_service) was measured nonexistent — 0 `source: derived` rows across 105 units, builder references neither catalogue — and the CLAIM was corrected at 3.0.0 (M-ADR 0203 §4.5 / F2, gap class absent-derivation per M-ADR 0196 §4.1). The edge is forward-one-directional until a decision builds a reverse source.'
1952
1920
  columns:
1953
1921
  - name: id
1954
1922
  type: string
@@ -1962,7 +1930,8 @@ catalogues:
1962
1930
  - name: source
1963
1931
  type: string
1964
1932
  nullable: false
1965
- description: 'declared — the only emitted value. `derived` is reserved vocabulary: the reverse derivation it anticipated was never built (0 rows across 105 measured units) and the claim was corrected at 3.0.0 (M-ADR 0203 §4.5 / F2); the value re-enters if a decision builds a reverse source.'
1933
+ description: "declared — the only emitted value. `derived` is reserved vocabulary: the reverse derivation it anticipated was never built (0 rows across 105 measured units) and the claim was corrected at 3.0.0 (M-ADR 0203 §4.5 / F2); the value re-enters if a decision builds a reverse source."
1934
+ description: "Edge: capability is bound to a contract. Whether the capability exposes or depends on it is not stated by the source (traceability.contracts), so this description asserts no direction (M-ADR 0211 §1). Forward-declared only. Forward-declared only (traceability.contracts). The reverse derivation this description long claimed (service_contract ⋈ capability_service) was measured nonexistent — 0 `source: derived` rows across 105 units, builder references neither catalogue — and the CLAIM was corrected at 3.0.0 (M-ADR 0203 §4.5 / F2, gap class absent-derivation per M-ADR 0196 §4.1). The edge is forward-one-directional until a decision builds a reverse source."
1966
1935
  foreign_keys:
1967
1936
  - column: capability_id
1968
1937
  references: capabilities.id
@@ -1972,7 +1941,6 @@ catalogues:
1972
1941
  nullable: false
1973
1942
  journey_feature:
1974
1943
  primary_key: id
1975
- description: 'Edge: journey touches features. Parsed from Related features bullet.'
1976
1944
  columns:
1977
1945
  - name: id
1978
1946
  type: string
@@ -1983,6 +1951,7 @@ catalogues:
1983
1951
  - name: feature_id
1984
1952
  type: string
1985
1953
  nullable: false
1954
+ description: "Edge: journey touches features. Parsed from Related features bullet."
1986
1955
  foreign_keys:
1987
1956
  - column: journey_id
1988
1957
  references: user_journeys.id
@@ -1992,7 +1961,6 @@ catalogues:
1992
1961
  nullable: false
1993
1962
  persona_feature:
1994
1963
  primary_key: id
1995
- description: 'Edge: persona uses features. Parsed from Related features bullet.'
1996
1964
  columns:
1997
1965
  - name: id
1998
1966
  type: string
@@ -2003,6 +1971,7 @@ catalogues:
2003
1971
  - name: feature_id
2004
1972
  type: string
2005
1973
  nullable: false
1974
+ description: "Edge: persona uses features. Parsed from Related features bullet."
2006
1975
  foreign_keys:
2007
1976
  - column: persona_id
2008
1977
  references: personas.id
@@ -2012,7 +1981,6 @@ catalogues:
2012
1981
  nullable: false
2013
1982
  feature_service:
2014
1983
  primary_key: id
2015
- description: 'Edge: feature is implemented by service. Parsed from Feature Services table in feature-tree.md.'
2016
1984
  columns:
2017
1985
  - name: id
2018
1986
  type: string
@@ -2023,6 +1991,7 @@ catalogues:
2023
1991
  - name: service_id
2024
1992
  type: string
2025
1993
  nullable: false
1994
+ description: "Edge: feature is implemented by service. Parsed from Feature Services table in feature-tree.md."
2026
1995
  foreign_keys:
2027
1996
  - column: feature_id
2028
1997
  references: features.id
@@ -2032,7 +2001,6 @@ catalogues:
2032
2001
  nullable: false
2033
2002
  feature_event:
2034
2003
  primary_key: id
2035
- description: 'Edge: feature publishes or consumes event. Derived only — emitted from the `feature_service ⋈ service_event` join, mirroring M-ADR 0160''s capability_event derived path one rung lower in the capability/feature/service hierarchy. Every row carries `source=derived`; there is no authored shape (the authored signal lives at the service level via `service_event`, which the feature inherits through `feature_service`). PK is `{feature_id}__{event_id}__{role}` so the same feature can carry both publishes + consumes rows for the same event without collision. Schema 2.15.0 per M-ADR 0161.'
2036
2004
  columns:
2037
2005
  - name: id
2038
2006
  type: string
@@ -2051,6 +2019,7 @@ catalogues:
2051
2019
  type: string
2052
2020
  nullable: false
2053
2021
  description: Always `derived` (schema 2.15.0). The column is retained for symmetry with `capability_event.source` and to keep the door open for an authored shape if one surfaces; today every row is derived.
2022
+ description: "Edge: feature publishes or consumes event. Derived only — emitted from the `feature_service ⋈ service_event` join, mirroring M-ADR 0160's capability_event derived path one rung lower in the capability/feature/service hierarchy. Every row carries `source=derived`; there is no authored shape (the authored signal lives at the service level via `service_event`, which the feature inherits through `feature_service`). PK is `{feature_id}__{event_id}__{role}` so the same feature can carry both publishes + consumes rows for the same event without collision. Schema 2.15.0 per M-ADR 0161."
2054
2023
  foreign_keys:
2055
2024
  - column: feature_id
2056
2025
  references: features.id
@@ -2062,7 +2031,6 @@ catalogues:
2062
2031
  role: enums.event_participation
2063
2032
  feature_repo:
2064
2033
  primary_key: id
2065
- description: 'Edge: feature is implemented in repo. From contributes_to.artifact_type=feature-set.'
2066
2034
  columns:
2067
2035
  - name: id
2068
2036
  type: string
@@ -2073,6 +2041,7 @@ catalogues:
2073
2041
  - name: repo_id
2074
2042
  type: string
2075
2043
  nullable: false
2044
+ description: "Edge: feature is implemented in repo. From contributes_to.artifact_type=feature-set."
2076
2045
  foreign_keys:
2077
2046
  - column: feature_id
2078
2047
  references: features.id
@@ -2082,12 +2051,11 @@ catalogues:
2082
2051
  nullable: false
2083
2052
  feature_contract:
2084
2053
  primary_key: id
2085
- description: 'Edge: feature is exposed via contract. Derived — forward: capability_feature ⋈ capability_contract (on capability_id); reverse: feature_service ⋈ service_contract (on service_id). Both join paths are run and merged; duplicate (feature_id, contract_id) pairs are deduplicated. contract_id is external for app/integration profiles where contracts live in the platform SDD. Added in schema 2.3.0.'
2086
2054
  columns:
2087
2055
  - name: id
2088
2056
  type: string
2089
2057
  nullable: false
2090
- description: '{feature_id}__{contract_id}.'
2058
+ description: "{feature_id}__{contract_id}."
2091
2059
  - name: feature_id
2092
2060
  type: string
2093
2061
  nullable: false
@@ -2098,6 +2066,7 @@ catalogues:
2098
2066
  type: string
2099
2067
  nullable: true
2100
2068
  description: cap-feature-cap-contract | feature-service-service-contract. Diagnostic only — records which join path produced the row.
2069
+ description: "Edge: feature is exposed via contract. Derived — forward: capability_feature ⋈ capability_contract (on capability_id); reverse: feature_service ⋈ service_contract (on service_id). Both join paths are run and merged; duplicate (feature_id, contract_id) pairs are deduplicated. contract_id is external for app/integration profiles where contracts live in the platform SDD. Added in schema 2.3.0."
2101
2070
  foreign_keys:
2102
2071
  - column: feature_id
2103
2072
  references: features.id
@@ -2108,12 +2077,11 @@ catalogues:
2108
2077
  external: true
2109
2078
  feature_subscription_channels:
2110
2079
  primary_key: id
2111
- description: 'Edge: feature delivers async push via a named channel/topic. Peer of `graphql_operations:` in the per-feature evidence shape — `graphql_operations:` carries the GraphQL operation names declared in the schema (Queries / Mutations / Subscriptions); `feature_subscription_channels` rows carry the channel/topic layer that physically delivers the push events (AppSync WebSocket endpoints, Pekko WS channels, MQTT topics, server-sent-event streams). Per resolved decision §1 of `content/plans/v0-9-0-cohort-sweep-derived-bundle.md`: a single GraphQL Subscription operation may listen on multiple channels; one channel may be consumed by multiple operations — modelling as a separate edge catalogue (not as a feature column) accommodates the many-to-many. Built per-SDD from `reverse-evidence/feature-grounding-evidence.yaml` `subscription_channels:` entries on each feature. Added in schema 2.9.0.'
2112
2080
  columns:
2113
2081
  - name: id
2114
2082
  type: string
2115
2083
  nullable: false
2116
- description: '{feature_id}__{channel_name}.'
2084
+ description: "{feature_id}__{channel_name}."
2117
2085
  - name: feature_id
2118
2086
  type: string
2119
2087
  nullable: false
@@ -2124,7 +2092,7 @@ catalogues:
2124
2092
  - name: transport
2125
2093
  type: string
2126
2094
  nullable: false
2127
- description: 'Delivery protocol: `appsync-websocket | pekko-ws | mqtt | sse | webhook-push | other`. The `other` value is escape-valve; adopters using it SHOULD record the actual transport in evidence.'
2095
+ description: "Delivery protocol: `appsync-websocket | pekko-ws | mqtt | sse | webhook-push | other`. The `other` value is escape-valve; adopters using it SHOULD record the actual transport in evidence."
2128
2096
  - name: evidence
2129
2097
  type: string
2130
2098
  nullable: true
@@ -2141,18 +2109,18 @@ catalogues:
2141
2109
  type: string
2142
2110
  nullable: true
2143
2111
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2112
+ description: "Edge: feature delivers async push via a named channel/topic. Peer of `graphql_operations:` in the per-feature evidence shape — `graphql_operations:` carries the GraphQL operation names declared in the schema (Queries / Mutations / Subscriptions); `feature_subscription_channels` rows carry the channel/topic layer that physically delivers the push events (AppSync WebSocket endpoints, Pekko WS channels, MQTT topics, server-sent-event streams). Per resolved decision §1 of `content/plans/v0-9-0-cohort-sweep-derived-bundle.md`: a single GraphQL Subscription operation may listen on multiple channels; one channel may be consumed by multiple operations — modelling as a separate edge catalogue (not as a feature column) accommodates the many-to-many. Built per-SDD from `reverse-evidence/feature-grounding-evidence.yaml` `subscription_channels:` entries on each feature. Added in schema 2.9.0."
2144
2113
  foreign_keys:
2145
2114
  - column: feature_id
2146
2115
  references: features.id
2147
2116
  nullable: false
2148
2117
  capability_domain_model:
2149
2118
  primary_key: id
2150
- description: 'Edge: capability references a domain model. Forward: declared in `traceability.domain_model` field of the capability traceability manifest. Reverse: inferred via capability → domain → domain_model. Platform-profile only. Added in schema 2.4.0; see M-ADR 0142.'
2151
2119
  columns:
2152
2120
  - name: id
2153
2121
  type: string
2154
2122
  nullable: false
2155
- description: '{capability_id}__{domain_model_id}.'
2123
+ description: "{capability_id}__{domain_model_id}."
2156
2124
  - name: capability_id
2157
2125
  type: string
2158
2126
  nullable: false
@@ -2163,6 +2131,7 @@ catalogues:
2163
2131
  type: string
2164
2132
  nullable: false
2165
2133
  description: traceability-manifest | inferred.
2134
+ description: "Edge: capability references a domain model. Forward: declared in `traceability.domain_model` field of the capability traceability manifest. Reverse: inferred via capability → domain → domain_model. Platform-profile only. Added in schema 2.4.0; see M-ADR 0142."
2166
2135
  foreign_keys:
2167
2136
  - column: capability_id
2168
2137
  references: capabilities.id
@@ -2172,12 +2141,11 @@ catalogues:
2172
2141
  nullable: false
2173
2142
  feature_domain_model:
2174
2143
  primary_key: id
2175
- description: 'Edge: feature operates on a domain model. Derived from capability_feature ⋈ capability_domain_model (on capability_id). Platform-profile only. Orphan features (no capability link) get no row. Added in schema 2.4.0; see M-ADR 0142.'
2176
2144
  columns:
2177
2145
  - name: id
2178
2146
  type: string
2179
2147
  nullable: false
2180
- description: '{feature_id}__{domain_model_id}.'
2148
+ description: "{feature_id}__{domain_model_id}."
2181
2149
  - name: feature_id
2182
2150
  type: string
2183
2151
  nullable: false
@@ -2188,6 +2156,7 @@ catalogues:
2188
2156
  type: string
2189
2157
  nullable: true
2190
2158
  description: cap-feature-cap-domain-model. Diagnostic only.
2159
+ description: "Edge: feature operates on a domain model. Derived from capability_feature ⋈ capability_domain_model (on capability_id). Platform-profile only. Orphan features (no capability link) get no row. Added in schema 2.4.0; see M-ADR 0142."
2191
2160
  foreign_keys:
2192
2161
  - column: feature_id
2193
2162
  references: features.id
@@ -2197,7 +2166,6 @@ catalogues:
2197
2166
  nullable: false
2198
2167
  persona_journey:
2199
2168
  primary_key: id
2200
- description: 'Edge: persona participates in journey. Roles: primary | handoff | supporting.'
2201
2169
  columns:
2202
2170
  - name: id
2203
2171
  type: string
@@ -2212,6 +2180,7 @@ catalogues:
2212
2180
  type: string
2213
2181
  nullable: false
2214
2182
  description: primary | handoff | supporting.
2183
+ description: "Edge: persona participates in journey. Roles: primary | handoff | supporting."
2215
2184
  foreign_keys:
2216
2185
  - column: persona_id
2217
2186
  references: personas.id
@@ -2223,12 +2192,11 @@ catalogues:
2223
2192
  role: enums.journey_participation
2224
2193
  persona_c4system:
2225
2194
  primary_key: id
2226
- description: 'Edge: persona (C4 Person) uses a C4 system. Captures the L1 context ''Person uses System'' relationship, extracted from Person(...) macros on the L1 context diagram and matched to personas rows. Per M-ADR 0155. Added in schema 2.10.0.'
2227
2195
  columns:
2228
2196
  - name: id
2229
2197
  type: string
2230
2198
  nullable: false
2231
- description: '{persona_id}__{c4_system_id}.'
2199
+ description: "{persona_id}__{c4_system_id}."
2232
2200
  - name: persona_id
2233
2201
  type: string
2234
2202
  nullable: false
@@ -2239,6 +2207,7 @@ catalogues:
2239
2207
  type: string
2240
2208
  nullable: true
2241
2209
  description: Optional interaction label from the Rel(...) line, e.g. 'Web browser' / 'Mobile app'.
2210
+ description: "Edge: persona (C4 Person) uses a C4 system. Captures the L1 context 'Person uses System' relationship, extracted from Person(...) macros on the L1 context diagram and matched to personas rows. Per M-ADR 0155. Added in schema 2.10.0."
2242
2211
  foreign_keys:
2243
2212
  - column: persona_id
2244
2213
  references: personas.id
@@ -2248,14 +2217,11 @@ catalogues:
2248
2217
  nullable: false
2249
2218
  persona_container:
2250
2219
  primary_key: id
2251
- description: 'Edge: a persona uses a C4 container — the L2-granularity companion to persona_c4system (M-ADR 0189 F26 §3, ratified 2026-07-10). Eleven of one estate''s L2 diagrams and the bulk of another''s 81 unroutable Rels drew Person→Container relationships that had no catalogue and, until F26, no finding. Harvested at member tier from Rel(...) lines whose endpoints resolve to a file-local Person and a local container (either direction; the row is normalised persona→container). A Person that matches no persona row is a coverage finding, never a silent skip. Both authoring directions feed from the same diagram surface (M-ADR 0157 parity). Added in schema 2.34.0.
2252
-
2253
- '
2254
2220
  columns:
2255
2221
  - name: id
2256
2222
  type: string
2257
2223
  nullable: false
2258
- description: '{persona_id}__{container_id}.'
2224
+ description: "{persona_id}__{container_id}."
2259
2225
  - name: persona_id
2260
2226
  type: string
2261
2227
  nullable: false
@@ -2266,6 +2232,8 @@ catalogues:
2266
2232
  type: string
2267
2233
  nullable: true
2268
2234
  description: Optional interaction label from the Rel(...) line. May hold multiple '; '-joined labels (F25).
2235
+ description: |
2236
+ Edge: a persona uses a C4 container — the L2-granularity companion to persona_c4system (M-ADR 0189 F26 §3, ratified 2026-07-10). Eleven of one estate's L2 diagrams and the bulk of another's 81 unroutable Rels drew Person→Container relationships that had no catalogue and, until F26, no finding. Harvested at member tier from Rel(...) lines whose endpoints resolve to a file-local Person and a local container (either direction; the row is normalised persona→container). A Person that matches no persona row is a coverage finding, never a silent skip. Both authoring directions feed from the same diagram surface (M-ADR 0157 parity). Added in schema 2.34.0.
2269
2237
  foreign_keys:
2270
2238
  - column: persona_id
2271
2239
  references: personas.id
@@ -2275,12 +2243,11 @@ catalogues:
2275
2243
  nullable: false
2276
2244
  system_external_dependency:
2277
2245
  primary_key: id
2278
- description: 'Edge: a C4 system integrates with an external software system. Captures the L1 context ''System integrates with External System'' relationship, extracted from System_Ext(...) + Rel(...) on L1/L2 diagrams. Per M-ADR 0155. Container-level external dependencies are out of scope (system-level only). Added in schema 2.10.0. From 2.30.0 (M-ADR 0189 §4.4): edges whose external endpoint the aggregator adjudicates as an INTERNAL system are rewritten onto system_system_dependency and removed from this catalogue.'
2279
2246
  columns:
2280
2247
  - name: id
2281
2248
  type: string
2282
2249
  nullable: false
2283
- description: '{c4_system_id}__{external_system_id}.'
2250
+ description: "{c4_system_id}__{external_system_id}."
2284
2251
  - name: c4_system_id
2285
2252
  type: string
2286
2253
  nullable: false
@@ -2295,6 +2262,7 @@ catalogues:
2295
2262
  type: string
2296
2263
  nullable: true
2297
2264
  description: The Rel's non-external endpoint resolved to a local container at member tier, when it is one (F17, 2.33.0) — the datum that lets adjudication rewrite this edge onto container_dependency instead of destroying it. Empty when the endpoint is the system itself or unresolvable.
2265
+ description: "Edge: a C4 system integrates with an external software system. Captures the L1 context 'System integrates with External System' relationship, extracted from System_Ext(...) + Rel(...) on L1/L2 diagrams. Per M-ADR 0155. Container-level external dependencies are out of scope (system-level only). Added in schema 2.10.0. From 2.30.0 (M-ADR 0189 §4.4): edges whose external endpoint the aggregator adjudicates as an INTERNAL system are rewritten onto system_system_dependency and removed from this catalogue."
2298
2266
  foreign_keys:
2299
2267
  - column: c4_system_id
2300
2268
  references: c4_systems.id
@@ -2307,14 +2275,11 @@ catalogues:
2307
2275
  nullable: true
2308
2276
  container_dependency:
2309
2277
  primary_key: id
2310
- description: 'Edge: a C4 container depends on another INTERNAL container (adopter finding F17 — F6 exactly one tier down: "no edge for internal" at L2). Derived by the aggregator at adjudication: an external-system candidate that resolves to an internal container was never external — each of its dependency edges whose member-resolved `from_container_id` is known is rewritten here, and a candidate with no remaining edges is dropped (it was a phantom duplicate of the container). A candidate with unconvertible edges is kept with the tier-contradiction finding, so no edge is ever destroyed to make a build quieter — the measured cost that stopped an adopter remediating 22 contradictions was eight real edges. ALSO emitted at member tier (F19, 2.33.1): the C4-correct authoring — Rel(container_a, container_b) between two Container(...) nodes — emits its edge directly; adjudication merges into a catalogue that already has content rather than being its only source, so the metamodel no longer rewards mis-declaration over correct authoring. Added in schema 2.33.0.
2311
-
2312
- '
2313
2278
  columns:
2314
2279
  - name: id
2315
2280
  type: string
2316
2281
  nullable: false
2317
- description: '{from_container_id}__{to_container_id}.'
2282
+ description: "{from_container_id}__{to_container_id}."
2318
2283
  - name: from_container_id
2319
2284
  type: string
2320
2285
  nullable: false
@@ -2333,6 +2298,8 @@ catalogues:
2333
2298
  type: string
2334
2299
  nullable: true
2335
2300
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2301
+ description: |
2302
+ Edge: a C4 container depends on another INTERNAL container (adopter finding F17 — F6 exactly one tier down: "no edge for internal" at L2). Derived by the aggregator at adjudication: an external-system candidate that resolves to an internal container was never external — each of its dependency edges whose member-resolved `from_container_id` is known is rewritten here, and a candidate with no remaining edges is dropped (it was a phantom duplicate of the container). A candidate with unconvertible edges is kept with the tier-contradiction finding, so no edge is ever destroyed to make a build quieter — the measured cost that stopped an adopter remediating 22 contradictions was eight real edges. ALSO emitted at member tier (F19, 2.33.1): the C4-correct authoring — Rel(container_a, container_b) between two Container(...) nodes — emits its edge directly; adjudication merges into a catalogue that already has content rather than being its only source, so the metamodel no longer rewards mis-declaration over correct authoring. Added in schema 2.33.0.
2336
2303
  foreign_keys:
2337
2304
  - column: from_container_id
2338
2305
  references: c4_containers.id
@@ -2342,14 +2309,11 @@ catalogues:
2342
2309
  nullable: false
2343
2310
  system_system_dependency:
2344
2311
  primary_key: id
2345
- description: 'Edge: a C4 system depends on another INTERNAL system (M-ADR 0189 §4.3). Derived by the aggregator at adjudication (§4.4): an external-system candidate whose declared identity resolves to an internal system was never external — its Rel(...) dependency edges are rewritten onto this catalogue and the candidate row is dropped. Not emitted at member tier (a member cannot see sibling systems); headers-only there, like cross_sdd_platform_capability. Both authoring directions feed it from the same diagram surface (M-ADR 0157 parity). Added in schema 2.30.0.
2346
-
2347
- '
2348
2312
  columns:
2349
2313
  - name: id
2350
2314
  type: string
2351
2315
  nullable: false
2352
- description: '{from_system_id}__{to_system_id}.'
2316
+ description: "{from_system_id}__{to_system_id}."
2353
2317
  - name: from_system_id
2354
2318
  type: string
2355
2319
  nullable: false
@@ -2368,6 +2332,8 @@ catalogues:
2368
2332
  type: string
2369
2333
  nullable: true
2370
2334
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2335
+ description: |
2336
+ Edge: a C4 system depends on another INTERNAL system (M-ADR 0189 §4.3). Derived by the aggregator at adjudication (§4.4): an external-system candidate whose declared identity resolves to an internal system was never external — its Rel(...) dependency edges are rewritten onto this catalogue and the candidate row is dropped. Not emitted at member tier (a member cannot see sibling systems); headers-only there, like cross_sdd_platform_capability. Both authoring directions feed it from the same diagram surface (M-ADR 0157 parity). Added in schema 2.30.0.
2371
2337
  foreign_keys:
2372
2338
  - column: from_system_id
2373
2339
  references: c4_systems.id
@@ -2377,12 +2343,11 @@ catalogues:
2377
2343
  nullable: false
2378
2344
  c4_container_entity:
2379
2345
  primary_key: id
2380
- description: 'Derived edge: C4 container is responsible for data-model entity. Added in schema 2.13.0 per M-ADR 0159 §4.8. Pure transitive derivation: `service_entity ⋈ c4_containers.service_id`. Only the subset of containers with `service_id` populated contribute edges (per M-ADR 0155 the container ↔ service cardinality is o-or-1; data-store containers and infra-umbrella containers without a service mapping legitimately emit no rows).'
2381
2346
  columns:
2382
2347
  - name: id
2383
2348
  type: string
2384
2349
  nullable: false
2385
- description: 'Composite PK: {container_id}__{entity_id}.'
2350
+ description: "Composite PK: {container_id}__{entity_id}."
2386
2351
  - name: container_id
2387
2352
  type: string
2388
2353
  nullable: false
@@ -2400,6 +2365,7 @@ catalogues:
2400
2365
  type: string
2401
2366
  nullable: true
2402
2367
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2368
+ description: "Derived edge: C4 container is responsible for data-model entity. Added in schema 2.13.0 per M-ADR 0159 §4.8. Pure transitive derivation: `service_entity ⋈ c4_containers.service_id`. Only the subset of containers with `service_id` populated contribute edges (per M-ADR 0155 the container ↔ service cardinality is o-or-1; data-store containers and infra-umbrella containers without a service mapping legitimately emit no rows)."
2403
2369
  foreign_keys:
2404
2370
  - column: container_id
2405
2371
  references: c4_containers.id
@@ -2409,12 +2375,11 @@ catalogues:
2409
2375
  nullable: false
2410
2376
  c4_system_entity:
2411
2377
  primary_key: id
2412
- description: 'Derived edge: C4 system is responsible for data-model entity. Added in schema 2.13.0 per M-ADR 0159 §4.8. Pure aggregation roll-up: `c4_container_entity ⋈ c4_containers.system_id`, with container_count recording how many of the system''s containers touch the entity (governance signal for cross-container concerns).'
2413
2378
  columns:
2414
2379
  - name: id
2415
2380
  type: string
2416
2381
  nullable: false
2417
- description: 'Composite PK: {system_id}__{entity_id}.'
2382
+ description: "Composite PK: {system_id}__{entity_id}."
2418
2383
  - name: system_id
2419
2384
  type: string
2420
2385
  nullable: false
@@ -2432,6 +2397,7 @@ catalogues:
2432
2397
  type: string
2433
2398
  nullable: true
2434
2399
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2400
+ description: "Derived edge: C4 system is responsible for data-model entity. Added in schema 2.13.0 per M-ADR 0159 §4.8. Pure aggregation roll-up: `c4_container_entity ⋈ c4_containers.system_id`, with container_count recording how many of the system's containers touch the entity (governance signal for cross-container concerns)."
2435
2401
  foreign_keys:
2436
2402
  - column: system_id
2437
2403
  references: c4_systems.id
@@ -2441,7 +2407,6 @@ catalogues:
2441
2407
  nullable: false
2442
2408
  capability_adr:
2443
2409
  primary_key: id
2444
- description: 'Edge: ADR informs capability. Forward: declared in capability spec Architecture Decisions. Reverse: same plus heuristic match supplements with confidence.'
2445
2410
  columns:
2446
2411
  - name: id
2447
2412
  type: string
@@ -2456,6 +2421,7 @@ catalogues:
2456
2421
  type: string
2457
2422
  nullable: false
2458
2423
  description: spec | high | medium.
2424
+ description: "Edge: ADR informs capability. Forward: declared in capability spec Architecture Decisions. Reverse: same plus heuristic match supplements with confidence."
2459
2425
  foreign_keys:
2460
2426
  - column: capability_id
2461
2427
  references: capabilities.id
@@ -2465,7 +2431,6 @@ catalogues:
2465
2431
  nullable: false
2466
2432
  adr_supersedes:
2467
2433
  primary_key: id
2468
- description: 'Edge: superseding ADR → superseded ADR. Parsed from Supersedes bullets where prose references a known ADR id.'
2469
2434
  columns:
2470
2435
  - name: id
2471
2436
  type: string
@@ -2476,6 +2441,7 @@ catalogues:
2476
2441
  - name: superseded_adr_id
2477
2442
  type: string
2478
2443
  nullable: false
2444
+ description: "Edge: superseding ADR → superseded ADR. Parsed from Supersedes bullets where prose references a known ADR id."
2479
2445
  foreign_keys:
2480
2446
  - column: superseding_adr_id
2481
2447
  references: adrs.id
@@ -2485,14 +2451,11 @@ catalogues:
2485
2451
  nullable: false
2486
2452
  product_platform_dependencies:
2487
2453
  primary_key: id
2488
- description: 'Per-SDD edge: an application-side or integration-side SDD declares that its product depends on a platform-side capability + service pair. Built from `reverse-evidence/feature-grounding-evidence.yaml` `platform_dependencies:` block (product-level — the cohort source shape carries product-scoped dependency rows with a `consumed_by:` list naming which services within the consuming product depend on the target). Each row records one (consuming product, target capability, target service) triple. The aggregator then joins these rows against platform-side `capability_service` to emit `cross_sdd_platform_capability` edges at aggregation time. Cross- SDD references (target_capability_id, target_service_id) are external — they''re not expected to resolve in the per-SDD build, only at aggregation. Added in schema 2.9.0; see `content/plans/v0-9-0-cohort-sweep-derived-bundle.md` §"Cross-SDD platform-capability-edge".
2489
-
2490
- '
2491
2454
  columns:
2492
2455
  - name: id
2493
2456
  type: string
2494
2457
  nullable: false
2495
- description: '{product_id}__{target_capability_id}__{target_service_id}, EXCEPT for async shared-stream rows (M-ADR 0192) where there is no realiser service: the third component falls back to the stream contract_path, i.e. {product_id}__{target_capability_id}__{contract_path}. For OFF-PLATFORM rows (M-ADR 0204, target_locus external|legacy) there is no platform capability either: id = {product_id}__{target_locus}__{target_external_system_id}, falling back to contract_path as the third component when no external-system id is named. This keeps the PK stable and collision-free when a product depends on the same capability via two distinct streams.'
2458
+ description: "{product_id}__{target_capability_id}__{target_service_id}, EXCEPT for async shared-stream rows (M-ADR 0192) where there is no realiser service: the third component falls back to the stream contract_path, i.e. {product_id}__{target_capability_id}__{contract_path}. For OFF-PLATFORM rows (M-ADR 0204, target_locus external|legacy) there is no platform capability either: id = {product_id}__{target_locus}__{target_external_system_id}, falling back to contract_path as the third component when no external-system id is named. This keeps the PK stable and collision-free when a product depends on the same capability via two distinct streams."
2496
2459
  - name: product_id
2497
2460
  type: string
2498
2461
  nullable: false
@@ -2500,7 +2463,7 @@ catalogues:
2500
2463
  - name: target_capability_id
2501
2464
  type: string
2502
2465
  nullable: true
2503
- description: 'Capability the consuming product depends on. Resolves at aggregation against a sibling SDD''s capabilities.id; external by definition. Conditionally nullable (M-ADR 0204 §4.3): EMPTY when target_locus is external|legacy — there is no platform capability to name on an off-platform row, and demanding a value is what put a product''s own feature slug in this column. A platform-locus row still requires it.'
2466
+ description: "Capability the consuming product depends on. Resolves at aggregation against a sibling SDD's capabilities.id; external by definition. Conditionally nullable (M-ADR 0204 §4.3): EMPTY when target_locus is external|legacy — there is no platform capability to name on an off-platform row, and demanding a value is what put a product's own feature slug in this column. A platform-locus row still requires it."
2504
2467
  - name: target_locus
2505
2468
  type: string
2506
2469
  nullable: true
@@ -2508,11 +2471,11 @@ catalogues:
2508
2471
  - name: target_external_system_id
2509
2472
  type: string
2510
2473
  nullable: true
2511
- description: 'For target_locus external|legacy rows only: the M-ADR 0189 external-system entry id the dependency targets (authored in the source file''s service_id slot; the builder routes it here so the FK columns stay clean). Deliberately NOT a declared FK: corroboration against c4_external_systems is WARNING-severity at aggregation (M-ADR 0204 §4.2), because the C4 surface may legitimately lag discovery, and a declared FK can only fail.'
2474
+ description: "For target_locus external|legacy rows only: the M-ADR 0189 external-system entry id the dependency targets (authored in the source file's service_id slot; the builder routes it here so the FK columns stay clean). Deliberately NOT a declared FK: corroboration against c4_external_systems is WARNING-severity at aggregation (M-ADR 0204 §4.2), because the C4 surface may legitimately lag discovery, and a declared FK can only fail."
2512
2475
  - name: target_service_id
2513
2476
  type: string
2514
2477
  nullable: true
2515
- description: 'Service identifier the consuming product depends on. Resolves at aggregation against a sibling SDD''s services.id; external by definition. The join key the aggregator uses to derive cross_sdd_platform_capability for SYNCHRONOUS dependencies. Conditionally nullable (M-ADR 0192): for an async shared-stream dependency (contract_type in the async set — `event`/`event-stream`/`stream`) there is no single realiser service, so this is empty and the dependency binds to the stream contract_path + target_capability_id instead. A synchronous contract_type still requires it. Made nullable in schema 2.36.0.'
2478
+ description: "Service identifier the consuming product depends on. Resolves at aggregation against a sibling SDD's services.id; external by definition. The join key the aggregator uses to derive cross_sdd_platform_capability for SYNCHRONOUS dependencies. Conditionally nullable (M-ADR 0192): for an async shared-stream dependency (contract_type in the async set — `event`/`event-stream`/`stream`) there is no single realiser service, so this is empty and the dependency binds to the stream contract_path + target_capability_id instead. A synchronous contract_type still requires it. Made nullable in schema 2.36.0."
2516
2479
  - name: target_domain
2517
2480
  type: string
2518
2481
  nullable: true
@@ -2524,7 +2487,7 @@ catalogues:
2524
2487
  - name: required_stability
2525
2488
  type: string
2526
2489
  nullable: true
2527
- description: 'provisional | locked | unknown. Optional; the consuming SDD''s expectation of contract stability — and only that: where the target lives and what lifecycle its implementation is in are separate concerns that do not belong in this field. Not a bound enum: an out-of-vocabulary value is carried, not rejected, and is reported by validate-app-dependencies.sh.'
2490
+ description: "provisional | locked | unknown. Optional; the consuming SDD's expectation of contract stability — and only that: where the target lives and what lifecycle its implementation is in are separate concerns that do not belong in this field. Not a bound enum: an out-of-vocabulary value is carried, not rejected, and is reported by validate-app-dependencies.sh."
2528
2491
  - name: contract_path
2529
2492
  type: string
2530
2493
  nullable: true
@@ -2541,6 +2504,8 @@ catalogues:
2541
2504
  type: string
2542
2505
  nullable: true
2543
2506
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2507
+ description: |
2508
+ Per-SDD edge: an application-side or integration-side SDD declares that its product depends on a platform-side capability + service pair. Built from `reverse-evidence/feature-grounding-evidence.yaml` `platform_dependencies:` block (product-level — the cohort source shape carries product-scoped dependency rows with a `consumed_by:` list naming which services within the consuming product depend on the target). Each row records one (consuming product, target capability, target service) triple. The aggregator then joins these rows against platform-side `capability_service` to emit `cross_sdd_platform_capability` edges at aggregation time. Cross- SDD references (target_capability_id, target_service_id) are external — they're not expected to resolve in the per-SDD build, only at aggregation. Added in schema 2.9.0; see `content/plans/v0-9-0-cohort-sweep-derived-bundle.md` §"Cross-SDD platform-capability-edge".
2544
2509
  foreign_keys:
2545
2510
  - column: product_id
2546
2511
  references: products.id
@@ -2555,14 +2520,11 @@ catalogues:
2555
2520
  external: true
2556
2521
  cross_sdd_platform_capability:
2557
2522
  primary_key: id
2558
- description: 'Federated edge: an application-side or integration-side SDD''s `product_platform_dependencies` reference resolves against a platform-side SDD''s capability spec via the platform capability''s `capability_service` roster. Surfaces ecosystem-wide platform- consumer relationships at product → capability granularity. Built **only at aggregation time** — `sdd-cli catalogue aggregate` joins each consuming SDD''s `product_platform_dependencies` rows against every other SDD''s `capability_service` rows on `target_service_id == service_id`, emitting one row per resolved (consuming-product, platform-capability) pair. Per-SDD builders emit nothing for this catalogue; the aggregator owns it entirely. A platform-dependency whose target_service_id doesn''t resolve to any platform-side capability_service row is logged as an `orphan` finding and produces no row. Cross-SDD references are external by definition. Added in schema 2.9.0; see `content/plans/v0-9-0-cohort-sweep-derived-bundle.md` §"Cross-SDD platform-capability-edge" and M-ADR 0134.
2559
-
2560
- '
2561
2523
  columns:
2562
2524
  - name: id
2563
2525
  type: string
2564
2526
  nullable: false
2565
- description: '{consuming_sdd_id}__{consuming_product_id}__{platform_sdd_id}__{platform_capability_id}__{service_id}. Composite encoding so the same (consuming product, platform capability) pair can appear once per resolving service when a product depends on multiple services owned by the same capability.'
2527
+ description: "{consuming_sdd_id}__{consuming_product_id}__{platform_sdd_id}__{platform_capability_id}__{service_id}. Composite encoding so the same (consuming product, platform capability) pair can appear once per resolving service when a product depends on multiple services owned by the same capability."
2566
2528
  - name: consuming_sdd_id
2567
2529
  type: string
2568
2530
  nullable: false
@@ -2583,6 +2545,8 @@ catalogues:
2583
2545
  type: string
2584
2546
  nullable: false
2585
2547
  description: Service identifier the consuming SDD references and the platform SDD owns. The join key.
2548
+ description: |
2549
+ Federated edge: an application-side or integration-side SDD's `product_platform_dependencies` reference resolves against a platform-side SDD's capability spec via the platform capability's `capability_service` roster. Surfaces ecosystem-wide platform- consumer relationships at product → capability granularity. Built **only at aggregation time** — `sdd-cli catalogue aggregate` joins each consuming SDD's `product_platform_dependencies` rows against every other SDD's `capability_service` rows on `target_service_id == service_id`, emitting one row per resolved (consuming-product, platform-capability) pair. Per-SDD builders emit nothing for this catalogue; the aggregator owns it entirely. A platform-dependency whose target_service_id doesn't resolve to any platform-side capability_service row is logged as an `orphan` finding and produces no row. Cross-SDD references are external by definition. Added in schema 2.9.0; see `content/plans/v0-9-0-cohort-sweep-derived-bundle.md` §"Cross-SDD platform-capability-edge" and M-ADR 0134.
2586
2550
  foreign_keys:
2587
2551
  - column: consuming_product_id
2588
2552
  references: products.id
@@ -2598,14 +2562,11 @@ catalogues:
2598
2562
  external: true
2599
2563
  application_data_plane_bindings:
2600
2564
  primary_key: id
2601
- description: 'Application-product edge (M-ADR 0193): one row per declared data-plane binding — a typed way the service sources, holds, produces or exposes data. The data-plane is a COMPOSITION of these bindings, a second axis orthogonal to `application_archetype` (0191). Built per-SDD from the manifest''s `data_plane.bindings` block (application-product only; other profiles emit headers-only). The `pattern` vocabulary splits by DIRECTION (§4.7): an INBOUND data-sourcing sub-set (retrieve | own-store | stream-ingest | project) and an OUTPUT-side sub-set (generate | publish), materialised as the derived `direction` column. An INBOUND binding whose `target` is a platform capability/service reconciles with `product_platform_dependencies` — a `retrieve@internal` binding is a synchronous platform dependency and a `stream-ingest@internal` binding is the M-ADR 0192 `contract_type: event` async dependency; the genuinely new inbound rows are `own-store` (a self-binding) and any `external-vendor` binding. OUTPUT-side rows do NOT participate in that reconciliation (§4.7 rule 1): `publish` is a contract the service PROVIDES, not one it consumes, so it has no inbound counterpart to cross-check — consumers must filter on `direction` before reconciling, which is what the column is for. The archetype-default-vs-declared WARN keys on the bare `pattern` token and so spans both directions (§4.7 rule 2). Added in schema 2.37.0; `direction` added in 2.40.0.
2602
-
2603
- '
2604
2565
  columns:
2605
2566
  - name: id
2606
2567
  type: string
2607
2568
  nullable: false
2608
- description: '{product_id}__{pattern}__{locality}__{target} (empty components collapse to blanks). A duplicate emits a divergence finding and is dropped. `direction` is NOT a component — it is derived from `pattern`, so it adds nothing to identity.'
2569
+ description: "{product_id}__{pattern}__{locality}__{target} (empty components collapse to blanks). A duplicate emits a divergence finding and is dropped. `direction` is NOT a component — it is derived from `pattern`, so it adds nothing to identity."
2609
2570
  - name: product_id
2610
2571
  type: string
2611
2572
  nullable: false
@@ -2613,15 +2574,15 @@ catalogues:
2613
2574
  - name: pattern
2614
2575
  type: string
2615
2576
  nullable: false
2616
- description: 'Closed method-tier enum: retrieve | own-store | stream-ingest | project (inbound, data-sourcing) | generate | publish (output-side, per M-ADR 0193 §4.7). How the data relates to the service (§4.1).'
2577
+ description: "Closed method-tier enum: retrieve | own-store | stream-ingest | project (inbound, data-sourcing) | generate | publish (output-side, per M-ADR 0193 §4.7). How the data relates to the service (§4.1)."
2617
2578
  - name: direction
2618
2579
  type: string
2619
2580
  nullable: false
2620
- description: 'inbound | output. DERIVED from `pattern` by a single method-tier mapping — not authored, and not a manifest field, so it cannot disagree with `pattern`. Materialises the output-side sub-set §4.7 declares (generate/publish => output; everything else => inbound). Exists because three §4.7 rules branch on direction: platform-dep reconciliation is inbound-only, the archetype WARN must compare like with like, and the M-ADR 0187 convergence reasoning differs by direction. Added in 2.40.0.'
2581
+ description: "inbound | output. DERIVED from `pattern` by a single method-tier mapping — not authored, and not a manifest field, so it cannot disagree with `pattern`. Materialises the output-side sub-set §4.7 declares (generate/publish => output; everything else => inbound). Exists because three §4.7 rules branch on direction: platform-dep reconciliation is inbound-only, the archetype WARN must compare like with like, and the M-ADR 0187 convergence reasoning differs by direction. Added in 2.40.0."
2621
2582
  - name: locality
2622
2583
  type: string
2623
2584
  nullable: true
2624
- description: 'Closed enum: internal-platform | internal-domain | external-vendor. Where the other end sits. REQUIRED on the inbound data-sourcing patterns (retrieve/stream-ingest/project); may be empty for own-store (a self-binding with no other end) and for the output-side patterns (generate/publish), which may carry one but do not require it (M-ADR 0193 §4.7).'
2585
+ description: "Closed enum: internal-platform | internal-domain | external-vendor. Where the other end sits. REQUIRED on the inbound data-sourcing patterns (retrieve/stream-ingest/project); may be empty for own-store (a self-binding with no other end) and for the output-side patterns (generate/publish), which may carry one but do not require it (M-ADR 0193 §4.7)."
2625
2586
  - name: transport
2626
2587
  type: string
2627
2588
  nullable: true
@@ -2646,20 +2607,19 @@ catalogues:
2646
2607
  type: string
2647
2608
  nullable: true
2648
2609
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2610
+ description: |
2611
+ Application-product edge (M-ADR 0193): one row per declared data-plane binding — a typed way the service sources, holds, produces or exposes data. The data-plane is a COMPOSITION of these bindings, a second axis orthogonal to `application_archetype` (0191). Built per-SDD from the manifest's `data_plane.bindings` block (application-product only; other profiles emit headers-only). The `pattern` vocabulary splits by DIRECTION (§4.7): an INBOUND data-sourcing sub-set (retrieve | own-store | stream-ingest | project) and an OUTPUT-side sub-set (generate | publish), materialised as the derived `direction` column. An INBOUND binding whose `target` is a platform capability/service reconciles with `product_platform_dependencies` — a `retrieve@internal` binding is a synchronous platform dependency and a `stream-ingest@internal` binding is the M-ADR 0192 `contract_type: event` async dependency; the genuinely new inbound rows are `own-store` (a self-binding) and any `external-vendor` binding. OUTPUT-side rows do NOT participate in that reconciliation (§4.7 rule 1): `publish` is a contract the service PROVIDES, not one it consumes, so it has no inbound counterpart to cross-check — consumers must filter on `direction` before reconciling, which is what the column is for. The archetype-default-vs-declared WARN keys on the bare `pattern` token and so spans both directions (§4.7 rule 2). Added in schema 2.37.0; `direction` added in 2.40.0.
2649
2612
  foreign_keys:
2650
2613
  - column: product_id
2651
2614
  references: products.id
2652
2615
  nullable: false
2653
2616
  application_data_plane_deviations:
2654
2617
  primary_key: id
2655
- description: 'Application-product annotation (M-ADR 0191 §4.3 overlay): one row per declared departure from the archetype''s default data-plane composition. Built per-SDD from the manifest''s `data_plane.deviations` block so the overlay WARN — which runs at AGGREGATION tier, where the reference- architecture bundle (and its `expected_bindings`) resolves — can suppress a mismatch it is told is sanctioned variance. The `expectation` value is the **bare pattern token** (`retrieve` | `own-store` | `stream-ingest` | `project` | `generate` | `publish`) that the product knowingly diverges from; it must match the pattern the WARN keys on. The token set spans both directions — the WARN keys on the bare pattern, so an output-side expectation is deviated exactly like an inbound one (M-ADR 0193 §4.7 rule 2). Added in schema 2.38.0; output-side tokens documented in 2.40.0.
2656
-
2657
- '
2658
2618
  columns:
2659
2619
  - name: id
2660
2620
  type: string
2661
2621
  nullable: false
2662
- description: '{product_id}__{expectation}. A duplicate emits a divergence finding and is dropped.'
2622
+ description: "{product_id}__{expectation}. A duplicate emits a divergence finding and is dropped."
2663
2623
  - name: product_id
2664
2624
  type: string
2665
2625
  nullable: false
@@ -2680,20 +2640,19 @@ catalogues:
2680
2640
  type: string
2681
2641
  nullable: true
2682
2642
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2643
+ description: |
2644
+ Application-product annotation (M-ADR 0191 §4.3 overlay): one row per declared departure from the archetype's default data-plane composition. Built per-SDD from the manifest's `data_plane.deviations` block so the overlay WARN — which runs at AGGREGATION tier, where the reference- architecture bundle (and its `expected_bindings`) resolves — can suppress a mismatch it is told is sanctioned variance. The `expectation` value is the **bare pattern token** (`retrieve` | `own-store` | `stream-ingest` | `project` | `generate` | `publish`) that the product knowingly diverges from; it must match the pattern the WARN keys on. The token set spans both directions — the WARN keys on the bare pattern, so an output-side expectation is deviated exactly like an inbound one (M-ADR 0193 §4.7 rule 2). Added in schema 2.38.0; output-side tokens documented in 2.40.0.
2683
2645
  foreign_keys:
2684
2646
  - column: product_id
2685
2647
  references: products.id
2686
2648
  nullable: false
2687
2649
  application_conformance_coverage:
2688
2650
  primary_key: id
2689
- description: 'Application-product annotation (M-ADR 0191 §4.3 overlay, second element — WS4): one row per conformance tag the product asserts about its archetype''s conformance expectations. Built per-SDD from the manifest''s `conformance` block so the AGGREGATION-tier conformance GATE can read it. `status=covered` means the product''s own conformance suite exercises the tag; `status=deviated` means the product declares (with a rationale) that it deliberately does not. At aggregation, an archetype-expected conformance tag that is neither covered nor deviated raises a deviation-visible WARN. The method gates the DECLARATION — it does not run the adopter''s conformance suite. Added in schema 2.39.0.
2690
-
2691
- '
2692
2651
  columns:
2693
2652
  - name: id
2694
2653
  type: string
2695
2654
  nullable: false
2696
- description: '{product_id}__{tag}. A duplicate emits a divergence finding and is dropped.'
2655
+ description: "{product_id}__{tag}. A duplicate emits a divergence finding and is dropped."
2697
2656
  - name: product_id
2698
2657
  type: string
2699
2658
  nullable: false
@@ -2718,18 +2677,19 @@ catalogues:
2718
2677
  type: string
2719
2678
  nullable: true
2720
2679
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2680
+ description: |
2681
+ Application-product annotation (M-ADR 0191 §4.3 overlay, second element — WS4): one row per conformance tag the product asserts about its archetype's conformance expectations. Built per-SDD from the manifest's `conformance` block so the AGGREGATION-tier conformance GATE can read it. `status=covered` means the product's own conformance suite exercises the tag; `status=deviated` means the product declares (with a rationale) that it deliberately does not. At aggregation, an archetype-expected conformance tag that is neither covered nor deviated raises a deviation-visible WARN. The method gates the DECLARATION — it does not run the adopter's conformance suite. Added in schema 2.39.0.
2721
2682
  foreign_keys:
2722
2683
  - column: product_id
2723
2684
  references: products.id
2724
2685
  nullable: false
2725
2686
  screens:
2726
2687
  primary_key: id
2727
- description: 'UI screen specified in the OpenUI Lang grammar (per M-ADR 0166). One row per screen / coherent screen group. Application-product profile (other profiles emit headers-only). Source: authored `screens/*.md` (frontmatter + ```openui-lang block); the reverse toolkit produces these from a router + component-tree projection.'
2728
2688
  columns:
2729
2689
  - name: id
2730
2690
  type: string
2731
2691
  nullable: false
2732
- description: 'Slugged PK: {product_id}-{screen-slug}.'
2692
+ description: "Slugged PK: {product_id}-{screen-slug}."
2733
2693
  - name: name
2734
2694
  type: string
2735
2695
  nullable: false
@@ -2765,7 +2725,7 @@ catalogues:
2765
2725
  - name: evidence_class
2766
2726
  type: string
2767
2727
  nullable: true
2768
- description: 'Evidence class of the screen''s claims, from frontmatter `evidence_class:` (alias `evidence-class:`). Free-form; conventional values code-reverse | vendor-doc | operational (M-ADR 0175). Empty when undeclared. Completes the evidence-class dimension for the packaged-SaaS case: a packaged-SaaS SDD catalogues the vendor''s STANDARD screens (documentation-reversed from vendor publications, `vendor-doc`) alongside the organisation''s CUSTOMISED screens (code-reversed, `code-reverse`) per M-ADR 0175 §3.1 — without this column the two are indistinguishable, and doc-derived UI claims masquerade as code-verified. Orthogonal to `source` (`screen-spec` | `screen-extraction`), which records the authoring DIRECTION, not the evidence''s strength: a `screen-extraction` screen can be either class, since a vendor''s documented UI is extracted-but-not-code-verified. Added in schema 2.42.0.'
2728
+ description: "Evidence class of the screen's claims, from frontmatter `evidence_class:` (alias `evidence-class:`). Free-form; conventional values code-reverse | vendor-doc | operational (M-ADR 0175). Empty when undeclared. Completes the evidence-class dimension for the packaged-SaaS case: a packaged-SaaS SDD catalogues the vendor's STANDARD screens (documentation-reversed from vendor publications, `vendor-doc`) alongside the organisation's CUSTOMISED screens (code-reversed, `code-reverse`) per M-ADR 0175 §3.1 — without this column the two are indistinguishable, and doc-derived UI claims masquerade as code-verified. Orthogonal to `source` (`screen-spec` | `screen-extraction`), which records the authoring DIRECTION, not the evidence's strength: a `screen-extraction` screen can be either class, since a vendor's documented UI is extracted-but-not-code-verified. Added in schema 2.42.0."
2769
2729
  - name: source_sdd_id
2770
2730
  type: string
2771
2731
  nullable: true
@@ -2774,18 +2734,18 @@ catalogues:
2774
2734
  type: string
2775
2735
  nullable: true
2776
2736
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2737
+ description: "UI screen specified in the OpenUI Lang grammar (per M-ADR 0166). One row per screen / coherent screen group. Application-product profile (other profiles emit headers-only). Source: authored `screens/*.md` (frontmatter + ```openui-lang block); the reverse toolkit produces these from a router + component-tree projection."
2777
2738
  foreign_keys:
2778
2739
  - column: product_id
2779
2740
  references: products.id
2780
2741
  nullable: false
2781
2742
  ui_components:
2782
2743
  primary_key: id
2783
- description: 'An entry in the adopter-owned component registry that screens compose against (per M-ADR 0166) — the UI-structure contract. A screen composes registry components but never defines one. Application-product profile. Source: components referenced across the SDD''s screen-spec ```openui-lang blocks (registry projection); the reverse toolkit discovers the authoritative registry from the design-system import surface.'
2784
2744
  columns:
2785
2745
  - name: id
2786
2746
  type: string
2787
2747
  nullable: false
2788
- description: 'Slugged PK: {product_id}-{component-slug}.'
2748
+ description: "Slugged PK: {product_id}-{component-slug}."
2789
2749
  - name: name
2790
2750
  type: string
2791
2751
  nullable: false
@@ -2797,7 +2757,7 @@ catalogues:
2797
2757
  - name: kind
2798
2758
  type: string
2799
2759
  nullable: true
2800
- description: 'Optional classification: layout | display | input | chart | element | composite | remote | remote-iframe | remote-webcomponent. A `remote*` kind marks a micro-frontend federation seam (M-ADR 0166 §4.7).'
2760
+ description: "Optional classification: layout | display | input | chart | element | composite | remote | remote-iframe | remote-webcomponent. A `remote*` kind marks a micro-frontend federation seam (M-ADR 0166 §4.7)."
2801
2761
  - name: source
2802
2762
  type: string
2803
2763
  nullable: false
@@ -2810,18 +2770,18 @@ catalogues:
2810
2770
  type: string
2811
2771
  nullable: true
2812
2772
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2773
+ description: "An entry in the adopter-owned component registry that screens compose against (per M-ADR 0166) — the UI-structure contract. A screen composes registry components but never defines one. Application-product profile. Source: components referenced across the SDD's screen-spec ```openui-lang blocks (registry projection); the reverse toolkit discovers the authoritative registry from the design-system import surface."
2813
2774
  foreign_keys:
2814
2775
  - column: product_id
2815
2776
  references: products.id
2816
2777
  nullable: false
2817
2778
  screen_component:
2818
2779
  primary_key: id
2819
- description: 'Edge: screen composes a UI component. Parsed from the screen-spec ```openui-lang block''s component references (per M-ADR 0166).'
2820
2780
  columns:
2821
2781
  - name: id
2822
2782
  type: string
2823
2783
  nullable: false
2824
- description: 'Composite PK: {screen_id}__{component_id}.'
2784
+ description: "Composite PK: {screen_id}__{component_id}."
2825
2785
  - name: screen_id
2826
2786
  type: string
2827
2787
  nullable: false
@@ -2836,6 +2796,7 @@ catalogues:
2836
2796
  type: string
2837
2797
  nullable: true
2838
2798
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2799
+ description: "Edge: screen composes a UI component. Parsed from the screen-spec ```openui-lang block's component references (per M-ADR 0166)."
2839
2800
  foreign_keys:
2840
2801
  - column: screen_id
2841
2802
  references: screens.id
@@ -2845,12 +2806,11 @@ catalogues:
2845
2806
  nullable: false
2846
2807
  screen_feature:
2847
2808
  primary_key: id
2848
- description: 'Edge: screen realises a feature (traceability). Forward: `realises:` frontmatter on the screen-spec. Reverse: route → feature mapping. Per M-ADR 0166.'
2849
2809
  columns:
2850
2810
  - name: id
2851
2811
  type: string
2852
2812
  nullable: false
2853
- description: 'Composite PK: {screen_id}__{feature_id}. For app/integration builds the feature_id may be a bare realises slug until the aggregator resolves it to the platform feature id (then the PK is regenerated).'
2813
+ description: "Composite PK: {screen_id}__{feature_id}. For app/integration builds the feature_id may be a bare realises slug until the aggregator resolves it to the platform feature id (then the PK is regenerated)."
2854
2814
  - name: screen_id
2855
2815
  type: string
2856
2816
  nullable: false
@@ -2865,6 +2825,7 @@ catalogues:
2865
2825
  type: string
2866
2826
  nullable: true
2867
2827
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2828
+ description: "Edge: screen realises a feature (traceability). Forward: `realises:` frontmatter on the screen-spec. Reverse: route → feature mapping. Per M-ADR 0166."
2868
2829
  foreign_keys:
2869
2830
  - column: screen_id
2870
2831
  references: screens.id
@@ -2877,12 +2838,11 @@ catalogues:
2877
2838
  - integration-product
2878
2839
  persona_screen:
2879
2840
  primary_key: id
2880
- description: 'Edge: persona can access a screen. Forward: `persona_access:` frontmatter. Reverse: route persona-access guards, permission/feature-flag config, or a host shell''s per-persona menu (where the backend pre-filters visible screens). Per M-ADR 0166.'
2881
2841
  columns:
2882
2842
  - name: id
2883
2843
  type: string
2884
2844
  nullable: false
2885
- description: 'Composite PK: {persona_id}__{screen_id}.'
2845
+ description: "Composite PK: {persona_id}__{screen_id}."
2886
2846
  - name: persona_id
2887
2847
  type: string
2888
2848
  nullable: false
@@ -2897,6 +2857,7 @@ catalogues:
2897
2857
  type: string
2898
2858
  nullable: true
2899
2859
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2860
+ description: "Edge: persona can access a screen. Forward: `persona_access:` frontmatter. Reverse: route persona-access guards, permission/feature-flag config, or a host shell's per-persona menu (where the backend pre-filters visible screens). Per M-ADR 0166."
2900
2861
  foreign_keys:
2901
2862
  - column: persona_id
2902
2863
  references: personas.id
@@ -2906,12 +2867,11 @@ catalogues:
2906
2867
  nullable: false
2907
2868
  screen_action:
2908
2869
  primary_key: id
2909
- description: 'Edge: screen emits an action, optionally resolved to a catalogued event. The behavioural MFE seam — inter-bundle communication as a catalogued contract, not an ad-hoc string. Forward: `action=` declarations in the ```openui-lang block. Reverse: emitted custom-event / event-bus wiring. event_id is external-capable (the event may live in the platform SDD). Per M-ADR 0166 + M-ADR 0156.'
2910
2870
  columns:
2911
2871
  - name: id
2912
2872
  type: string
2913
2873
  nullable: false
2914
- description: 'Composite PK: {screen_id}__{action-slug}.'
2874
+ description: "Composite PK: {screen_id}__{action-slug}."
2915
2875
  - name: screen_id
2916
2876
  type: string
2917
2877
  nullable: false
@@ -2931,6 +2891,7 @@ catalogues:
2931
2891
  type: string
2932
2892
  nullable: true
2933
2893
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2894
+ description: "Edge: screen emits an action, optionally resolved to a catalogued event. The behavioural MFE seam — inter-bundle communication as a catalogued contract, not an ad-hoc string. Forward: `action=` declarations in the ```openui-lang block. Reverse: emitted custom-event / event-bus wiring. event_id is external-capable (the event may live in the platform SDD). Per M-ADR 0166 + M-ADR 0156."
2934
2895
  foreign_keys:
2935
2896
  - column: screen_id
2936
2897
  references: screens.id
@@ -2941,7 +2902,6 @@ catalogues:
2941
2902
  external: true
2942
2903
  conformance_finding:
2943
2904
  primary_key: id
2944
- description: 'Conformance-reverse drift summary, one row per check (method M-ADR 0180). NOT produced by `catalogue build` (it reads the spec repo) — produced by `sdd-cli conformance --emit-finding` (which has the code repo) and federated here by the aggregator. Each row is a run-dated snapshot of declared-vs-observed drift for an implementation member (M-ADR 0181 role/lifecycle), so estate-wide conformance is queryable (aggregate union) and trendable (snapshot diff across runs/commits). Verdicts are PROVISIONAL — disposition (code-defect | spec-stale | divergence) is triage, recorded elsewhere. No enforced FK on implementation_repo: the code repo is frequently cross-repo and not in this SDD''s repositories.csv. Added in schema 2.25.0.'
2945
2905
  columns:
2946
2906
  - name: id
2947
2907
  type: string
@@ -2984,11 +2944,11 @@ catalogues:
2984
2944
  - name: declared_not_observed
2985
2945
  type: number
2986
2946
  nullable: false
2987
- description: 'Count declared but not observed (candidate: spec-stale / unimplemented / dangling).'
2947
+ description: "Count declared but not observed (candidate: spec-stale / unimplemented / dangling)."
2988
2948
  - name: observed_not_declared
2989
2949
  type: number
2990
2950
  nullable: false
2991
- description: 'Count observed but not declared (candidate: binding-stale / code-defect).'
2951
+ description: "Count observed but not declared (candidate: binding-stale / code-defect)."
2992
2952
  - name: needs_triage
2993
2953
  type: boolean
2994
2954
  nullable: false
@@ -3005,24 +2965,14 @@ catalogues:
3005
2965
  type: string
3006
2966
  nullable: true
3007
2967
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2968
+ description: "Conformance-reverse drift summary, one row per check (method M-ADR 0180). NOT produced by `catalogue build` (it reads the spec repo) — produced by `sdd-cli conformance --emit-finding` (which has the code repo) and federated here by the aggregator. Each row is a run-dated snapshot of declared-vs-observed drift for an implementation member (M-ADR 0181 role/lifecycle), so estate-wide conformance is queryable (aggregate union) and trendable (snapshot diff across runs/commits). Verdicts are PROVISIONAL — disposition (code-defect | spec-stale | divergence) is triage, recorded elsewhere. No enforced FK on implementation_repo: the code repo is frequently cross-repo and not in this SDD's repositories.csv. Added in schema 2.25.0."
3008
2969
  quality_scores:
3009
2970
  primary_key: id
3010
- description: 'Rubric assessment of a target artefact, one row per (target, rubric), per M-ADR 0205 §4.5. Source: `orchestration/gate-registry/<rubric>-scores.yaml` — the authored surface stays YAML because a score is a judgment, authored where it asserts intent; these rows are DERIVED and never edited.
3011
-
3012
- Models the EFFECTIVE score only — `current`, as chosen by the registry''s `selection_policy`. The authored `reviews[]` history is deliberately not catalogued: variable-length history in a fixed-grain catalogue would give two answers to "what is the score". `review_run_id` and `selection_method` make each row name which review it is.
3013
-
3014
- THE BUILDER MUST READ TWO AUTHORED DIALECTS. All fifteen method-side templates specify a nested shape (`selection_policy` / `current` / `reviews`), but the live forward-estate data is overwhelmingly FLAT — `gate`/`weighted_score`/`scored_at`/`scored_by`/`scores`/`flags` directly on the entry. Measured 2026-08-06: reading only the template shape would catalogue 6 entries out of 204. The templates were modernised; the data was not migrated, and both are legitimate.
3015
-
3016
- `rubric_id` comes from the file''s `registry_type` when declared, else the filename stem minus `-scores` — NEVER the container key, which is unreliable (4 of 10 forward registries drift from the method template) and non-unique (`domains` names both domain-architecture and intent-quality; `capabilities` names both feature-grounding and traceability-manifest).
3017
-
3018
- Scope: the weighted house form only. The banded reverse family is additive later via `scoring_form` (see that enum).
3019
-
3020
- '
3021
2971
  columns:
3022
2972
  - name: id
3023
2973
  type: string
3024
2974
  nullable: false
3025
- description: 'PK: {rubric_id}__{target_kind}__{target_ref}. Composite in one slug because the natural key is a triple and the rest of this schema keys on a single `id`.'
2975
+ description: "PK: {rubric_id}__{target_kind}__{target_ref}. Composite in one slug because the natural key is a triple and the rest of this schema keys on a single `id`."
3026
2976
  - name: rubric_id
3027
2977
  type: string
3028
2978
  nullable: false
@@ -3034,7 +2984,7 @@ catalogues:
3034
2984
  - name: target_kind
3035
2985
  type: string
3036
2986
  nullable: false
3037
- description: 'What kind of thing was scored: adr | contract | c4_diagram | capability | domain | feature | product | repository | persona | screen | glossary | integration | user_story | work_order | strategic_doc. Polymorphic because scored units span catalogue entities and non-catalogued artefacts (M-ADR 0205 §4.5).'
2987
+ description: "What kind of thing was scored: adr | contract | c4_diagram | capability | domain | feature | product | repository | persona | screen | glossary | integration | user_story | work_order | strategic_doc. Polymorphic because scored units span catalogue entities and non-catalogued artefacts (M-ADR 0205 §4.5)."
3038
2988
  - name: target_ref
3039
2989
  type: string
3040
2990
  nullable: false
@@ -3058,19 +3008,19 @@ catalogues:
3058
3008
  - name: band
3059
3009
  type: string
3060
3010
  nullable: true
3061
- description: 'Named band for a `banded` row; empty for a weighted one. DELIBERATELY UNBOUND, and for the same reason `dimension_key` is not normalised: the vocabulary belongs to the rubric, not to the method. Measured across the reverse estate at 3.3.0 — `reverseability` uses easy | moderate | hard | very-hard (a DIFFICULTY scale, where a higher band is worse), while `repo_doc_quality`, `product_synthesis_quality`, `reverse_platform_evidence_quality` and `artifact_quality` use strong | working (a QUALITY scale). One closed enum over both would assert that `hard` and `working` are comparable, which they are not. A consumer comparing bands must therefore group by rubric_id first.'
3011
+ description: "Named band for a `banded` row; empty for a weighted one. DELIBERATELY UNBOUND, and for the same reason `dimension_key` is not normalised: the vocabulary belongs to the rubric, not to the method. Measured across the reverse estate at 3.3.0 — `reverseability` uses easy | moderate | hard | very-hard (a DIFFICULTY scale, where a higher band is worse), while `repo_doc_quality`, `product_synthesis_quality`, `reverse_platform_evidence_quality` and `artifact_quality` use strong | working (a QUALITY scale). One closed enum over both would assert that `hard` and `working` are comparable, which they are not. A consumer comparing bands must therefore group by rubric_id first."
3062
3012
  - name: band_total
3063
3013
  type: int
3064
3014
  nullable: true
3065
- description: 'Integer total a `banded` rubric summed its dimensions to, before mapping to `band`; empty for a weighted row. Kept SEPARATE from weighted_score rather than sharing it: the scales are incompatible (a banded total ranges 0-13 against a weighted 1-5), and a single column holding both would make any average over it silently wrong. Separation makes an aggregate over weighted_score correct by construction rather than by the caller remembering to filter on scoring_form.'
3015
+ description: "Integer total a `banded` rubric summed its dimensions to, before mapping to `band`; empty for a weighted row. Kept SEPARATE from weighted_score rather than sharing it: the scales are incompatible (a banded total ranges 0-13 against a weighted 1-5), and a single column holding both would make any average over it silently wrong. Separation makes an aggregate over weighted_score correct by construction rather than by the caller remembering to filter on scoring_form."
3066
3016
  - name: scored_at
3067
3017
  type: date
3068
3018
  nullable: true
3069
- description: 'Date of the effective assessment, from `scored_at` (the forward house form''s field name — NOT `assessed_at`, which is the reverse family''s file-level field). Date-typed: per the M-ADR 0205 §4.1 engine''s TRY_CAST semantics, a prose value here is reported as a type nonconformance rather than aborting the load or being smoothed away — the `adrs.decision_date` case, which reverse practice already exercises.'
3019
+ description: "Date of the effective assessment, from `scored_at` (the forward house form's field name — NOT `assessed_at`, which is the reverse family's file-level field). Date-typed: per the M-ADR 0205 §4.1 engine's TRY_CAST semantics, a prose value here is reported as a type nonconformance rather than aborting the load or being smoothed away — the `adrs.decision_date` case, which reverse practice already exercises."
3070
3020
  - name: corpus_ref
3071
3021
  type: string
3072
3022
  nullable: true
3073
- description: 'The commit the assessment read — the precise staleness anchor. NEW AUTHORING introduced by this change-set: no score written before it carries one, so this column is empty across both estates at introduction and fills forward as registries are rewritten. The reverse family already has the idea under a different name (`snapshot.source_revision`).'
3023
+ description: "The commit the assessment read — the precise staleness anchor. NEW AUTHORING introduced by this change-set: no score written before it carries one, so this column is empty across both estates at introduction and fills forward as registries are rewritten. The reverse family already has the idea under a different name (`snapshot.source_revision`)."
3074
3024
  - name: staleness_basis
3075
3025
  type: string
3076
3026
  nullable: false
@@ -3082,7 +3032,7 @@ catalogues:
3082
3032
  - name: selection_method
3083
3033
  type: string
3084
3034
  nullable: true
3085
- description: 'How the effective review was chosen — see the score_selection_method enum. Empty in the flat dialect, which carries no selection_policy: absence means ''the only review'', not ''policy unknown''.'
3035
+ description: "How the effective review was chosen — see the score_selection_method enum. Empty in the flat dialect, which carries no selection_policy: absence means 'the only review', not 'policy unknown'."
3086
3036
  - name: scorer_provider
3087
3037
  type: string
3088
3038
  nullable: true
@@ -3106,11 +3056,11 @@ catalogues:
3106
3056
  - name: flag_count
3107
3057
  type: int
3108
3058
  nullable: false
3109
- description: 'Number of heuristic flags raised. Normalises two authored dialects: `flags: {name: bool}` (count the true ones) and `flags_raised: [names]` (count the list). A per-flag child catalogue is deliberately NOT built — it arrives when a named query needs to filter by flag name, not by accretion.'
3059
+ description: "Number of heuristic flags raised. Normalises two authored dialects: `flags: {name: bool}` (count the true ones) and `flags_raised: [names]` (count the list). A per-flag child catalogue is deliberately NOT built — it arrives when a named query needs to filter by flag name, not by accretion."
3110
3060
  - name: hard_gate_triggered
3111
3061
  type: boolean
3112
3062
  nullable: false
3113
- description: 'Whether any hard gate fired. Normalises `hard_gates: {triggered, reasons}` and `hard_gates_triggered: [reasons]`.'
3063
+ description: "Whether any hard gate fired. Normalises `hard_gates: {triggered, reasons}` and `hard_gates_triggered: [reasons]`."
3114
3064
  - name: required_actions_count
3115
3065
  type: int
3116
3066
  nullable: false
@@ -3127,22 +3077,23 @@ catalogues:
3127
3077
  type: string
3128
3078
  nullable: true
3129
3079
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3080
+ description: |
3081
+ Rubric assessment of a target artefact, one row per (target, rubric), per M-ADR 0205 §4.5. Source: `orchestration/gate-registry/<rubric>-scores.yaml` — the authored surface stays YAML because a score is a judgment, authored where it asserts intent; these rows are DERIVED and never edited.
3082
+ Models the EFFECTIVE score only — `current`, as chosen by the registry's `selection_policy`. The authored `reviews[]` history is deliberately not catalogued: variable-length history in a fixed-grain catalogue would give two answers to "what is the score". `review_run_id` and `selection_method` make each row name which review it is.
3083
+ THE BUILDER MUST READ TWO AUTHORED DIALECTS. All fifteen method-side templates specify a nested shape (`selection_policy` / `current` / `reviews`), but the live forward-estate data is overwhelmingly FLAT — `gate`/`weighted_score`/`scored_at`/`scored_by`/`scores`/`flags` directly on the entry. Measured 2026-08-06: reading only the template shape would catalogue 6 entries out of 204. The templates were modernised; the data was not migrated, and both are legitimate.
3084
+ `rubric_id` comes from the file's `registry_type` when declared, else the filename stem minus `-scores` — NEVER the container key, which is unreliable (4 of 10 forward registries drift from the method template) and non-unique (`domains` names both domain-architecture and intent-quality; `capabilities` names both feature-grounding and traceability-manifest).
3085
+ Scope: the weighted house form only. The banded reverse family is additive later via `scoring_form` (see that enum).
3130
3086
  foreign_keys:
3131
3087
  - column: sdd_id
3132
3088
  references: products.id
3133
3089
  nullable: true
3134
3090
  quality_score_dimensions:
3135
3091
  primary_key: id
3136
- description: 'One row per (target, rubric, dimension) — the per-dimension detail behind a `quality_scores` row, per M-ADR 0205 §4.5.
3137
-
3138
- A child catalogue rather than columns, and this is forced rather than stylistic: the fifteen rubrics carry FIFTEEN DISJOINT dimension vocabularies (`A1`-`A8`, `C1`-`C8`, `G1`-`G7`, `T1`-`T7`, `D1`-`D6`, `S1`-`S6`, `I1`-`I6`, plus five fully-named sets such as `definition_precision` and `intent_fidelity`) — 45 distinct keys measured in one estate alone. No fixed column set can hold them; serialised JSON in a cell would be unjoinable and break the relational metamodel; generic `d1..d8` columns would be lossy and re-create the positional-index failure class. A child table is what this metamodel already does for every one-to-many, and it joins natively on the M-ADR 0205 §4.1 engine.
3139
-
3140
- '
3141
3092
  columns:
3142
3093
  - name: id
3143
3094
  type: string
3144
3095
  nullable: false
3145
- description: 'PK: {quality_score_id}__{dimension_key}.'
3096
+ description: "PK: {quality_score_id}__{dimension_key}."
3146
3097
  - name: quality_score_id
3147
3098
  type: string
3148
3099
  nullable: false
@@ -3162,7 +3113,7 @@ catalogues:
3162
3113
  - name: dimension_key
3163
3114
  type: string
3164
3115
  nullable: false
3165
- description: 'The rubric''s own dimension identifier, verbatim — `A1` where the rubric uses codes, `definition_precision` where it uses names. NOT normalised into a method-wide vocabulary: the key is how the rubric and its registry refer to the dimension, and rewriting it here would make the row untraceable to the rubric that produced it.'
3116
+ description: "The rubric's own dimension identifier, verbatim — `A1` where the rubric uses codes, `definition_precision` where it uses names. NOT normalised into a method-wide vocabulary: the key is how the rubric and its registry refer to the dimension, and rewriting it here would make the row untraceable to the rubric that produced it."
3166
3117
  - name: dimension_score
3167
3118
  type: number
3168
3119
  nullable: true
@@ -3170,7 +3121,7 @@ catalogues:
3170
3121
  - name: dimension_weight
3171
3122
  type: number
3172
3123
  nullable: true
3173
- description: 'Weight the rubric assigns the dimension, where discoverable. Usually EMPTY: weights live in the rubric document and the registry header comment, not per entry — so this column is honest about the fact that a weighted_score cannot currently be recomputed from these rows alone.'
3124
+ description: "Weight the rubric assigns the dimension, where discoverable. Usually EMPTY: weights live in the rubric document and the registry header comment, not per entry — so this column is honest about the fact that a weighted_score cannot currently be recomputed from these rows alone."
3174
3125
  - name: source_sdd_id
3175
3126
  type: string
3176
3127
  nullable: true
@@ -3179,24 +3130,20 @@ catalogues:
3179
3130
  type: string
3180
3131
  nullable: true
3181
3132
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3133
+ description: |
3134
+ One row per (target, rubric, dimension) — the per-dimension detail behind a `quality_scores` row, per M-ADR 0205 §4.5.
3135
+ A child catalogue rather than columns, and this is forced rather than stylistic: the fifteen rubrics carry FIFTEEN DISJOINT dimension vocabularies (`A1`-`A8`, `C1`-`C8`, `G1`-`G7`, `T1`-`T7`, `D1`-`D6`, `S1`-`S6`, `I1`-`I6`, plus five fully-named sets such as `definition_precision` and `intent_fidelity`) — 45 distinct keys measured in one estate alone. No fixed column set can hold them; serialised JSON in a cell would be unjoinable and break the relational metamodel; generic `d1..d8` columns would be lossy and re-create the positional-index failure class. A child table is what this metamodel already does for every one-to-many, and it joins natively on the M-ADR 0205 §4.1 engine.
3182
3136
  foreign_keys:
3183
3137
  - column: quality_score_id
3184
3138
  references: quality_scores.id
3185
3139
  nullable: false
3186
3140
  scaffolds:
3187
3141
  primary_key: id
3188
- description: 'Forward scaffold declaration, one row per unit of work, per M-ADR 0207 §4.1. Source: `orchestration/scaffolds/*.yaml` — the authored surface stays YAML because a scaffold is a declaration of intent, authored where the work is scoped; these rows are DERIVED and never edited (M-ADR 0205 §4.0 governs unchanged).
3189
-
3190
- The scaffold states the catalogue shape a unit of work will comprise — its items are `scaffold_items` rows — and the declared-vs-derived delta against the built catalogues is the unit''s definition of done: delta zero (structural) AND every realised artefact score-current (content, via `quality_scores`), per M-ADR 0207 §4.5. The unit is the change-set''s declared delta; estate-level scaffold totality is an explicit non-goal (M-ADR 0207 §4.4), so an estate region no scaffold covers produces no finding.
3191
-
3192
- `corpus_ref` is REQUIRED — a scaffold without an anchor cannot carry a staleness verdict, and M-ADR 0207 §4.6 makes the anchor part of the declaration, not an optional refinement. Staleness itself is computed at coverage time (the scores idiom), never stored here.
3193
-
3194
- '
3195
3142
  columns:
3196
3143
  - name: id
3197
3144
  type: string
3198
3145
  nullable: false
3199
- description: 'PK: the manifest''s declared unit id (kebab-case slug). Unique per SDD; the aggregator namespaces cross-SDD ids exactly as for every other catalogue.'
3146
+ description: "PK: the manifest's declared unit id (kebab-case slug). Unique per SDD; the aggregator namespaces cross-SDD ids exactly as for every other catalogue."
3200
3147
  - name: name
3201
3148
  type: string
3202
3149
  nullable: false
@@ -3212,7 +3159,7 @@ catalogues:
3212
3159
  - name: corpus_ref
3213
3160
  type: string
3214
3161
  nullable: false
3215
- description: 'The commit the scaffold was declared against — the staleness anchor, mirroring quality_scores.corpus_ref (M-ADR 0207 §4.6: one staleness idiom, not two). Required: a manifest without one fails validation rather than emitting an unanchorable row.'
3162
+ description: "The commit the scaffold was declared against — the staleness anchor, mirroring quality_scores.corpus_ref (M-ADR 0207 §4.6: one staleness idiom, not two). Required: a manifest without one fails validation rather than emitting an unanchorable row."
3216
3163
  - name: manifest_schema
3217
3164
  type: string
3218
3165
  nullable: false
@@ -3229,6 +3176,10 @@ catalogues:
3229
3176
  type: string
3230
3177
  nullable: true
3231
3178
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3179
+ description: |
3180
+ Forward scaffold declaration, one row per unit of work, per M-ADR 0207 §4.1. Source: `orchestration/scaffolds/*.yaml` — the authored surface stays YAML because a scaffold is a declaration of intent, authored where the work is scoped; these rows are DERIVED and never edited (M-ADR 0205 §4.0 governs unchanged).
3181
+ The scaffold states the catalogue shape a unit of work will comprise — its items are `scaffold_items` rows — and the declared-vs-derived delta against the built catalogues is the unit's definition of done: delta zero (structural) AND every realised artefact score-current (content, via `quality_scores`), per M-ADR 0207 §4.5. The unit is the change-set's declared delta; estate-level scaffold totality is an explicit non-goal (M-ADR 0207 §4.4), so an estate region no scaffold covers produces no finding.
3182
+ `corpus_ref` is REQUIRED — a scaffold without an anchor cannot carry a staleness verdict, and M-ADR 0207 §4.6 makes the anchor part of the declaration, not an optional refinement. Staleness itself is computed at coverage time (the scores idiom), never stored here.
3232
3183
  foreign_keys:
3233
3184
  - column: sdd_id
3234
3185
  references: products.id
@@ -3237,18 +3188,11 @@ catalogues:
3237
3188
  status: enums.scaffold_status
3238
3189
  scaffold_items:
3239
3190
  primary_key: id
3240
- description: 'One declared item of a scaffold — an entity, edge, or contract the unit of work promises — per M-ADR 0207 §4.1. Derived from the manifest''s item list; `state` is the builder''s resolution verdict against the same build''s catalogue rows.
3241
-
3242
- THE POLYMORPHIC TARGET DECLARES NO FOREIGN KEY, by design (the quality_scores.target_ref precedent, taken further): a scaffold exists to reference targets BEFORE they exist. FK truth here is CONDITIONAL ON STATE — a `declared` item''s (target_kind, target_ref) MUST NOT resolve in the built catalogues, a `realised` item''s MUST — and the builder''s resolution pass is what enforces it: it computes `state` FROM resolution, so a disagreement between state and resolution cannot be emitted by a conforming builder. The M-ADR 0207 §4.8 delta instrument re-derives the same verdict on the engine as its self-check.
3243
-
3244
- `target_kind` is the CATALOGUE NAME the target should appear in (services, capabilities, repo_contract, contracts, …) — bound to the schema''s own catalogue list by the builder: an unknown target_kind is a loud convention finding, never a silently-dropped item (M-ADR 0207 §4.1). For `edge` items the endpoints are declared in edge_source_ref/edge_target_ref, mapped to the edge catalogue''s FK columns in schema declaration order; target_ref then carries the builder-computed endpoint slug so the PK stays single-column.
3245
-
3246
- '
3247
3191
  columns:
3248
3192
  - name: id
3249
3193
  type: string
3250
3194
  nullable: false
3251
- description: 'PK: {scaffold_id}__{item_kind}__{target_kind}__{target_ref}. Composite in one slug because the natural key is a quadruple and the rest of this schema keys on a single `id`.'
3195
+ description: "PK: {scaffold_id}__{item_kind}__{target_kind}__{target_ref}. Composite in one slug because the natural key is a quadruple and the rest of this schema keys on a single `id`."
3252
3196
  - name: scaffold_id
3253
3197
  type: string
3254
3198
  nullable: false
@@ -3264,15 +3208,15 @@ catalogues:
3264
3208
  - name: target_ref
3265
3209
  type: string
3266
3210
  nullable: false
3267
- description: 'Identifier of the declared target in the vocabulary of its catalogue: the declared id for entity items, the repo-relative spec path for contract items (matching contracts.spec_path), the builder-computed {source}__{target} endpoint slug for edge items.'
3211
+ description: "Identifier of the declared target in the vocabulary of its catalogue: the declared id for entity items, the repo-relative spec path for contract items (matching contracts.spec_path), the builder-computed {source}__{target} endpoint slug for edge items."
3268
3212
  - name: edge_source_ref
3269
3213
  type: string
3270
3214
  nullable: true
3271
- description: 'For edge items: the declared source endpoint, in the vocabulary of the edge catalogue''s first FK column (schema declaration order). Empty for entity and contract items.'
3215
+ description: "For edge items: the declared source endpoint, in the vocabulary of the edge catalogue's first FK column (schema declaration order). Empty for entity and contract items."
3272
3216
  - name: edge_target_ref
3273
3217
  type: string
3274
3218
  nullable: true
3275
- description: 'For edge items: the declared target endpoint, second FK column. Empty for entity and contract items.'
3219
+ description: "For edge items: the declared target endpoint, second FK column. Empty for entity and contract items."
3276
3220
  - name: state
3277
3221
  type: string
3278
3222
  nullable: false
@@ -3285,6 +3229,10 @@ catalogues:
3285
3229
  type: string
3286
3230
  nullable: true
3287
3231
  description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3232
+ description: |
3233
+ One declared item of a scaffold — an entity, edge, or contract the unit of work promises — per M-ADR 0207 §4.1. Derived from the manifest's item list; `state` is the builder's resolution verdict against the same build's catalogue rows.
3234
+ THE POLYMORPHIC TARGET DECLARES NO FOREIGN KEY, by design (the quality_scores.target_ref precedent, taken further): a scaffold exists to reference targets BEFORE they exist. FK truth here is CONDITIONAL ON STATE — a `declared` item's (target_kind, target_ref) MUST NOT resolve in the built catalogues, a `realised` item's MUST — and the builder's resolution pass is what enforces it: it computes `state` FROM resolution, so a disagreement between state and resolution cannot be emitted by a conforming builder. The M-ADR 0207 §4.8 delta instrument re-derives the same verdict on the engine as its self-check.
3235
+ `target_kind` is the CATALOGUE NAME the target should appear in (services, capabilities, repo_contract, contracts, …) — bound to the schema's own catalogue list by the builder: an unknown target_kind is a loud convention finding, never a silently-dropped item (M-ADR 0207 §4.1). For `edge` items the endpoints are declared in edge_source_ref/edge_target_ref, mapped to the edge catalogue's FK columns in schema declaration order; target_ref then carries the builder-computed endpoint slug so the PK stays single-column.
3288
3236
  foreign_keys:
3289
3237
  - column: scaffold_id
3290
3238
  references: scaffolds.id