Files
legal-ai/docs/spec/05-qa-review.md

16 KiB
Raw Blame History

05 — בקרת איכות ושערים אנושיים (QA & Human Review)

קובץ-תחום זה כפוף ל-חוקת המערכת ומפרט את שלב הביקורת לפני ייצוא: (1) שערי-QA אוטומטיים (validate_decision — 6 בדיקות) ו-(2) שערים אנושיים (אישור הלכה, בחירת תוצאה, פידבק היו"ר). הוא אוכף את INV-G10 (שערים אנושיים) ואת INV-G11 (תוכן מנומק).

⚠ קובץ מעורב — שני מודלי-סמכות. לפי החוקה (§3, §5):

  • שערי-הממשל (שערים אנושיים, שער-הייצוא) הם invariants הנדסיים במודל הממשל-שיפוטי → נושאים מקורות: (NCSC/JTC · CEPEJ 2018 · FJC) + סטטוס: verified.
  • מכניקת בדיקות-התוכן (מה הבדיקה האוטומטית בוחנת בפועל — רקע ניטרלי, ללא כפילות, כיסוי-טענות) היא תוכן-משפטי → נושאת מקור-סמכות: (היו"ר + מסמכי-הפרויקט + 04-analysis-writing.md), ללא מקורות חיצוניים וללא סטטוס.

1. שערי-QA אוטומטיים — validate_decision

validate_decision(case_number) (wrapper ב-tools/drafting.py:363, נחשף ב-server.py:551) טוען את בלוקי-ההחלטה והטענות מה-DB ומריץ 6 בדיקות, אז כותב את התוצאות לטבלת qa_results ומחזיר passed / critical_failures / export_blocked. הליבה: services/qa_validator.py:292 (validate_decision). כל בדיקה מחזירה {name, passed, errors, severity}; severity ∈ {critical, warning}.

חישוב החסימה: critical_failures = Σ(not passed ∧ severity=="critical") (qa_validator.py:338), ו-export_blocked = critical_failures > 0 (qa_validator.py:362). בדיקת warning שנכשלת מורידה passed=False אך אינה חוסמת ייצוא. ראה §3 / INV-QA3.

1.1 ששת השערים

# בדיקה מה בוחנת severity פונקציה (file:line)
1 neutral_background רקע (בלוק ו) ללא מילות-שיפוט (VALUE_WORDS) וללא ציטוט-צד (QUOTE_INDICATORS) warning check_neutral_backgroundqa_validator.py:66
2 claims_coverage כל טענה מבלוק ז נענתה בבלוק י (בדיקה סמנטית דרך Claude) critical check_claims_coverageqa_validator.py:107
3 weight_compliance משקל-מילים של כל בלוק בטווח לפי סוג-ערר (WEIGHT_RANGES) warning check_weight_complianceqa_validator.py:177
4 structural_integrity בלוקי-חובה קיימים (ה, ז, י, יא) + בלוק י הוא הכבד ביותר critical check_structural_integrityqa_validator.py:206
5 no_duplication אין משפט מבלוק ו (>30 תווים) שחוזר מילה-במילה בבלוק י warning check_no_duplicationqa_validator.py:235
6 sequential_numbering מספור-סעיפים רציף בכל הבלוקים, מתחיל ב-1, ללא פערים warning check_sequential_numberingqa_validator.py:261

1.2 דקויות חשובות (אל תניח — מהקוד)

  • רק 2 שערים קריטיים חוסמים ייצוא: claims_coverage ו-structural_integrity. שאר הארבעה הם warning בנתיב הרגיל — qa_validator.py:86, 202, 257, 286.
  • דקות neutral_background — שני נתיבי-החזרה: הנתיב הרגיל מסומן warning (:86); נתיב ה-fallback של בלוק-ו ריק/חסר מסומן critical (:70) אך מחזיר passed=True, ולכן אינו נספר ב-critical_failures ואינו חוסם ייצוא. תפקודית — השער אינו חוסם.
  • claims_coverage סובלני ל-20%: עובר אם len(missing) ≤ total*0.2 (qa_validator.py:170). מסנן לטענות appellant/respondent שאינן מבלוק-ז (qa_validator.py:120-129), כי טענות committee/permit_applicant הן עמדות-הגנה ולא דורשות מענה. כשל-פענוח של Claude → fallback passed=True כדי לא לחסום ייצוא על תקלת-LLM (qa_validator.py:148-152).
  • neutral_background ריק = עובר: בלוק ו ריק/חסר מחזיר passed=True (qa_validator.py:69). הבדיקה היא lexical (רשימת-מילים + regex), לא סמנטית.
  • no_duplication תופס רק חזרה מילה-במילה (substring) — לא פרפרזה.
  • כל ריצה מנקה את qa_results הקודמות של התיק ואז כותבת מחדש (qa_validator.py:344-357).

1.3 שערי-התוכן מתפעלים את WR1WR3

שלוש מ-6 הבדיקות הן ההפעלה האוטומטית (חלקית) של ה-invariants של התוכן ב- 04-analysis-writing.md:

שער QA invariant-תוכן פער (אוטומטי מול הגדרה)
neutral_background INV-WR1 lexical בלבד — לא תופס שיפוט עקיף; warning, לא critical
no_duplication INV-WR2 מילה-במילה בלבד — לא תופס כפילות מנוסחת-מחדש
claims_coverage INV-WR3 סמנטי (Claude), סובלני ל-20% חוסר

ראה INV-QA4. WR4 (טענות מקוריות) ו-WR5 ("מבחן-השופט") אינם מכוסים על-ידי validate_decision — WR4 נאכף בנקודת-החילוץ (extract_claims), WR5 הוא שער-איכות אנושי/agent. הסוכן legal-qa (ראה X4-agents.md) מוסיף שערים ידניים מעבר ל-6 הקוד-יים (קול-דפנה, שאילתות-קורפוס, צירוף-פסיקה) — .claude/agents/legal-qa.md.


2. שערים אנושיים — היו"ר מכריעה

המערכת מסייעת; ההכרעה היא של היו"ר. שלושה שערים אנושיים מובנים בקוד-הזרימה ואינם ניתנים לעקיפה אוטומטית (זהו INV-G10).

2.1 אישור הלכה (halacha approval)

הלכות מחולצות אוטומטית מפסיקה (halacha_extractor.py), אך נכנסות כ-pending_review ובלתי-נראות לחיפוש עד אישור היו"ר:

  • כתיבה: db.add_halacha קובע review_status = "approved" if auto_approve else "pending_review" (db.py:3003), כאשר auto_approve נגזר מסף-ביטחון HALACHA_AUTO_APPROVE_THRESHOLD (ברירת-מחדל 0.80, config.py:111). הלכות מתחת לסף נשארות pending_review.
  • שער-האישור: halacha_review(halacha_id, status, reviewer="דפנה", …) (tools/precedent_library.py:291, נחשף ב-server.py:298) — היו"ר מאשרת/דוחה/עורכת. status ∈ {pending_review, approved, rejected, published} (precedent_library.py:311).
  • תור-ההמתנה: halachot_pending(limit=100) (precedent_library.py:335) מחזיר את review_status='pending_review'.
  • חשיפה רק לאחר אישור: החיפוש מסנן h.review_status IN ('approved','published') (db.py:3168 ו-db.py:3401) — הלכה שלא אושרה לעולם לא עולה בתוצאות.

2.2 בחירת תוצאה (outcome selection)

set_outcome(case_number, outcome, reasoning="") (tools/workflow.py:145, server.py:646) — היו"ר קובעת outcome ∈ {rejected, accepted, partial} (workflow.py:163). זוהי הכרעה משפטית: היא קודמת לכתיבת-הטיוטה וקובעת את מסלול-הדיון (ראה 04-analysis-writing.md §3). אין נתיב שבו המערכת בוחרת תוצאה לבד — אם לא סופק נימוק, המערכת מציעה כיווני-נימוק (brainstorm), אך הבחירה נשארת אנושית.

2.3 פידבק היו"ר (chair feedback)

  • record_chair_feedback(case_number, feedback_text, block_id, category, …) (tools/workflow.py:348, server.py:896) — מתעד הערת-דפנה; category מתוך {missing_content, wrong_tone, wrong_structure, factual_error, style, other} (workflow.py:367).
  • list_chair_feedback(case_number, category, unresolved_only=True) (tools/workflow.py:393, server.py:910) — שליפה לסקירה.

הפידבק מזין את לולאת-הלמידה (07-learning.md) ואת legal-decision-lessons.md. זהו שיפוט-אנושי על איכות — לעולם לא מוסק או מוחל אוטומטית.


3. Invariants של התחום

INV-QA1: אישור הלכה הוא שער אנושי (governance →G10)

כלל: אישור הלכה הוא הכרעה ידנית של היו"ר. הלכות שחולצו אוטומטית הן pending_review עד שהיו"ר מאשרת; רק הלכות מאושרות (approved/published) עולות בחיפוש. תור-ההמתנה חייב להיות נראה (halachot_pending) כדי שאישור-חסר לא יישאר סמוי. מקורות: NCSC/JTC — Principles & Practices for AI Use in Courts (human-in-the-loop) · Council of Europe / CEPEJ (2018, under user control) · Federal Judicial Center — Judicial Writing Manual (2d ed.) | סטטוס: verified אכיפה: ברירת-מחדל pending_review בכתיבה (db.py:3003) + סינון review_status IN ('approved','published') בכל query (db.py:3168, db.py:3401) + שער-אישור halacha_review (precedent_library.py:291). הפרה ידועה: 10/19 הלכות מאושרות — שער-ידני שקוף בלי נראות-backlog; ההפרש התגלה במקרה → ממצא ל-audit (ראה גם INV-G10).

INV-QA2: בחירת-תוצאה ופידבק הם שערים אנושיים (governance →G10)

כלל: בחירת התוצאה (set_outcome) ופידבק-היו"ר (record_chair_feedback) הם שערים אנושיים — לעולם לא אוטומטיים. המערכת מסייעת (מציעה כיווני-נימוק, מתעדת הערות), אך ההכרעה והשיפוט-על-האיכות הם של היו"ר. מקורות: NCSC/JTC — Principles & Practices for AI Use in Courts ("never replace human judgment") · Council of Europe / CEPEJ (2018, under user control) · Federal Judicial Center — Judicial Writing Manual (2d ed.) | סטטוס: verified אכיפה: set_outcome דורש outcome מפורש מהיו"ר (workflow.py:145-165); record_chair_feedback/list_chair_feedback מתעדים בלבד (workflow.py:348, 393) — אין מסלול-קוד שמסיק תוצאה או פידבק לבד. הפרה ידועה:

INV-QA3: החלטה לא מיוצאת עם כשל קריטי (governance →G10)

כלל: החלטה אינה ניתנת לייצוא כל עוד שער-QA קריטי נכשל (claims_coverage או structural_integrity). export_blocked חייב להיבדק לפני ייצוא; ייצוא בכשל-קריטי הוא הפרה. שערי-warning שנכשלים מתועדים אך אינם חוסמים. מקורות: NCSC/JTC — Principles & Practices for AI Use in Courts (controlled, auditable AI output) · Council of Europe / CEPEJ (2018, under user control) · Federal Judicial Center — Judicial Writing Manual (2d ed.) | סטטוס: verified אכיפה: export_blocked = critical_failures > 0 (qa_validator.py:362); נאכף בשער-הזרימה של הסוכן legal-exporter ("לעולם אל תייצא בלי validate_decision קודם", "בדוק שאין כשלים קריטיים" — .claude/agents/legal-exporter.md:71, 149). קושר ל-06-export.md. הפרה ידועה: export_docx (drafting.py:384) אינו מריץ validate_decision בעצמו — החסימה היא ברמת-הזרימה/agent, לא hard-block בקוד-הייצוא. פער זה → ראה §4 (audit).

INV-QA4: שערי-התוכן האוטומטיים אוכפים את WR1WR3 (content →G11)

כלל: שערי-התוכן האוטומטיים מתפעלים את invariants-התוכן: neutral_backgroundWR1 (רקע ניטרלי) · no_duplicationWR2 (ללא כפילות) · claims_coverageWR3 (מענה-לטענות). האכיפה האוטומטית היא רצפה, לא תקרה — WR4/WR5 וההבטים העדינים (שיפוט-עקיף, כפילות מנוסחת-מחדש) נשארים בשיקול-הדעת האנושי (INV-QA1QA3). מקור-סמכות: היו"ר (עו"ד דפנה תמיר) + 04-analysis-writing.md (INV-WR1WR3) + mcp-server/src/legal_mcp/services/qa_validator.py (הבדיקות בפועל). אכיפה: check_neutral_background (qa_validator.py:66), check_no_duplication (qa_validator.py:235), check_claims_coverage (qa_validator.py:107). הפרה ידועה:


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

  • Halacha backlog בלתי-נראה (INV-QA1): 10/19 הלכות מאושרות; 9 נשארו pending_review ולא עלו בחיפוש. השער עבד כשורה — אך חוסר-נראות של ה-backlog הסתיר את הפער עד שהתגלה במקרה. Target: מדד-נראות (count pending_review) כחלק מבדיקת-בריאות, לא רק halachot_pending בדרישה. ראה audit.
  • שער-ייצוא אכוף-זרימה ולא אכוף-קוד (INV-QA3): export_docx לא קורא ל-validate_decision; החסימה תלויה במשמעת הסוכן legal-exporter. Target: hard-block בתוך export_docx (בדיקת qa_results/export_blocked לפני כתיבת DOCX) כדי שלא יהיה ניתן לעקיפה.

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

  • 00-constitution.md — INV-G10 (שערים אנושיים) + INV-G11 + הבחנת שתי-הסמכויות.
  • 04-analysis-writing.md — INV-WR1WR5 שהשערים האוטומטיים מתפעלים.
  • 06-export.md — ייצוא DOCX (השלב אחרי המעבר בשער הקריטי).
  • 07-learning.md — לולאת פידבק-היו"ר + Hermes שמעדכנת lessons/SKILL.
  • X4-agents.md — הסוכן legal-qa (שערים ידניים נוספים) ו-legal-exporter.
  • X5-audit-provenance.md — audit-trail לפלטי-AI ועקיבוּת-מקור.