Files
breakpilot-compliance/backend-compliance/compliance/api/reasoning_routes.py
T
Benjamin Admin 50ae9e94d1 feat(interpretation-in-map): judge a customer interpretation within the map (step 5)
Thin adapter — it judges the customer's reading WITHIN the already-built
RegulatoryMap, it does not assess abstract legal questions and it is not RCI.

- Reuses the existing assess_interpretation (no new legal reasoning); the 6
  verdicts (plausible/too_narrow/too_broad/partially_correct/unsupported/uncertain)
  pass through unchanged.
- Restricts affected_regulations/affected_obligations to those present in the map
  (intersection); links to the map's uncertain regulations.
- Touched unsupported domains (wastewater/chemicals/...) are reported as
  future_corpus_domains (future_corpus_needed) — never pseudo-evaluated.
- Customer-readable explanation ("Ihre Interpretation ist wahrscheinlich zu eng. …
  Betroffen in Ihrer Map: CRA.").
- POST /reasoning/interpretation-in-map (renders the map, then interprets).
- 7 tests; 63 green (existing reasoning MVP stays green), mypy clean, LOC ok.

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

99 lines
3.8 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
POST /reasoning/product-scope -> gate on facts, else run discover_scope once
POST /reasoning/regulatory-map -> customer-readable read-model over the scope
POST /reasoning/interpretation-in-map -> judge a customer interpretation within the map
"""
from __future__ import annotations
from fastapi import APIRouter
from compliance.interpretation_map import (
InterpretationInMapRequest,
InterpretationInMapResult,
interpret_in_map,
)
from compliance.product_scope import (
ProductScopeRequest,
ProductScopeResponse,
resolve_product_scope,
)
from compliance.regulatory_map import RegulatoryMap, RegulatoryMapRequest, render_regulatory_map
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("/product-scope", response_model=ProductScopeResponse)
def product_scope(req: ProductScopeRequest) -> ProductScopeResponse:
return resolve_product_scope(req.product_profile)
@router.post("/regulatory-map", response_model=RegulatoryMap)
def regulatory_map(req: RegulatoryMapRequest) -> RegulatoryMap:
return render_regulatory_map(req.product_profile)
@router.post("/interpretation-in-map", response_model=InterpretationInMapResult)
def interpretation_in_map(req: InterpretationInMapRequest) -> InterpretationInMapResult:
reg_map = render_regulatory_map(req.product_profile)
return interpret_in_map(reg_map, req.customer_interpretation)
@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,
)