Files
legal-ai/mcp-server/tests/test_docket_grounding.py
Chaim 63387c0d7d
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 5s
INV-AG3 Agent Tool Grants / agent-tool-grants (pull_request) Successful in 5s
Lint — undefined names / undefined-names (pull_request) Successful in 11s
fix(extraction): מספר-תיק שהומצא נכתב לשדה-הזהות — עיגון בטקסט לפני כתיבה (#232 מלכודת 3)
ערר (מרכז) 1094-09-19 (פדילה) נשמר כ-`1094-09-14` בעוד כל חמשת מסמכי
התיק גורסים ...-19. `_is_clean_docket` בדק **צורה בלבד**, ושתי הצורות
תקינות — כך שספרה שגויה אחת עברה את השער וניתקה את השורה מכל הפניה
לתיק האמיתי. `case_number` הוא שדה-זהות; זה לא שדה-תצוגה שאפשר לתקן
בקריאה.

שורש נוסף שהתגלה תוך כדי: ב-1094-09-19 המספר **אינו מופיע ב-full_text
כלל** (הטקסט מתחיל ב"בפני:"), כלומר המודל הפיק ספרות שאין להן עיגון
במקור — בדיוק מה ש-INV-AH בא למנוע.

מה שונה
- `_docket_grounded()` — כל קבוצת-ספרות של ה-docket חייבת להופיע, בסדר,
  בטקסט ההחלטה או בערך שהיא מחליפה. סובלני למפריד (`-` מול `/`), לרווחים
  סביבו, ולתווי-כיווניות (RLM/LRM) שנדחסים בתוך המספר ב-PDF עברי.
  המקורות לעולם אינם פלט-המודל עצמו — אחרת הבדיקה מעגלית.
- סירוב לכתוב מלווה `logger.warning` מפורש (§6) במקום להסתמך על הצורה.
- הפרומפט תוקן: הדוגמאות היו דו-חלקיות בלבד ('1062/24'), מה שהטה נגד
  docket תלת-חלקי של ועדות ערר. נוספו דוגמאות תלת-חלקיות והוראה מפורשת
  לא להשלים/לנחש/לתקן ספרה, ולהחזיר ריק כשהמספר אינו בטקסט.

אימות מול הקורפוס החי (386 שורות): מתוך 50 השורות שהנרמול חל עליהן
בפועל — **0 נחסמות**. הגארד חוסם רק ספרות שאין להן עיגון באף מקור.

invariants: INV-AH (quote-or-retract על שדה-זהות) · G1 (נרמול במקור) ·
§6 (סירוב מדווח, לא נבלע)

טסטים: 7 חדשים (tests/test_docket_grounding.py), הראשון שבהם משחזר בדיוק
את הרגרסיה — שתי הצורות עוברות את בדיקת-הצורה, רק הנכונה מעוגנת.
521 עוברים.
2026-08-05 10:45:22 +00:00

66 lines
2.9 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
"""#232 trap 3 — a well-formed docket is not necessarily the right docket.
ערר (מרכז) 1094-09-19 (פדילה) was stored as ``1094-09-14``: shape-valid, so
``_is_clean_docket`` waved it through, but wrong — and case_number is the
identity field, so the row detached from every reference to the real case.
Grounding the digits in the source text is what shape validation cannot do.
"""
from legal_mcp.services.precedent_metadata_extractor import (
_docket_grounded,
_is_clean_docket,
_strip_invisibles,
)
HEADER = "ערר (ועדות ערר - תכנון ובנייה מרכז) 1094-09-19 פדילה אברהים נ' הוועדה המקומית"
def test_the_regression_shape_valid_but_wrong_digit():
"""Both pass the shape check; only the real one is grounded."""
assert _is_clean_docket("1094-09-14")
assert _is_clean_docket("1094-09-19")
assert _docket_grounded("1094-09-19", HEADER)
assert not _docket_grounded("1094-09-14", HEADER)
def test_separator_and_spacing_are_tolerated():
"""A real docket must still match when the source writes it differently."""
assert _docket_grounded("1094-09-19", "בערר 1094/09/19 נקבע")
assert _docket_grounded("4768/22", "עת\"מ 4768-22 פלוני")
assert _docket_grounded("1132-09-24", "תיק 1132 - 09 - 24")
def test_bidi_marks_inside_the_number_do_not_defeat_grounding():
"""Hebrew legal PDFs embed RLM/LRM between digits and separators."""
noisy = "ערר (‏מרכז‏) 1094-09-19 פדילה"
assert _strip_invisibles(noisy).count("") == 0
assert _docket_grounded("1094-09-19", noisy)
def test_grounding_accepts_the_value_being_replaced():
"""Normalising an uploader's citation string into a clean docket is the
whole point of the rewrite — the digits come from there, not the text."""
citation = "ערר (ועדות ערר - תכנון ובנייה מרכז) 1094-09-19 פדילה נ' טירה (נבו 4.12.2019)"
assert _docket_grounded("1094-09-19", "", citation)
assert not _docket_grounded("1094-09-14", "", citation)
def test_two_and_three_part_dockets_both_ground():
assert _docket_grounded("8031/21", "בהיטל השבחה 8031/21 נדון")
assert _docket_grounded("85074-09-24", "בל\"מ 85074-09-24")
def test_non_numeric_or_empty_never_grounds():
assert not _docket_grounded("", HEADER)
assert not _docket_grounded("ערר 1094", HEADER)
assert not _docket_grounded("abc-de", HEADER)
def test_absent_from_every_source_is_refused():
"""The פדילה failure mode: text has no docket at all, so anything the
model offers is ungrounded and must not reach the identity field."""
body = "בפני: יו\"ר הוועדה: רונית אלפר, עו\"ד\nהעוררים: 1. פדילה אברהים"
assert not _docket_grounded("1094-09-14", body)
assert not _docket_grounded("1094-09-19", body)