From 92f0c7d208745c4bc679130c881d6c139a181e86 Mon Sep 17 00:00:00 2001 From: Chaim Date: Sat, 20 Jun 2026 11:35:59 +0000 Subject: [PATCH] fix(corpus): refresh searchable flag on metadata patch (INV-DM1, G1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- mcp-server/src/legal_mcp/services/db.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mcp-server/src/legal_mcp/services/db.py b/mcp-server/src/legal_mcp/services/db.py index 5964f78..45669fe 100644 --- a/mcp-server/src/legal_mcp/services/db.py +++ b/mcp-server/src/legal_mcp/services/db.py @@ -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: