chore: fix .gitignore inline comments + add untracked code files
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m32s
G12 Leak-Guard / leak-guard (push) Successful in 5s
Lint — undefined names / undefined-names (push) Successful in 11s

Inline # comments in gitignore are not supported — they were silently
breaking three patterns (data/checkpoints/, data/adapter-migration-state.json,
.claude/agents/.generated/). Moved comments to their own lines and added
missing entries for runtime dirs (data/audit/, data/logs/, etc.) and
temp files (.interaction_tmp.json, .design-build/, .taskmaster bak files).

Also tracks previously untracked legitimate files: scripts, tests, docs,
skills references, .env.example, taskmaster templates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-27 12:46:32 +00:00
parent b4a68cf5da
commit 4de555367d
17 changed files with 3108 additions and 3 deletions

View File

@@ -0,0 +1,170 @@
# ממצאי ביקורת — ארכיטקטורת קורפוס־הפסיקה + מצב הדאטה בפועל
> **מקור:** Claude (Opus 4.8) · **תאריך:** 2026-06-20 · **קונטקסט:** חקירה לקראת תכנון־מחדש של קורפוס־הפסיקה.
> מסמך זה הוא **אחד מכמה** קלטי־סוכנים שחיים אוסף; ייעודו להזין את שלב־הסינתזה. אינו תכנית — הוא **אבחון**.
>
> **שאלת־המוצא של חיים:** "הקורפוס נבנה מראש לא נכון, אני כל הזמן מתעסק בתיקונים. האם כדאי ליצור מחדש את קורפוס־הפסיקה ולהתחיל דף נקי?"
>
> **המודל הרצוי (כפי שחיים תיאר אותו):** מאגר פסקי־דין והחלטות ועדות־ערר; חוקר־התקדימים מזהה בשלב ניתוח־הערר פס"ד/החלטות שדנו במקרה דומה או הלכה דומה; הסוכן־הכותב משייך ומזכיר אותם בפרק הדיון וההכרעה בסגנון דפנה. שלושה מקורות־הזנה: (1) החלטות דפנה עצמה, (2) ועדות־ערר אחרות שמצטטות פסיקה, (3) פס"ד עליון/מחוזי.
---
## 0. תקציר־מנהלים (TL;DR)
**מה ש"בנוי לא נכון" אינו הסכמה — היא שכבת־הביצוע.** הסכמה כבר תואמת בדיוק את המודל שחיים תיאר: טבלה אחת (`case_law`) ששלושת המקורות נכנסים אליה דרך `source_kind`/`source_type`; שלושת ה־`search_*` הם שלושה *מסננים* על אותו מקור, לא שלושה מאגרים מקבילים (G2 מקוים ברמת־הסכמה). **רֵבילד של הסכמה ייצר בדיוק את אותה סכמה** — ולכן אינו פותר דבר, ומסכן ב־second-system syndrome.
מה שכן מחולל את "התיקונים האינסופיים" — שלושה כשלי־ביצוע מדידים:
1. **חוזה־קליטה רופף** → 66% מהפסיקה בלי `practice_area`, 31 רשומות ריקות, אכיפת־שלמות (INV-DM1) מופרת בפועל.
2. **צינור הלכות→קנוני מייצר רעש** → 5,472 קנוני, מתוכם 5,456 סינגלטונים, **0 published** → השכבה שאמורה להזין את הכותב (INV-G10) **אינרטית לגמרי**.
3. **כפילות `style_corpus`** → 55 החלטות דפנה חיות בשני נתיבי־אחזור.
**המלצה:** לא לשרוף את הסכמה. כן לבצע "איפוס שכבות־נגזרות" צר (truncate ל-chunks+halachot+canonical והרצה־מחדש), **אבל רק אחרי תיקון החוזה והסף** — אחרת מחזירים את אותו בלגן (G1: תיקון במקור, לא בקריאה). מסמכי־המקור (363 רשומות, 332 עם full_text) נשמרים; הם יקרים ו/או ניתנים לקליטה־מחדש מ־PDF.
---
## 1. מצב הדאטה בפועל (שאילתות חיות מול legal_ai @ localhost:5433, 2026-06-20)
```
┌─────────────────────────────────────┬─────────┬──────────────────────────────────┐
│ Metric │ Count │ Reading │
├─────────────────────────────────────┼─────────┼──────────────────────────────────┤
│ case_law (total precedents) │ 363 │ קטן — re-ingestable │
│ • external_upload (court rulings) │ 240 │ מקור (3) — עליון/מחוזי │
│ • internal_committee (ועדות ערר) │ 92 │ מקור (1)+(2) │
│ • (יתר — ללא source_kind מובהק) │ 31 │ = הרשומות הריקות (ראה למטה) │
│ style_corpus (החלטות דפנה) │ 55 │ כפילות עם internal_committee │
│ precedent_chunks │ 11,904 │ נגזר — מתחדש מ-full_text │
│ halachot (total) │ 5,489 │ נגזר │
│ • approved/published │ 1,352 │ 25% בלבד │
│ • pending_review (backlog ידני) │ 2,402 │ 44% — צוואר־בקבוק │
│ canonical_halachot (V41) │ 5,472 │ כמעט 1:1 עם halachot ⚠️ │
│ • singletons (instance_count=1) │ 5,456 │ דה־דופ כמעט לא קרה │
│ • merged (instance_count>=2) │ 16 │ 0.3% מיזוג │
│ • published (מגיע לסוכן הכותב) │ 0 │ ⚠️ השכבה אינרטית לחלוטין │
│ case_law w/o practice_area │ 240 │ 66% — חופף-בדיוק לפסיקה החיצונית │
│ case_law missing summary │ 27 │ │
│ case_law w/ 0 chunks / no full_text │ 31 │ רשומות שבורות/ריקות │
│ distinct practice_area │ 4 │ rishuy/betterment/197/(ריק) │
└─────────────────────────────────────┴─────────┴──────────────────────────────────┘
practice_area breakdown:
(ריק) 240 ← כל הפסיקה החיצונית ללא סיווג
rishuy_uvniya 70
betterment_levy 50
compensation_197 3
```
**קריאות מפתח:**
- **240 = 240:** מספר הפסיקה־החיצונית שווה־בדיוק למספר חסרי־`practice_area`. כלומר אף פס"ד חיצוני לא סווג לתחום — סינון לפי תחום באחזור פשוט לא עובד עליהם.
- **5,456 / 5,472 סינגלטונים:** מנוע הקנוניזציה (V41) רץ אך לא מאחד. סף 0.85 כנראה הדוק מדי, או שהחילוץ מנסח כל הלכה ייחודית מספיק כדי לא להתלכד.
- **0 published canonical:** לפי INV-G10 רק קנוני `published` מגיע לכתיבה. אפס. **כל מנגנון V41 כרגע מנותק מהכתיבה בפועל.**
- **2,402 pending_review:** צוואר־הבקבוק הוא אישור־אנושי ידני, לא טכנולוגיה.
---
## 2. מפת הארכיטקטורה — קורפוס אחד, שלושה מסננים
**פיזית: טבלה אחת.** כל שלושת המקורות מתכנסים ל-`case_law`, מתחתיה `precedent_chunks` (FK) ו-`halachot` (FK), ומעל ה-`halachot` שכבת `canonical_halachot` (V41).
```
canonical_halachot (עקרונות מאוחדים — V41; כיום אינרטי, 0 published)
▲ 1:many
halachot (מופע-להלכה per precedent; review_status gate)
▲ FK
case_law (רישום מרכזי — court rulings + ועדות-ערר)
├─ source_kind='external_upload' → פס"ד עליון/מחוזי [מקור 3]
└─ source_kind='internal_committee'→ ועדות-ערר + דפנה [מקור 1+2]
▼ FK
precedent_chunks (chunks + embedding vector(1024))
בנפרד:
style_corpus (55 החלטות דפנה — נתיב-אחזור מקביל ל-search_decisions)
document_chunks (מסמכי-תיק + style; FK→documents→cases)
```
**שלושת נתיבי־האחזור (לא שלושה מאגרים — שלושה scopes):**
```
┌──────────────────────────────┬─────────────────────────┬────────────────────────────┐
│ Tool │ Table / filter │ Purpose │
├──────────────────────────────┼─────────────────────────┼────────────────────────────┤
│ search_decisions │ document_chunks │ סגנון/קול: החלטות דפנה │
│ │ (scoped case/area) │ + מסמכי-תיק │
│ search_precedent_library │ case_law + chunks/halach │ source_kind=external_upload│
│ │ ot, source_kind filter │ → פסיקה חיצונית │
│ search_internal_decisions │ אותן פונקציות DB, │ source_kind=internal_ │
│ │ source_kind אחר │ committee → ועדות-ערר │
└──────────────────────────────┴─────────────────────────┴────────────────────────────┘
```
שתי האחרונות קוראות **לאותן פונקציות DB** (`search_precedent_library_semantic`/`_lexical`) עם `source_kind` שונה. זו הפרדה־בשאילתה, לא קוד מקביל.
---
## 3. שלושת המקורות של חיים → איפה הם נופלים היום
```
┌────────────────────────────────────┬───────────────────────────────┬─────────────────────────┐
│ Source (חיים) │ Stored as │ Retrieval │
├────────────────────────────────────┼───────────────────────────────┼─────────────────────────┤
│ (1) החלטות דפנה עצמה │ style_corpus + (מהוגר ל-) │ search_decisions + │
│ │ case_law internal_committee │ search_internal_decisions│
│ │ chair_name='דפנה תמיר' │ ← כפילות / נתיב-כפול │
│ (2) ועדות-ערר אחרות │ case_law internal_committee │ search_internal_decisions│
│ │ chair_name=<אחר>, district │ │
│ (3) פס"ד עליון/מחוזי │ case_law external_upload │ search_precedent_library │
│ │ source_type='court_ruling' │ │
└────────────────────────────────────┴───────────────────────────────┴─────────────────────────┘
```
**מסקנה:** המודל המנטלי של חיים **כבר ממומש בסכמה**. אין צורך להמציא מבנה חדש — צריך לאכוף את המבנה הקיים בקליטה, ולחבר את שכבת־הקנוני לכתיבה.
---
## 4. הדיאגנוזה — מה "בנוי לא נכון" (3 מחוללי־כאב)
### 4.1 חוזה־קליטה רופף (root cause #1)
- 66% מהפסיקה ללא `practice_area`; 27 ללא summary; 31 ללא full_text/chunks.
- אין אכיפה ש"`searchable=false` עד שהמטא שלם" → INV-DM1 מופר בפועל.
- **כל העלאה מוסיפה חוב** במקום רשומה שלמה. זה המקור לתיקונים החוזרים.
### 4.2 צינור הלכות→קנוני מייצר רעש, לא ערך (root cause #2)
- 5,456/5,472 סינגלטונים → דה־דופ לא עובד (סף 0.85? ניסוח־חילוץ?).
- **0 published** → השכבה שאמורה להזין את הכותב (INV-G10) מנותקת.
- 2,402 בתור־אישור־ידני → הצינור מייצר מהר יותר ממה שאדם מאשר.
- **זה בולע את רוב זמן־התחזוקה.**
### 4.3 כפילות style_corpus (root cause #3)
- 55 החלטות דפנה בשני מקומות + שני נתיבי־אחזור.
- צריך מקור־אמת אחד: או `style_corpus` SoT וה-`case_law` נגזר, או הפוך.
---
## 5. ההמלצה — לא רֵבילד־סכמה; "איפוס שכבות־נגזרות" אחרי תיקון־חוזה
**אסור** לשרוף ולהעלות־מחדש את `case_law` — תבנה אותה סכמה ותאבד מטא־דאטה ידני. **כן** הגיוני רֵבילד צר של ה**נגזר**, אבל בסדר הזה (G1 — מקור לפני תסמין):
1. **קודם החוזה:** אכוף ב-`*_upload` שדות־חובה (practice_area, summary, full_text); כשל → `searchable=false`. נקה/מחק את 31 הריקות.
2. **תקן את הקנוניזציה:** כוונן סף 0.85, הגדר מתי `published`, ובדוק ניסוח־החילוץ. בלי זה אין טעם להריץ מחדש.
3. **רק אז** re-derive מהמקור הקיים: chunks → halachot → canonical.
4. **הכרע style_corpus:** מקור־אמת אחד.
**מתי רֵבילד־מלא כן מוצדק:** רק אם יתגלה שמסמכי־המקור עצמם (PDF/full_text של 363) פגומים/חסרים. המספרים *לא* מראים זאת (332/363 עם full_text תקין).
---
## 6. שאלות פתוחות לשלב־הסינתזה
- **למה 0 published בקנוני?** האם זה סף, ניסוח־חילוץ, או שפשוט אף אחד לא אישר? (קריטי — קובע אם V41 שמיש בכלל.)
- **style_corpus מול case_law:** מי SoT? (משפיע על search_decisions מול search_internal_decisions.)
- **practice_area לפסיקה חיצונית:** לחלץ אוטומטית בקליטה, או להשאיר ידני?
- **תור־האישור (2,402):** האם המנגנון (פאנל/active-learning, #133) יכול לסגור את הפער, או שצריך לחתוך את קצב־החילוץ?
---
## 7. נספח — קבצים מרכזיים (file:line)
- סכמה: `mcp-server/src/legal_mcp/services/db.py` (case_law, precedent_chunks, halachot, canonical_halachot)
- קליטה חיצונית: `mcp-server/src/legal_mcp/tools/precedent_library.py` (`precedent_library_upload`)
- קליטה פנימית: `mcp-server/src/legal_mcp/tools/internal_decisions.py` (`internal_decision_upload`)
- הגירת style→case_law: `mcp-server/src/legal_mcp/services/internal_decisions.py` (`migrate_from_style_corpus`, chair/district hardcoded)
- אחזור: `mcp-server/src/legal_mcp/tools/search.py`, `services/hybrid_search.py`, `services/db.py` (`search_precedent_library_semantic`/`_lexical`)
- ספ: `docs/spec/02-data-model.md` (INV-DM17), `docs/spec/03-retrieval.md` (INV-RET15), `docs/spec/00-constitution.md` (G2/G10)

View File

@@ -0,0 +1,125 @@
# 06 — נדיבות-המחלץ: `application` בהחלטות-ועדה (כימות חוצה-קורפוס)
> **קלט-נתונים** ליוזמה, נמדד חי על **5,489 רשומות `halachot`** (כל הקורפוס, 2026-06-20).
> נולד משאלת-חיים: "8508-03-24 מפיק 71 הלכות ממתינות — האם המחלץ נדיב מדי על החלטות-ועדה,
> או שזה ספציפי לתיק הזה?" התשובה: **שיטתי, לא ספציפי — אבל הנדיבות מוצדקת.**
>
> **מתכתב עם [`00-final-synthesis.md`](00-final-synthesis.md):** הנתונים כאן **מחזקים** את הכרעת-הסינתזה
> ("לא לחתוך") ומוסיפים שני דברים שלא היו לה: (א) כימות חוצה-קורפוס של ה-`application`, (ב) ממצא
> חדש וגדול יותר — `nli_unsupported` על הפסיקה החיצונית. ראה §4 (יישוב-מתח) ו-§5 (דרכי-פעולה).
---
## 1. הממצא המרכזי — `application` הוא תופעה שיטתית של החלטות-ועדה
הפרדנו את הקורפוס לפי `authority` (נגזר דטרמיניסטית מ-`precedent_level`, [02-data-model §162](../spec/02-data-model.md)):
`binding` = פסיקת-עליון/מנהלי · `persuasive` = ועדת-ערר מחוזית.
```text
source rows rt=application nli_unsupported any-flag
court (binding) 3,603 0.2% 39.7% 45.4%
committee (persuasive) 1,842 13.7% 25.0% 30.5%
```
- **`rule_type='application'` הוא כמעט-בלעדית של ועדות:** 13.7% מול 0.2%. מתוך 258 רשומות-`application`
בכל הקורפוס, **~252 מגיעות מהחלטות-ועדה.** פער של פי-~70.
- **עקבי בין תחומים** (לא עניין-שמאות נקודתי):
```text
committee, rt=application by practice_area:
rishuy_uvniya 13.5% betterment_levy 14.1% compensation_197 18.8%
```
**הפרשנות (תואם [02-data-model §163](../spec/02-data-model.md)):** `application` = "החלה תלוית-עובדות —
לרוב לא-הלכה". ועדת-ערר היא גוף מיישֵם: היא לא יוצרת הלכה (רק בית-משפט עושה זאת), אלא **מיישמת
פסיקת-עליון קיימת** (לוסטרניק, דלי-דליה) על עובדות-התיק. לכן חילוץ מהחלטת-ועדה מייצר באופן מובנה
שיעור גבוה של יישומי-דוקטרינה. **זו תכונה של מקור-הנתונים, לא באג של המחלץ.**
## 2. 8508-03-24 — מייצג בקצה-העליון, לא חריג
```text
דירוג 8508-03-24: 7 מתוך 45 תיקי-ועדה (≥15 רשומות) · 27% application (rt או flag)
חציון תיקי-הוועדה: 11.9%
מעליו: 1001-02-19 (40%) · 1044-08-22 (37%) · 9002-24 (33%) · 1007-01-25 (30%)
```
8508 הוא ~פי-2.3 מהחציון (רבעון-עליון), אבל מה שבולט בו הוא בעיקר ש**הוא התיק הארוך בקורפוס**
(111 רשומות) — אז 27% נותן 30 פריטי-`application` במספר מוחלט, הגבוה בקורפוס. כלומר: **כמות גבוהה,
שיעור גבוה-אך-נורמלי.** אין כאן פתולוגיה ייחודית לתיק.
## 3. מנגנון-הניתוב הקיים (איך זה כבר מטופל ב-UI)
הפיצול בתור-ההלכות (`/precedents` → "תור הלכות") אינו לפי `exclude_low_quality`, אלא לפי
`isExtractionFixItem(h) = (quality_flags.length>0) && !panel_round`
([web-ui/.../precedent-library.ts:652](../../web-ui/src/lib/api/precedent-library.ts#L652)):
```text
8508-03-24, 71 ממתינות (מצב 2026-06-20):
bucket # panel? →"להכרעתך" →"דורש תיקון-חילוץ"
clean (ללא דגל) 40 15/40 40 0
application 23 0/23 0 23
nli_unsupported 4 4/4 4 0
thin_restatement 4 0/4 0 4
```
**משמעות:** פריטי-`application` (חסרי-פאנל) כבר מנותבים ל**"דורש תיקון-חילוץ"** — **מחוץ** לתור-ההכרעה
של היו"ר. כלומר המערכת כבר מסננת אותם מהעומס-הידני. (הפאנל התלת-מודלי, [halacha_panel_approve.py:191](../../scripts/halacha_panel_approve.py#L191),
מטפל רק בדליים `clean`+`nli`; `application` ו-`defect` עוקפים אותו במכוון.)
## 4. ⚠️ יישוב-המתח מול הסינתזה — `application` ≠ "רעש"
זו הנקודה הקריטית להעברה. **אסור** לתרגם "13.7% application" ל"13.7% רעש לחיתוך". המבחן בסינתזה
(§2 שם) כבר הוכיח שחיתוך-אגרסיבי על 8508 השמיד את **לוסטרניק** ו-~22 עקרונות-ליבה. רוב פריטי-ה-`application`
הם בדיוק יישומי-הדוקטרינה הללו — **בני-ציטוט שהכותב צריך**. דוגמאות אמיתיות מ-8508 שמסומנות `application`:
```text
"ציפיות הנובעות אך ממיקומם של המקרקעין... אין לנטרלן" ← לוסטרניק מיושמת — לשמור!
"בחישוב שווי במצב קודם יש לכלול ציפיות כלליות... ולא ספציפיות" ← ליבת חישוב היטל-ההשבחה
"קביעת מקדם מצויה בליבת שיקול-דעת השמאי, והוועדה לא תתערב" ← סטנדרט אי-התערבות מיושם
```
לכן: **הנתון הזה תומך ב"שמור-בספק" של עמוד-1/2 בסינתזה.** המסקנה הנכונה אינה "לסנן application" אלא
"`application` מאשר שעקרוני-הוועדה הם persuasive-יישומיים — לדרג אותם נמוך באחזור (רמה B), לא למחוק
אותם (רמה A)". `importance=0` ל-8508 כבר משקיע אותם ממילא.
## 5. ⭐ ממצא-לוואי גדול יותר — `nli_unsupported` על הפסיקה החיצונית
```text
nli_unsupported: court (binding) 39.7% ≫ committee 25.0%
any-flag: court 45.4% · committee 30.5%
```
**כמעט מחצית מעקרוני-הפסיקה-החיצונית נושאים דגל-איכות, בעיקר `nli_unsupported`** (הכלל אינו נגזר
לוגית מהציטוט התומך שלו, [halacha_quality.py:282](../../mcp-server/src/legal_mcp/services/halacha_quality.py#L282)).
זה **מגמד מספרית** את סוגיית-ה-`application`, ונוגע ישירות ל"רמה A = ניקוי-רעש" של הסינתזה:
**מהו ה"רעש" שמנקים?** הדגל הדומיננטי הוא `nli`, והוא מרוכז בפסיקה, לא בוועדות.
שתי השערות מתחרות, שצריך להכריע ביניהן **לפני** שמשתמשים ב-`nli` כמסנן-רעש ברמה A:
- **(א) הבודק מחמיר מדי** — סף-ה-NLI חותך יישורים לגיטימיים → 40% הם false-positives, וה"רעש" מדומה.
- **(ב) החילוץ-מהפסיקה לקוי** — ציטוטים תומכים שלא מיישרים לכלל → בעיית-חילוץ אמיתית בקנה-מידה.
ההכרעה משנה את כל אסטרטגיית רמה-A. **אנו ממליצים לאמת זאת על מדגם-זהב לפני כל שימוש ב-`nli` כסיגנל.**
---
## 6. דרכי-פעולה מוצעות (לסוכן-הקורפוס)
ממוין מהשמרני לאגרסיבי. ההמלצה שלנו: **B כברירת-מחדל + C כעבודה-מקבילה**; להימנע מ-A ומ-D.
| # | פעולה | טיעון | סיכון | המלצה |
|---|-------|-------|-------|-------|
| **A** | לכוונן את ה-prompt לדכא `application` מוועדות במקור | מטפל-בשורש (G1); חוסך 14% רשומות | **גבוה** — סותר את מבחן-8508; משמיד יישומי-לוסטרניק בני-ציטוט | ✗ לא |
| **B** | להשאיר את החילוץ; לסמוך על הניתוב הקיים (`application`→"תיקון", מחוץ לתור-היו"ר) + לדרג נמוך ב-RRF | תואם-סינתזה (שמור-בספק + דרג-בזמן-אחזור); אפס סיכון-אובדן | הרעש נשאר ב-DB (אחסון בלבד) | ✓ **כן — ברירת-מחדל** |
| **C** | לחקור קודם את `nli_unsupported` (40% פסיקה): מדגם-זהב, להכריע (א) מחמיר-מדי מול (ב) חילוץ-לקוי | זה הסיגנל הגדול; הכרחי לפני שמגדירים "רעש" ברמה A | דורש מדגם מתויג-ידנית | ✓ **כן — במקביל** |
| **D** | להפסיק חילוץ-עקרונות מוועדות לגמרי | רוב עקרוני-הוועדה הם שכתוב-persuasive של עליון | **קיצוני** — נוגד 07-learning §61 (ועדות ברות-ציטוט במכוון); נוגע INV-LRN | ✗ לא (אלא בהכרעת-יו"ר מפורשת) |
### ההמלצה המזוקקת
1. **לא לגעת בחילוץ-מוועדות** — הנתון מאשר שהנדיבות מוצדקת; `application`=יישום-בר-ציטוט, לא זבל. עקבי עם
הכרעת-הסינתזה "לא לחתוך".
2. **רמה B עושה את העבודה**`importance` boost ב-RRF מטביע את עקרוני-הוועדה ה-persuasive מתחת
לפסיקה-המחייבת, בלי למחוק דבר. 8508 (`importance≈0`) שוקע ממילא.
3. **להעביר את ה-`nli` לראש תור-המחקר** — לפני שמשתמשים בו כמסנן-רעש ברמה A, לאמת אם 40% אמיתי.
---
> **מקור-הנתונים:** `GET /api/halachot?limit=100000` (5,489 שורות) + per-case `?case_law_id=…`.
> ניתן לשחזר את כל המספרים מהשאילתות האלו. הקאנון הוא live — שיעורים ינועו ככל שהדריינר/פאנל רצים.