""" _serialize.py - Compact JSON views of pipeline state for the text QAQC stages. The full sheet/cluster objects carry base64 images and bookkeeping that would blow up prompt token counts. These helpers strip them to the fields the reasoning prompts actually need. """ import json from typing import Dict, List def slim_assertion(a: Dict) -> Dict: out = { "sheet_number": a.get("sheet_number"), "discipline": a.get("discipline"), "attribute": a.get("attribute"), "value": a.get("value"), "source_text": a.get("source_text"), "location_key": a.get("location_key"), } if a.get("normalized_value") is not None: out["normalized_value"] = a["normalized_value"] return {k: v for k, v in out.items() if v is not None} def slim_sheets(sheets: List[Dict]) -> List[Dict]: return [ { "sheet_number": s.get("sheet_number"), "discipline": s.get("discipline"), "sheet_title": s.get("sheet_title"), "level": s.get("level"), "assertions": [ { "attribute": a.get("attribute"), "value": a.get("value"), "source_text": a.get("source_text"), "location_key": a.get("location_key"), **({"normalized_value": a["normalized_value"]} if a.get("normalized_value") is not None else {}), } for a in s.get("assertions", []) ], } for s in sheets ] def slim_clusters(clusters: List[Dict]) -> List[Dict]: return [ { "key": c.get("key"), "location": c.get("location"), "disciplines": c.get("disciplines"), "kind": c.get("kind"), **({"disputed_attributes": c["disputed_attributes"]} if c.get("disputed_attributes") else {}), "assertions": [slim_assertion(a) for a in c.get("assertions", [])], } for c in clusters ] def dumps(obj) -> str: return json.dumps(obj, ensure_ascii=True)