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>
This commit is contained in:
2026-06-06 17:41:39 +00:00
parent 24f9ceb164
commit 79b9c37301
14 changed files with 168 additions and 240 deletions

View File

@@ -234,14 +234,15 @@ def test_mcp_precedent_upload_rejects_arar_citation() -> None:
"ARAR 8126-25 ב. קרן-נכסים",
):
result = loop.run_until_complete(call(citation))
assert "error" in result, (
# GAP-48: tools return the {status,data,message} envelope.
assert result.get("status") == "error", (
f"expected guard to reject {citation!r}, got {result!r}"
)
# The error message should mention internal_decision_upload so
# the caller knows the alternative path.
assert "internal_decision_upload" in result["error"], (
assert "internal_decision_upload" in result["message"], (
f"error message should redirect to internal_decision_upload, "
f"got {result['error']!r}"
f"got {result['message']!r}"
)
finally:
loop.close()