feat(mcp): FU-14 GAP-45 — extraction_status (חשיפת תור-החילוץ הסמוי)

INV-TOOL4 (visibility / persistence). תור בקשות-החילוץ (metadata/halacha) נשמר
ב-case_law.{metadata,halacha}_extraction_requested_at ומרוקן ע"י
precedent_process_pending — אבל לא היה כלי לראות את עומק-התור.

נוסף:
- db.extraction_queue_status() — count + גיל הבקשה הוותיקה לכל kind (read-only).
- plib.extraction_status() — tool wrapper (envelope _ok/_err).
- רישום extraction_status ב-server.py ליד precedent_process_pending.
- precedent_process_pending קיבל _clamp_limit (עקביות עם GAP-53).

תוספתי, read-only, אפס שבירה. עודכנו X9 (INV-TOOL4 ) ו-gap-audit (GAP-45 ).
py_compile עבר על 3 קבצי הקוד.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-06 15:00:25 +00:00
parent 0d0f5aa8e9
commit ea8b48c6ac
5 changed files with 48 additions and 4 deletions

View File

@@ -290,10 +290,16 @@ async def style_corpus_pending_enrichment(limit: int = 50) -> str:
return await train_tools.list_corpus_pending_enrichment(_clamp_limit(limit))
@mcp.tool()
async def extraction_status() -> str:
"""סטטוס תור-החילוץ — כמה פסיקות ממתינות לחילוץ metadata/halacha + גיל הבקשה הוותיקה. read-only (חושף את התור ש-precedent_process_pending מרוקן)."""
return await plib.extraction_status()
@mcp.tool()
async def precedent_process_pending(kind: str = "metadata", limit: int = 20) -> str:
"""ריקון תור בקשות חילוץ שנשלחו מ-UI. kind: 'metadata' או 'halacha'. מריץ extractor מקומית עם CLI על כל פריט בתור, ומנקה את הסימון אחרי הצלחה."""
return await plib.precedent_process_pending(kind, limit)
return await plib.precedent_process_pending(kind, _clamp_limit(limit))
@mcp.tool()

View File

@@ -4332,6 +4332,31 @@ async def list_pending_extraction_requests(
return out
async def extraction_queue_status() -> dict:
"""Pending-extraction queue depth per kind (INV-TOOL4 visibility / GAP-45).
Surfaces the otherwise-hidden queue that ``process_pending_extractions``
drains: how many case_law rows still carry a metadata/halacha extraction
request, and the age of the oldest one. Read-only — does not drain.
"""
pool = await get_pool()
async with pool.acquire() as conn:
meta = await conn.fetchrow(
"SELECT COUNT(*) AS n, MIN(metadata_extraction_requested_at) AS oldest "
"FROM case_law WHERE metadata_extraction_requested_at IS NOT NULL"
)
hal = await conn.fetchrow(
"SELECT COUNT(*) AS n, MIN(halacha_extraction_requested_at) AS oldest "
"FROM case_law WHERE halacha_extraction_requested_at IS NOT NULL"
)
def _fmt(r: dict) -> dict:
oldest = r["oldest"]
return {"pending": r["n"], "oldest_request": oldest.isoformat() if oldest else None}
return {"metadata": _fmt(meta), "halacha": _fmt(hal)}
async def clear_extraction_request(
case_law_id: UUID, kind: str = "metadata",
) -> None:

View File

@@ -233,6 +233,19 @@ async def precedent_reindex(case_law_id: str) -> str:
return _ok(result)
async def extraction_status() -> str:
"""סטטוס תור-החילוץ — כמה פסיקות ממתינות לחילוץ metadata/halacha (INV-TOOL4 / GAP-45).
חושף את התור ש-precedent_process_pending מרוקן: עומק-תור + גיל הבקשה
הוותיקה ביותר לכל סוג. read-only — אינו מרוקן את התור.
"""
try:
status = await db.extraction_queue_status()
except Exception as e:
return _err(str(e))
return _ok(status)
async def precedent_process_pending(kind: str = "metadata", limit: int = 20) -> str:
"""ריקון תור בקשות חילוץ שנערמו ע"י כפתורי ה-UI. kind: 'metadata' או 'halacha'.