13 KiB
01 — קליטה מאוחדת (Unified Ingest Contract)
קובץ-תחום זה כפוף ל-חוקת המערכת ומפרט את חוזה הקליטה של כל סוגי ה-intake. הוא אוכף את G2 (מקור-אמת יחיד, אין מסלולים מקבילים) ואת G3 (ingest אחיד ו-idempotent), ונשען על G4 ו-G6.
כשל-השורש שהקובץ מייבש: שני מסלולי ingest לישויות-אחיות שמתפצלים — ingest_precedent
(פסיקה חיצונית) מול ingest_internal_decision (החלטות-ועדה). מסלולים מקבילים גוררים drift:
פריט שנקלט במסלול אחד מקבל טיפול שונה מפריט במסלול האחר, והפער מתגלה רק כשרשומה חסרה
metadata או לא נמצאת בחיפוש. החוזה כאן מגדיר מסלול קנוני אחד ש-3 סוגי ה-intake עוברים בו.
1. שלושת סוגי ה-intake
| סוג-intake | מזהה-קנוני | קורפוס-יעד | מאפיין ייחודי |
|---|---|---|---|
| מסמכי-תיק (case documents) | case_number + מזהה-מסמך |
תיק ערר פעיל | משויך לתיק, מסווג לפי סוג-מסמך |
| פסיקה חיצונית (external precedent) | citation (קנוני) |
case_law (external) |
staging לפי source_type, ולידציית-enums, citation guard, multimodal |
| החלטות-ועדה (internal-committee) | case_number (קנוני) |
case_law (internal_committee) |
staging לפי district, chair_name חובה, גזירת district/proceeding_type |
שלושתם הם ישויות-אחיות: אותו טיפוס-עיבוד (קובץ → טקסט → chunks → embeddings → metadata → הלכות), נבדלים בפרמטרים בלבד — לא במסלול-קוד. זוהי משמעות "סימטריה" (חוקה §6).
2. המסלול הקנוני (Canonical Pipeline)
צעדי-העיבוד, בסדר מחייב. כל סוג-intake עובר את אותם צעדים; ההבדל הוא אילו פרמטרים מוזרקים בקלט, לא אילו צעדים מורצים.
- Stage file — העתקה דטרמיניסטית לאחסון המתמיד. נתיב-ה-staging הוא פרמטר
(
source_typeלפסיקה חיצונית, district להחלטות-ועדה), לא ענף-קוד נפרד. - Extract text —
extractor.extract_text→(text, page_count, page_offsets). טקסט ריק = כשל מדווח (לא בליעה שקטה; חוקה §6). - Strip Nevo preamble —
extractor.strip_nevo_preambleלהסרת עטיפת-Nevo. אחיד לכל סוג. - Chunk — היררכי (
chunk_document_hierarchical) אםPARENT_DOC_RETRIEVAL_ENABLED, אחרת שטוח (chunk_document). אותו ענף-flag בדיוק לכל סוג — בורר הצ'אנקינג נגזר מ-config, לא מסוג-ה-intake. - Embed —
embeddings.embed_texts(..., input_type="document")ל-children (היררכי) או לכל ה-chunks (שטוח). - Store chunks —
store_precedent_chunks_hierarchicalאוstore_precedent_chunks. - Page-image embed (multimodal) — אם
MULTIMODAL_ENABLEDוגם הקובץ PDF וגםpage_count>0: הטמעת עמודי-תמונה (_embed_precedent_pages). non-fatal: מסלול-הטקסט כבר הצליח. התנאי אחיד — הפעלה תלויה ב-flag+סוג-קובץ, לא בסוג-ה-intake. - Queue metadata extraction —
request_metadata_extraction(case_law_id). נדרש לכל סוג שתומך במטא-דאטה (ראה INV-ING3). - Queue halacha extraction —
request_halacha_extraction(case_law_id). - Set statuses —
extraction_status=completed,halacha_status=pending. החילוץ ה-LLM-י (metadata + הלכות) רץ בנפרד מ-Claude Code המקומי (precedent_process_pending), כיclaudeCLI אינו זמין בקונטיינר.
צעדים שחייבים להיות אחידים בכל סוג (תיקון האסימטריה): 2 (extract), 3 (strip-Nevo), 4 (בורר-chunk לפי flag), 5–6 (embed+store), 7 (multimodal — לפי flag+PDF, לא לפי סוג), 8–9 (תיזמון שני החילוצים), 10 (statuses). מה שרשאי להשתנות לפי סוג: נתיב-ה-staging (צעד 1), ולידציות-קלט ספציפיות, וגזירת-שדות (district/proceeding_type) — אלו פרמטרים של אותו מסלול, לא מסלול נפרד.
3. Invariants של התחום
INV-ING1: מסלול-קליטה קנוני יחיד
כלל: כל סוגי ה-intake (מסמכי-תיק / פסיקה חיצונית / החלטות-ועדה) זורמים דרך פונקציית-
קליטה קנונית אחת. סוג-intake חדש מורחב דרך פרמטרים של אותה פונקציה — לעולם לא דרך
פונקציה מקבילה. נתון-נגזר (district, proceeding_type) מחושב בתוך המסלול, לא בענף נפרד.
מקורות: Martin Kleppmann, DDIA (O'Reilly, 2017 — system of record יחיד) · Martin
Fowler (Canonical Data Model) · SSOT (Single Source of Truth) | סטטוס: verified
אכיפה: ביקורת-ארכיטקטורה + כלל-הנדסה "סימטריה" (חוקה §6); הקליטה מתנקזת לפונקציה אחת
שמקבלת פרמטרי-סוג. אוכף את G2.
הפרה ידועה: היום קיימים שני מסלולים — ingest_precedent
(precedent_library.py:88) ו-ingest_internal_decision (internal_decisions.py:73) —
שמשכפלים את צעדי 2–10 ומתפצלים בפרטים → ממצא ל-audit.
INV-ING2: קליטה idempotent על המזהה הקנוני
כלל: הקליטה היא idempotent על המזהה הקנוני (citation לפסיקה חיצונית,
case_number להחלטות-ועדה ולמסמכי-תיק). קליטה חוזרת של אותו פריט = upsert —
אין רשומה כפולה ואין chunks כפולים; התוצאה זהה.
מקורות: Martin Kleppmann, DDIA (idempotence & exactly-once) · Stripe / CDC
idempotency-key pattern · ISO 8000 (Data quality) | סטטוס: verified
אכיפה: מפתח-upsert דטרמיניסטי על המזהה הקנוני בנקודת-הקליטה (create_external_case_law
/ create_internal_committee_decision) + ולידציית-כתיבה; קשור ל-
X1-identifiers.md (נרמול בכתיבה). אוכף את
G3.
הפרה ידועה: 3 החלטות "סופר" נקלטו ב-3 פורמטים (8126/24, ציטוט-מלא כ-case_number)
— היעדר מפתח-upsert דטרמיניסטי גרר רשומות-כפל במקום עדכון → ממצא ל-audit.
INV-ING3: תור חילוץ מטא-דאטה + הלכות לכל סוג
כלל: חילוץ-מטא-דאטה וגם חילוץ-הלכות מתוזמנים (queue) עבור כל סוג-intake שתומך
בהם — תיזמון אחיד, לא מותנה במסלול. שני התורים נפתחים יחד בסיום העיבוד הלא-LLM-י.
מקורות: ISO 8000 (completeness) · DAMA-UK Six Primary Dimensions for Data Quality
(2013, completeness) · Martin Fowler (quality-at-source) | סטטוס: verified
אכיפה: קריאה ל-request_metadata_extraction ו-request_halacha_extraction
בנקודת-סיום-הקליטה, לכל סוג; חוזה-שלמות יסמן רשומה ללא מטא-דאטה כלא-שמישה
(G4, מפורט ב-
02-data-model.md).
הפרה ידועה: המסלול הפנימי (internal_decisions.py:208) מתזמן רק
request_halacha_extraction ואינו קורא ל-request_metadata_extraction (בניגוד
ל-precedent_library.py:292-293 שקורא לשניהם) → ערן סופר 8046/24 נקלטה בלי
metadata (headnote/summary/tags ריקים) → ממצא ל-audit.
INV-ING4: re-index בקליטה-חוזרת (upsert ⇒ re-embed)
כלל: קליטה-חוזרת ששינתה את תוכן-הפריט מפעילה re-index — chunks ו-embeddings ישנים נמחקים ונבנים מחדש מהתוכן החדש. אין embeddings מיושנים אחרי upsert. מקורות: Pinecone (index freshness / data sync) · Weaviate (re-vectorization on update) · RAG freshness (Lewis et al., 2020, NeurIPS) | סטטוס: verified אכיפה: טריגר re-embed בנתיב ה-upsert של הקליטה + בדיקת-בריאות לגילוי drift; מפורט ב-02-data-model.md ו-03-retrieval.md. אוכף את G6. הפרה ידועה: —
4. מצב קיים מול יעד — audit-findings
הסעיף מתעד את ההבדלים בין שני המסלולים הקיימים. אלו תסמינים לאיחוד תחת המסלול הקנוני, לא התנהגויות תקינות. כל פריט אומת מול הקוד בפועל.
- חילוץ מטא-דאטה חסר במסלול הפנימי.
ingest_precedentקורא ל-request_metadata_extractionו-request_halacha_extraction(precedent_library.py:292-293);ingest_internal_decisionקורא רק ל-request_halacha_extraction(internal_decisions.py:208) — איןrequest_metadata_extraction. זו ההפרה הקונקרטית של INV-ING3 (ערן סופר 8046/24). יעד: צעד 8 אחיד לשני הסוגים. - ולידציית-enums א-סימטרית. המסלול החיצוני מוודא
practice_area/source_typeמול רשימות חוקיות (precedent_library.py:131-134); המסלול הפנימי אינו מוודא enums. יעד: ולידציה אחידה בנקודת-הקליטה (חוזה-שלמות, G4). - staging מפוצל. החיצוני עושה stage לפי
source_type(precedent_library.py:138); הפנימי עושה stage לפי district (internal_decisions.py:113-115). יעד: נתיב-staging כפרמטר של המסלול הקנוני (צעד 1), לא ענף-קוד. - גזירת-שדות רק במסלול הפנימי. הפנימי גוזר district מ-court (
:104) ו-proceeding_type מ-appeal_subtype/case_name (:105), ודורשchair_name(:134). החיצוני אינו גוזר אלו. יעד: גזירה כפרמטר אופציונלי של המסלול הקנוני (שדות-סוג, לא מסלול-סוג). - citation guard רק במסלול החיצוני. החיצוני חוסם ציטוט שמתחיל ב-
ערר/בל"מומפנה למסלול הפנימי (precedent_library.py:124-130). היעד שומר על השער הזה כניתוב-סוג בתוך המסלול הקנוני, לא כהפרדת-פונקציות. - multimodal page-image embed רק במסלול החיצוני. החיצוני מטמיע עמודי-תמונה כש-
MULTIMODAL_ENABLED+ PDF (precedent_library.py:272-278); הפנימי אינו מטמיע עמודי-תמונה. יעד: צעד 7 אחיד — מותנה ב-flag+סוג-קובץ בלבד. - fallback
case_name→citationרק במסלול החיצוני. החיצוני נופל ל-citationכשם כשחסרcase_name(precedent_library.py:158); הפנימי נופל ל-case_number(internal_decisions.py:130). יעד: מדיניות-fallback אחת לשם-תצוגה במסלול הקנוני.
5. הפניות-אחיות
- 00-constitution.md — invariants גלובליים + כללי-הנדסה.
- 02-data-model.md — סכמת-האחסון + חוזה-שלמות שאוכף את תוצרי הקליטה.
- 03-retrieval.md — אחזור, re-index, eval — היעד של ה-chunks הנקלטים.
- X1-identifiers.md — נרמול המזהה הקנוני בכתיבה (בסיס ל-INV-ING2).
- X5-audit-provenance.md — שלמות-רשומה + עקיבוּת-מקור של פריט נקלט.