@sdd-method/verify-cli 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/catalogue/baseline-check.js +17 -2
- package/dist/lib/catalogue/canonical-schema.yaml +476 -10
- package/dist/lib/catalogue/coverage-render.js +30 -0
- package/dist/lib/catalogue/engine-validator.js +17 -0
- package/dist/lib/catalogue/graph-projection.js +17 -0
- package/dist/lib/catalogue/impact-run.js +2 -2
- package/dist/lib/catalogue/manifest-loader.js +9 -0
- package/dist/lib/catalogue/platform-scope.js +7 -0
- package/dist/lib/catalogue/rubric-coverage-map.yaml +91 -2
- package/dist/lib/catalogue/scores-coverage.js +38 -0
- package/dist/lib/catalogue/validate.js +33 -9
- package/dist/lib/validate/aggregate.js +31 -15
- package/dist/lib/validate/bundle-coherence.js +7 -2
- package/dist/lib/validate/dispatch.js +25 -0
- package/dist/lib/validate/index.js +32 -10
- package/dist/lib/validate/yaml-parse.js +112 -0
- package/dist/verbs/catalogue-verify.js +1 -1
- package/package.json +1 -1
- package/scripts/validate-app-dependencies.sh +24 -4
- package/scripts/validate-app-docs.sh +18 -4
|
@@ -63,6 +63,16 @@ export async function runBaselineCheck(options, write) {
|
|
|
63
63
|
write("[error] baseline-check: no findings source (--findings <path>, or pipe them in)\n");
|
|
64
64
|
return { exitCode: 2 };
|
|
65
65
|
}
|
|
66
|
+
// An input with no lines at all is not "zero findings": every real findings
|
|
67
|
+
// stream (build, coverage, validate output) carries at least its own metric
|
|
68
|
+
// and verdict lines. The default source is stdin, so an empty pipe arrives
|
|
69
|
+
// here as nothing — refused, never compared (empty-set sweep, R2).
|
|
70
|
+
if (findingsText.trim() === "") {
|
|
71
|
+
write(`[error] baseline-check: the findings stream is EMPTY — no lines of any kind. ` +
|
|
72
|
+
`This is not zero findings; it is no measurement (an empty pipe, or the wrong ` +
|
|
73
|
+
`file). Pass --findings <path> to the captured stream\n`);
|
|
74
|
+
return { exitCode: 2 };
|
|
75
|
+
}
|
|
66
76
|
let baselineText;
|
|
67
77
|
try {
|
|
68
78
|
baselineText = await readFile(baselinePath, "utf-8");
|
|
@@ -102,7 +112,8 @@ export async function runBaselineCheck(options, write) {
|
|
|
102
112
|
// The condition is deliberately narrow: live gate-acting findings ZERO, baseline
|
|
103
113
|
// non-empty, and EVERY entry closed. That triple cannot arise from ordinary
|
|
104
114
|
// remediation without also being worth a human look.
|
|
105
|
-
|
|
115
|
+
const allClosed = live.lines.length === 0 && base.lines.length > 0 && cmp.stale.length === base.lines.length;
|
|
116
|
+
if (allClosed) {
|
|
106
117
|
write(`[finding] divergence: baseline_check compared ZERO live gate-acting findings ` +
|
|
107
118
|
`against ${base.lines.length} baseline entr(ies) and reported ALL of them closed. ` +
|
|
108
119
|
`This is reported as a DEFECT rather than a pass: an all-closed baseline is far ` +
|
|
@@ -131,6 +142,10 @@ export async function runBaselineCheck(options, write) {
|
|
|
131
142
|
// Only genuinely unbaselined findings fail. A reworded finding is the case
|
|
132
143
|
// this whole mechanism exists to stop failing, and a closed one is good news
|
|
133
144
|
// that a re-take tidies — neither is a regression.
|
|
134
|
-
|
|
145
|
+
// The all-closed guard FAILS the gate (empty-set sweep, R2, ruled 2026-09-29):
|
|
146
|
+
// it used to print "a DEFECT rather than a pass" and exit 0, so the regression
|
|
147
|
+
// gate still passed on exactly the empty/wrong stream it was written to catch.
|
|
148
|
+
// A genuinely all-fixed estate re-takes its baseline once, deliberately.
|
|
149
|
+
return { exitCode: cmp.unbaselined.length > 0 || allClosed ? 1 : 0 };
|
|
135
150
|
}
|
|
136
151
|
//# sourceMappingURL=baseline-check.js.map
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
# Emitted by sdd-cli's YAML emitter with no line folding; the three header scalars are quoted for the
|
|
8
8
|
# textual readers downstream. The one deliberate difference from the authored form is schema_status:
|
|
9
9
|
# the authored form says canonical; a projection never does.
|
|
10
|
-
schema_version: "3.
|
|
10
|
+
schema_version: "3.18.0"
|
|
11
11
|
schema_owner: "sdd-method"
|
|
12
12
|
schema_status: "generated"
|
|
13
13
|
enums:
|
|
@@ -129,8 +129,12 @@ enums:
|
|
|
129
129
|
description: Docs-only repo.
|
|
130
130
|
runtime: false
|
|
131
131
|
emits_service_row: false
|
|
132
|
+
- value: firmware
|
|
133
|
+
description: "Firmware that runs on a device: the application image, bootloader, loader, on-device plug-ins (M-ADR 0215). Runtime, but emits no service row — a device is not a node in the platform's service graph. Its tooling, test benches and libraries keep their own kinds."
|
|
134
|
+
runtime: true
|
|
135
|
+
emits_service_row: false
|
|
132
136
|
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).
|
|
137
|
+
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); firmware runs, but on a device, so it is runtime without a service row (M-ADR 0215) — service emission follows emits_service_row, not runtime. 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).
|
|
134
138
|
capability_exemption_reason:
|
|
135
139
|
values:
|
|
136
140
|
- value: infrastructure
|
|
@@ -246,7 +250,7 @@ enums:
|
|
|
246
250
|
description: A persona the journey passes to or from.
|
|
247
251
|
- value: supporting
|
|
248
252
|
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."
|
|
253
|
+
description: "The kind of participation a persona has in a user journey, in `persona_journey.role` — the M-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."
|
|
250
254
|
model_notation:
|
|
251
255
|
values:
|
|
252
256
|
- value: mermaid-erd
|
|
@@ -474,20 +478,134 @@ enums:
|
|
|
474
478
|
- value: code-vs-contract
|
|
475
479
|
- value: binding-vs-reality
|
|
476
480
|
description: M-ADR 0194 conformance finding target. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
|
|
477
|
-
|
|
481
|
+
implementation_role:
|
|
478
482
|
values:
|
|
479
483
|
- value: as-is
|
|
484
|
+
description: The existing implementation.
|
|
480
485
|
- value: to-be
|
|
481
|
-
|
|
482
|
-
|
|
486
|
+
description: The target implementation the spec is migrating toward.
|
|
487
|
+
description: An implementation member's role against its spec (M-ADR 0181 §2.1). Bound at 3.13.0 on conformance_finding as conformance_role; renamed at 3.15.0, when implementation_members became its owner (M-ADR 0214 §4.2) — the values did not change.
|
|
488
|
+
implementation_lifecycle:
|
|
483
489
|
values:
|
|
484
490
|
- value: active
|
|
491
|
+
description: In service and the current implementation.
|
|
485
492
|
- value: planned
|
|
493
|
+
description: "Not yet built: the repository may not exist yet."
|
|
486
494
|
- value: deprecated
|
|
495
|
+
description: "Still running, scheduled for retirement (M-ADR 0214 §4.7: what some bindings called sunset)."
|
|
487
496
|
- value: migrating
|
|
497
|
+
description: Being moved onto, or off, while both sides run.
|
|
488
498
|
- value: legacy-active
|
|
499
|
+
description: The as-is implementation, still serving while a to-be replaces it.
|
|
489
500
|
- value: decommissioned
|
|
490
|
-
|
|
501
|
+
description: "Retired: no longer running."
|
|
502
|
+
description: An implementation member's lifecycle (M-ADR 0181 §2.1). Bound at 3.13.0 on conformance_finding as conformance_lifecycle; renamed at 3.15.0, when implementation_members became its owner (M-ADR 0214 §4.2) — the values did not change.
|
|
503
|
+
repo_scope:
|
|
504
|
+
values:
|
|
505
|
+
- value: component
|
|
506
|
+
description: "Part of what this SDD specifies: the SDD's artefact stack applies, and its capabilities or other services depend on it."
|
|
507
|
+
- value: support
|
|
508
|
+
description: "Supports a component without being one: its operational configuration, tooling, tests, collections, or a library it consumes."
|
|
509
|
+
description: Whether a mirrored repository is inside the scope of what its SDD specifies (M-ADR 0213). Deliberately neither a profile (profile is the SDD's) nor a role (role is M-ADR 0181's as-is | to-be); a repository's kind is component_type.
|
|
510
|
+
evidence_direction:
|
|
511
|
+
values:
|
|
512
|
+
- value: forward-authored
|
|
513
|
+
description: The spec came first and the code was built from it.
|
|
514
|
+
- value: seeding-reverse
|
|
515
|
+
description: A spec that never existed, recovered from pre-existing internal code.
|
|
516
|
+
- value: external-doc-reverse
|
|
517
|
+
description: The external surface a product consumes, grounded in a third party's published API or documentation.
|
|
518
|
+
- value: conformance-reverse
|
|
519
|
+
description: Own forward or maintained code, verified against its spec, with legitimate evolution fed back.
|
|
520
|
+
description: How an implementation member is evidenced (M-ADR 0180 §2.1; forward-authored added by M-ADR 0181 §2.1).
|
|
521
|
+
member_presence:
|
|
522
|
+
values:
|
|
523
|
+
- value: observed
|
|
524
|
+
description: Exported and observed in this baseline.
|
|
525
|
+
- value: carried
|
|
526
|
+
description: "Not re-exported: carried from an earlier baseline (carried_from), with its reason."
|
|
527
|
+
- value: removed
|
|
528
|
+
description: In the prior baseline and not in this one (members_removed), with its reason.
|
|
529
|
+
description: A snapshot member's presence in its baseline — the three states the snapshot conventions record (M-ADR 0214 §4.4).
|
|
530
|
+
conformance_disposition:
|
|
531
|
+
values:
|
|
532
|
+
- value: conformant
|
|
533
|
+
description: Code matches spec.
|
|
534
|
+
- value: conformant-open
|
|
535
|
+
description: "Both sides agree the item is deferred or absent: an open decision, not drift."
|
|
536
|
+
- value: code-defect
|
|
537
|
+
description: "The spec is authority: fix the code."
|
|
538
|
+
- value: spec-stale
|
|
539
|
+
description: "The code legitimately evolved: update the spec."
|
|
540
|
+
- value: divergence
|
|
541
|
+
description: "A genuine design question: triage, don't fail."
|
|
542
|
+
description: The triage outcome of a conformance-reverse delta (M-ADR 0180 §2.3). Bound so every file that records an outcome records one of these; the triage records are not yet catalogued (M-ADR 0214 §4.8).
|
|
543
|
+
delta_disposition:
|
|
544
|
+
values:
|
|
545
|
+
- value: capability-added
|
|
546
|
+
description: The code gained a capability the spec does not have.
|
|
547
|
+
- value: capability-removed
|
|
548
|
+
description: The code lost a capability the spec still has.
|
|
549
|
+
- value: spec-update
|
|
550
|
+
description: "The code legitimately evolved within a capability: the spec follows."
|
|
551
|
+
- value: refactor-only-no-spec-change
|
|
552
|
+
description: "The code changed and its behaviour did not: no spec change."
|
|
553
|
+
- value: ambiguous
|
|
554
|
+
description: "Cannot be classified from the delta alone: triage."
|
|
555
|
+
description: The classification of a delta-reverse finding between two snapshots (M-ADR 0180 §2.7). Bound so every file that records one records one of these; delta findings are not yet catalogued (M-ADR 0214 §4.8).
|
|
556
|
+
supply_verdict:
|
|
557
|
+
values:
|
|
558
|
+
- value: supported
|
|
559
|
+
description: The item reaches the canonical boundary from this integration.
|
|
560
|
+
- value: partial
|
|
561
|
+
description: It reaches it with a stated limitation (rate, scope, accuracy).
|
|
562
|
+
- value: source-absent
|
|
563
|
+
description: "The provider cannot supply it: nobody's work."
|
|
564
|
+
- value: gateway-gap
|
|
565
|
+
description: "The provider can and this integration does not: the integration's work."
|
|
566
|
+
- value: not-applicable
|
|
567
|
+
description: The item does not apply to this integration.
|
|
568
|
+
description: "What an integration states about a data item (M-ADR 0216 §4.2). unknown is NOT a member: it is the reading of no row."
|
|
569
|
+
supply_basis:
|
|
570
|
+
values:
|
|
571
|
+
- value: code
|
|
572
|
+
description: Read from the integration's code.
|
|
573
|
+
- value: grounded
|
|
574
|
+
description: Grounded in a vendor or source artefact.
|
|
575
|
+
- value: declared
|
|
576
|
+
description: Declared by the integration's own configuration.
|
|
577
|
+
- value: inferred
|
|
578
|
+
description: Inferred, with no artefact stating it.
|
|
579
|
+
description: The evidence class of a supply statement.
|
|
580
|
+
data_necessity:
|
|
581
|
+
values:
|
|
582
|
+
- value: required
|
|
583
|
+
description: The feature cannot work without it (or without one member of its alternative_group).
|
|
584
|
+
- value: enhances
|
|
585
|
+
description: The feature works without it, less well. Never decides coverage.
|
|
586
|
+
description: How a feature needs a data item.
|
|
587
|
+
support_verdict:
|
|
588
|
+
values:
|
|
589
|
+
- value: supported
|
|
590
|
+
description: Every requirement is met.
|
|
591
|
+
- value: partial
|
|
592
|
+
description: Every requirement is met or partly met, and one only partly.
|
|
593
|
+
- value: unknown
|
|
594
|
+
description: No requirement is unmet, and one is undecided because no supply row exists.
|
|
595
|
+
- value: unsupported
|
|
596
|
+
description: A requirement is unmet; limiting_item_id and limiting_reason name it.
|
|
597
|
+
- value: not-applicable
|
|
598
|
+
description: Every required item is not-applicable to this integration.
|
|
599
|
+
description: Whether one integration supports one feature at the canonical boundary (M-ADR 0216 §4.4).
|
|
600
|
+
limiting_reason:
|
|
601
|
+
values:
|
|
602
|
+
- value: source-absent
|
|
603
|
+
description: "The provider cannot supply the item: nobody's work."
|
|
604
|
+
- value: gateway-gap
|
|
605
|
+
description: "The integration does not supply what the provider has: the integration's work."
|
|
606
|
+
- value: no-canonical-home
|
|
607
|
+
description: "The platform has no canonical field for the item: platform contract work."
|
|
608
|
+
description: Why an unsupported feature is unsupported, and so whose work the gap is.
|
|
491
609
|
catalogues:
|
|
492
610
|
domains:
|
|
493
611
|
primary_key: id
|
|
@@ -875,7 +993,7 @@ catalogues:
|
|
|
875
993
|
- name: domain_id
|
|
876
994
|
type: string
|
|
877
995
|
nullable: true
|
|
878
|
-
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."
|
|
996
|
+
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. External for application- and integration-product SDDs since 3.17.0, as capabilities.domain_id is: an app or integration SDD files its own domain-scoped decisions under a platform-side domain (e.g. integrations) it does not declare, so its build logs an external finding naming the value, and the owning platform's aggregate validates it — and fails there if that platform declares no such domain."
|
|
879
997
|
- name: decision_date
|
|
880
998
|
type: date
|
|
881
999
|
nullable: true
|
|
@@ -905,6 +1023,9 @@ catalogues:
|
|
|
905
1023
|
- column: domain_id
|
|
906
1024
|
references: domains.id
|
|
907
1025
|
nullable: true
|
|
1026
|
+
external_for_profiles:
|
|
1027
|
+
- application-product
|
|
1028
|
+
- integration-product
|
|
908
1029
|
- column: superseded_by_id
|
|
909
1030
|
references: adrs.id
|
|
910
1031
|
nullable: true
|
|
@@ -1670,6 +1791,7 @@ catalogues:
|
|
|
1670
1791
|
- name: profile
|
|
1671
1792
|
type: string
|
|
1672
1793
|
nullable: false
|
|
1794
|
+
description: "DEPRECATED (removal at 4.0.0): not an SDD profile. The per-repo field reused sdd_profile's values to record only whether a mirrored repository is one of the SDD's own components or a supporting one — see repo_scope (M-ADR 0213)."
|
|
1673
1795
|
- name: group
|
|
1674
1796
|
type: string
|
|
1675
1797
|
nullable: true
|
|
@@ -1713,6 +1835,10 @@ catalogues:
|
|
|
1713
1835
|
type: string
|
|
1714
1836
|
nullable: true
|
|
1715
1837
|
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.
|
|
1838
|
+
- name: repo_scope
|
|
1839
|
+
type: string
|
|
1840
|
+
nullable: true
|
|
1841
|
+
description: "Whether the repository is inside the scope of what THIS SDD specifies, from its reverse-metadata.yaml (M-ADR 0213 §4.2): component (part of what the SDD specifies) or support (supports a component without being one). Empty for a repository with no reverse metadata. Its kind is component_type; the SDD's profile is products/applications.profile."
|
|
1716
1842
|
foreign_keys:
|
|
1717
1843
|
- column: domain_id
|
|
1718
1844
|
references: domains.id
|
|
@@ -1722,6 +1848,7 @@ catalogues:
|
|
|
1722
1848
|
nullable: true
|
|
1723
1849
|
column_enums:
|
|
1724
1850
|
component_type: enums.service_type
|
|
1851
|
+
repo_scope: enums.repo_scope
|
|
1725
1852
|
domain_models:
|
|
1726
1853
|
primary_key: id
|
|
1727
1854
|
columns:
|
|
@@ -3279,8 +3406,8 @@ catalogues:
|
|
|
3279
3406
|
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."
|
|
3280
3407
|
column_enums:
|
|
3281
3408
|
target: enums.conformance_target
|
|
3282
|
-
role: enums.
|
|
3283
|
-
lifecycle: enums.
|
|
3409
|
+
role: enums.implementation_role
|
|
3410
|
+
lifecycle: enums.implementation_lifecycle
|
|
3284
3411
|
quality_scores:
|
|
3285
3412
|
primary_key: id
|
|
3286
3413
|
columns:
|
|
@@ -3555,3 +3682,342 @@ catalogues:
|
|
|
3555
3682
|
column_enums:
|
|
3556
3683
|
item_kind: enums.scaffold_item_kind
|
|
3557
3684
|
state: enums.scaffold_item_state
|
|
3685
|
+
implementations:
|
|
3686
|
+
primary_key: id
|
|
3687
|
+
columns:
|
|
3688
|
+
- name: id
|
|
3689
|
+
type: string
|
|
3690
|
+
nullable: false
|
|
3691
|
+
description: The binding's implementation key — the same value every snapshot manifest of this implementation carries as implementation.
|
|
3692
|
+
- name: name
|
|
3693
|
+
type: string
|
|
3694
|
+
nullable: false
|
|
3695
|
+
description: The binding's name key, else the id.
|
|
3696
|
+
- name: spec
|
|
3697
|
+
type: string
|
|
3698
|
+
nullable: false
|
|
3699
|
+
description: The spec this implementation implements — the binding's spec key.
|
|
3700
|
+
- name: snapshot_area
|
|
3701
|
+
type: string
|
|
3702
|
+
nullable: true
|
|
3703
|
+
description: Store-relative path of this implementation's snapshot area (M-ADR 0214 §4.4), from the binding. Empty when the implementation has none.
|
|
3704
|
+
- name: doc_path
|
|
3705
|
+
type: string
|
|
3706
|
+
nullable: false
|
|
3707
|
+
description: Path of the binding file, relative to the SDD root.
|
|
3708
|
+
- name: source_sdd_id
|
|
3709
|
+
type: string
|
|
3710
|
+
nullable: true
|
|
3711
|
+
description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
|
|
3712
|
+
- name: platform_sdd_id
|
|
3713
|
+
type: string
|
|
3714
|
+
nullable: true
|
|
3715
|
+
description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4.
|
|
3716
|
+
description: "An implementation of this SDD's spec: the durable system identity whose snapshots are its versions (M-ADR 0181 §2.5, M-ADR 0214 §4.1). One row per .sdd/implementation-binding.yaml that names its implementation; a binding without an implementation key emits nothing and a finding, because there is no identity to key on."
|
|
3717
|
+
implementation_members:
|
|
3718
|
+
primary_key: id
|
|
3719
|
+
columns:
|
|
3720
|
+
- name: id
|
|
3721
|
+
type: string
|
|
3722
|
+
nullable: false
|
|
3723
|
+
description: <implementation_id>::<repo_key>.
|
|
3724
|
+
- name: implementation_id
|
|
3725
|
+
type: string
|
|
3726
|
+
nullable: false
|
|
3727
|
+
- name: repo_id
|
|
3728
|
+
type: string
|
|
3729
|
+
nullable: true
|
|
3730
|
+
description: The member's repository when it resolves in this SDD's repositories. Empty for a planned member whose repository does not exist yet; a member of any other lifecycle that does not resolve is a builder finding.
|
|
3731
|
+
- name: repo_key
|
|
3732
|
+
type: string
|
|
3733
|
+
nullable: false
|
|
3734
|
+
description: The repository the binding names (its member repo key), resolved or not.
|
|
3735
|
+
- name: role
|
|
3736
|
+
type: string
|
|
3737
|
+
nullable: true
|
|
3738
|
+
- name: lifecycle
|
|
3739
|
+
type: string
|
|
3740
|
+
nullable: true
|
|
3741
|
+
- name: evidence_direction
|
|
3742
|
+
type: string
|
|
3743
|
+
nullable: true
|
|
3744
|
+
description: How this member is evidenced (M-ADR 0180 §2.1, placed on the member by M-ADR 0181 §2.1). Empty when the binding does not say.
|
|
3745
|
+
- name: source_sdd_id
|
|
3746
|
+
type: string
|
|
3747
|
+
nullable: true
|
|
3748
|
+
description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
|
|
3749
|
+
- name: platform_sdd_id
|
|
3750
|
+
type: string
|
|
3751
|
+
nullable: true
|
|
3752
|
+
description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4.
|
|
3753
|
+
description: "Edge: a repository is a member of an implementation, with the member's role, lifecycle and evidence direction (M-ADR 0181 §2.1, M-ADR 0214 §4.2). Role and lifecycle live here once: repo_capability, repo_contract and feature_repo resolve their repository to this row rather than copying them (M-ADR 0214 §4.3). Membership is independent of the repository's repo_scope (M-ADR 0213): a shared library under conformance checks is a support member."
|
|
3754
|
+
foreign_keys:
|
|
3755
|
+
- column: implementation_id
|
|
3756
|
+
references: implementations.id
|
|
3757
|
+
nullable: false
|
|
3758
|
+
- column: repo_id
|
|
3759
|
+
references: repositories.id
|
|
3760
|
+
nullable: true
|
|
3761
|
+
column_enums:
|
|
3762
|
+
role: enums.implementation_role
|
|
3763
|
+
lifecycle: enums.implementation_lifecycle
|
|
3764
|
+
evidence_direction: enums.evidence_direction
|
|
3765
|
+
snapshots:
|
|
3766
|
+
primary_key: id
|
|
3767
|
+
columns:
|
|
3768
|
+
- name: id
|
|
3769
|
+
type: string
|
|
3770
|
+
nullable: false
|
|
3771
|
+
description: <implementation_id>@<baseline_id>.
|
|
3772
|
+
- name: implementation_id
|
|
3773
|
+
type: string
|
|
3774
|
+
nullable: false
|
|
3775
|
+
- name: baseline_id
|
|
3776
|
+
type: string
|
|
3777
|
+
nullable: false
|
|
3778
|
+
description: The observation date (YYYY-MM-DD) — the baseline folder and the manifest's snapshot_id.
|
|
3779
|
+
- name: prior_snapshot_id
|
|
3780
|
+
type: string
|
|
3781
|
+
nullable: true
|
|
3782
|
+
description: The snapshot this one was diffed from — <implementation_id>@<prior_snapshot>. Empty for the first.
|
|
3783
|
+
- name: credential_scan_result
|
|
3784
|
+
type: string
|
|
3785
|
+
nullable: true
|
|
3786
|
+
description: The manifest's credential_scan.result (clean, or what was found). Empty when no scan is recorded.
|
|
3787
|
+
- name: source_sdd_id
|
|
3788
|
+
type: string
|
|
3789
|
+
nullable: true
|
|
3790
|
+
description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
|
|
3791
|
+
- name: platform_sdd_id
|
|
3792
|
+
type: string
|
|
3793
|
+
nullable: true
|
|
3794
|
+
description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4.
|
|
3795
|
+
description: One implementation's member set pinned at one observation (M-ADR 0181 §2.5, M-ADR 0214 §4.4). One row per dated baseline in the implementation's snapshot area whose snapshot.yaml names the same implementation. Needs the snapshot store root (build --snapshot-store or SDD_SNAPSHOT_STORE); without it the catalogue is empty and the build says so.
|
|
3796
|
+
foreign_keys:
|
|
3797
|
+
- column: implementation_id
|
|
3798
|
+
references: implementations.id
|
|
3799
|
+
nullable: false
|
|
3800
|
+
- column: prior_snapshot_id
|
|
3801
|
+
references: snapshots.id
|
|
3802
|
+
nullable: true
|
|
3803
|
+
snapshot_members:
|
|
3804
|
+
primary_key: id
|
|
3805
|
+
columns:
|
|
3806
|
+
- name: id
|
|
3807
|
+
type: string
|
|
3808
|
+
nullable: false
|
|
3809
|
+
description: <snapshot_id>::<repo_key>.
|
|
3810
|
+
- name: snapshot_id
|
|
3811
|
+
type: string
|
|
3812
|
+
nullable: false
|
|
3813
|
+
- name: repo_id
|
|
3814
|
+
type: string
|
|
3815
|
+
nullable: true
|
|
3816
|
+
description: The member's repository when it resolves in this SDD's repositories; empty otherwise (a removed member's repository may be gone).
|
|
3817
|
+
- name: repo_key
|
|
3818
|
+
type: string
|
|
3819
|
+
nullable: false
|
|
3820
|
+
description: The manifest's canonical_repo_key.
|
|
3821
|
+
- name: source_revision
|
|
3822
|
+
type: string
|
|
3823
|
+
nullable: false
|
|
3824
|
+
description: The revision observed (for a removed member, its last revision).
|
|
3825
|
+
- name: observed_at
|
|
3826
|
+
type: string
|
|
3827
|
+
nullable: true
|
|
3828
|
+
description: "The member's own observation date: the baseline's for an observed member, the earlier one for a carried member, the last observed for a removed one."
|
|
3829
|
+
- name: presence
|
|
3830
|
+
type: string
|
|
3831
|
+
nullable: false
|
|
3832
|
+
- name: source_sdd_id
|
|
3833
|
+
type: string
|
|
3834
|
+
nullable: true
|
|
3835
|
+
description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
|
|
3836
|
+
- name: platform_sdd_id
|
|
3837
|
+
type: string
|
|
3838
|
+
nullable: true
|
|
3839
|
+
description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4.
|
|
3840
|
+
description: "Edge: a repository at one revision in one snapshot, with its presence — observed in this baseline, carried from an earlier one, or removed since the prior (M-ADR 0214 §4.4)."
|
|
3841
|
+
foreign_keys:
|
|
3842
|
+
- column: snapshot_id
|
|
3843
|
+
references: snapshots.id
|
|
3844
|
+
nullable: false
|
|
3845
|
+
- column: repo_id
|
|
3846
|
+
references: repositories.id
|
|
3847
|
+
nullable: true
|
|
3848
|
+
column_enums:
|
|
3849
|
+
presence: enums.member_presence
|
|
3850
|
+
data_items:
|
|
3851
|
+
primary_key: id
|
|
3852
|
+
columns:
|
|
3853
|
+
- name: id
|
|
3854
|
+
type: string
|
|
3855
|
+
nullable: false
|
|
3856
|
+
description: di.<category>.<name>, e.g. di.motion.speed.
|
|
3857
|
+
- name: name
|
|
3858
|
+
type: string
|
|
3859
|
+
nullable: false
|
|
3860
|
+
- name: category
|
|
3861
|
+
type: string
|
|
3862
|
+
nullable: false
|
|
3863
|
+
description: Open grouping (motion, behaviour, tyre, energy, …).
|
|
3864
|
+
- name: canonical_field
|
|
3865
|
+
type: string
|
|
3866
|
+
nullable: true
|
|
3867
|
+
description: The integration-facing canonical contract field that carries the item. EMPTY means the platform has no canonical home for it, and coverage reads every requirement on it as unmet (no-canonical-home).
|
|
3868
|
+
- name: description
|
|
3869
|
+
type: string
|
|
3870
|
+
nullable: true
|
|
3871
|
+
- name: source_sdd_id
|
|
3872
|
+
type: string
|
|
3873
|
+
nullable: true
|
|
3874
|
+
description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
|
|
3875
|
+
- name: platform_sdd_id
|
|
3876
|
+
type: string
|
|
3877
|
+
nullable: true
|
|
3878
|
+
description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator (M-ADR 0208 §4.4).
|
|
3879
|
+
description: "A unit of data an integration may supply and a feature may need, at the canonical boundary (M-ADR 0216 §4.1). Platform-owned, like events. Not a wire signal: payload grammar stays adopter territory."
|
|
3880
|
+
integration_data_item:
|
|
3881
|
+
primary_key: id
|
|
3882
|
+
columns:
|
|
3883
|
+
- name: id
|
|
3884
|
+
type: string
|
|
3885
|
+
nullable: false
|
|
3886
|
+
description: <integration_id>::<data_item_id>::<evidence_ref>.
|
|
3887
|
+
- name: integration_id
|
|
3888
|
+
type: string
|
|
3889
|
+
nullable: false
|
|
3890
|
+
- name: data_item_id
|
|
3891
|
+
type: string
|
|
3892
|
+
nullable: false
|
|
3893
|
+
- name: verdict
|
|
3894
|
+
type: string
|
|
3895
|
+
nullable: false
|
|
3896
|
+
description: Bound to supply_verdict. A mapping-table row is supported, or partial when its Notes begin with partial; the Data Items Not Supplied section carries the rest.
|
|
3897
|
+
- name: basis
|
|
3898
|
+
type: string
|
|
3899
|
+
nullable: true
|
|
3900
|
+
description: "Bound to supply_basis: the evidence class of the statement."
|
|
3901
|
+
- name: evidence_ref
|
|
3902
|
+
type: string
|
|
3903
|
+
nullable: false
|
|
3904
|
+
description: Path and line of the statement.
|
|
3905
|
+
- name: checked_at
|
|
3906
|
+
type: string
|
|
3907
|
+
nullable: true
|
|
3908
|
+
description: "The governing Checked: line of the section, verbatim (a date, or a source revision). Reported for age; never read as a verdict."
|
|
3909
|
+
- name: source_sdd_id
|
|
3910
|
+
type: string
|
|
3911
|
+
nullable: true
|
|
3912
|
+
description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
|
|
3913
|
+
- name: platform_sdd_id
|
|
3914
|
+
type: string
|
|
3915
|
+
nullable: true
|
|
3916
|
+
description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator (M-ADR 0208 §4.4).
|
|
3917
|
+
description: "Supply: what one integration states about one data item, from its feature-grounding (M-ADR 0216 §4.2). Several rows per item are normal (one per evidence_ref); coverage reads the best. No row reads unknown, and unknown is never written."
|
|
3918
|
+
foreign_keys:
|
|
3919
|
+
- column: integration_id
|
|
3920
|
+
references: integrations.id
|
|
3921
|
+
nullable: false
|
|
3922
|
+
- column: data_item_id
|
|
3923
|
+
references: data_items.id
|
|
3924
|
+
nullable: false
|
|
3925
|
+
external_for_profiles:
|
|
3926
|
+
- application-product
|
|
3927
|
+
- integration-product
|
|
3928
|
+
column_enums:
|
|
3929
|
+
verdict: enums.supply_verdict
|
|
3930
|
+
basis: enums.supply_basis
|
|
3931
|
+
feature_data_requirement:
|
|
3932
|
+
primary_key: id
|
|
3933
|
+
columns:
|
|
3934
|
+
- name: id
|
|
3935
|
+
type: string
|
|
3936
|
+
nullable: false
|
|
3937
|
+
description: <feature_id>::<data_item_id>.
|
|
3938
|
+
- name: feature_id
|
|
3939
|
+
type: string
|
|
3940
|
+
nullable: false
|
|
3941
|
+
- name: data_item_id
|
|
3942
|
+
type: string
|
|
3943
|
+
nullable: false
|
|
3944
|
+
- name: necessity
|
|
3945
|
+
type: string
|
|
3946
|
+
nullable: false
|
|
3947
|
+
description: Bound to data_necessity.
|
|
3948
|
+
- name: alternative_group
|
|
3949
|
+
type: string
|
|
3950
|
+
nullable: true
|
|
3951
|
+
description: "Empty, or a label: required rows sharing a label are satisfied by any one of them."
|
|
3952
|
+
- name: basis_ref
|
|
3953
|
+
type: string
|
|
3954
|
+
nullable: true
|
|
3955
|
+
description: Where the need is stated (path and line).
|
|
3956
|
+
- name: source_sdd_id
|
|
3957
|
+
type: string
|
|
3958
|
+
nullable: true
|
|
3959
|
+
description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
|
|
3960
|
+
- name: platform_sdd_id
|
|
3961
|
+
type: string
|
|
3962
|
+
nullable: true
|
|
3963
|
+
description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator (M-ADR 0208 §4.4).
|
|
3964
|
+
description: "Demand: a data item one feature needs, from the feature spec's Data Requirements table (M-ADR 0216 §4.3). Feature grain only: a capability's need is the union of its features'."
|
|
3965
|
+
foreign_keys:
|
|
3966
|
+
- column: feature_id
|
|
3967
|
+
references: features.id
|
|
3968
|
+
nullable: false
|
|
3969
|
+
- column: data_item_id
|
|
3970
|
+
references: data_items.id
|
|
3971
|
+
nullable: false
|
|
3972
|
+
external_for_profiles:
|
|
3973
|
+
- application-product
|
|
3974
|
+
- integration-product
|
|
3975
|
+
column_enums:
|
|
3976
|
+
necessity: enums.data_necessity
|
|
3977
|
+
feature_integration_support:
|
|
3978
|
+
primary_key: id
|
|
3979
|
+
columns:
|
|
3980
|
+
- name: id
|
|
3981
|
+
type: string
|
|
3982
|
+
nullable: false
|
|
3983
|
+
description: <feature_id>::<integration_id>.
|
|
3984
|
+
- name: feature_id
|
|
3985
|
+
type: string
|
|
3986
|
+
nullable: false
|
|
3987
|
+
- name: integration_id
|
|
3988
|
+
type: string
|
|
3989
|
+
nullable: false
|
|
3990
|
+
- name: verdict
|
|
3991
|
+
type: string
|
|
3992
|
+
nullable: false
|
|
3993
|
+
description: "Bound to support_verdict. Each requirement is decided first (an alternative_group is unmet only when every member is); the feature takes the worst: unsupported > unknown > partial > supported. not-applicable only when every required item is."
|
|
3994
|
+
- name: limiting_item_id
|
|
3995
|
+
type: string
|
|
3996
|
+
nullable: true
|
|
3997
|
+
description: "For unsupported: the deciding requirement's item. Empty otherwise."
|
|
3998
|
+
- name: limiting_reason
|
|
3999
|
+
type: string
|
|
4000
|
+
nullable: true
|
|
4001
|
+
description: "For unsupported: bound to limiting_reason. Empty otherwise."
|
|
4002
|
+
- name: source_sdd_id
|
|
4003
|
+
type: string
|
|
4004
|
+
nullable: true
|
|
4005
|
+
description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
|
|
4006
|
+
- name: platform_sdd_id
|
|
4007
|
+
type: string
|
|
4008
|
+
nullable: true
|
|
4009
|
+
description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator (M-ADR 0208 §4.4).
|
|
4010
|
+
description: "Coverage: whether one integration can support one feature, DERIVED at aggregation from supply and demand (M-ADR 0216 §4.4); empty in a member build. SUPPORTED MEANS THE ITEMS REACH THE CANONICAL BOUNDARY, NOT THAT THE FEATURE WORKS END TO END: routing past that boundary is not checked."
|
|
4011
|
+
foreign_keys:
|
|
4012
|
+
- column: feature_id
|
|
4013
|
+
references: features.id
|
|
4014
|
+
nullable: false
|
|
4015
|
+
- column: integration_id
|
|
4016
|
+
references: integrations.id
|
|
4017
|
+
nullable: false
|
|
4018
|
+
- column: limiting_item_id
|
|
4019
|
+
references: data_items.id
|
|
4020
|
+
nullable: true
|
|
4021
|
+
column_enums:
|
|
4022
|
+
verdict: enums.support_verdict
|
|
4023
|
+
limiting_reason: enums.limiting_reason
|
|
@@ -78,6 +78,9 @@ export function renderRepoCapability(findings, metrics) {
|
|
|
78
78
|
}));
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
+
if (metrics.total === 0 && findings.length === 0) {
|
|
82
|
+
lines.push(`[metric] repo_capability_resolution: n/a — 0 repository rows, nothing to resolve`);
|
|
83
|
+
}
|
|
81
84
|
if (metrics.total > 0) {
|
|
82
85
|
const resolved = metrics.byCapability + metrics.byExemption;
|
|
83
86
|
const pct = fmt1f((100.0 * resolved) / metrics.total);
|
|
@@ -125,6 +128,9 @@ export function renderServiceCapability(findings, metrics, tier) {
|
|
|
125
128
|
`capability_service.csv); check the aggregate next${leverageNote(f)}`);
|
|
126
129
|
}
|
|
127
130
|
}
|
|
131
|
+
if (metrics.total === 0 && findings.length === 0) {
|
|
132
|
+
lines.push(`[metric] service_capability_resolution (tier=${tier}): n/a — 0 service rows, nothing to resolve`);
|
|
133
|
+
}
|
|
128
134
|
if (metrics.total > 0) {
|
|
129
135
|
const resolved = metrics.claimed + metrics.exempt;
|
|
130
136
|
const pct = fmt1f((100.0 * resolved) / metrics.total);
|
|
@@ -426,6 +432,14 @@ export function renderScoresCoverage(res, tier) {
|
|
|
426
432
|
`catalogue row — the assessment describes something the model no longer ` +
|
|
427
433
|
`holds; re-key the registry entry or withdraw the score`);
|
|
428
434
|
}
|
|
435
|
+
else if (f.kind === "recorded-path-mismatch") {
|
|
436
|
+
// COVERAGE class — report-only by ruling (decision #3, 2026-09-29): it
|
|
437
|
+
// becomes gate-acting only once both estates read zero, and that is a
|
|
438
|
+
// deliberate later change to this one word, as for orphaned-score above.
|
|
439
|
+
out.push(`[finding] coverage: ${f.rubricId} score for ${f.subject} — the recorded file ` +
|
|
440
|
+
`is not the target's catalogue path, so the assessment may describe a copy the ` +
|
|
441
|
+
`catalogue cannot see; re-score against the catalogue path or re-point file_path`);
|
|
442
|
+
}
|
|
429
443
|
else {
|
|
430
444
|
out.push(`[finding] coverage: ${f.subject}`);
|
|
431
445
|
}
|
|
@@ -470,6 +484,22 @@ export function renderScoresCoverage(res, tier) {
|
|
|
470
484
|
out.push(`[metric] scores_coverage.${m.rubricId}: ${m.covered}/${m.eligible} ` +
|
|
471
485
|
`${m.targetKind}(s) scored, ${m.scored} score(s) present, ${m.orphaned} orphaned`);
|
|
472
486
|
}
|
|
487
|
+
// Recorded-path check (decision #3): stated for every rubric with scores,
|
|
488
|
+
// including the ones it cannot check — n/a is named, never read as agreement.
|
|
489
|
+
const scoredMetrics = res.metrics.filter((m) => m.scored > 0);
|
|
490
|
+
const checkable = scoredMetrics.filter((m) => m.recordedPath !== null);
|
|
491
|
+
const notCheckable = scoredMetrics.filter((m) => m.recordedPath === null);
|
|
492
|
+
if (scoredMetrics.length > 0) {
|
|
493
|
+
const sum = (k) => checkable.reduce((a, m) => a + (m.recordedPath?.[k] ?? 0), 0);
|
|
494
|
+
out.push(`[metric] scores_coverage.recorded_path: ${sum("agree")} agree, ${sum("mismatch")} mismatch, ` +
|
|
495
|
+
`${sum("noRecordedPath")} with no recorded path — across ${checkable.length} rubric(s) whose ` +
|
|
496
|
+
`catalogue holds the scored file's path` +
|
|
497
|
+
(notCheckable.length > 0
|
|
498
|
+
? `; n/a for ${notCheckable.length} (${notCheckable.map((m) => m.rubricId).join(", ")}) — ` +
|
|
499
|
+
`the catalogue does not hold the path of the file those rubrics score`
|
|
500
|
+
: "") +
|
|
501
|
+
` (report-only; a path filled in from the catalogue agrees by construction)`);
|
|
502
|
+
}
|
|
473
503
|
// The excluded population is printed BESIDE the denominator it shrank, never
|
|
474
504
|
// folded into it. A reader comparing this run against a pre-filter baseline
|
|
475
505
|
// must be able to see why the denominator moved without re-deriving it, and
|