Files
legal-ai/mcp-server/src/legal_mcp/tools/court_fetch.py
Chaim f56309da5a feat(X13): auto-trigger court fetch from digests + drain tool
סוגר את הלולאה — יומון שמצביע על פס"ד בית-משפט שלא בקורפוס מזניק אחזור
אוטומטי, וקושר את היומון חזרה אחרי הקליטה (INV-DIG3 + INV-CF2).

- digest_library.try_autolink: בכשל-קישור, אם הציטוט מסווג כפס"ד-בימ"ש
  (supreme/admin) → _enqueue_court_fetch יוצר court_fetch_jobs(pending);
  ועדת-ערר (skip) לא מוזנק. never-raises (לא שובר קליטת-יומון).
- orchestrator.drain_pending(limit): מנקז pending/failed סדרתי (cooldown,
  INV-CF4), fetch+ingest לכל אחד; בהצלחה מקשר את היומון ל-case_law שנקלט.
- כלי-MCP court_fetch_drain + רישום ב-server.py.
- X13 spec: עודכן (הפער ב-INV-CF2 סומן כמתוקן).

נבדק מול ה-DB: עת"מ 46111-12-22 → job tier=admin pending digest-linked;
ערר 1110/20 → לא מוזנק. כלי מקומי בלבד (ingest = claude CLI).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 20:04:12 +00:00

67 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""MCP tools for the X13 court-verdict auto-fetch subsystem.
- ``court_verdict_fetch`` — classify a citation, fetch the verdict from the
matching public source (Supreme portal / נט המשפט), and ingest it into the
precedent library via the canonical pipeline. The standalone entry point
(also driven automatically from digest auto-link, see X12/X13).
- ``court_fetch_status`` — inspect the fetch-job queue (pending/failed/manual).
Local-only: ``court_verdict_fetch`` runs the ingest pipeline, which drives
halacha extraction via the local ``claude`` CLI — same constraint as
``precedent_process_pending``. Invoking it from the container will fail.
"""
from __future__ import annotations
from legal_mcp.services import court_fetch_orchestrator as orch
from legal_mcp.services import db
from legal_mcp.tools.envelope import err as _err, ok as _ok
async def court_verdict_fetch(citation: str) -> str:
"""אחזור אוטומטי של פסק-דין בית-משפט וקליטה לקורפוס.
מקבל ציטוט (למשל 'עת"מ 46111-12-22' או 'עע"מ 1234/22'), מסווג את הערכאה,
מוריד את הפסק מהמקור הציבורי המתאים, וקולט אותו דרך צינור-הקליטה הקנוני.
ערר/בל"מ (ועדת-ערר) אינם ניתנים לאחזור ציבורי ויסומנו כפער.
"""
if not (citation or "").strip():
return _err("citation is required")
try:
result = await orch.fetch_and_ingest(citation.strip())
except Exception as e: # noqa: BLE001 — surfaced, not swallowed (INV-CF2)
return _err(f"אחזור נכשל: {e}")
status = result.get("status")
if status in ("done", "already_done"):
return _ok(result, message="הפסק נקלט לקורפוס")
if status == "skipped":
return _ok(result, message="ועדת-ערר — לא ניתן לאחזור ציבורי (סומן כפער)")
if status in ("manual", "awaiting_manual"):
return _ok(result, message="האחזור האוטונומי נכשל — הוסלם להורדה ידנית")
if status == "unrecognized":
return _err("הציטוט לא זוהה כמספר-תיק תקין")
return _ok(result, message=f"סטטוס: {status}")
async def court_fetch_status(case_number: str = "", status_filter: str = "") -> str:
"""סטטוס תור-האחזור. case_number לפריט יחיד, או status_filter לסינון רשימה."""
if case_number.strip():
from legal_mcp.services.court_citation import normalize_case_number
job = await db.court_fetch_job_get(normalize_case_number(case_number))
if not job:
return _ok({"job": None}, message="אין job עבור תיק זה")
return _ok({"job": job})
jobs = await db.court_fetch_job_list(status=status_filter.strip() or None)
return _ok({"jobs": jobs, "count": len(jobs)})
async def court_fetch_drain(limit: int = 10) -> str:
"""ריקון תור-האחזור: מוריד וקולט את ה-jobs הממתינים (pending/failed) שהיומונים
מילאו, וקושר כל פסק שנקלט חזרה ליומון-המקור. סדרתי. כלי מקומי בלבד."""
try:
result = await orch.drain_pending(limit=max(1, min(int(limit or 10), 50)))
except Exception as e: # noqa: BLE001
return _err(f"ריקון התור נכשל: {e}")
return _ok(result, message=f"עובדו {result.get('processed', 0)}, נקלטו {result.get('done', 0)}")