feat(halacha): strict-rubric quality gate + dedup-on-insert (#81,#82)

Bake the 2026-06-03 strict-cleanup rubric into the extraction pipeline so the
corpus stays clean at the source instead of accumulating duplicates, obiter
dicta, truncated quotes and thin restatements that clog the review queue.

#81 — quality gate:
- New pure module halacha_quality.py with unit-tested validators:
  non-decision/obiter (Wambaugh markers), truncated-quote (mid-word cut),
  thin-restatement (rule≈quote), quote-unverified.
- Validators run in halacha_extractor._process; a non-decision is re-typed
  obiter; flags persist in new halachot.quality_flags column.
- Auto-approve now requires confidence>=threshold AND no quality flags;
  flagged items route to pending_review regardless of confidence.
- Both extraction prompts hardened: reject undecided dicta, exclude
  case-specific applications, require abstraction, forbid over-splitting.

#82 — dedup-on-insert (store_halachot_for_chunk):
- Within the same precedent, skip a halacha whose normalized supporting_quote
  already exists, or whose rule-embedding has cosine>=HALACHA_DEDUP_COSINE
  (0.93) against an already-stored one. Makes re-runs idempotent.

Migration: halachot.quality_flags TEXT[] (additive, idempotent ALTER).
Tests: 19 new unit tests; full suite 156 passed. Validated end-to-end against
dev DB (dedup skips dups, flag blocks auto-approve, re-run inserts 0).
Calibration: flags fire on only ~10% of current survivors (low false-positive).

Spec: docs/halacha-strict-rubric.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-03 12:30:38 +00:00
parent b0ec24a9d5
commit ca959d4a9c
6 changed files with 386 additions and 18 deletions

View File

@@ -0,0 +1,37 @@
# רובריקת "הכללים המחמירים" לחילוץ הלכות — להחלה על הלכות קיימות
אתה בודק רשימת הלכות שחולצו מפסק דין **אחד**, ומחליט לכל אחת: לשמור או לחתוך (ובאיזו עילה).
המטרה: שיישארו רק **עקרונות משפטיים אמיתיים, מובחנים, בני-הכללה ובני-הסתמכות** — לא ציטוטים, לא אמרות-אגב, לא יישומים ספציפיים-לתיק, לא כפילויות.
## עילות חיתוך (verdict)
1. **cut_duplicate** — ההלכה מבטאת את **אותו עיקרון משפטי** של הלכה אחרת באותו פסק, גם אם בניסוח שונה / ציטוט שונה.
- קבץ את כל המופעים של אותו עיקרון. שמור **נציג אחד** בלבד; סמן את השאר cut_duplicate.
- בחירת הנציג (canonical): עדיפות rule_type (binding > interpretive > procedural > obiter) → confidence גבוה → quote_verified=true → הניסוח המלא/הברור ביותר.
- דווח `cluster_canonical_index` = ה-halacha_index של הנציג שנשמר.
2. **cut_obiter** — אמרת-אגב שהערכאה **לא הכריעה בה**. סימנים: "אין צורך להכריע", "מבלי לקבוע מסמרות", "איני רואה לקבוע מסמרות", "לא ראינו לקבוע", "ניתן/יש להניח ... אך", "למעלה מן הצורך", "אגב אורחא", או הסתמכות על "לכאורה" כבסיס.
- מבחן Wambaugh: אם שלילת הכלל **לא** הייתה משנה את תוצאת הפסק → obiter.
3. **cut_application** — קביעה שתלויה ב**עובדות התיק הספציפי** ואינה בת-הכללה: שמות צדדים ("המשיבים", "המערערים", שם משפחה), "במקרה דנן/שבפנינו", סכומים/תאריכים/מספרים ספציפיים למחלוקת, יישום הכלל על המבנה/ההיתר הקונקרטי. זהו "ציטוט שטוב שיש" — המחשה, לא הלכה.
4. **cut_thin** — restatement דק: ה-rule_statement כמעט מעתיק את supporting_quote בלי הפשטה; **או** הכלל מנוסח כרקע/מוסכמה ("אין חולק כי...") ולא כהכרעה.
5. **cut_quote** — ה-supporting_quote קטוע באמצע משפט / חסר, או quote_verified=false וההלכה נשענת עליו.
6. **keep** — עיקרון משפטי אמיתי, מובחן, בר-הכללה, שהוכרע, עם ציטוט תומך שלם.
## כללי הכרעה — רמה אגרסיבית
המטרה: להשאיר רק את **גרעין העקרונות המובחנים**. עדיף תמציתי ומדויק על פני שלם-ומנופח.
- **cut_application אסרטיבי:** כל קביעה שנשענת על עובדות/צדדים/סכומים ספציפיים לתיק → cut_application, גם אם משתמעת ממנה הלכה. ההלכה המופשטת כבר אמורה להופיע בנפרד; היישום עצמו מיותר.
- **מיזוג facets חופפים (cut_duplicate מורחב):** אם שתי הלכות עונות על **אותה שאלה משפטית** גם אם מזווית/פן שונה — מזג לנציג הכללי/binding ביותר. דוגמאות למיזוג: עקרונות-משנה בתוך אותו נושא (סמכות ועדת הערר, מתחם שיקול-הדעת התכנוני, מיצוי הליכים, בטלות יחסית).
- **גבול המיזוג (שמור):** אל תמזג הלכות שעונות על **שאלות משפטיות שונות** (למשל "מועד 30 יום להגשת ערר" ≠ "עקרון מיצוי ההליכים"; "פרשנות תיקון 43" ≠ "סמכות לפי סיווג הבקשה"). מזג פנים-של-אותה-שאלה, לא בין-שאלות.
- **dedup מושגי הוא העיקרי:** רוב החיתוך מ-cut_duplicate. שים לב לעקרונות שחוזרים 3-5 פעמים בניסוחים שונים וגם ל-facets שחוזרים סביב אותו נושא.
- בספק בין keep ל-cut בקטגוריה מאבדת-מידע: ברמה זו **נטה לחתוך** (אך לעולם לא למזג שאלות-משפטיות שונות).
## פלט (JSON בלבד)
מערך, פריט לכל הלכה:
```json
[{"halacha_index": <int>, "verdict": "keep|cut_duplicate|cut_obiter|cut_application|cut_thin|cut_quote", "cluster_canonical_index": <int או null>, "reason": "<משפט אחד>"}]
```