feat(vocabulary): Domain Vocabulary — identity vs representation; regulation aliases fix the KPI normalization

Before the next Journey: the LANGUAGE. With 5 knowledge objects but no vocabulary, the same reise gets
named four different ways (ISO9001->MaschinenVO vs Quality Management->Product Safety vs ...). The spec
answers ONE question: which terms are IDENTITIES and which are REPRESENTATIONS of the same meaning?

- spec docs-src/architecture/domain-vocabulary-spec-v1.md (PROPOSAL): identity hierarchy
  (Requirement RQ / Capability MCAP [Registry 2C] / regulation-source-target / Journey Class MJRN
  [PROVISIONAL] / Journey instance / Playbook MPLB); canonical name + aliases; capability vocabulary =
  the Capability Registry (not rebuilt); reorder Vocabulary -> Transition #2 -> #3 -> Rule of Three.
- knowledge/vocabulary/regulations.yaml: regulation/standard IDENTITIES (id + canonical + aliases).
  SOLVES the regulation-ID normalization the KPIs flagged: CRA == "Cyber Resilience Act" == "Regulation
  (EU) 2024/2847" all resolve to `cra`; ISO9001/QMS -> iso9001; etc. Shared artifact (@Legal-KG/@Execution
  please adopt).
- knowledge/vocabulary/journey_classes.yaml (PROVISIONAL): clusters our transitions into classes
  (Information Security -> Product Cybersecurity; Quality Management -> Product Compliance/Safety).
  Finding: ISO9001->MaschinenVO is an INSTANCE of an existing class (like ISO9001->CRA, ISO13485->MDR),
  not a new kind -> avoids duplication. Journey Class is a new abstraction -> its own Rule of Three (no
  MJRN minting yet).
- reference suite: both KPIs now read aliases from regulations.yaml instead of hard-coded maps; the
  "Regelwerk-ID-Normalisierung" line flips TODO -> PASS. KPI numbers unchanged (vocab is a superset).
- Side effect = Requirements Intelligence: a Tender "Security Patch Procedure" resolves to MCAP-0017.

7 vocabulary tests (17 with domain programs), check-loc 0. Knowledge data + spec + reference harness =
non-runtime -> no deploy (ADR-001). No new module, no runtime change, no minting (Freeze).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-06-28 08:11:30 +02:00
parent 23a6f02ec2
commit ecae5bc7f1
6 changed files with 239 additions and 10 deletions
@@ -141,6 +141,25 @@ def completeness_section() -> None:
])
def _regulation_aliases(base_dir):
"""Build a normalized alias -> canonical-id map from the Domain Vocabulary (regulations.yaml)."""
import os
import yaml
path = os.path.join(base_dir, "..", "knowledge", "vocabulary", "regulations.yaml")
amap = {}
with open(path, encoding="utf-8") as h:
for r in (yaml.safe_load(h) or {}).get("regulations", []):
for name in [r["canonical"]] + list(r.get("aliases", [])):
amap["".join(c for c in str(name).lower() if c.isalnum())] = r["id"]
return amap
def _canon_reg(s, amap):
"""Canonicalize a regulation string via the vocabulary (replaces the old hard-coded alias maps)."""
return amap.get("".join(c for c in str(s).lower() if c.isalnum()),
"".join(c for c in str(s).lower() if c.isalnum()))
def domain_programs_section(base_dir) -> None:
"""Domain Knowledge Program v1 — per-domain maturity KPI DERIVED from the corpus (computed-not-stored)."""
import os
@@ -159,11 +178,10 @@ def domain_programs_section(base_dir) -> None:
for f in sorted(os.listdir(pdir)) if f.endswith(".yaml")]
progs = sorted((p for p in _all if "backlog_rank" in p), key=lambda p: p["backlog_rank"]) # domain programs only
_ALIAS = {"cyber resilience act": "cra", "maschinenverordnung": "maschinenvo", "iatf": "iatf16949"}
_amap = _regulation_aliases(base_dir) # Domain Vocabulary (regulations.yaml)
def _canon(r):
k = str(r).strip().lower()
return _ALIAS.get(k, k)
return _canon_reg(r, _amap)
def _hits(reg_lists, src):
cs = {_canon(s) for s in src}
@@ -199,7 +217,7 @@ def domain_programs_section(base_dir) -> None:
coverage_table([
("Domain Knowledge Program (7-Stufen-Produktionsstraße)", "PASS", "%d Domänen im Backlog, Industrial Automation #1" % len(progs)),
("Reifegrad-KPI (computed-not-stored)", "PASS", "aus echtem Korpus abgeleitet (TP/PB/RTS je Domäne)"),
("Regelwerk-ID-Normalisierung", "TODO", "Alias CRA/MaschinenVO im KPI — kanonische IDs ausstehend"),
("Regelwerk-ID-Normalisierung (Domain Vocabulary)", "PASS", "Aliase aus `vocabulary/regulations.yaml`, nicht mehr hartkodiert"),
])
@@ -224,12 +242,10 @@ def transition_coverage_section(base_dir) -> None:
for it in (to if isinstance(to, list) else [to]) if isinstance(it, dict)]
pats.append((frm, [t for t in tos if t], str(d.get("status", "draft"))))
_ALIAS = {"isoiec27001": "iso27001", "isoiec62443": "iec62443",
"cyberresilienceact": "cra", "maschinenverordnung": "maschinenvo"}
_amap = _regulation_aliases(base_dir) # Domain Vocabulary (regulations.yaml)
def _c(s):
k = "".join(ch for ch in str(s).lower() if ch.isalnum())
return _ALIAS.get(k, k)
return _canon_reg(s, _amap)
_RANK = {"draft": 1, "reviewed": 2, "validated": 3, "proven": 4}
_ICON = {0: "⚪ nicht begonnen", 1: "🟡 Draft", 2: "✅ reviewed", 3: "✅ validated", 4: "✅ Gold"}