"""Strict proposal schema for language-model compiler integration.""" from typing import Literal from pydantic import Field, model_validator from .schema import Record from .compiled import Node,Plan class Obligation(Record): id: str endpoint: str unit: str context_ids: list[str] support: Literal['calibrated','proxy'] threshold: float direction: Literal['ge','le'] scale: float=Field(gt=0) threshold_source: str worker: str class Hypothesis(Record): id: str mechanism: str evidence_ids: list[str] opposing_evidence_ids: list[str] counterexample: str obligation_ids: list[str] class PlanNode(Record): id: str tool: str revision: str inputs: list[str] outputs: list[str] cost: int=Field(ge=1) attempts: int=Field(ge=1,le=3) class PlanProposal(Record): task_hash: str evidence_snapshot_hash: str hypotheses: list[Hypothesis]=Field(max_length=3) obligations: list[Obligation] nodes: list[PlanNode] required: list[str]=Field(min_length=1) budget: int=Field(ge=0) seed: int diagnostics: list[str] @model_validator(mode='after') def references(self): ids={o.id for o in self.obligations} if len(ids)!=len(self.obligations):raise ValueError('duplicate obligation') for h in self.hypotheses: if not h.evidence_ids or not set(h.obligation_ids)<=ids:raise ValueError('incomplete hypothesis') return self def execution_plan(self): if self.diagnostics:raise ValueError('unresolved proposal diagnostics') return Plan(tuple(Node(n.id,n.tool,n.revision,tuple(n.inputs),tuple(n.outputs),n.cost,n.attempts) for n in self.nodes),tuple(self.required),self.budget,self.seed)