feat(ui): אינדיקטור התקדמות לחילוץ מטא-דאטה + מתג-מקטעים בספריית הפסיקה

שתי בעיות UX בדף /precedents:

1. חילוץ מטא-דאטה לא נתן שום אינדיקציה שהוא רץ. בניגוד לחילוץ טקסט/הלכות
   (extraction_status / halacha_extraction_status) למטא-דאטה היתה רק חותמת-זמן
   metadata_extraction_requested_at — אין מצב "processing", לכן StatusPill לא
   הציג כלום. נוספה עמודת metadata_extraction_status ('pending'|'processing'|
   'completed'|'failed') במתכונת העמודות הקיימות, וה-worker
   (process_pending_extractions + reextract_metadata) מעדכן אותה: processing
   בתחילת פריט, completed בסיום (מנקה גם את החותמת), pending בכשל (לריטריי).
   ה-UI מציג תג "מחלץ מטא-דאטה" + באנר מונה-אצווה עם אחוז התקדמות (high-water-mark
   של עומק-התור) שמתעדכן אוטומטית דרך ה-polling הקיים (5ש').

2. שתי טבלאות מוערמות (בתי משפט / ועדות ערר) חייבו גלילה ארוכה. הוחלפו במתג-
   מקטעים — טבלה אחת בכל פעם, עם שמירה על העמודות הייעודיות לכל סוג.

Invariants: G2 (מרחיב מנגנון-סטטוס קיים, לא מסלול מקביל), INV-TOOL4/GAP-45
(המשך חשיפת תור-החילוץ הסמוי). אין נגיעה בתוכן משפטי (G11).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-06 16:21:41 +00:00
parent 9c77123fa3
commit 6bf19bd0d7
4 changed files with 215 additions and 29 deletions

View File

@@ -610,6 +610,11 @@ ALTER TABLE case_law ADD COLUMN IF NOT EXISTS document_id UUID REFERENCES docume
ALTER TABLE case_law ADD COLUMN IF NOT EXISTS extraction_status TEXT DEFAULT 'pending';
-- 'pending' | 'processing' | 'completed' | 'failed'
ALTER TABLE case_law ADD COLUMN IF NOT EXISTS halacha_extraction_status TEXT DEFAULT 'pending';
ALTER TABLE case_law ADD COLUMN IF NOT EXISTS metadata_extraction_status TEXT DEFAULT 'pending';
-- 'pending' | 'processing' | 'completed' | 'failed'. Mirrors the
-- text/halacha status columns so the UI can show a live badge while the
-- local-MCP worker drains the metadata queue (previously only the
-- metadata_extraction_requested_at timestamp existed — no 'processing').
ALTER TABLE case_law ADD COLUMN IF NOT EXISTS practice_area TEXT DEFAULT '';
ALTER TABLE case_law ADD COLUMN IF NOT EXISTS appeal_subtype TEXT DEFAULT '';
ALTER TABLE case_law ADD COLUMN IF NOT EXISTS headnote TEXT DEFAULT '';
@@ -3070,6 +3075,27 @@ async def set_case_law_halacha_status(case_law_id: UUID, status: str) -> None:
)
async def set_case_law_metadata_status(case_law_id: UUID, status: str) -> None:
"""Set metadata-extraction status. Mirrors ``set_case_law_halacha_status``:
on terminal states ('completed'/'failed') we also clear
``metadata_extraction_requested_at`` so the local-MCP queue
(`process_pending_extractions`, which scans ``WHERE *_requested_at IS NOT
NULL``) stops re-picking the row and the UI's ``isPrecedentActive`` check
settles."""
pool = await get_pool()
if status in ("completed", "failed"):
await pool.execute(
"UPDATE case_law SET metadata_extraction_status = $2, "
"metadata_extraction_requested_at = NULL WHERE id = $1",
case_law_id, status,
)
else:
await pool.execute(
"UPDATE case_law SET metadata_extraction_status = $2 WHERE id = $1",
case_law_id, status,
)
async def list_external_case_law(
practice_area: str = "",
court: str = "",
@@ -3126,6 +3152,7 @@ async def list_external_case_law(
summary, headnote, subject_tags, source_kind,
chair_name, district, citation_formatted,
extraction_status, halacha_extraction_status,
metadata_extraction_status,
metadata_extraction_requested_at,
halacha_extraction_requested_at,
created_at,
@@ -4274,8 +4301,12 @@ async def request_metadata_extraction(case_law_id: UUID) -> bool:
fills empty fields), so this is safe.
"""
pool = await get_pool()
# Reset the status to 'pending' alongside the timestamp so a re-request
# after a prior 'completed'/'failed' run shows "בתור" again in the UI
# instead of a stale terminal badge.
result = await pool.execute(
"UPDATE case_law SET metadata_extraction_requested_at = now() "
"UPDATE case_law SET metadata_extraction_requested_at = now(), "
"metadata_extraction_status = 'pending' "
"WHERE id = $1",
case_law_id,
)