feat(reasoning): Regulatory Reasoning Engine MVP (scope/obligations/implementation/interpretation)
Deterministic reasoning layer ON TOP of the Legal Knowledge Graph (obligation
registry) and the Compliance Execution Graph (control mapping/evidence). Answers
which regulations apply to a concrete product, which obligations follow, whether
the customer's implementation covers them, and whether a customer interpretation
is too narrow/broad/plausible.
- ProductProfile with tri-state facts (Optional[bool]=None => uncertain, never
false security); safe predicate evaluator (no eval).
- 6 regulation triggers (CRA/MaschinenVO/RED/EMV/DataAct/NIS2) with missing-fact
prompts; 24 obligation scope rules.
- CRA obligation_ids RE-USED verbatim from the registry (93 ids) — never re-minted
(control_uuid trap); Machine/Data-Act flagged proposed=True.
- required_evidence constrained to the framework-agnostic shared evidence catalog;
capabilities echo the planned Obligation->Capability layer.
- Overlap groups (CRA<->MaschinenVO cyber-safety) + evidence-for-multiple (USP).
- 4 endpoints POST /reasoning/{scope,obligations,implementation-assessment,
interpretation-assessment}; thin handlers, registered in api/__init__.py.
- 22 tests (5 machine-builder scenarios + 10 acceptance questions). No DB
migration, no RAG, no new controls.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -77,6 +77,7 @@ _ROUTER_MODULES = [
|
||||
"licenses_routes",
|
||||
"template_rule_routes",
|
||||
"specialist_agent_routes",
|
||||
"reasoning_routes",
|
||||
]
|
||||
|
||||
_loaded_count = 0
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
"""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-assessment -> claim coverage per obligation
|
||||
POST /reasoning/interpretation-assessment -> verdict on a customer interpretation
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from compliance.reasoning import (
|
||||
assess_implementation,
|
||||
assess_interpretation,
|
||||
derive_obligations,
|
||||
discover_scope,
|
||||
)
|
||||
from compliance.reasoning.schemas import (
|
||||
ImplementationRequest,
|
||||
ImplementationResponse,
|
||||
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-assessment", response_model=ImplementationResponse)
|
||||
def implementation_assessment(req: ImplementationRequest) -> ImplementationResponse:
|
||||
return assess_implementation(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,
|
||||
)
|
||||
Reference in New Issue
Block a user