Files
legal-ai/docs/spec/X5-audit-provenance.md

16 KiB
Raw Blame History

X5 — Audit-Trail ועקיבוּת-מקור (Provenance)

קובץ-תחום זה כפוף ל-חוקת המערכת ומגדיר את חוזה העקיבוּת וה-audit-trail (TARGET) של עוזר משפטי: (א) כל תוצר מסיוע-AI (בלוק-טיוטה, תוצאת-אחזור, הצעת-curator) מתעד מה הפיק אותו (מקורות/נתונים/מודל); (ב) כל סמכות מצוטטת בהחלטה פתירה חזרה לקורפוס; (ג) שלמות-הרשומה לאורך זמן — החלטה/רשומה שלמה ובלתי-משתנה אלא דרך שינויים עקיבים ומיוחסים (היסטוריית git + Track Changes). הקובץ אוכף את INV-G9 (עקיבוּת + audit-trail) ואת INV-G5 (attribution באחזור).

TARGET, לא תיאור-מצב. היכן שהקוד בפועל סוטה מהיעד — מתועד כ-audit-finding (§5), תסמין לתיקון, לא התנהגות תקינה. כל טענה על הקוד מצוטטת file:line.

כשל-השורש שהקובץ מייבש: קיימים רכיבי-עקיבוּת נקודתיים (commit git לפלטים · model_used לכל בלוק · decision_paragraphs.citations · גרף-ציטוטים · telemetry של חיפושים), אך אין רשומת-provenance מאוחדת מקצה-לקצה שמקשרת בלוק-החלטה → קטעי-הקורפוס/הגנרציות שהפיקו אותו, וטבלת ה-audit_log אינה מתועדת בפועל לרוב פעולות ה-AI.


1. שלוש שכבות העקיבוּת (TARGET)

שכבה מה צריך להירשם היכן (קיים / יעד)
A — provenance של תוצר-AI לכל בלוק-טיוטה/תוצאת-אחזור/הצעת-curator: מודל, סוג-גנרציה, וקטעי-המקור (chunks/precedents) שהוזנו קיים חלקית: decision_blocks.model_used/generation_type/temperature (db.py:326-328); חסר קישור בלוק→קטעי-מקור
B — עקיבוּת ציטוט→קורפוס כל סמכות מצוטטת פתירה ל-case_law_id/document_id + locator קיים: decision_paragraphs.citations JSONB [{case_law_id,text,type}] (db.py:343); גרף precedent_internal_citations (db.py:937-947)
C — שלמות-רשומה לאורך זמן החלטה/מסמך שלם ובלתי-משתנה אלא דרך שינוי עקיב ומיוחס קיים: commit git לכל פלט (git_sync.commit_and_push); Track Changes ב-revisions (06-export §3)

2. רכיבי-העקיבוּת הקיימים (מאומת file:line)

  1. קיבוע-פלט ב-git. כל כתיבת-DOCX/עדכון-תיק מקובעת בהיסטוריית-git של תיקיית-התיק: export_docx (drafting.py:408), export_interim_draft (drafting.py:536), apply_user_edit (drafting.py:582), revise_draft (drafting.py:695), עדכון-תיק (cases.py:387), הוספת-מסמך (documents.py:86) — כולם git_sync.commit_and_push(...) (git_sync.py:75). זו שכבת ה-audit-trail של שלמות-הפלט (שכבה C).
  2. provenance של מודל לכל בלוק. decision_blocks נושא model_used / generation_type / temperature (db.py:326-328), הנכתבים ב-upsert של ה-block-writer (block_writer.py:1017-1034, _build_result :400-407). מתעד איזה מודל הפיק את הבלוק (שכבה A — חלקי).
  3. עקיבוּת ציטוט ברמת-סעיף. decision_paragraphs.citations (db.py:343) שומר [{case_law_id, text, type}] — כל ציטוט בסעיף מצביע ל-case_law (שכבה B). telemetry ממנף זאת ל-"cited == relevant" (telemetry.py:18-23).
  4. גרף-ציטוטים פנימי. precedent_internal_citations (db.py:937-947) רושם קשת החלטה→החלטה מצוטטת (resolved ל-case_law או stub); נחשף דרך extract_internal_citations / list_internal_citations / list_incoming_citations (citations.py:40,81,112). ON CONFLICT DO NOTHING → idempotent (citations.py:54).
  5. locator פתיר בכל תוצאת-אחזור. כל span מוחזר נושא מזהה-מקור + locator (03-retrieval INV-RET5, search.py:77-86,322-343); הלכות נושאות supporting_quote (db.py:652) + page_number (db.py:631,711,729).
  6. telemetry של חיפושים. telemetry.log_search_bg (ב-search.py) → מפעיל את log_search האסינכרוני → search_logs (telemetry.py:105,161, search.py:62,118,190,271) רושם query/practice_area/top_case_law_ids — תצפית על מה נשלף, fire-and-forget (telemetry.py:8-12,100-101).
  7. לקחים ופידבק מיוחסים. decision_lessons.source (db.py:208: manual/curator/chair/ style_analyzer) ו-chair_feedback.lesson_extracted/applied_to (db.py:458-459) מתעדים את מקור הלקח (07-learning.md).
  8. טבלת audit_log (פעולה כללית). log_action(action, case_id, document_id, details, user) (עמודת-DB: actor) (audit.py:18-44) → audit_log (db.py:159-167, אינדקסים :168-170). קיימת, אך נכתבת כיום כמעט-ורק ב-case_subtype_override (cases.py:203) — ראה §5.

