"""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)}")