feat: Environmental stress test — the architecture works OUTSIDE cyber (Phase Ω, data-only)

First NON-cyber stress test. Every prior journey was cyber (infosec/software/product security).
Environmental brings a completely different mental model (substance flows, emissions, water,
chemicals, energy, circularity). The claim under test: RS-005 carries it UNCHANGED — only new DATA,
zero runtime code.

ISO 14001 (an EMS) is modelled as a Company Profile and run through the SAME engines as ISO 27001 ->
CRA (new pattern transition_pattern_iso14001_to_environmental_v1.yaml, capabilities as VERBS):
  - ISO 14001 yields 5 environmental MANAGEMENT capabilities (Welt-1, probably present)
  - the concrete substance/emission/water/material EVIDENCE is the 11-capability delta
  - rejected_assumptions state what ISO 14001 does NOT produce (substance lists, REACH, emissions,
    battery passports, water analyses) — preserving the Welt-1/Welt-2 separation
  - the Journey Matcher stays domain-agnostic: ISO14001->Environmental 100%, cyber journeys 0%

Result: a non-cyber domain ran through Reality -> ... -> Journey with 0 new runtime classes and 0
new pipeline — a stronger generality proof than ten more cyber regulations.

Also extends the Architecture Stability ledger with the third KPI column the user requested — "new
capability types" — as a granularity Frühindikator (a domain needing ~80 new types at 0 runtime would
flag a too-coarse/too-fine capability model). Environmental = 16 types (5 mgmt + 11 evidence), in
range. Ledger now flags cyber vs non_cyber family. Non-runtime -> no deploy. 19 tests pass, check-loc 0.
This commit is contained in:
Benjamin Admin
2026-06-28 11:10:07 +02:00
parent 2805256c33
commit fbbd0957bd
8 changed files with 382 additions and 19 deletions
@@ -0,0 +1,107 @@
# ruff: noqa
# mypy: ignore-errors
"""Environmental stress test — does the architecture work OUTSIDE cyber? (Phase Ω)
Every prior journey lived in the cyber family (CRA / MaschinenVO / TISAX / ISO 27001 / OEM / Tender —
all infosec, software, product cybersecurity). This is the first NON-cyber stress test: substance flows,
emissions, water, chemicals, energy, circularity. The claim under test is NOT "we built an environmental
cluster" but "RS-005 carries an entirely different mental model UNCHANGED — only new DATA, zero runtime".
It runs ISO 14001 (an EMS, as a Company Profile, Welt-1) -> an Environmental target through the SAME
engines used for ISO 27001 -> CRA, and asks the SAME question: which environmental capabilities are
still missing? Plus the new quality question (rejected_assumptions): which capabilities does ISO 14001
typically NOT produce? And it runs the Journey Matcher to confirm it stays domain-agnostic.
Synthetic, no real names. Non-runtime -> no deploy.
Run: cd backend-compliance && PYTHONPATH=. python3 reference_scenarios/environmental_stress_test.py
"""
from __future__ import annotations
import os
import yaml
from compliance.company import (
CompanyContext, Certification, CapabilityMappingEntry, build_company_profile,
)
from compliance.reasoning.enums import Confidence
from compliance.transition_reasoning import (
TransitionContext, TransitionGoal, TargetRequirement, assess_transition, CoverageStatus,
)
from compliance.journey_matcher import JourneySignature, match_journeys
OUT = []
def w(s=""):
OUT.append(s)
_K = os.path.join(os.path.dirname(__file__), "..", "knowledge", "transition_patterns")
def _load(name):
return yaml.safe_load(open(os.path.join(_K, name), encoding="utf-8"))
ENV = _load("transition_pattern_iso14001_to_environmental_v1.yaml")
mgmt = [a["capability"] for a in ENV["likely_covered"]] # what ISO 14001 DOES give (Welt-1)
concrete = [d["capability"] for d in ENV["delta_requirements"]] # what it does NOT give (the delta)
# ── Company Profile: ISO 14001 -> the management capabilities only (NO concrete evidence) ────
profile = build_company_profile(
CompanyContext(company_id="env", certifications=[Certification(certification_id="ISO14001")]),
{"ISO14001": CapabilityMappingEntry(capability_ids=mgmt, confidence=Confidence.MEDIUM)})
# ── SAME engine as ISO 27001 -> CRA: required = management + concrete; delta = what's missing ─
reqs = [TargetRequirement(capability_id=c) for c in mgmt + concrete]
assess = assess_transition(TransitionContext(company_id="env", target=TransitionGoal(target_id="Environmental")), reqs, profile)
covered = sorted({c.capability_id for c in assess.coverage if c.status != CoverageStatus.MISSING})
delta = sorted({c.capability_id for c in assess.coverage if c.status == CoverageStatus.MISSING})
# ── Journey Matcher: stays domain-agnostic? cyber journeys must score ~0 on an env delta ─────
def _sig(name, label):
p = _load(name)
return JourneySignature(journey_id=p.get("id", name), label=label,
capability_pattern=[d["capability"] for d in p["delta_requirements"]])
journeys = [
_sig("transition_pattern_iso14001_to_environmental_v1.yaml", "ISO14001 -> Environmental"),
_sig("transition_pattern_iso27001_to_cra_maschinenvo_v1.yaml", "ISO27001 -> CRA + MaschinenVO"),
_sig("transition_pattern_isms_to_tisax_v1.yaml", "ISMS -> TISAX"),
]
match = match_journeys(delta, journeys)
w("# Environmental Stress Test — funktioniert die Architektur AUSSERHALB von Cyber? (Phase Ω)")
w("")
w('_Erster Nicht-Cyber-Test. Nicht „wir bauen einen Umwelt-Cluster", sondern: trägt RS-005 ein völlig anderes Denkmodell (Stoffe/Emissionen/Wasser/Energie/Kreislauf) UNVERÄNDERT — nur neue DATEN, null Runtime-Code? ISO 14001 als Company Profile (Welt-1), dieselbe Engine wie ISO 27001 → CRA. Synthetisch, keine echten Namen._')
w("")
w("## 1. ISO 14001 als Company Profile — Management, nicht Evidence")
w("- ISO 14001 liefert **Umwelt-MANAGEMENT-Disziplin** (Welt-1, wahrscheinlich vorhanden): %s." % ", ".join("`%s`" % c for c in mgmt))
w("- Über **dieselbe** `assess_transition`-Engine wie im Cyber-Fall — **keine Zeile neuer Runtime-Code**, nur ein neues Pattern-YAML.")
w("")
w("## 2. RS-005 stellt dieselbe Frage: welche Umwelt-Capabilities fehlen?")
w("> %s" % assess.summary.headline)
w("- **Vermutlich vorhanden (Management):** %d%s" % (len(covered), ", ".join("`%s`" % c for c in covered[:3]) + ""))
w("- **Delta (konkrete Evidence, fehlt): %d Capabilities** — z. B. %s" % (len(delta), ", ".join("`%s`" % c for c in delta[:4])))
w("- Capabilities sind **Verben** (capability-is-a-verb): `manage_chemical_substances`, `measure_air_emissions`, `issue_battery_passport` …")
w("")
w("## 3. Neue Qualitätsfrage — was erzeugt ISO 14001 typischerweise NICHT? _(rejected_assumptions, Welt-1/Welt-2)_")
for r in ENV["rejected_assumptions"]:
w("- %s" % r)
w("")
w("→ Genau wie ISO 9001 → CRA: ein **Managementsystem** gibt die Disziplin, aber **nicht die konkrete substanz-/produktspezifische Evidence**. Die Welt-1/Welt-2-Trennung bleibt erhalten.")
w("")
w("## 4. Journey Matcher bleibt domänen-agnostisch")
w("> %s" % match.headline)
w("| Journey | erklärt das Umwelt-Delta |")
w("|---|---|")
for m in match.matches:
w("| %s | %d%% |" % (m.label, round(m.score * 100)))
w("")
w("→ Die **Cyber-Journeys erklären 0 %** des Umwelt-Deltas — der Matcher rät nicht, er erklärt nur, was das Delta wirklich beschreibt.")
w("")
w("## Befund")
w("")
w('> **Ein völlig anderes Denkmodell (Umwelt) lief durch `Reality → Evidence → Capability → Required → Delta → Journey` ohne eine Zeile neuen Runtime-Code — nur ein neues Pattern-YAML + injizierte Required-Caps.** Das ist ein stärkerer Generalitätsbeweis als zehn weitere Cyber-Regelwerke: die Architektur ist nicht „Compliance/Cyber", sondern ein allgemeines Trägersystem. **%d neue Capability-Typen** (5 Management + %d konkrete Evidence) — in der Größenordnung der Cyber-Domänen, kein Granularitäts-Frühindikator. Architecture Stability: **0 neue Runtime-Klassen, 0 neue Pipeline.**' % (len(mgmt) + len(concrete), len(concrete)))
w("")
print("\n".join(OUT))