| """Stable case-summary contract shared by the current corpus and future re-extractions.""" |
| import json |
| import os |
| import re |
|
|
|
|
| def _clean(value): |
| return re.sub(r"\s+", " ", str(value or "")).strip() |
|
|
|
|
| def _summary_text(value): |
| if isinstance(value, str): |
| return _clean(value) |
| if not isinstance(value, dict): |
| return "" |
| direct = value.get("text") or value.get("summary") |
| if direct: |
| return _clean(direct) |
| parts = [] |
| for key, label in ( |
| ("facts", "Facts"), |
| ("issues", "Issues"), |
| ("holding", "Holding"), |
| ("reasoning", "Reasoning"), |
| ("outcome", "Outcome"), |
| ): |
| item = value.get(key) |
| if isinstance(item, list): |
| item = "; ".join(_clean(x) for x in item if _clean(x)) |
| item = _clean(item) |
| if item: |
| parts.append(f"{label}: {item}") |
| return " ".join(parts) |
|
|
|
|
| def load_case_summaries(data_dir): |
| """Load the first supported extraction sidecar; absent files are a valid pre-migration state.""" |
| for filename in ("judgment_summaries.jsonl", "case_summaries.jsonl"): |
| path = os.path.join(data_dir, filename) |
| if not os.path.exists(path): |
| continue |
| rows = {} |
| with open(path, encoding="utf-8") as fh: |
| for line in fh: |
| try: |
| row = json.loads(line) |
| except Exception: |
| continue |
| doc_id = row.get("doc_id") |
| if doc_id and _summary_text(row.get("summary") or row.get("case_summary")): |
| rows[doc_id] = row |
| return rows, filename |
| return {}, None |
|
|
|
|
| def case_summary_record(meta=None, synthetic=None, extracted=None): |
| """Choose one honest summary source without falling back to arbitrary opening text.""" |
| meta = meta or {} |
| synthetic = synthetic or {} |
| extracted = extracted or {} |
|
|
| text = _summary_text(extracted.get("summary") or extracted.get("case_summary")) |
| if text: |
| return { |
| "available": True, |
| "text": text[:5000], |
| "source": "extracted_summary", |
| "generated": bool(extracted.get("generated", True)), |
| "provider": _clean(extracted.get("provider") or extracted.get("source_provider")), |
| "version": _clean(extracted.get("version") or extracted.get("extraction_version")), |
| } |
|
|
| text = _summary_text(meta.get("summary") or meta.get("case_summary")) |
| if text: |
| return { |
| "available": True, |
| "text": text[:5000], |
| "source": "extracted_summary", |
| "generated": bool(meta.get("summary_generated", True)), |
| "provider": _clean(meta.get("source_provider")), |
| "version": _clean(meta.get("extraction_version")), |
| } |
|
|
| text = _clean(synthetic.get("held")) |
| if text: |
| return { |
| "available": True, |
| "text": text[:5000], |
| "source": "synthetic_headnote", |
| "generated": True, |
| "provider": "", |
| "version": _clean(synthetic.get("model")), |
| } |
|
|
| text = _clean(meta.get("held")) |
| if text: |
| return { |
| "available": True, |
| "text": text[:5000], |
| "source": "reporter_headnote", |
| "generated": False, |
| "provider": "", |
| "version": "", |
| } |
|
|
| return { |
| "available": False, |
| "text": "", |
| "source": "unavailable", |
| "generated": False, |
| "provider": "", |
| "version": "", |
| } |
|
|