fix(precedents): מראה-מקום never blank — seed at upload + inline Gemini enrichment (root cause)
Root cause: the upload form "מראה המקום" field is stored only as case_number; citation_formatted was left empty and filled ONLY by the async metadata extraction, which runs in the local drainer (not the container) because it was lumped with halacha extraction. Result: the chair saw an empty מראה-מקום during the window and re-typed it by hand. Fix (hybrid — Option C): - Seed: _create_external_record / create_external_case_law store the chair's typed citation as citation_formatted at INSERT, so the field is never blank. A cited_only→external promotion preserves an existing non-empty value (prior edit). - Enrich: ingest_precedent runs metadata extraction INLINE in-container (gemini_session is direct REST, no local CLI) with force_citation=True, upgrading the seed to the canonical derived citation (parties + reporter + date) before the chair opens the page. Best-effort: on no key / API failure the seed remains and the queued metadata drain stays as the fallback. Halacha extraction is untouched (stays local — claude_session). - apply_to_record / extract_and_apply gain force_citation: re-assemble even when citation_formatted is non-empty, writing only when assembly SUCCEEDS (seed preserved on abstention). The drainer keeps the default (False) so a chair's manual edit in /precedents/[id] is never clobbered. Ops: GOOGLE_GEMINI_API_KEY added to the legal-ai Coolify app (runtime) — the SoT value from Infisical nautilus:/external-apis/gemini, validated against the API. Invariants: G2 (one citation-resolution + one metadata-extraction path, reused — no parallel logic), INV-ID2/X1§3 (citation_formatted stays a derived field; the seed is provisional and upgraded), INV-G10 (chair edits preserved). No schema change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -68,7 +68,11 @@ def _external_staging_subdir(inputs: dict) -> str:
|
||||
|
||||
|
||||
async def _create_external_record(**kw) -> dict:
|
||||
"""Adapter: maps canonical inputs (citation) to create_external_case_law(case_number)."""
|
||||
"""Adapter: maps canonical inputs (citation) to create_external_case_law(case_number).
|
||||
|
||||
The chair's typed citation seeds ``citation_formatted`` so the מראה-מקום is never
|
||||
blank before metadata extraction; the inline enrichment upgrades it to the
|
||||
canonical form (see ``ingest_precedent``)."""
|
||||
return await db.create_external_case_law(
|
||||
case_number=kw["citation"].strip(),
|
||||
case_name=kw["case_name"],
|
||||
@@ -84,6 +88,7 @@ async def _create_external_record(**kw) -> dict:
|
||||
precedent_level=kw.get("precedent_level", ""),
|
||||
is_binding=kw.get("is_binding", True),
|
||||
document_id=kw.get("document_id"),
|
||||
citation_formatted=kw["citation"].strip(),
|
||||
)
|
||||
|
||||
|
||||
@@ -126,10 +131,28 @@ async def ingest_precedent(
|
||||
"appeal_subtype": appeal_subtype, "subject_tags": subject_tags,
|
||||
"is_binding": is_binding, "headnote": headnote, "summary": summary,
|
||||
}
|
||||
return await ingest.ingest_document(
|
||||
result = await ingest.ingest_document(
|
||||
_EXTERNAL_SPEC, inputs=inputs, file_path=file_path,
|
||||
document_id=document_id, progress=progress,
|
||||
)
|
||||
# Inline metadata enrichment (Gemini, in-container — gemini_session is direct
|
||||
# REST, no local CLI). UPGRADES the seeded provisional citation_formatted to the
|
||||
# canonical derived form (parties + reporter + date) so the מראה-מקום is correct
|
||||
# the moment the chair opens /precedents/[id] — not deferred to the local drainer.
|
||||
# force_citation=True overwrites the seed only; chair edits aren't reachable yet
|
||||
# (row just created). Best-effort: on no key / API failure the seed remains and
|
||||
# the queued metadata drain (request_metadata_extraction, already set) is the
|
||||
# fallback. Halacha extraction is NOT touched here — it stays local (claude_session).
|
||||
cid = result.get("case_law_id") if isinstance(result, dict) else None
|
||||
if cid:
|
||||
try:
|
||||
from legal_mcp.services import precedent_metadata_extractor as _pme
|
||||
r = await _pme.extract_and_apply(UUID(str(cid)), force_citation=True)
|
||||
if r.get("status") == "completed":
|
||||
await db.set_case_law_metadata_status(UUID(str(cid)), "completed")
|
||||
except Exception as e: # noqa: BLE001 — enrichment is best-effort; drainer is fallback
|
||||
logger.warning("inline metadata enrichment failed for %s (drainer will retry): %s", cid, e)
|
||||
return result
|
||||
|
||||
|
||||
async def reextract_halachot(
|
||||
|
||||
Reference in New Issue
Block a user