3. Invariants של התחום

INV-AUD1: כל תוצר מסיוע-AI מתעד את ה-provenance שלו (→G9)

כלל: כל תוצר שנוצר בסיוע-AI — בלוק-טיוטה, תוצאת-אחזור, הצעת-curator — רושם את מקורו: איזה מודל הפיק אותו, באיזה סוג-גנרציה, ואילו קטעי-מקור (chunks/precedents/מסמכי-תיק) הוזנו אליו. הרשומה ניתנת-לביקורת בדיעבד (מי/מתי/ממה). מקורות: Council of Europe / CEPEJ — European Ethical Charter on AI in judicial systems (2018, transparency/traceability + user-control) · NCSC/JTC — Principles & Practices for AI Use in Courts (auditable AI output) · ISO 15489-1:2016 (records authenticity — metadata about creation) | סטטוס: verified אכיפה: decision_blocks.model_used/generation_type/temperature בכל upsert של בלוק (block_writer.py:1017-1034); telemetry על כל חיפוש (telemetry.py:105); יעד נוסף: קישור מפורש בלוק→קטעי-מקור (provenance edges) + כתיבת audit_log.log_action לכל גנרציה. אוכף את G9. הפרה ידועה (GAP): ה-provenance קיים חלקיתmodel_used נרשם לכל בלוק, וה-commit ב-git מקבע פלטים, אך אין רשומה מאוחדת שמקשרת בלוק-החלטה לקטעי-הקורפוס/הגנרציות שהזינו אותו, וטבלת audit_log כמעט-ולא נכתבת לפעולות-AI (רק case_subtype_override, cases.py:203) → יעד (§5).

INV-AUD2: רשומה שמורה שלמה ובלתי-משתנה אלא דרך שינוי עקיב ומיוחס (→G9, שלמות-רשומה)

כלל: החלטה/רשומה שמורה היא שלמה ובלתי-משתנה — כל שינוי בה נעשה רק דרך מנגנון עקיב ומיוחס (commit git עם הודעה + actor, או Track Changes מיוחסות), ולא דרך דריסה שקטה. ניתן לשחזר את מצב-הרשומה בכל נקודת-זמן ולזהות מי שינה מה ומתי. מקורות: ISO 15489-1:2016 (§5.2.2 — integrity: records protected against unauthorized alteration; אמינות/שלמות-רשומה) · Council of Europe / CEPEJ (2018, traceability) · DAMA-UK — Six Primary Dimensions for Data Quality (2013, consistency/integrity over time) | סטטוס: verified אכיפה: קיבוע git לכל פלט (git_sync.commit_and_pushdrafting.py:408,536,582,695; cases.py:387; documents.py:86) עם הודעה תיאורית; Track Changes ב-revisions עוקבות (06-export §3); decision_blocks עם מפתח קנוני UNIQUE(decision_id, block_id) (db.py:333) ו-updated_at. אוכף את G9. הפרה ידועה: עריכת-DOCX (revise_draft/apply_user_edit) הופכת את active_draft_path למקור- בפועל בלי לעדכן את בלוקי-ה-DB חזרה — הנתון-הנגזר זוחל למקור-אמת ושלמות ה-DB מול המסמך-החי נחלשת (06-export INV-EX1) → ממצא ל-audit.

INV-AUD3: כל סמכות מצוטטת פתירה חזרה לקורפוס (→G5)

כלל: כל סמכות-משפטית המצוטטת בהחלטה (פסק-דין, הלכה, מסמך-תיק) פתירה לרשומת-מקור בקורפוס דרך locator יציב — case_law_id/document_id + מזהה-עמוד/chunk/quote. ציטוט שאינו פתיר אינו תקין; הוא נחסם או מסומן לאימות-יו"ר. זהו צד-ה-attribution של INV-RET5. מקורות: Pinecone — Implement multitenancy (metadata-locator לכל פריט מואנדקס) · RAG attribution (Lewis et al., 2020, NeurIPS — pinned/non-leaking provenance) · ISO 8000 (Data quality — completeness/identifiability) | סטטוס: verified אכיפה: decision_paragraphs.citations [{case_law_id,text,type}] (db.py:343); גרף precedent_internal_citations (db.py:937-947) פותר ציטוט ל-case_law קיים או שומר stub; פורמטרי-האחזור מצרפים מזהה+locator (search.py:77-86,322-343). אוכף את G5. הפרה ידועה (GAP): הקישור קיים ברמת-הסעיף (decision_paragraphs.citations), אך אין אכיפה שכל ציטוט בטקסט-הבלוק אכן מקושר לרשומת-קורפוס; ציטוט שהמודל ייצר בלי locator יכול לעבור בלי חסימה אוטומטית — אימות נשען על שער-היו"ר (05-qa-review) → יעד.


