66be23f0c4
The first multi-regulation pattern: each capability declares `covers_targets`, so we can answer the convergence USP — "which capability satisfies CRA AND MaschinenVO at once?" - knowledge: transition_pattern_iso27001_to_cra_maschinenvo_v1.yaml (pattern_type: regulatory_convergence, status draft). The cyber-safety bridge = MaschinenVO Annex III 1.1.9 "protection against corruption" overlapping CRA integrity. 4 convergence capabilities cover BOTH; 5 CRA-only; 3 MaschinenVO-only. - product: compliance/transition_reasoning/convergence.py — regulatory_convergence() pure/deterministic/computed-not-stored, no new graph/class (freeze v1.0 untouched). No app caller yet -> non-runtime, no deploy (ADR-001). - reference suite: Cross-Regulation Capability Mapping section renders the customer sentence "von N neuen Massnahmen erfuellen M gleichzeitig CRA und MaschinenVO". - README: term -> Regulatory Transition / Convergence Pattern; covers_targets documented. - tests: test_regulatory_convergence (18 transition+company pass), mypy --strict clean. Curated expert knowledge, AI first draft (L1/draft) — Annex/Article refs indicative, review_required by a machinery-safety expert. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
55 lines
2.1 KiB
Python
55 lines
2.1 KiB
Python
"""Cross-Regulation Capability Mapping (Regulatory Convergence) — RS-005.
|
|
|
|
Answers the USP question: „Welche Capability deckt gleichzeitig mehrere Regelwerke ab?"
|
|
Given, per capability, the set of target regulations it covers (`covers_targets`,
|
|
curated knowledge from a Regulatory Convergence Pattern), it computes how many
|
|
capabilities cover >= 2 regulations at once — the basis for the customer sentence
|
|
„von N Maßnahmen decken M gleichzeitig CRA und MaschinenVO".
|
|
|
|
Pure, deterministic, computed-not-stored. No new graph/base class/meta-model class
|
|
(freeze v1.0 untouched). Python 3.9 compatible (no `|` unions).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Dict, List
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class RegulatoryConvergence(BaseModel):
|
|
targets: List[str] = Field(default_factory=list)
|
|
per_target_count: Dict[str, int] = Field(default_factory=dict) # capabilities each target requires
|
|
multi_target_capabilities: List[str] = Field(default_factory=list) # cover >= 2 targets
|
|
single_target_capabilities: List[str] = Field(default_factory=list)
|
|
headline: str = "" # NO percentages
|
|
|
|
|
|
def regulatory_convergence(
|
|
capability_targets: Dict[str, List[str]], targets: List[str]
|
|
) -> RegulatoryConvergence:
|
|
"""capability_targets: capability_id -> regulations it covers. `targets`: the regulations in scope."""
|
|
target_set = set(targets)
|
|
per: Dict[str, int] = {t: 0 for t in targets}
|
|
multi: List[str] = []
|
|
single: List[str] = []
|
|
for cap, covers in capability_targets.items():
|
|
in_scope = [t for t in covers if t in target_set]
|
|
for t in in_scope:
|
|
per[t] += 1
|
|
if len(in_scope) >= 2:
|
|
multi.append(cap)
|
|
elif len(in_scope) == 1:
|
|
single.append(cap)
|
|
headline = (
|
|
"%d von %d Capabilities decken >= 2 Regelwerke gleichzeitig ab (%s)."
|
|
% (len(multi), len(capability_targets), " + ".join(targets))
|
|
)
|
|
return RegulatoryConvergence(
|
|
targets=list(targets),
|
|
per_target_count=per,
|
|
multi_target_capabilities=sorted(multi),
|
|
single_target_capabilities=sorted(single),
|
|
headline=headline,
|
|
)
|