Files
legal-ai/mcp-server/src/legal_mcp/tools/legal_arguments.py
Chaim 79b9c37301 feat(mcp): FU-14 GAP-48 פרוסה 2 — envelope אחיד ל-11 משפחות-כלים
המשך מיגרציית INV-TOOL1 מעבר למשפחת-החיפוש (#71). הומרו ל-{status,data,message}:
precedent_library, citations, internal_decisions, missing_precedents,
training_enrichment, precedents, legal_arguments, cases, documents, workflow
(~55 כלים). בוטלו 5 עותקי _ok/_err משוכפלים (alias ל-tools/envelope.py — SSoT, G2).

עיקרון: envelope-status = הצלחת-הקריאה-לכלי; תוצאה-עסקית (idempotent_existing,
noop, completed...) נשמרת בתוך data. err רק לכשל אמיתי (not-found/invalid/exception).

תאימות-API: צרכני web/app.py של cases/workflow/precedents חוּוטו דרך
envelope_unwrap + בדיקת status=="error"→4xx — תשובת ה-HTTP זהה, web-ui לא מושפע.
(documents/legal_arguments/citations/... אינם נצרכים מ-app.py — agent-only.)

בדיקות: 182/182 עוברים (test_corpus_constraints עודכן לחוזה החדש).
נותר: משפחת drafting (מסלול הפקת-ההחלטה) בפרוסה נפרדת עם שער טסט-ייצוא.

Invariants: מקדם INV-TOOL1 + G2 (SSoT, ביטול כפילות). מתועד ב-X9 + gap-audit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 17:41:39 +00:00

75 lines
2.3 KiB
Python

"""MCP tools — aggregated legal arguments (claim de-duplication)."""
from __future__ import annotations
from uuid import UUID
from legal_mcp.services import argument_aggregator, db
from legal_mcp.tools.envelope import empty, err, ok # GAP-48: SSoT envelope
async def aggregate_claims_to_arguments(
case_number: str,
force: bool = False,
) -> str:
"""כינוס פרופוזיציות גולמיות לטיעונים משפטיים מובחנים.
Args:
case_number: מספר תיק הערר.
force: True = למחוק טיעונים קיימים ולחשב מחדש.
"""
case = await db.get_case_by_number(case_number)
if not case:
return err(f"תיק {case_number} לא נמצא.")
case_id = UUID(case["id"])
result = await argument_aggregator.aggregate_claims_to_arguments(
case_id, force=force,
)
result["case_number"] = case_number
return ok(result)
async def get_legal_arguments(
case_number: str,
party: str = "",
) -> str:
"""שליפת טיעונים משפטיים מאוגדים לתיק.
Args:
case_number: מספר תיק הערר.
party: סינון לפי צד (appellant/respondent/committee/permit_applicant).
ריק = כל הצדדים.
"""
case = await db.get_case_by_number(case_number)
if not case:
return err(f"תיק {case_number} לא נמצא.")
case_id = UUID(case["id"])
args = await argument_aggregator.get_legal_arguments(case_id, party=party)
if not args:
return empty(
"לא נמצאו טיעונים מאוגדים. הרץ aggregate_claims_to_arguments תחילה.",
data={"case_number": case_number, "arguments": []},
)
# Group by party for nicer display.
party_he = {
"appellant": "עוררים",
"respondent": "משיבים",
"committee": "ועדה מקומית",
"permit_applicant": "מבקשי היתר",
"unknown": "צד לא מזוהה",
}
by_party: dict[str, list[dict]] = {}
for a in args:
label = party_he.get(a["party"], a["party"])
by_party.setdefault(label, []).append(a)
return ok({
"case_number": case_number,
"total": len(args),
"by_party": by_party,
})