fix(corpus): refresh searchable flag on metadata patch (INV-DM1, G1)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 3s
Lint — undefined names / undefined-names (pull_request) Successful in 10s

The `searchable` completeness flag is recomputed only at ingest end and after
the Gemini metadata extractor. Internal-committee decisions skip Gemini, so
when their summary/subject_tags/metadata are filled after ingest the flag goes
stale and the row stays invisible to RAG despite being complete. Found 4 such
decisions (1049-06-21, 8126-03-25 [יעקב עמיאל], 8181-21 [האוניברסיטה העברית],
85074-04-25) — all complete (chunks+embeddings, extraction+halacha completed,
metadata present) yet searchable=false.

Fix: recompute_searchable() at the end of update_case_law — the single
chokepoint for metadata patches — so the derived flag never drifts from the
content (G1). Existing stale rows already corrected via a one-off canonical
recompute_searchable(None) run (corpus: 328 -> 332 searchable).

Invariants: INV-DM1 (completeness contract) · G1 (normalize derived value at
the write, no read-time patch).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-20 11:35:59 +00:00
parent 422d79f9e8
commit 92f0c7d208

View File

@@ -4534,7 +4534,16 @@ async def update_case_law(case_law_id: UUID, **fields) -> dict | None:
params.append(v)
sql = f"UPDATE case_law SET {', '.join(set_parts)} WHERE id = $1 RETURNING *"
row = await pool.fetchrow(sql, *params)
return _row_to_case_law(row) if row else None
if row is None:
return None
# `searchable` is a DERIVED completeness flag (INV-DM1). It is computed at
# ingest end and after the Gemini metadata extractor — but internal-committee
# decisions skip Gemini, so when their summary/tags/metadata are filled later
# (manual edit, deterministic enrichment) the flag would otherwise go stale
# and the row stays invisible to RAG. Recompute at this write so the derived
# value never drifts from the content (G1: normalize at the source).
await recompute_searchable(case_law_id)
return await get_case_law(case_law_id)
async def set_case_law_extraction_status(case_law_id: UUID, status: str) -> None: