Files
breakpilot-compliance/backend-compliance/compliance/profile/__init__.py
T
Benjamin Admin 739a477d3f feat(profile): CanonicalProductRegulatoryProfile convergence layer (types + mappers + tests)
ONE canonical product profile so the Go gap engine and the Python reasoning
engine stop diverging ("SPS mit Remote Access" means the same everywhere).
gap.ProductProfile LEADS; the reasoning ProductProfile becomes an adapter/DTO.
Types + mappers only — no regulation logic, no Go changes, no UI, no new questions.

- CanonicalProductRegulatoryProfile mirrors gap.ProductProfile + the Navigator
  gaps the audit found: economic-operator role, radio_module, generates_usage_data,
  lifecycle_phase, structured BOM (ProductComponent), safety-vs-security split,
  machine-vs-component + a forward-looking EnvironmentalImpact domain (wastewater/
  air/chemicals triggers — fields only, no rules yet).
- Mappers: from_product_wizard (lossless), from_company_profile (prefill incl.
  the machineBuilder block), to_gap_profile (emits the unchanged gap JSON shape),
  to_reasoning_profile (projects into the reasoning ProductProfile; AI stays
  delegated to ai-act/ucca). Only profile->reasoning is coupled; reasoning stays
  hermetic.
- 10 tests = the 10 acceptance criteria incl. ProductWizard round-trip lossless,
  markets no longer forced ['EU'], and canonical->reasoning->discover_scope
  proving one semantic profile drives the engine. 33 tests green, mypy clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-26 09:52:46 +02:00

39 lines
1.1 KiB
Python

"""Product profile convergence layer.
ONE canonical product profile (`CanonicalProductRegulatoryProfile`) that the Go
gap engine and the Python reasoning engine both project from — so "SPS mit
Remote Access" means the same thing everywhere. gap.ProductProfile leads; the
reasoning ProductProfile is an adapter/DTO. Types + mappers only — no regulation
logic, no UI, no new questions.
"""
from __future__ import annotations
from .canonical import (
CanonicalLifecyclePhase,
CanonicalProductRegulatoryProfile,
CanonicalProductType,
ComponentKind,
EconomicOperatorRole,
EnvironmentalImpact,
ProductComponent,
)
from .from_company_profile import from_company_profile
from .from_product_wizard import from_product_wizard
from .to_gap import to_gap_profile
from .to_reasoning import to_reasoning_profile
__all__ = [
"CanonicalProductRegulatoryProfile",
"CanonicalProductType",
"EconomicOperatorRole",
"CanonicalLifecyclePhase",
"ComponentKind",
"ProductComponent",
"EnvironmentalImpact",
"from_product_wizard",
"from_company_profile",
"to_gap_profile",
"to_reasoning_profile",
]