126 lines
9.8 KiB
Markdown
126 lines
9.8 KiB
Markdown
# Gap-Audit — פערים בין המערכת הקיימת ל-spec
|
||
|
||
מסמך זה הוא **מפת-הפערים הקנונית** בין המערכת הקיימת (קוד ב-`web/`, `mcp-server/`,
|
||
`scripts/`) לבין ה-invariants שב-[`docs/spec/`](README.md). הוא תוצר של תת-פרויקט 2
|
||
(מיפוי-פערים), ומובחן מ-[`docs/audit-report.md`](../audit-report.md) הישן: ה-audit הוא
|
||
דוח-מצב נקודתי, וזה ה-gap-map שמקשר כל ממצא ל-invariant מופר וליחידת-תיקון.
|
||
|
||
**איך הופק:** סקירה חוצת-קבצים של כל קבצי-הספ (00 + 01–07 + X1–X5) מול הקוד הקיים,
|
||
30.5.2026. כל ממצא נושא: `invariant מופר` (ה-G*/INV-* שהוא סותר), הערכת-`severity`,
|
||
`קבצים מושפעים` (file:line), ו-`תיקון מוצע`.
|
||
|
||
**הערה על severity/priority:** דירוג ה-severity להלן הוא הערכה הנדסית (לפי סיכון
|
||
לשלמות-נתונים, דליפה חוצת-קורפוס, ועקיפת שער אנושי). **קביעת ה-priority בפועל —
|
||
מה לתקן ראשון — היא של היו"ר.** ה-severity מנמק; הוא אינו מכריע.
|
||
|
||
---
|
||
|
||
## 23 הממצאים
|
||
|
||
| ID | כותרת | invariant מופר | severity | קבצים מושפעים (file:line) | תיקון מוצע |
|
||
|----|-------|----------------|----------|---------------------------|------------|
|
||
| GAP-01 | שני מסלולי ingest מקבילים שמתפצלים | INV-ING1, G2 | High | `precedent_library.py:88`, `internal_decisions.py:73` | מסלול-קליטה קנוני יחיד; ישויות-אחיות חולקות פייפליין |
|
||
| GAP-02 | ingest פנימי מדלג על חילוץ metadata | INV-ING3, DM1, RET2 | Critical | `internal_decisions.py:208` | להוסיף `request_metadata_extraction` לכל סוג; חוסם indexing ריק |
|
||
| GAP-03 | אין upsert דטרמיניסטי על מזהה קנוני | INV-ING2, G3 | Critical | `precedent_library.py`, `internal_decisions.py` | upsert על מפתח קנוני — קליטה חוזרת = update לא duplicate |
|
||
| GAP-04 | ולידציית-enum א-סימטרית | INV-G4 | Medium | `precedent_library.py:131-134` | להחיל אותה ולידציית practice_area/source_type בשני המסלולים |
|
||
| GAP-05 | staging/derivation/citation-guard/multimodal/fallback א-סימטריים | INV-ING1, G2 | High | `01-ingest §4` (שני המסלולים) | מיזוג כל שלבי-העיבוד למסלול הקנוני האחד |
|
||
| GAP-06 | case_number מנורמל בקריאה בלבד | INV-G1, ID1 | High | `db.py:1196-1211` | נרמול בנקודת-הכתיבה; `8126-25`→canonical |
|
||
| GAP-07 | מספרי-תיק מעורבים (חודש/חסר) — reconciliation חד-פעמי | INV-ID1 | High | data (cases, case_law) | מיגרציה: canonical = הצורה הרשמית שהוקצתה [chair-confirmed] |
|
||
| GAP-08 | ציטוט-מלא נשמר כ-case_number | INV-DM2, ID2 | Medium | data (legacy pre-V15) | ניקוי: ציטוט = שדה-תצוגה נגזר, לא מזהה |
|
||
| GAP-09 | `embedding` אינו GENERATED (בניגוד ל-tsvectors) | INV-DM3, RET, G6 | High | schema (chunks/case_law) | re-index באכיפה — טריגר או GENERATED-equivalent בשינוי תוכן |
|
||
| GAP-10 | דליפת הלכה חוצת-קורפוס | INV-RET1, G5 | Critical | `db.py:3168`, `db.py:3401`, JOINs `3236-3238`/`3475-3477` | להוסיף `cl.source_kind` ל-halacha_filters |
|
||
| GAP-11 | אין eval harness / gold-set מתויג | INV-RET4, G8 | High | `telemetry.log_search_bg` (היחיד) | להקים eval harness + gold-set; precision/recall נמדד |
|
||
| GAP-12 | search_decisions מזהיר אך לא חוסם practice_area חסר | INV-RET, G5 | High | `search.py:45-49`, `search.py:172-176` | לחסום query בלי practice_area — ערבוב-תחום אסור |
|
||
| GAP-13 | אין דגל `searchable` מפורש | INV-DM1 | Medium | schema (case_law, chunks) | דגל `searchable` שמסומן רק כשחוזה-השלמות מתקיים |
|
||
| GAP-14 | backlog הלכות סמוי | INV-QA1, G10 | Medium | (אין health-check) | לחשוף `pending_review` ב-health-check / dashboard |
|
||
| GAP-15 | שער-ייצוא נאכף-זרימה ולא נאכף-קוד | INV-QA3, EX3 | Critical | `drafting.py:384` | `export_docx` קורא `validate_decision` + בודק `export_blocked` |
|
||
| GAP-16 | neutral_background קריטי-אך-עובר | INV-QA3 (`05 §1.2`) | High | `qa_validator.py:70` | בלוק-ו ריק/חסר = passed=False; חוסם ייצוא |
|
||
| GAP-17 | active_draft_path נגזר זוחל ל-source-of-truth | INV-EX1, AUD2 | High | `db.py:189` | DOCX = נגזר; re-sync בלוקים אחרי revise/apply_user_edit |
|
||
| GAP-18 | audit_log כמעט לא נכתב | INV-AUD1 | High | `cases.py:203` (היחיד) | כתיבת audit על upload/extract/write_block/export |
|
||
| GAP-19 | אין קישור block→source-chunks | INV-AUD1 | High | `decision_blocks` (model_used בלבד) | לתעד אילו chunks/precedents הזינו כל בלוק |
|
||
| GAP-20 | citation→corpus לא נאכף אוטומטית | INV-AUD3 | Medium | `decision_paragraphs.citations` | ולידציה שכל ציטוט בטקסט פתיר לקורפוס |
|
||
| GAP-21 | cross-company sync ידני ולא-נאכף | INV-MC1 | Medium | `sync_agents_across_companies.py:387-389` | אכיפת `--apply` אחרי שינוי-Master; להרעיש על דילוג adapter_type |
|
||
| GAP-22 | אינטגרציית-Paperclip על נוהל ולא מחסום-קוד | INV-INT1, INT3 | Medium | schema / lint (אין) | אילוץ-schema נגד DB-insert; linter נגד httpx/curl גולמי |
|
||
| GAP-23 | הספ עדיין לא מחובר לסוכנים | INV-AG1 | High | `.claude/agents/HEARTBEAT.md`, agent files | חובת קריאת 00-constitution + ספ-תחום לפני פעולה |
|
||
|
||
---
|
||
|
||
## יחידות-תיקון מוצעות (Proposed Fix-Units)
|
||
|
||
23 הממצאים מקובצים ל-8 יחידות-עבודה קוהרנטיות. הקיבוץ נגזר מהעיקרון שרבים מהממצאים
|
||
נפתרים יחד (כל פערי ה-ingest-asymmetry → יחידה אחת). זהו זרע למשימות TaskMaster
|
||
ולתת-פרויקט 3 (שכבת-שלמות).
|
||
|
||
### FU-1 — איחוד מסלול-הקליטה (Unify ingest path)
|
||
- **מכסה:** GAP-01, GAP-02, GAP-04, GAP-05
|
||
- **מספק invariants:** INV-ING1, INV-ING3, INV-G2, INV-G4; (תורם ל-DM1/RET2 דרך GAP-02)
|
||
- **effort:** L
|
||
- **תלויות:** — (יסוד — FU-2/FU-3 נשענים עליה)
|
||
- **סוג:** pure-code
|
||
|
||
### FU-2 — קליטה idempotent + מזהים קנוניים
|
||
- **מכסה:** GAP-03, GAP-06, GAP-07, GAP-08, GAP-13
|
||
- **מספק invariants:** INV-ING2, INV-G3, INV-G1, INV-ID1, INV-ID2, INV-DM2, INV-DM1
|
||
- **effort:** L
|
||
- **תלויות:** FU-1 (מסלול אחד לפני upsert אחיד)
|
||
- **סוג:** **data-migration** — GAP-07 reconciliation של case_number מעורב (chair-confirmed),
|
||
GAP-08 ניקוי ציטוט-כ-מזהה; + code (upsert key, write-time normalize, דגל searchable)
|
||
|
||
### FU-3 — re-index באכיפה בשינוי-תוכן
|
||
- **מכסה:** GAP-09
|
||
- **מספק invariants:** INV-DM3, INV-G6, INV-RET (freshness)
|
||
- **effort:** M
|
||
- **תלויות:** FU-1 (re-embed יושב בקליטה הקנונית)
|
||
- **סוג:** **data-migration** — re-chunk/re-embed של רשומות קיימות + טריגר/אכיפה קדימה
|
||
|
||
### FU-4 — הפרדת-קורפוס נאכפת בכל query
|
||
- **מכסה:** GAP-10, GAP-12
|
||
- **מספק invariants:** INV-RET1, INV-G5
|
||
- **effort:** M
|
||
- **תלויות:** — (עצמאי; דחוף — Critical leak)
|
||
- **סוג:** pure-code
|
||
|
||
### FU-5 — eval harness + נראות-בריאות
|
||
- **מכסה:** GAP-11, GAP-14
|
||
- **מספק invariants:** INV-RET4, INV-G8, INV-QA1, INV-G10 (נראות backlog)
|
||
- **effort:** M
|
||
- **תלויות:** FU-2 (gold-set יציב דורש מזהים קנוניים)
|
||
- **סוג:** pure-code + **chair-decision** — הגדרת gold-set מתויג דורשת אישור היו"ר
|
||
(מה "תוצאה נכונה" לכל query)
|
||
|
||
### FU-6 — שערי-QA נאכפים-קוד (Code-enforced gates)
|
||
- **מכסה:** GAP-15, GAP-16
|
||
- **מספק invariants:** INV-QA3, INV-EX3, INV-G10
|
||
- **effort:** S
|
||
- **תלויות:** — (עצמאי; חוסם עקיפת-ייצוא)
|
||
- **סוג:** pure-code
|
||
|
||
### FU-7 — Audit-trail + provenance (זרע תת-פרויקט 3)
|
||
- **מכסה:** GAP-17, GAP-18, GAP-19, GAP-20
|
||
- **מספק invariants:** INV-AUD1, INV-AUD2, INV-AUD3, INV-EX1, INV-G9
|
||
- **effort:** L
|
||
- **תלויות:** FU-1 (provenance נלכד בקליטה/כתיבה הקנונית)
|
||
- **סוג:** pure-code (schema-additive) — חלק מ-GAP-17 דורש **data-backfill** קל
|
||
לסנכרון בלוקים↔DOCX קיימים
|
||
|
||
### FU-8 — מחסומי-תהליך הופכים למחסומי-קוד
|
||
- **מכסה:** GAP-21, GAP-22, GAP-23
|
||
- **מספק invariants:** INV-MC1, INV-INT1, INV-INT3, INV-AG1
|
||
- **effort:** M
|
||
- **תלויות:** ה-spec גמור (GAP-23 דורש קבצי-ספ יציבים לחבר לסוכנים)
|
||
- **סוג:** pure-code + **chair-decision** — GAP-23 (חיבור ספ לסוכני-Paperclip) הוא
|
||
prerequisite לתת-פרויקט 5 ומשנה התנהגות-סוכן בייצור
|
||
|
||
---
|
||
|
||
## סיכום סיווג לפי סוג-עבודה
|
||
|
||
- **pure-code (ללא מיגרציה):** FU-1, FU-4, FU-6; הליבה של FU-7, FU-8.
|
||
- **דורש data-migration:** FU-2 (case_number reconciliation, ניקוי ציטוטים), FU-3
|
||
(re-chunk/re-embed), backfill קל ב-FU-7 (סנכרון בלוקים↔DOCX).
|
||
- **דורש chair-decision:** FU-5 (הגדרת gold-set), FU-8/GAP-23 (חיבור ספ לסוכנים);
|
||
GAP-07 כבר chair-confirmed (canonical = הצורה הרשמית שהוקצתה).
|
||
|
||
**רצף מומלץ (תלויות):** FU-1 → FU-2 → FU-3; FU-4 ו-FU-6 במקביל (עצמאיים, Critical);
|
||
FU-7 אחרי FU-1; FU-5 אחרי FU-2; FU-8 אחרי ייצוב-הספ.
|