"""Agent-visible instance model and the held-out ground truth carrier. HeldOut never crosses the tool boundary: ToolRegistry (envir/tools.py) accepts only Instance — enforced by signature, tested in test_tools.py. """ from __future__ import annotations import json from dataclasses import dataclass, field def _jsonable(obj): # sets iterate in hash order, which is randomized across processes — # sort them or byte-identity breaks across machines if isinstance(obj, (set, frozenset)): return sorted(str(x) for x in obj) return str(obj) def canonical_json(obj) -> str: return json.dumps(obj, sort_keys=True, separators=(",", ":"), default=_jsonable) @dataclass(frozen=True) class Entry: entry_id: str header: dict lines: tuple[dict, ...] @dataclass(frozen=True) class Document: doc_id: str entry_id: str doc_type: str filename: str pages: tuple[str, ...] @dataclass(frozen=True) class Instance: task_id: str seed: int entries: tuple[Entry, ...] documents: tuple[Document, ...] policies: dict[str, str] master_data: dict[str, dict] @dataclass(frozen=True) class DefectRecord: entry_id: str defect_type: str revealing_evidence_id: str | None correct_verdict: str @dataclass(frozen=True) class HeldOut: defects: tuple[DefectRecord, ...] required_docs: frozenset[str] evidence_map: dict[str, frozenset[str]] claims: dict[str, dict[str, int]] = field(default_factory=dict) @dataclass(frozen=True) class TaskInstance: instance: Instance heldout: HeldOut