"""Response schemas for the product-scope orchestrator (step 3). These are application/API types — NOT compliance-meta-model classes (architecture freeze v1.0 untouched). The scope verdict itself is produced by the existing `discover_scope`; nothing here adds scope rules. """ from __future__ import annotations from enum import Enum from typing import List, Optional from pydantic import BaseModel, Field from compliance.navigator.engine import CompletenessSummary from compliance.navigator.questions import NavigatorQuestion from compliance.profile.canonical import CanonicalProductRegulatoryProfile from compliance.reasoning.enums import Confidence from compliance.reasoning.schemas import ( ApplicableRegulation, ExcludedRegulation, UncertainRegulation, ) class ScopeStatus(str, Enum): NEEDS_FACTS = "needs_facts" # P0 facts missing -> ask, do not decide RESOLVED = "resolved" # minimum facts present -> scope decided class UnsupportedDomain(BaseModel): """A domain the product triggers but the corpus does not yet cover. Surfaced for transparency (no false completeness) — NEVER a legal evaluation. """ domain: str trigger: str status: str = "future_corpus_needed" note: str = "" class RegulatoryScopeResult(BaseModel): applicable_regulations: List[ApplicableRegulation] = Field(default_factory=list) excluded_regulations: List[ExcludedRegulation] = Field(default_factory=list) uncertain_regulations: List[UncertainRegulation] = Field(default_factory=list) unsupported_domains: List[UnsupportedDomain] = Field(default_factory=list) reasoning_summary: str = "" confidence: Confidence = Confidence.MEDIUM class ProductScopeRequest(BaseModel): product_profile: CanonicalProductRegulatoryProfile class ProductScopeResponse(BaseModel): status: ScopeStatus completeness_summary: CompletenessSummary # case NEEDS_FACTS missing_facts: List[str] = Field(default_factory=list) suggested_questions: List[NavigatorQuestion] = Field(default_factory=list) # case RESOLVED regulatory_scope: Optional[RegulatoryScopeResult] = None