4. רשומת-ה-provenance המאוחדת (TARGET)

היעד שמאחד את שלוש השכבות: לכל בלוק-החלטה נשמר, מעבר ל-model_used הקיים, קישור לקטעי- המקור שהוזנו לגנרציה (chunk-ids/case_law_ids שהוחזרו מהאחזור והוצגו ל-writer) — כך שניתן לענות "מאיזו פסיקה/מסמך נולד המשפט הזה?". המנגנון הקנוני המוצע: כתיבת audit_log.log_action (audit.py:18) בכל גנרציה (action="write_block", details={model, generation_type, source_chunk_ids, retrieved_case_law_ids}) — הטבלה כבר תומכת ב-details JSONB + actor + case_id/document_id (db.py:159-167). זה ממיר את ה-audit_log מ"כמעט-ריק" ל-audit-trail מקצה-לקצה, בלי טבלה חדשה (תואם כלל-ההנדסה "סימטריה" — הרחבת מסלול קיים, חוקה §6).


5. Current vs Target — ממצאי-audit

ההבדלים בין הקוד בפועל ל-TARGET. אלו תסמינים, לא התנהגויות תקינות. כל פריט אומת מול הקוד.

  • audit_log קיימת אך כמעט-ולא נכתבת (INV-AUD1). log_action (audit.py:18-44) ו-טבלת audit_log (db.py:159-167) מוכנות, אך הקריאה היחידה בפועל היא case_subtype_override (cases.py:203) — אין רישום ל-upload/extract_claims/write_block/export (למרות ש-docstring של log_action מונה אותם, audit.py:28). תסמין: אין audit-trail אחיד "מי עשה מה מתי" לרוב פעולות-ה-AI. יעד: קריאת log_action בכל פעולה משנה-מצב, כולל גנרציות.
  • אין קישור בלוק→קטעי-מקור (INV-AUD1). decision_blocks מתעד model_used/generation_type (db.py:326-327) אך לא את ה-chunks/precedents שהוזנו לגנרציה. תסמין: אי-אפשר לשחזר מאיזו פסיקה/מסמך נגזר בלוק ספציפי. יעד: רשומת-provenance מאוחדת (§4).
  • ציטוט→קורפוס לא נאכף אוטומטית (INV-AUD3). decision_paragraphs.citations (db.py:343) תומך בקישור, אך אין בדיקה שכל ציטוט בטקסט אכן פתיר ל-case_law. תסמין: ציטוט שהמודל ייצר בלי locator יכול לעבור. יעד: ולידציה שכל citation בעלת case_law_id פתיר, אחרת flag לאימות-יו"ר.
  • שלמות ה-DB מול ה-DOCX-החי נחלשת אחרי עריכה (INV-AUD2). אחרי revise_draft/apply_user_edit, active_draft_path הופך מקור-בפועל בלי re-sync לבלוקים (db.py:189; 06-export INV-EX1). יעד: re-sync מהבלוקים או חוזה מפורש + health-check לגילוי drift.
  • telemetry בולעת שגיאות בשתיקה (תיעוד, לא הערכה). log_search swallow מכוון (telemetry.py:100-101) כדי שלא להפיל חיפוש — תקין כ-fire-and-forget, אך אינו audit-trail מהימן (רשומה עלולה ללכת לאיבוד בשקט). תואם את העיקרון "אין בליעה שקטה" רק כי זו telemetry-תצפית, לא רשומת-שלמות; ה-audit-trail המהימן הוא git (§2.1).

6. הפניות-אחיות

  • 00-constitution.mdINV-G9 (עקיבוּת + audit-trail) · INV-G5 (attribution).
  • 03-retrieval.md — INV-RET5 (locator פתיר בכל span — בסיס ל-INV-AUD3).
  • 06-export.md — INV-EX2 (עקיבוּת בפלט) + commit git (INV-AUD2).
  • 05-qa-review.md — שער-היו"ר שמאמת ציטוטים (משלים את INV-AUD3).
  • 02-data-model.mddecision_blocks/decision_paragraphs/case_law (הישויות שעליהן נשמרת ה-provenance).
  • 07-learning.mddecision_lessons.source + chair_feedback (מקור הלקחים).
  • 01-ingest.md — קליטה שמייצרת את הקטעים שאליהם פותרים ציטוטים.