Files
breakpilot-compliance/backend-compliance/tests/test_certification_hypotheses.py
T
Benjamin Admin 2d2cb2a244 feat: Certification Capability Hypotheses — capability-centric library + empirical confidence
The bottleneck is knowledge, not the endpoint. This builds the knowledge the Onboarding Advisor needs,
restructured per the user's key insight: NOT "ISO27001 -> 30 capabilities" but each hypothesis as its
own object "capability -> supported_by: [certs]". A capability is written ONCE with all supporting
certs, so the shared management-system core (document control, incident, supplier, audit, access,
asset, monitoring, training, crypto, release, risk) covers most certifications with ~18 hypotheses
instead of ~300 — and multi-certification merges AUTOMATICALLY (a company's inferred caps = every
hypothesis whose supported_by intersects its certs).

Welt-1 throughout: "IF cert present, EXPECT capability (verification required)", never "erfüllt".
Capabilities NO cert suggests (SBOM, signed updates, CVD, support period) have no hypothesis -> they
stay in the delta and get asked. confidence is EMPIRICAL: computed from real-onboarding observations
(confirmed/(confirmed+refuted)), None until calibrated — never an LLM/expert score (record_observation
+ empirical_confidence). The long-term moat: knowledge that learns from reality, not from a norm.

compliance/onboarding/hypotheses.py (resolve_for_certifications / inferred_hypotheses / empirical_
confidence / record_observation) feeds the existing advisor_start unchanged; the demo now runs on the
curated library. Pure, mypy --strict clean, library is DATA (no norm text, no real names). Non-runtime
-> no deploy. 12 tests pass, check-loc 0.
2026-06-28 13:16:45 +02:00

76 lines
3.6 KiB
Python

"""Certification Capability Hypotheses — capability-centric library + empirical confidence.
Pins the reuse design (one capability, many supporting certs -> ~40-60 hypotheses, not ~300), the
automatic multi-certification merge, the empirical (computed) confidence loop, and the Welt-1 guarantee
that capabilities NO cert suggests (SBOM, signed updates, CVD) are never inferred -> they stay in the
delta and get asked. Then the Advisor consumes the resolved library end-to-end.
"""
from __future__ import annotations
import os
import yaml
from compliance.onboarding import (
CapabilityHypothesis,
HypothesisObservations,
OnboardingInput,
advisor_start,
empirical_confidence,
inferred_hypotheses,
record_observation,
resolve_for_certifications,
)
from compliance.transition_reasoning import TargetRequirement
_DIR = os.path.dirname(__file__)
_LIB = [CapabilityHypothesis(**h) for h in yaml.safe_load(
open(os.path.join(_DIR, "..", "knowledge", "certification_hypotheses", "hypotheses.yaml"), encoding="utf-8"))["hypotheses"]]
def test_library_is_capability_centric_and_reuses_certs():
# the shared core is small (reuse, not 30-per-cert) and document control is supported by many certs
doc = next(h for h in _LIB if h.capability == "document_and_change_control")
assert len(doc.supported_by) >= 4
assert len(_LIB) <= 60 # whole library, not ~300
def test_multi_certification_merges_automatically():
# a company with ISO9001 + ISO14001 + TISAX gets the UNION of their hypotheses, deduped
merged = inferred_hypotheses(["ISO9001", "ISO14001", "TISAX"], _LIB)
caps = {h.capability for h in merged}
assert "document_and_change_control" in caps # ISO9001 + TISAX
assert "information_security_management" in caps # TISAX
assert "environmental_management_documentation" in caps # ISO14001
# SBOM / signed updates are suggested by NO certificate -> never inferred
assert "sbom_creation" not in caps and "secure_signed_update_distribution" not in caps
def test_empirical_confidence_is_computed_not_assigned():
obs = HypothesisObservations()
assert empirical_confidence(obs) is None # null until observed
obs = record_observation(obs, True)
obs = record_observation(obs, True)
obs = record_observation(obs, False)
assert empirical_confidence(obs) == 0.67 # 2 / 3, from observations only
def test_resolve_adapts_to_advisor_input():
res = resolve_for_certifications(["ISO27001", "ISO9001"], _LIB)
assert "incident_management" in res["ISO27001"]
assert "document_and_change_control" in res["ISO9001"]
def test_advisor_consumes_the_library_end_to_end():
cra = yaml.safe_load(open(os.path.join(_DIR, "..", "knowledge", "transition_patterns",
"transition_pattern_iso27001_to_cra_maschinenvo_v1.yaml"), encoding="utf-8"))
req = [TargetRequirement(capability_id=a["capability"]) for a in cra["likely_covered"]]
req += [TargetRequirement(capability_id=d["capability"], expected_evidence=d.get("expected_evidence", []))
for d in cra["delta_requirements"]]
inp = OnboardingInput(company="x", certifications=["ISO27001", "TISAX", "ISO9001", "ISO14001"], target=["CRA"])
hyp = resolve_for_certifications(inp.certifications, _LIB) # library -> advisor input
res = advisor_start(inp, hyp, req, target_id="CRA", corpus_status={"CRA": "validated"})
assert res.inferred_assumptions and res.next_best_questions
assert any(r.certification == "ISO14001" for r in res.rejected_assumptions) # not relevant to CRA