Files
breakpilot-compliance/backend-compliance/compliance/api/reasoning_routes.py
T
Benjamin Admin 5e5002c883 refactor(reasoning): enforce ClaimCoverage (Welt 1) vs ComplianceStatus (Welt 2) boundary [F1]
Architecture-validation finding: the implementation mode produced compliance-
flavored output ("teilweise erfüllt", "covered") from a mere customer claim,
blurring the line to the Execution layer. This is a design decision, not a text
fix — the reasoning layer judges only the customer's STATEMENT, never conformity.

- CoverageStatus -> ClaimCoverage; values are claim-relative + carry "potential":
  potentially_addresses / partially_addresses / does_not_address /
  insufficient_information.
- ImplementationAssessment -> ClaimObligationMapping (coverage_status ->
  claim_coverage); ImplementationResponse -> ImplementationReasoningResponse
  (assessments -> mappings, + explicit `disclaimer`); request renamed; engine
  entry assess_implementation -> reason_implementation_claim.
- Endpoint /reasoning/implementation-assessment -> /reasoning/implementation-reasoning.
- Summary/explanations reworded: "adressiert wahrscheinlich N Pflichten … für
  eine Bewertung der tatsächlichen Umsetzung sind Nachweise erforderlich (keine
  Konformitätsaussage)". No "erfüllt"/"abgedeckt" leaks.
- New guard test asserts no compliance verdict leaks (no "erfüllt"; disclaimer
  separates ClaimCoverage from ComplianceStatus). 23 tests green, mypy clean.

Discovery (scope/obligations) was already structurally claim-free and unaffected.

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

69 lines
2.5 KiB
Python

"""HTTP endpoints for the Regulatory Reasoning Engine (spec §7).
Thin handlers — all reasoning lives in `compliance.reasoning.*`. No DB, no RAG;
pure deterministic rule evaluation.
POST /reasoning/scope -> which regulations apply + missing facts
POST /reasoning/obligations -> obligations, overlaps, multi-evidence
POST /reasoning/implementation-reasoning -> claim->obligation mapping (Welt 1, no verdict)
POST /reasoning/interpretation-assessment -> verdict on a customer interpretation
"""
from __future__ import annotations
from fastapi import APIRouter
from compliance.reasoning import (
assess_interpretation,
derive_obligations,
discover_scope,
reason_implementation_claim,
)
from compliance.reasoning.schemas import (
ImplementationReasoningRequest,
ImplementationReasoningResponse,
InterpretationRequest,
InterpretationResponse,
ObligationsRequest,
ObligationsResponse,
ScopeRequest,
ScopeResponse,
)
router = APIRouter(prefix="/reasoning", tags=["reasoning"])
@router.post("/scope", response_model=ScopeResponse)
def scope_discovery(req: ScopeRequest) -> ScopeResponse:
scope = discover_scope(req.product_profile)
return ScopeResponse(
regulatory_scope=scope,
missing_facts=scope.missing_facts,
confidence=scope.confidence,
)
@router.post("/obligations", response_model=ObligationsResponse)
def applicable_obligations(req: ObligationsRequest) -> ObligationsResponse:
return derive_obligations(req.product_profile, req.regulatory_scope)
@router.post("/implementation-reasoning", response_model=ImplementationReasoningResponse)
def implementation_reasoning(req: ImplementationReasoningRequest) -> ImplementationReasoningResponse:
return reason_implementation_claim(req.product_profile, req.customer_claim)
@router.post("/interpretation-assessment", response_model=InterpretationResponse)
def interpretation_assessment(req: InterpretationRequest) -> InterpretationResponse:
result = assess_interpretation(req.customer_interpretation, req.product_profile)
return InterpretationResponse(
assessment=result.assessment,
affected_regulations=result.affected_regulations,
affected_obligations=result.affected_obligations,
corrected_interpretation=result.corrected_interpretation,
risks=result.risks,
legal_basis_refs=result.legal_basis_refs,
explanation=result.explanation,
confidence=result.confidence,
)