50ae9e94d1
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>
99 lines
3.8 KiB
Python
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,
|
|
)
|