Files
legal-ai/scripts/SCRIPTS.md
Chaim 70a06c3745
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 5s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
fix(calibration): drop block-yod + per-cell guard + incremental write (#208)
A live calibration run crashed with no error handling and lost ~2h of work:
the per-cell loop in _run() reached block-yod (discussion), block_writer.write_block
raised ValueError("לא ניתן לכתוב בלוק דיון ללא כיוון מאושר…") because the discussion
block needs an approved direction calibration cases don't have, and since the report
was only written at the very end of main(), every completed generation was lost.

Three robustness fixes (no metric/scoring change — G2):

1. Drop block-yod from default CALIBRATABLE_BLOCKS — out of WS5 interim-draft scope
   AND structurally non-calibratable standalone (needs brainstorm→approve_direction).
   Kept in new VALID_BLOCKS so a user can still force it via --blocks block-yod.
2. Per-cell try/except in _run(): any single (case, block, effort) cell failure is
   logged as a warning (case/block/effort/error) and skipped, never fatal —
   defense-in-depth for a forced block-yod and for transient rate-limits mid-run.
3. Incremental persistence: _write_report flushes after each completed block (ts
   threaded into _run), so a crash later in the grid never loses finished blocks.
   JSON/MD shape unchanged — partial results omit not-yet-done blocks from by_block.

--self-test: ALL PASS (14/14). block-yod gone from --dry-run defaults.

Invariants — נוגע / מקיים:
- G8 (eval-harness robustness) — partial results persist; a single-cell failure is
  non-fatal; the harness survives block-yod's missing-direction raise and rate-limits.
- G2 (מקור-מדידה יחיד) — no metric-path change; _score_cell / block_distance_to_final
  / recommend_effort / aggregate_cell untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 15:49:15 +00:00

81 KiB
Raw Blame History

scripts/ — מדריך סקריפטים

כלל: כל עדכון, יצירה, או מחיקה של סקריפט בתיקייה זו מחייב עדכון של קובץ זה.


סקריפטים פעילים

מקובצים לפי תת-נושא (כותרות ###). דף /scripts קורא את הכותרות ומקבץ לפיהן. סקריפט חוזר/קבוע — הוסף כאן תחת תת-הנושא המתאים; סקריפט חד-פעמי (מיגרציה/backfill/POC שהורץ פעם-אחת) — תחת ## חד פעמי שבהמשך, באותו תת-נושא.

סוכנים, Paperclip ואדפטרים

Script Type Purpose Scheduled
pc.sh bash wrapper לכל קריאות Paperclip API מסוכנים — מוסיף Authorization, X-Paperclip-Run-Id (audit trail), Content-Type, base URL. תחביר: pc.sh <METHOD> <PATH> [BODY_JSON]. אסור curl ישיר ל-$PAPERCLIP_API_URL. ראה HEARTBEAT.md §0. counterpart ב-Python: web/paperclip_api.py. נקרא ע"י סוכנים
sync_agents_across_companies.py python סנכרון סוכנים מ-CMP (1xxx, master) ל-CMPA (8xxx, mirror) — Gap #25. משווה adapter_config (model/timeout/instructions/skills/etc), runtime_config (heartbeat), ושדות top-level (budget/metadata/icon/title/role). מסנן אוטומטית local skills שלא קיימים ב-mirror. לוגיקת subset (mirror יכול להחזיק יותר skills כי ה-API מוסיף required runtime skills). תומך --verify/--dry-run/--apply [--only NAME]. גיבוי אוטומטי. דורש PAPERCLIP_BOARD_API_KEY. להריץ אחרי כל שינוי הגדרות ב-CMP. ⚠ אם adapter_type שונה בין CMP ל-CMPA — --apply מדלג על הסוכן; --verify מדווח אותו רם כ-DRIFT. בעת מעבר adapter (למשל ל-deepseek_local) חובה לעדכן ידנית בשתי החברות. --verify יוצא exit≠0 על כל drift (needs-sync / adapter-mismatch / missing-in-mirror) — שמיש כ-gate ל-cron/CI (GAP-21/FU-8a). ידני אחרי כל שינוי
fix_paperclipai_skills_drift.py python סקריפט חד-פעמי (בוצע 2026-05-04) שניקה drift על paperclipai/* skills בין CMP ל-CMPA. הסיר paperclip-dev מכל 14 הסוכנים, ודאג ש-paperclip-converting-plans-to-tasks קיים רק על CEO ו-analyst. תומך --apply (ברירת מחדל: dry-run). דורש PAPERCLIP_BOARD_API_KEY. נשמר לרפרנס למקרה שhdrift חוזר. חד-פעמי (בוצע)
classify_citation_treatments.py python סיווג-טיפול לקצוות-ציטוט (X11 Phase 2, #154) — לכל קצה ב-precedent_internal_citations (החלטת-ועדה מצטטת תקדים) מסווג את ה-treatment מתוך ה-match_context דרך corroboration.classify_treatment (Opus 4.8 @ xhigh, claude_session מקומי — לא בקונטיינר): followed/explained=חיובי, distinguished/criticized/questioned/overruled=שלילי. ממלא precedent_internal_citations.treatment כך ש-refresh_verified_layer לא יספור ציטוט שלילי כסמכות (INV-COR2) ו-db.citation_authority יציג פירוק לסוכנים. אידמפוטנטי (מדלג על מסווגים). --apply/--limit N/--case-law-id UUID. אחרי --apply הרץ build_verified_layer.py. דורש HOME=/home/chaim. ידני / אחרי גלי-ציטוט חדשים
adapter_profiles.py python (module) רישום-פרופילי-אדפטר — מקור-אמת יחיד ל-3 צירי-הכשל של מעבר-אדפטר: provider/default_model, instructions_mode (file_path בטוח-frontmatter מול content_arg ששובר ---), ו-tool_config (gemini_global excludeTools / frontmatter / hermes / codex_home). כולל codex_local עם משפחת מודלי OpenAI/Codex (gpt-*, o3*, o4*, codex-*). מיובא ע"י migrate_agent_adapter.py. הוספת אדפטר עתידי = רשומה אחת. לא מורץ ישירות. תשתית
migrate_agent_adapter.py python מעבר-אדפטר בטוח לכל סוכן ← כל אדפטר, בשתי החברות יחד (INV-MC1). מיישב model↔provider, גורס frontmatter לעותק .generated/<name>.nofm.md ל-content_arg adapters (אחרת קריסת gemini --prompt/hermes -q על ---), ומשחרר excludeTools גלובלי של gemini (--relax-tools). --check (preflight בלבד, exit≠0 על שגיאה — שער FU-8a) / --apply / --revert (שחזור מדויק מ-sidecar data/adapter-migration-state.json) / --verify (מסמן מצב לא-תואם/א-סימטרי, exit≠0). --agent "<שם>"|all --to <adapter> [--model X] [--relax-tools]. PATCH דרך /api/agents/{id} (לא DB). דורש PAPERCLIP_BOARD_API_KEY. הרץ עם mcp-server/.venv/bin/python. fallback-חירום כשנגמרים טוקני-Claude; החזר ל-claude_local כשחוזרים. ידני לפי צורך

אחזור, embeddings ו-multimodal

Script Type Purpose Scheduled
test_retrieval_by_name.py python בדיקת אחזור-לפי-שם (#52/RC-A) — מאמת שsearch_precedent_library/search_internal_decisions מדרגים את ההחלטה עצמה (אגסי) מעל מי שמצטט אותה, + רגרסיות לשאילתות מהותיות. הרצה: DOTENV_PATH=/home/chaim/.env DATA_DIR=.../data mcp-server/.venv/bin/python scripts/test_retrieval_by_name.py (exit 0 = עבר). ידני אחרי שינוי שכבת חיפוש
eval_gold_bootstrap.py python FU-5 (GAP-11) — bootstrap ל-gold-set של הערכת-אחזור ל-data/eval/gold-set.jsonl. שני מקורות: --source citations (cited==relevant מ-search_relevance_feedback; ריק עד שייצברו ציטוטים) ו---source known_item (query=שם-תיק → relevant=עצמו; אות אמיתי היום). Idempotent — שומר שורות source=chair, מחדש bootstrap_*. דורש POSTGRES. לפני eval; חוזר כשנצבר ground-truth
eval_retrieval.py python FU-5 (GAP-11, INV-RET4/G8) — harness הערכת-אחזור — מריץ את מסלול-האחזור בייצור (search_library/search_internal) על ה-gold-set, מחשב precision@k/recall@k/MRR/nDCG@k (k=5,10), מצרף overall+per-corpus+per-PA ל-data/eval/eval-report-<ts>.{json,md} + delta מול data/eval/baseline.json (מתעד retrieval_config). --self-test בודק את המטריקות offline; --update-baseline מאמץ snapshot. שער-CI במשמעת: הרץ לפני/אחרי כל שינוי בשכבת-האחזור באותו קונפיג. דורש POSTGRES+VOYAGE_API_KEY. לפני/אחרי שינוי RRF/k/embedder/rerank
legal-court-fetch-service.config.cjs pm2/js שירות-מארח Tier-1 לאחזור פסקי-דין מנט המשפט (X13) — 2 apps: (א) legal-court-fetch-xvfb (Xvfb :99, צג-וירטואלי ל-Camoufox); (ב) legal-court-fetch-service (python -m legal_mcp.court_fetch_service.server, bound 10.0.1.1:8771, Bearer COURT_FETCH_SHARED_SECRET מ-~/.legal-court-fetch-service.env, DISPLAY=:99). מריץ Camoufox דרך חבילת-הפייתון (in-process) כי הקונטיינר לא יכול דפדפן. תלות: pip install -e "mcp-server[court-fetch]" && python -m camoufox fetch. אחזור = ניווט→צופה→GetImages(X-Requested-With)→PDF, ללא CAPTCHA; כשל→ok:false→orchestrator מסלים ל-fallback אנושי. אומת על עת"מ 46111-12-22 (34 עמ'). מראָה לדפוס legal-chat-service.config.cjs. ספ: docs/spec/X13-court-fetch.md. התקנה: pm2 start scripts/legal-court-fetch-service.config.cjs && pm2 save. בריאות: curl http://10.0.1.1:8771/health. pm2 (host-side)
drain_court_fetch.py python ריקון תור-אחזור הפסיקה (X13) — קורא ל-court_fetch_orchestrator.drain_pending(limit) שמוריד+קולט כל job ממתין שהיומונים מילאו, וקושר חזרה ליומון. מקומי בלבד (ingest = claude CLI). no-op מהיר כשהתור ריק. הרצה ידנית: mcp-server/.venv/bin/python scripts/drain_court_fetch.py [limit]. דרך legal-court-fetch-drain.config.cjs (pm2 cron)
legal-court-fetch-drain.config.cjs pm2/js תזמון שעתי של drain_court_fetch.py (cron 17 * * * *, COURT_FETCH_DRAIN_CRON לעקיפה) — הופך את לולאת יומון→אחזור→קליטה ל-fully-autonomous. autorestart:false (one-shot per tick). דורש legal-court-fetch-service רץ. התקנה: pm2 start scripts/legal-court-fetch-drain.config.cjs && pm2 save. pm2 cron (host-side)
reembed_voyage.py python Re-embed כל הוקטורים ב-DB עם המודל ב-VOYAGE_MODEL (לאחר שינוי מודל). 5 טבלאות, 1024 דמ', batches של 100. ראה docs/voyage-upgrades-plan.md ידני (אחרי החלפת VOYAGE_MODEL)
multimodal_backfill.py python Backfill voyage-multimodal-3 page embeddings על מסמכי תיקים קיימים. idempotent (skips by default), forces MULTIMODAL_ENABLED=true ל-run, רץ מהקונטיינר. שלב C — ראה docs/voyage-upgrades-plan.md ידני per-case (python multimodal_backfill.py 8174-24 8137-24)
backfill_chunk_pages.py python Backfill page_number ב-document_chunks קיימים. legacy chunker לא tracked עמודים → page_number=NULL חוסם boost של multimodal hybrid (text+image join על אותו עמוד). re-extracts כל PDF (re-OCR אם צריך, ~$0.0015/page), מחשב page_offsets, ומעדכן chunks. idempotent ידני per-case (python backfill_chunk_pages.py 8174-24 8137-24)
compute_ndcg.py python חישוב nDCG@10 על search_relevance_feedback (TaskMaster #50, Stage C). aggregation לפי search_type ולפי שבוע, כולל top-cited case_law ו-coverage %. דגלים: --k 10, --weeks 12, --pretty. read-only, פלט JSON. משמש גם את GET /api/admin/rag-metrics (מיובא inline) — שינוי חתימה ב-compute() ישבור את ה-endpoint ידני / cron עתידי לדיווח שבועי
backfill_multimodal_precedents.py python Backfill voyage-multimodal-3 page embeddings על רשומות case_law (external_upload + internal_committee) שחסרות precedent_image_embeddings. בונה אינדקס קבצים מ-data/precedent-library/ ו-data/internal-decisions/, מנסה התאמה לפי tokens של מספרי תיק (כולל parts-match לפורמטים שונים של Nevo doc-id). מדלג על רשומות בלי קובץ-מקור או עם MD בלבד (PyMuPDF לא מרנדר MD). תומך --dry-run (default) / --apply / --only external_upload|internal_committee / --limit N. רץ בקונטיינר (יש /data + Voyage env). הופעל 2026-05-26: 70 חסרים → 26 backfilled (503 pages, ~$0.21 voyage tokens), 44 אין-קובץ-מקור. ניתן להריץ שוב אחרי שיועלו עוד PDF/DOCX לספרייה ידני

אחסון, DB ותורים

Script Type Purpose Scheduled
reap_orphan_procs.py python reaper לתהליכים-יתומים שמרווים את שרת Nautilus — הורג task-master-mcp (Node, מתנפח ל~3GB) ו-camoufox-bin (Firefox מ-X13 fetch שקרס) רק כשהם יתומים (ppid=1) — תהליך עם הורה-חי לעולם לא נוגעים בו. /proc טהור, בלי psutil. --dry-run (דיווח), --loop N (דמון כל N ש'). ראה זיכרון project_taskmaster_mcp_memory_leak. דרך legal-reaper.config.cjs (pm2)
legal-reaper.config.cjs pm2/js דמון pm2 ל-reap_orphan_procs.py --loop (ברירת-מחדל 180ש', REAP_INTERVAL_S לעקיפה). max_memory_restart 100M (ה-reaper עצמו לא ידלוף). התקנה: pm2 start scripts/legal-reaper.config.cjs && pm2 save. לוגים: pm2 logs legal-reaper. pm2 (host-side)
drain_metadata_queue.py python ריקון תור חילוץ-המטא של הפסיקהprocess_pending_extractions(kind='metadata') ב-batches עד ריק. רץ על Gemini Flash (structured JSON, gemini_session) — מהיר ואמין, במקום ה-claude CLI ה-agentic שפגע ב-error_max_turns. no-op מהיר כשריק. הרצה ידנית: mcp-server/.venv/bin/python scripts/drain_metadata_queue.py [batch]. דרך legal-metadata-drain.config.cjs (pm2 cron)
legal-metadata-drain.config.cjs pm2/js תזמון כל 15 דק' של drain_metadata_queue.py (cron */15 * * * *, METADATA_DRAIN_CRON לעקיפה) — מונע סתימה של תור חילוץ-המטא ב-/precedents. דורש GEMINI_API_KEY ב-~/.env. התקנה: pm2 start scripts/legal-metadata-drain.config.cjs && pm2 save. pm2 cron (host-side)
backup-db.sh bash גיבוי PostgreSQL יומי ל-data/backups/ (gzip) לתזמן: 0 2 * * *
restore-db.sh bash שחזור DB מגיבוי (companion ל-backup-db.sh) ידני
migrate_blobs_to_minio.py python #106.4 — הגירת בלובים לדיסק→MinIO (DB-driven, dry-run-default). סורק 6 עמודות-נתיב (documents.file_path · cases.active_draft_path · digests.source_document_path · draft_final_pairs.final_path · *_image_embeddings.image_thumbnail_path), מנרמל 3 פורמטי-נתיב legacy (container-abs /data/, host-abs, relative) ל-key יחסי-DATA_DIR, וגוזר bucket per-file-semantic (מסמך→documents, thumbnail→derived). dry-run מפיק תוכנית+מניפסט CSV (data/audit) + מדווח חסרים; --apply מעלה דרך mcli ומאמת size (דיסק לא נוגע → הפיך). אומת 2026-06-11: 3404 קבצים/899MB, 0 outside, 28 חסרים. חובה mcli alias legalminio. ידני — הגירת-אחסון X14
storage_leak_tripwire.py python INV-STG1 tripwire (ניטור-ריצה). משלים את ה-CI leak-guard: סורק בלובים ב-data/{cases,precedent-library,internal-decisions,digests,training} ומשווה מול ה-key-sets החיים של legal-documents/legal-derived (json-key match, סיווג bucket per-file כמו בהגירה). מדווח בלובים שדלפו (בדיסק אך לא ב-MinIO → יאבדו בניקוי, לא מוגשים/מגובים). read-only, --since <ISO>. אומת: 0 דליפות. חובה מקומי (mcli legalminio). תקופתי / לפני ניקוי-דיסק #128

הלכות, פאנל וסגנון

Script Type Purpose Scheduled
halacha_goldset.py python #81.7 — הארנס gold-set לאיכות חילוץ-הלכות. export --n N מייצא מדגם מרובד (לפי precedent×rule_type) ל-CSV עם עמודות-תיוג ריקות (is_holding/correct_type/quote_complete) לתיוג ידני (חיים/דפנה). score --in <csv> קורא את ה-CSV המתויג ומודד כל ולידטור (compute_quality_flags/is_fact_dependent/is_quote_truncated/is_thin_restatement) מול אמת-המידה האנושית: P/R/F1 + confusion. בסיס ל-#81.8 (כיול סף האישור). מייבא את אותם ולידטורים שה-extractor מריץ. רץ עם venv של mcp-server. הערה: קיים גם דף-תיוג אינטראקטיבי DB-backed (/goldset) — זה ה-CSV-fallback ידני — export→תיוג→score
goldset_panel_label.py python #81.7 — תיוג ה-gold-set בקונצנזוס תלת-מודלי (ללא man-in-the-loop, הנחיית-יו"ר 2026-06-11). מריץ את שלושת השופטים העצמאיים (Opus/claude_session · DeepSeek · Gemini, מיובאים מ-halacha_panel_approve) עם ה-prompt העשיר (is_holding+type+נימוק מ-goldset_ai_recommend) על כל פריט; רוב 2/3 נכתב ל-is_holding/correct_type עם tagged_by='panel:opus+deepseek+gemini'יצול→NULL→יו"ר, INV-G10). מודד Fleiss κ (3 מעריכים) ומריץ מבחן-אנונימיזציה (שמות-תיק ממוסכים→שיפוט-מחדש; flip=שינון). לא מעגלי — הוולידטורים הנמדדים rule-based. כותב per-model+consensus+anon ל-DB ודוח ל-data/audit/. מחליף תיוג-ידני; goldset_ai_recommend/goldset_independent_judge נשארים כבדיקות single-model. --limit/--no-anon/--force. חובה מקומי. ידני — לאחר יצירת/הרחבת batch
goldset_ai_recommend.py python #81.7 QA (single-model, נבלע ב-panel) — חוות-דעת claude בלבד ל-ai_*. כעת לינאז' 1/3 בתוך goldset_panel_label; נשאר כבדיקת-claude עצמאית/חידוש נקודתי. --force/--limit. חובה מקומי. ידני — בדיקה נקודתית
goldset_independent_judge.py python INV-DM7 ולידציה — שופט-תפקיד עצמאי שני ממודל אחר (DeepSeek API ישיר, OpenAI-compatible) ששובר את עיגון-ה-AI: מסווג rule_role בעיוור (בלי לראות תיוג-אדם או המלצת-claude) ומחשב מטריצת-הסכמה (deepseek↔אדם מול ai↔אדם) + ציר-גס (כלל-בר-הכללה מול application/obiter). ממצא (2026-06-07): ai↔אדם=100% (מעוגן), deepseek↔אדם=50% מדויק אך 92% גס → תת-הסוג holding/interpretive/procedural עמום-מטבעו (לא לשער עליו); הציר-הגס אמין חוצה-מודלים. read-only על הזהב. --model/--limit/--concurrency. מפתח מ-~/.hermes/profiles/deepseek/.env. raw→/tmp/goldset_judge_raw.json. ידני — ולידציית אמינות-תוויות
halacha_panel_approve.py python פאנל-אישור הלכות (Trust-or-Escalate, dry-run). 3 שופטים בלתי-תלויי-לינאז' (Opus/claude_session · DeepSeek · Gemini-2.5-flash) מצביעים על הציר-הגס האמין (92% חוצה-מודלים): נקיות→"הלכה לשמירה?"; nli_unsupported→"הציטוט תומך בכלל?" (שיפוט-מחדש); פגומות→re-extraction. רק ורדיקט מוסכם פועל אוטומטית, פיצול מסלים ליו"ר (INV-G10). --apply מחווט (clean: רוב 2/3; nli: פה-אחד-entailed מנקה flag) — הפיך, מגבה ל-data/audit/ קודם. מפתחות: DeepSeek מ-~/.hermes/..., Gemini מ-~/.env. חובה מקומי. dry-run 2026-06-07: 197→103 אוטו (פה-אחד) / ~15 (רוב). FU-1 (#133): כל סבב — הצבעות +נימוקי-כל-שופט — נשמר ל-halacha_panel_rounds בשני המצבים (capture-only, לא נוגע ב-halachot; apply_mode מתעד dry-run מול apply); ה-seed ללמידה נוצר בהצלבה מול הכרעת-היו"ר המאוחרת על אותה הלכה. --no-capture לדילוג. ידני / שלב-אימות-הלכות במסלול-הסופי
style_lesson_panel.py python פאנל-סגנון דו-סוכני (למידה כפולה). על-גבי דיסטילציית-ה-Opus (draft↔final ב-draft_final_pairs.analysis), שני שופטים בלתי-תלויים — DeepSeek + Gemini-2.5-flash — מצביעים לכל לקח על השאלה הגסה "האם זו הנחיית-סגנון מופשטת ובת-הכללה (INV-LRN5 — קול ולא מהות)?". הסכמה 2/2-keep → נכתב כ-decision_lesson (source=panel:deepseek+gemini); 2/2-drop → לא נכתב; פיצול/substance → מוסלם ליו"ר. --apply הפיך, מגבה ל-data/audit/. הטמעה ל-SKILL.md/lessons.md נשארת שער-יו"ר ידני (INV-G10). מפתחות כמו פאנל-ההלכות. חובה מקומי. --case <num> / --pair-id <uuid>. שלב-למידה במסלול-הסופי
final_learning_pipeline.py python תזמור שלב-הלמידה (פקודה אחת). מופעל ע"י הרמס כשלוחצים "הרץ למידת-קול" במסלול-הסופי. דטרמיניסטי: (1) ingest_final_version עם נתיב-הסופי, (2) רישום לקורפוס-הסגנון (idempotent), (3) style_lesson_panel --apply. עמיד (X16/INV-DUR1): 3 הצעדים רצים דרך _pipeline_runtime.py (משותף עם halacha) עם checkpoint לכל תיק — קריסה בפאנל [3] ממשיכה מ-[3] במקום לשלם שוב על דיסטילציית-Opus [1]. ברירת-מחדל auto-resume; --fresh ריצה נקייה. idempotent. חובה מקומי. --case <num> / --force / --fresh. אוטו (כפתור run-learning) / ידני
final_halacha_pipeline.py python תזמור שלב-אימות-ההלכות (פקודה אחת). מופעל ע"י הרמס כשלוחצים "הרץ אימות-הלכות". דטרמיניסטי: (0) precedent_extract_halachot (החלטה), (1) extract_internal_citations(chair), (2) corroboration.build_all(), (3) halacha_panel_approve --apply. עמיד (X16/INV-DUR1): 4 הצעדים רצים דרך _pipeline_runtime.py עם checkpoint לכל תיק — קריסה בפאנל [3] ממשיכה מ-[3]. ברירת-מחדל auto-resume; --fresh ריצה נקייה. חובה מקומי. --case <num> / --limit N / --fresh. אוטו (כפתור run-halacha) / ידני
_pipeline_runtime.py python runtime עמידות משותף (X16 / INV-DUR1) ל-final_halacha_pipeline ו-final_learning_pipeline (מימוש אחד, G2). עוטף רשימת-צעדים async ב-LangGraph StateGraph ליניארי עם AsyncSqliteSaver (checkpoint לכל צעד; resume מדלג על צעדים שהושלמו). degradation חיננית: ללא langgraph (pip install -e ".[durable]") — ריצה ליניארית כמו קודם (הכפתור לא נשבר). Step(name, run) + run_pipeline(steps, thread_id, checkpoint_db, fresh). נבדק: mcp-server/tests/test_pipeline_runtime.py. מיובא ע"י סקריפטי-המסלול-הסופי
curator_apply_pipeline_branch.py python מקור-אמת לחיווט-הכפתורים של הרמס. prompt-ה-curator חי רק ב-Paperclip DB (agents.adapter_config.promptTemplate). הסקריפט מקדים branch כך שיקיצה עם reason final_learning_*/final_halacha_* מריצה את ה-pipeline המתאים (HOME/DOTENV/DATA_DIR מוחלטים → DeepSeek+Gemini keys + DATA_DIR נפתרים נכון) ועוצרת, אחרת §A/§B כרגיל. idempotent (מסיר branch קודם). מחיל על שני הסוכנים (CMP+CMPA). --verify. להריץ אחרי reset/יצירה-מחדש של סוכן-curator. אחרי reset prompt של curator
halacha_panel_audit.py python רשת-ביטחון לפאנל (selective-prediction monitoring) — דוגם הלכות שאושרו ע"י הפאנל (reviewer LIKE 'panel:%'), מריץ עליהן שוב את הצבעת-ה-KEEP של 3 השופטים, ומציף כל מקרה שכעת נוטה DROP (false-keep פוטנציאלי). report-only כברירת-מחדל; --flag מחזיר את ה-flips ל-pending_review לסקירת-יו"ר. --sample N/--seed. בסיס 2026-06-07: 0/15. מיועד להרצה תקופתית (שבועי). מייבא שופטים מ-halacha_panel_approve. חובה מקומי. תקופתי (שבועי) — ניטור
halacha_panel_calibrate.py python כיול + מדידת הפאנל (Trust-or-Escalate, ICLR 2025). --source live (ברירת-מחדל): מריץ את שאלת-ה-KEEP על מדגם-הזהב ומודד מול is_holding precision+coverage+split-rate לכל מדיניות + false-keep/false-drop (מייבא שופטים מ-halacha_panel_approve, חובה מקומי). #133/FU-5--source captured: אפס-עלות (בלי re-vote/LLM) — מצליב סבבים שמורים (FU-1) מול הכרעות-יו"ר (FU-2) דרך db.panel_rounds_vs_chair ומדווח split-rate+auto-precision לכל סבב (מגמת הלולאה: ככל שהרובריקה משתפרת precision נשמר ו-split יורד); משתף את analyze_pairs של FU-4 (מקור-יחיד). שתי המדידות מדווחות anon-stability (מבחן-אנונימיזציה #81.7) כמטריקת-בריאות נגד echo-chamber. --batch/--limit/--concurrency. ידני — לפני חיווט --apply (live) / תקופתי — מעקב-לולאה (captured)
halacha_rubric_distill.py python #133/FU-4 — זיקוק-רובריקה PROPOSE-ONLY. מצליב halacha_panel_rounds (FU-1, הצבעות+נימוקים) מול הכרעות-היו"ר (FU-2, seeds ב-halacha_goldset batch chair-live) דרך db.panel_rounds_vs_chair (read-only), מנתח דטרמיניסטית כשלים שיטתיים (false-keep/false-drop, פיצולים-שהוכרעו, שיעור-מחלוקת-עם-היו"ר לכל שופט), ומציע KEEP_SYSTEM v2 + exemplars מופשטים (claude_session מקומי, אפס עלות) כדוח-diff ל-data/learning/rubric-proposal-<ts>.md. לעולם לא auto-apply — אימוץ v2 = עריכה אנושית של הקבוע דרך PR (INV-LRN1); exemplars מופשטים בלבד (INV-LRN5); הסיגנל היחיד = הכרעת-יו"ר, לא הצבעות-פאנל (anti-echo). מתחת ל-12 זוגות → "אין מספיק נתונים". --no-llm (סטטיסטיקה בלבד) / --limit N. חובה מקומי. תקופתי — אחרי שהצטברו הכרעות-יו"ר על מחלוקות-פאנל
backfill_canonical_halachot.py python V41 — הקמת מודל ההלכות הקנוניות (חד-פעמי + idempotent). (1) בונה רכיבים-קשורים (connected components) מ-equivalent_halachot (transitive closure — union-find). (2) לכל אשכול: בוחר נציג-קנוני (הכי הרבה corroboration → confidence → earliest), יוצר שורת canonical_halachot, ומעדכן canonical_id + instance_type לכל חברי האשכול. (3) לסינגלטונים (ללא קישורי-שוויון): 1:1 canonical. (4) מאכלס halacha_citation_corroboration.canonical_id מ-halachot.canonical_id. --dry-run (ברירת-מחדל, מחשב ומדווח בלבד) / --apply (כותב) / --verbose. לאחר הרצה: canonical_statement = ניסוח-נציג (pending_synthesis); עוקב: backfill_canonical_synthesis.py (Phase 4) יסנתז ניסוח-רחב דרך LLM. הרץ: mcp-server/.venv/bin/python scripts/backfill_canonical_halachot.py --apply. חד-פעמי (לאחר deploy V41) / idempotent לפי צורך
build_verified_layer.py python #153 — בניית שכבת-המאומת מאזכורים. "מאומת=אזכור, לא ביקורת" (chaim 2026-06-20): מריץ את ה-citator (extract_internal_citations) על כל החלטות-הוועדה (לא רק דפנה), ואז db.refresh_verified_layer שמחשב halachot.verified/cite_count מ-precedent_internal_citations (verified=פס"ד-המקור צוטט ע"י יו"ר; cite_count=# החלטות מצטטות). idempotent, גדל-אוטומטית עם החלטות חדשות. regex/embeddings בלבד, אפס-LLM. --no-citator (refresh בלבד). הרץ: mcp-server/.venv/bin/python scripts/build_verified_layer.py. חוזר (אחרי קליטת החלטות-יו"ר)
backfill_practice_area.py python #153 step 4 — חוזה-קליטה. 87% מהפסיקה-החיצונית בלי practice_area → אחזור-מסונן-תחום מחמיצן. מריץ סיווג קיים (derive_domain_practice_area דטרמיניסטי → precedent_metadata_extractor.extract_and_apply LLM) על הלא-מסווגים. מרוסן (extract_metadata=claude/sonnet). --dry-run/--apply/--limit/--no-throttle. going-forward כבר מחווט (ingest.py:233 מתזמן metadata); זה ל-backfill הקיימים (חלופה: להזין ל-metadata_extraction_requested_at ולתת ל-drain). חד-פעמי (backfill)
compute_principle_gold.py python #153 (נטוש) — גישת זיהוי-זהב ברמת-עיקרון דרך התאמת-match_context→הלכה. הוחלף ע"י "מאומת=אזכור" (build_verified_layer.py) אחרי שההתאמה נכשלה (match_context=רשימת-הפניות). נשמר לעיון. deprecated
cull_principles.py python #152 Phase C — סינון רטרואקטיבי של קורפוס-העקרונות דרך פאנל-3 (הפיך). מריץ על כל עיקרון 'original' קיים את אותו משטר שה-extractor משתמש בו להבא (services/panel_extraction.panel_keep_score, G2): 3 שופטים (Claude מקומי + DeepSeek + Gemini) מצביעים keep+score → כלל-האישור (3 קולות→שורד · 2 וציון≥0.85→שורד · 2 ו<0.85→יו"ר · ≤1→נדחה) → תקרת HALACHA_PANEL_MAX_NEW=5 לכל החלטה לפי ציון (apply_cap). נדחה → halachot.review_status='rejected' + ה-canonical שלו rejected (הפיך, גיבוי-CSV ב-data/audit/ לפני כל כתיבה). מרוסן ב-usage_limits (עוצר-רך בתקרת-שימוש, resumable). --dry-run (ברירת-מחדל) / --apply / --sample N (החלטות אקראיות) / --limit N / --no-throttle / --verbose. חובה מקומי (3 שופטים). הרץ: cd mcp-server && HOME=/home/chaim .venv/bin/python ../scripts/cull_principles.py --apply. חד-פעמי (סינון ראשוני) + ניתן-לחזרה
backfill_canonical_synthesis.py python V41 Phase 4 — סינתזת-LLM ל-canonical_statement (idempotent + resumable). עובר על canonicals ב-review_status='pending_synthesis' (רב-instance ראשונים) ומזקק לכל אחד ניסוח אחד כללי ומעוגן בציטוטי-המופעים (INV-AH) דרך services/canonical_synthesis.py (מסלול-יחיד, G2). שערים: עיגון/הימנעות, drift-floor (cosine מול המקור, ברירת-מחדל 0.80 — סטייה גדולה→נשמר המקור), ואיסור ציטוטי-תיק חדשים. בכל מקרה הסטטוס מתקדם ל-pending_review לשער-היו"ר (G10/INV-LRN6). מודל Opus (HALACHA_CANONICAL_SYNTH_MODEL). מרוסן ע"י usage_limits (עוצר-רך בתקרת-שימוש, resumable). --dry-run (ברירת-מחדל) / --apply / --sample N (מדגם אקראי לבדיקה) / --limit N / --no-throttle / --verbose. CSV-audit ל-data/audit/canonical-synthesis-*.csv. חובה מקומי (claude_session). הרץ: cd mcp-server && HOME=/home/chaim .venv/bin/python ../scripts/backfill_canonical_synthesis.py --apply. שוטף: כלי-MCP canonical_synthesize_pending. חד-פעמי (המסה הראשונית) + idempotent לחדשים
backfill_lesson_synthesis.py python #158 / INV-LRN8 — סינתזת-LLM של decision_lessons (idempotent + resumable). עובר על shards של practice_area+category עם ≥2 לקחי-סגנון approved, מאשכל near-duplicates (cosine ≥ LESSON_SYNTH_CLUSTER_THRESHOLD), וממזג כל אשכול ל"לקח-על" אחד מעוגן-מקור (INV-AH) עם drift-floor (LESSON_SYNTH_DRIFT_FLOOR מול centroid) דרך services/lesson_synthesis.py (מסלול-יחיד, G2). הלקח-על נכתב source='synthesis' (review_status='approved', שער-מדורג-הפיך), המקורות→superseded. כך הסט שזורם לכותב קטֵן ומשתבח (פותר את חיתוך limit=15, #157). מודל Opus (LESSON_SYNTH_MODEL), מרוסן usage_limits. --dry-run (ברירת-מחדל) / --apply / --practice-area / --category / --no-throttle / --verbose. CSV-audit ל-data/audit/lesson-synthesis-*.csv. חובה מקומי (claude_session). הרץ: cd mcp-server && HOME=/home/chaim .venv/bin/python ../scripts/backfill_lesson_synthesis.py --apply. שוטף: כלי-MCP lesson_synthesize_pending. idempotent — הרצה לפי צורך/כשמצטברים לקחים
halacha_batch_reconcile.py python #82.7 — dedup חוצה-פסקים offline (שמרני, dry-run בלבד). dedup-on-insert משווה רק תוך-פסק; כאן סף מחמיר (cosine ≥0.95, --cosine) ולא-הרסני: מאתר זוגות הלכות near-duplicate בין פסקים שונים (pgvector <=> exact) עם איתות לקסיקלי (Jaccard/Levenshtein) ומדווח ל-CSV ב-data/audit/ לסקירת היו"ר. לא מדלג/ממזג/מוחק. --include-pending. --link רושם את הזוגות שנמצאו כ-equivalent_halachot (parallel authority, #84.2 — deprecated post-V41 — השתמש ב-backfill_canonical_halachot.py --apply במקום). רץ עם venv של mcp-server. deprecated — הוחלף ב-backfill_canonical_halachot.py (V41). נשמר לצורכי audit
calibrate_halacha_dedup.py python #82.1 — כיול ספי ה-dedup הלקסיקלי (#82.3) מול gold-set הניקוי. קורא halacha-cleanup-manifest-*.csv (זוגות duplicate↔survivor מתויגי-אדם), טוען טקסט-survivor מה-DB, ו-sweep של (jaccard_min × levenshtein_min) עם P/R/F1, מסמן את נקודת-העבודה המוגדרת. אימת ש-(0.55, 0.70) → precision 1.0 (אפס false-merge), recall 0.30 — מתאים לאיתות-משני שחוסם auto-approve. --manifest <path>. רץ עם venv של mcp-server חד-פעמי — כיול (בוצע 2026-06-06)
ab_halacha_opus48.py python A/B לא-הרסני לחילוץ הלכות (Claude) — מריץ מחדש חילוץ הלכות על פסק-דין בודד דרך מודל/effort נבחרים (AB_MODEL/AB_EFFORT, ברירת-מחדל claude-opus-4-8/xhigh) ומשווה לסטטיסטיקות ההלכות הקיימות ב-DB בלי למחוק/לכתוב כלום. משכפל את halacha_extractor.extract() (אותם פרומפטים, בחירת-צ'אנקים, אימות-ציטוט) ומחליף רק את קריאת ה-LLM ב-claude -p --model --effort. מפיק data/ab_halacha_<case>_<effort>.json. הרצה: DOTENV_PATH=/home/chaim/.env DATA_DIR=.../data .venv/bin/python scripts/ab_halacha_opus48.py <case_law_id>. ממצא 2026-05-31 (שטיין 1128-08-20): Opus 4.8@xhigh חילץ 51 מול 124 בייצור (100% quote-verified מול 96%) אך ביטחון מכויל-נמוך יותר (חציון 0.75 מול 0.82) — ולכן לא מקטין את תור-האישור-הידני תחת sweep אוטו-אישור conf≥0.78 (26 מול 24). שיפור איכות, לא צמצום-תור. ידני (החלטת מודל-חילוץ)
ab_halacha_codex.py python A/B לא-הרסני לחילוץ הלכות (Codex/gpt-5.5) — עמית ל-ab_halacha_opus48 אך מחליף את claude -p ב-codex exec --model gpt-5.5 (אימות ChatGPT, ללא OPENAI_API_KEY). אותם פרומפטים ואותו הסקת quote-verification. הפלט האחרון של הסוכן (-o FILE) נפענח כ-JSON. AB_MODEL (default gpt-5.5), AB_REASONING low/medium/high/xhigh (default medium), AB_CONCURRENCY (default 1), CODEX_BIN. מפיק data/ab_halacha_codex_<case>_<model>_<reasoning>.json. הרצה: DOTENV_PATH=/home/chaim/.env DATA_DIR=.../data mcp-server/.venv/bin/python scripts/ab_halacha_codex.py <case_law_id>. ממצא 2026-06-17 (8181-21 האוניברסיטה העברית): gpt-5.5@medium חילץ 27 מול 28 של Opus (quote-verified 100%/100%), ביטחון חציון 0.86 מול 0.78 — אך 0 פריטים מתחת ל-0.7 (לעומת 9/28 של Opus = 32%), דבר המצביע על over-confidence. holding↑ (12 מול 7), procedural↓ (4 מול 7). מסקנה: ריאלי כ-fallback חירום; לא מוכן לייצור ללא כיול-ביטחון. ידני (בנצ'מרק מודל codex)
calibrate_effort.py python #208 (WS5/Q1, INV-G8 eval-harness) — כיול model×effort של הכותב מול הסופיים. A/B per-(תיק,בלוק,effort) על draft_final_pairs בעלי final_text: מייצר מחדש כל בלוק דרך מסלול-הייצור (block_writer.write_block(effort_override=…)claude_session.queryclaude -p, Opus 4.8 נעוץ, מקומי-בלבד) ומודד מול הסקשן המתאים בסופי דרך services/style_distance.block_distance_to_final (מקור-מדידה יחיד, G2): change_percent (compute_diff_stats) · anti_pattern_total (lessons.ANTI_PATTERNS, הסיגנל הנקי-לסגנון) · golden_ratio_deviation_pp · distance מרוכב. ממליץ per-בלוק על ה-effort בעל ה-distance-הממוצע-הנמוך (לצד ברירת-המחדל מ-#204). מפיק data/eval/effort-calibration-<ts>.{json,md} בכתיבה אינקרמנטלית — הדוח נכתב מחדש אחרי כל בלוק שמסתיים, כך שקריסה באמצע הגריד לא מאבדת בלוקים שכבר יוצרו (INV-G8). כל תא-(תיק,בלוק,effort) שנכשל (rate-limit חולף, או חריגה) נרשם כ-warning ומדולג — לא מפיל את הריצה. block-yod (דיון) הוצא מברירות-המחדל (CALIBRATABLE_BLOCKS) — דורש כיוון-מאושר (brainstorm→approve_direction) שתיקי-הכיול חסרים ולכן write_block זורק; נשאר ב-VALID_BLOCKS לכפייה ידנית (--blocks block-yod) על-אחריות-המשתמש, כשהשער-per-תא שומר אותו לא-פטאלי. ⚠️ גודל-מדגם מודפס בראש הדוח — עדות-כיוון, לא רגרסיה (מעט סופיים-עלויים). --self-test (offline, אפס DB/CLI — מוכיח את לוגיקת-המדידה) · --dry-run (תכנון-גריד) · --efforts/--blocks/--case/--repeats. חובה מקומי (claude CLI; לא בקונטיינר/worktree-ללא-CLI). הרצה: POSTGRES_PASSWORD=… mcp-server/.venv/bin/python scripts/calibrate_effort.py. ידני — לכיול ברירות-effort של הכותב
monitor_halacha_quality.py python מנטר איכות חילוץ הלכות. בודק drift של avg(confidence) בין baseline היסטורי לחלון אחרון. מחזיר JSON מטריקות + alert ב-stderr אם drift > threshold (ברירת מחדל 5%). 2 סדרות: trusted (approved+published) ו-all_extracted. תומך --window N / --threshold X / --min-sample N / --silent / --exit-on-alert. רץ ב-container או מקומית עם mcp-server/.venv (אין תלות ב-LLM, רק SQL). תזמון מומלץ: 0 8 * * 1 (יום ראשון 08:00, שבועי) 0 8 * * 1 (לתזמן)
audit_training_corpus.py python audit של style_corpus — לכל החלטה: שדות מטא-דאטה מאוכלסים (summary/outcome/key_principles/appeal_subtype/subject_categories), קישור ל-documents (FK + chunks + embeddings). מפיק data/audit/corpus-YYYY-MM-DD.json + summary בקונסול. דרוש POSTGRES_URL או POSTGRES_*. אין תלויות חיצוניות מלבד asyncpg. רץ מהמכונה המקומית (לא קונטיינר) — חיבור ישיר ל-Postgres :5433 ידני / קדם-עבודה לפני enrichment של מטא-דאטה
backfill_style_exemplars.py python T1 (style-acquisition) — מאכלס style_exemplars מקורפוס דפנה (style_corpus + internal_committee chair=דפנה): מפצל לסעיפים (chunker._split_into_sections) → פסקאות (25-450 מילים) → embed (Voyage) → שמירה עם section/outcome/practice_area. מאפשר לכותב לאחזר פסקאות-בלוק אמיתיות של דפנה (T2/T3). מקור-סגנון בלבד (INV-LRN5). אידמפוטנטי (מנקה per-decision). --dry-run (default) / --apply. דורש POSTGRES_URL + Voyage. רץ מקומית (venv). ידני (python scripts/backfill_style_exemplars.py --apply)

פסיקה, קורפוס ויומונים

Script Type Purpose Scheduled
nevo_ratio_benchmark.py python #86.3 — מדידת איכות חילוץ-הלכות מול ה-מיני-רציו של נבו (gold-set מקצועי חינמי). לכל פסק עם nevo_ratio (או נגזר מ-full_text אם טרם בוצע backfill): LLM-judge מקומי (claude_session, אפס עלות) ממפה סמנטית את הלכות-המערכת מול הלכות-נבו ומפיק recall (כיסוי הלכות-נבו), precision (אחוז הלכותינו הממופות), granularity (יחס פירוק — איתות over-extraction ל-#81.5). --case <num> / --all [--limit N] / --model / --out. כותב CSV ל-data/audit/. רץ עם venv של mcp-server (דורש Claude CLI מקומי). אומת על בג"ץ 1764/05: recall 0.875, precision 1.0, granularity 1.75x ידני — מדידת-איכות (CI/ad-hoc)
nevo_corpus_audit.py python #86.2/#86.3 — אודיט קורפוס-נבו (read-only). leak סורק chunks+הלכות למרקרי-preamble של נבו (מיובאים מ-extractor._NEVO_MARKERS), מבחין בין הווקטור המזיק (מרקר בתוך הלכה=רציו-עריכה כהלכה) ל-benign (רשימת-ציטוטים), ומפיק CSV. אומת 2026-06-11: 0 הלכות מזוהמות (שכבת-הידע נקייה) → אין purge/re-ingest (גם נוגד no-reocr). leak --apply מבצע backfill אדיטיבי של case_law.nevo_ratio מטקסט שמור (extract_nevo_ratio, ללא re-OCR) — captured 16→32. benchmark משווה הלכות-שלנו מול ה-מיני-רציו דרך הפאנל התלת-מודלי → recall כיסוי (1110-20: 13 הלכות, recall=1.0). חובה מקומי (benchmark). ידני — ניטור-זיהום / ground-truth
audit_corpus_integrity.py python בדיקה תקופתית של עקביות הקורפוס — 5 בדיקות SQL read-only על case_law ו-cases: (A) external_upload עם prefix פנימי ערר/בל"מ; (B) internal_committee חסר chair_name/district; (C) cases.practice_area מחוץ ל-{rishuy_uvniya, betterment_levy, compensation_197, ''}; (D) תיקים מוכרעים (final/exported/reviewed) ללא chair_name (chair ריק מפיל בשקט את העתק-הסופי לקורפוס-הפסיקה — INV-G1); (E) תיקי final חתומים שחסרים מקורפוס-הפסיקה הפנימי (internal_committee). כותב log מצטבר ל-data/logs/corpus_integrity_audit.log ובמצב הפרות שולח wakeup ל-CEO ב-Paperclip (best-effort, רק אם PAPERCLIP_API_URL+PAPERCLIP_API_KEY מוגדרים). דגל: --no-notify. Idempotent, יוצא 0. Cron יומי 07:00: 0 7 * * * /home/chaim/legal-ai/mcp-server/.venv/bin/python /home/chaim/legal-ai/scripts/audit_corpus_integrity.py 0 7 * * * (cron)
backfill_legal_arguments.py python Backfill legal_arguments לתיקים עם claims קיימים (TaskMaster #36). מקבץ פרופוזיציות גולמיות לטיעונים משפטיים מובחנים (~6-12 לכל צד) דרך argument_aggregator.aggregate_claims_to_arguments (Claude CLI). תומך --dry-run/--apply/--force/--case <num>.... חייב לרוץ מהמכונה המקומית (לא קונטיינר) — claude_session דורש Claude CLI ידני per-case (python scripts/backfill_legal_arguments.py --apply --case 1017-03-26)
ingest_bulletins.py python קליטת ארכיון העלון החודשי "עו"ד על נדל"ן" לקורפוס-הגילוי (X12) — כל PDF ב-data/bulletins/incoming/ מפוצל ע"י LLM למצביעי-פסיקה (digest_kind='decision') + מאמרים (digest_kind='article'), עם tag publication='עו"ד על נדל"ן', דרך bulletin_library.ingest_bulletin. idempotent (dedup per-item לפי content_hash; הרצה חוזרת מוסיפה רק חדשים); כשל בעלון אחד לא עוצר את ה-batch. רץ מהמכונה המקומית (LLM מקומי-בלבד) עם venv של mcp-server: mcp-server/.venv/bin/python scripts/ingest_bulletins.py [--dir PATH] [--limit N]. ידני, per-batch

תשתית, CI ו-hooks

Script Type Purpose Scheduled
spec-guard.sh bash PreToolUse hook לאכיפת "פרוטוקול כתיבת-קוד" (CLAUDE.md §פרוטוקול כתיבת-קוד) — בכל Edit/Write/MultiEdit על נתיב-קוד (web/, mcp-server/, web-ui/src/, scripts/, adapters/) מזריק תזכורת ל-Claude לקרוא את docs/spec/00-constitution.md+ספ-התחום ולוודא קיום G1G12 — לפני שכותבים. + leak-guard בזמן-אמת (G12): על כתיבה ל-mcp-server/src/* בודק את התוכן-הנכתב (new_string/content) ומזהיר אם מוזרק מונח-Paperclip לשכבת-האינטליגנציה (לא-deduped). המקבילה האינטראקטיבית ל-INV-AG1. קלט JSON ב-stdin, פלט hookSpecificOutput.additionalContext (non-blocking, exit 0). Dedup פעם-בסשן לתזכורת-הספ. רשום ב-.claude/settings.json. נקרא אוטומטית ע"י Claude Code (hook)
leak_guard.py python המאכף הקנוני של INV-G12 (שער-הפלטפורמה / docs/spec/X15 §4 / R4). שני כללים קשיחים: (1) mcp-server/src ללא סמלי-Paperclip (allowlist מנומק לפי substring); (2) רק web/agent_platform_port.py (+ קבצי-המעטפת) מייבאים את לקוח-Paperclip. stdlib-בלבד (אין venv). leak_guard.py = סריקת-repo (exit 1 על הפרה); leak_guard.py <file>... = קבצים נתונים (ל-hook). משותף ל-spec-guard.sh (hook), ל-CI (.gitea/workflows/leak-guard.yaml) ול-mcp-server/tests/test_platform_port_leak_guard.py. CI + hook + pytest
check_undefined_names.py python CI gate ל-undefined names (מחלקת ה-NameError). מריץ pyflakes על web, mcp-server/src, scripts ומפיל build (exit 1) רק על "undefined name"/"may be undefined" — לא על imports-לא-בשימוש/f-strings (רעש). זו בדיוק מחלקת-הבאג של PR #249 (שינוי-שם תיק → 500): שם שמופנה אך לא מיובא/מוגדר, חבוי בתוך background_tasks עד זמן-ריצה. דורש pyflakes (ה-workflow מתקין ל-venv זמני). משותף ל-CI (.gitea/workflows/lint.yaml). CI
auto-sync-cases.sh bash סנכרון תיקי ערר ל-Gitea — רץ כל דקה * * * * * (cron)
host_sync.sh bash מסנכרן את עץ-המארח ~/legal-ai ל-origin/main (ff-only) כדי שקוד-המארח (כותב/פאנלים/MCP שרצים מהעץ, לא בקונטיינר) יתעדכן אחרי merge; restart מדויק ל-chat/court-fetch/reaper רק כשקבציהם משתנים. בטוח: אף-פעם לא force; tasks.json הדירטי נשמר. סוגר את פער-פריסת-המארח (TaskMaster #160) * * * * * (cron, flock)
notify.py python שליחת מייל התראה מסוכנים via SMTP (Gmail) נקרא ע"י סוכנים
bidi_table.py python יצירת טבלאות box-drawing עם תמיכה ב-BiDi (עברית+אנגלית) ספריית עזר
convert_decision_template.py python המרת data/training/טיוטת החלטה.dotxskills/docx/decision_template.docx לטעינה ב-python-docx להריץ כשמתעדכנת התבנית
regenerate_voice_fingerprint.py python מסנתז מהקורפוס (style_corpus + דוגמאות + יחסים) הצעה לעדכון פרופיל-הקול (Opus מקומי). שער-יו"ר קשיח (INV-LRN1): כותב ל-data/curator-proposals/, לעולם לא דורס את docs/daphna-voice-fingerprint.md — היו"ר סוקרת ומקבעת ידנית. החצי-הפרוזה של #161 (החצי-המבני=ratios ב-PR#345). רץ על המארח (claude CLI). STYLE/METHOD בלבד (INV-LRN5) ידני / לתזמן תקופתית
deploy-track-changes.sh bash סנכרון skills CMP↔CMPA + בדיקות + הנחיות deploy לארכיטקטורת Track Changes ידני

חד פעמי

סקריפטים שהורצו פעם-אחת (מיגרציות / backfills / POCs), נשמרים לרפרנס. מקובצים לפי אותם תת-נושאים.

סוכנים, Paperclip ואדפטרים

Script Type Purpose Scheduled
sync_missing_agent_skills.py python סקריפט "אל-כשל" להוספת paperclipSkillSync ל-הגהת מסמכים ו-מנתח משפטי שפיספסו את ה-sync ההיסטורי (Gap #28). תומך --verify/--dry-run/--apply. גיבוי אוטומטי ל-agents-pre-skill-sync-*.sql. דורש PAPERCLIP_BOARD_API_KEY (Infisical /paperclip ב-nautilus env). idempotent. חד-פעמי (בוצע 2026-05-04). שמור לרפרנס
fix_paperclipai_skills_drift.py python סקריפט חד-פעמי (בוצע 2026-05-04) שניקה drift על paperclipai/* skills בין CMP ל-CMPA. הסיר paperclip-dev מכל 14 הסוכנים, ודאג ש-paperclip-converting-plans-to-tasks קיים רק על CEO ו-analyst. תומך --apply (ברירת מחדל: dry-run). דורש PAPERCLIP_BOARD_API_KEY. נשמר לרפרנס למקרה שhdrift חוזר. חד-פעמי (בוצע)

אחזור, embeddings ו-multimodal

Script Type Purpose Scheduled
voyage_context3_poc.py python POC #1 — voyage-3 vs voyage-context-3 על פסיקה אחת קצרה (קלמנוביץ, 63 chunks). הכרעה: context-3 לא מציג שיפור עקבי בנצ'מרק חד-פעמי, נשמר לרפרנס
voyage_context3_poc_long.py python POC #2 — voyage-context-3 על פסיקה ארוכה (אהרון ברק 219 chunks) עם sliding windows. הכרעה: context-3 לא משתפר על פסיקה גדולה בנצ'מרק חד-פעמי, נשמר לרפרנס
voyage_multimodal_poc.py python POC #3 — voyage-multimodal-3 על דוח שמאי (89 עמודים). הכרעה: שיפור משמעותי לטבלאות + 22 עמודי image-only שhttp text-OCR מאבד בנצ'מרק חד-פעמי, מוכן לשלב C
voyage_rerank_judge_poc.py python POC #4 — voyage-3 vs rerank-2 vs context-3 על אהרון ברק, 18 שאילתות, claude-haiku-4-5 כ-judge. הכרעה: rerank-2 ניצח עם +9% mean@3 בנצ'מרק חד-פעמי
voyage_rerank_corpus_poc.py python POC #5 — voyage-3 vs rerank-2 על קורפוס מלא (785 docs). הכרעה: +4.5% mean@3 כללי, +11.6% על P queries (practical) בנצ'מרק חד-פעמי, אישר את שלב B
rechunk_legacy_precedents.py python #57 — re-chunk + re-embed פסיקה שהוטמעה לפני תיקון ה-chunker (#55). בוחר כל case_law עם chunk זעיר (length(trim(content))<50 — טביעת-האצבע של ה-chunker הישן) ומריץ ingest.reindex_case_law (re-chunk+re-embed מ-full_text שמור בלבד — ללא re-OCR/LLM, feedback_no_reocr_retrofit; idempotent DELETE-then-INSERT). idempotent ברמת-הבאטץ' (שואב מחדש את הסט המושפע בכל ריצה). דגל --limit N. רץ עם venv של mcp-server (cd mcp-server && .venv/bin/python ../scripts/rechunk_legacy_precedents.py) חד-פעמי — מיגרציית-נתונים של פסיקה legacy (תוקן 2026-06-03)

אחסון, DB ותורים

Script Type Purpose Scheduled
reconcile_metadata_status.py python נרמול metadata_extraction_status תקוע (G1) — שורות עם ברירת-המחדל 'pending' שאינן בצנרת-Gemini נערמות כ-backlog-רפאים שהדריינר (סורק *_requested_at IS NOT NULL) לעולם לא מנקה ומנפח את מונה "ממתין" ב-/operations. מיישב כל שורה למצב-אמת במקור: internal_committeecompleted (מטא דטרמיניסטי, מחוץ ל-Gemini), external_upload מלא→completed, external_upload עם טקסט וחסר שם/תקציר→חותם requested_at (הדריינר יטפל), cited_only (אין טקסט)→skipped. מכסה את שני התורים (#140): אותו cited_only→skipped מוחל גם על halacha_extraction_status (תור-תאום, G2). אידמפוטנטי. תיקון-המקור הנלווה ב-db.create_internal_committee_decision + מסנן EXTRACTION_ELIGIBLE_PREDICATE ב-list_pending_extraction_requests. הרצה: mcp-server/.venv/bin/python scripts/reconcile_metadata_status.py. חד-פעמי / re-runnable כהגנת-drift

הלכות, פאנל וסגנון

Script Type Purpose Scheduled
reconcile_under_extracted_halacha.py python #144 — שחזור פסיקה תת-מחולצת שהושלמה אך עם 0 הלכות למרות ≥3 מקטעי-נימוק (legal_analysis/ruling/conclusion) — חתימת ה-checkpoint-הריק שנוצרה לפני תיקון limit-notice ב-claude_session. מאפס checkpoints + request_halacha_extraction (נתיב קנוני, G2) → הדריינר מחלץ מחדש. שמרני (≥3 מקטעים → לא מטפל ב-remand לגיטימי חסר-הלכה; אפס אובדן כי 0 הלכות ממילא). מחריג cited_only. אידמפוטנטי, dry-run כברירת-מחדל / --apply. הרצה: HOME=/home/chaim mcp-server/.venv/bin/python scripts/reconcile_under_extracted_halacha.py --apply. חד-פעמי / re-runnable
halacha_rule_role_backfill.py python INV-DM7 — backfill חד-פעמי: מסווג-מחדש את ההלכות הישנות (rule_type IN ('binding','persuasive') — ערכי-סמכות שנשמרו במסווה תפקיד לפני פיצול הצירים) לאחד מחמשת תפקידי-הכלל (holding/interpretive/procedural/application/obiter) דרך claude_session המקומי (אפס עלות). לא נוגע בסמכות (נגזרת מ-precedent_level). --apply (ברירת-מחדל dry-run) / --limit N / --concurrency. כותב backup CSV ל-data/audit/ תחילה. fail-safe (פריט שנכשל → נשמר ערך ישן). חובה מקומי (claude_session). ידני חד-פעמי אחרי deploy של פיצול-הסמכות
calibrate_halacha_dedup.py python #82.1 — כיול ספי ה-dedup הלקסיקלי (#82.3) מול gold-set הניקוי. קורא halacha-cleanup-manifest-*.csv (זוגות duplicate↔survivor מתויגי-אדם), טוען טקסט-survivor מה-DB, ו-sweep של (jaccard_min × levenshtein_min) עם P/R/F1, מסמן את נקודת-העבודה המוגדרת. אימת ש-(0.55, 0.70) → precision 1.0 (אפס false-merge), recall 0.30 — מתאים לאיתות-משני שחוסם auto-approve. --manifest <path>. רץ עם venv של mcp-server חד-פעמי — כיול (בוצע 2026-06-06)

תיקים, מספור ומיגרציות

Script Type Purpose Scheduled
migrate_gap51_outcomes.py python GAP-51 (FU-14) — נרמול ערכי outcome לאוצר הקנוני (rejected→rejection, accepted→full_acceptance, partial→partial_acceptance) ב-decisions.outcome + cases.expected_outcome. betterment_levy לא ממופה (practice_area, לא outcome). --dry-run (ברירת-מחדל) / --apply (גיבוי ל-data/audit/gap51-outcome-backup-*.csv + UPDATE טרנזקציוני). דורש POSTGRES_URL. בוצע 2026-06-06 (9 שורות). נוגע רק ב-cases/decisions — בטוח במקביל לחילוץ. חד-פעמי (בוצע)
fu2b_reconcile_internal_case_numbers.py python FU-2b (GAP-07/08) — תיאום case_number של internal_committee מציטוט-מלא למספר-בסיס קנוני (X1: trim·prefix-strip·/-, חודש נשמר). דטרמיניסטי (token יחיד; 0/>1 → flag). --dry-run (ברירת-מחדל) מפיק טבלת-תיאום ל-data/audit/fu2b-reconciliation-*.{csv,md} עם flags (DUP_CHECK / PROC_MISMATCH / MISMATCH). --apply --approved <csv> מגבה ואז מעדכן רק שורות שאושרו ע"י היו"ר. scope: internal בלבד (external → #68). FK-safe. חד-פעמי, chair-gated (apply רק אחרי אישור דפנה)
fu2c_reconcile_external_case_numbers.py python FU-2c (GAP-08, #68) — תיאום case_number של פסיקה חיצונית (source_kind <> internal_committee) מציטוט-מלא לצורה קנונית מציין-הליך + docket (החלטת-יו"ר 2026-05-31, Option A: / נשמר, לא -; תואם db.py:369 ו-INV-ID2). דטרמיניסטי (designator+docket; 0/>1 docket → flag). --dry-run (ברירת-מחדל) מפיק data/audit/fu2c-reconciliation-*.{csv,md} עם flags (MISMATCH / NO_CITATION / CIT_NO_DOCKET / DESIG_MISMATCH / DUP_CHECK). --apply --approved <csv> מגבה ואז מעדכן שורות לא-חוסמות (כולל ADVISORY/NO_CITATION). --overrides <csv> (id,proposed_canonical,reason) פותח שורות-חוסמות בהכרעת-יו"ר מפורשת (למשל פס"ד מאוחד — ראה data/audit/fu2c-overrides.csv לרשומת לויתן/קלמנוביץ). לוגיקת-החילוץ + פיצול flags אומתו offline על 24 רשומות. scope: external בלבד (internal = FU-2b). FK-safe. חד-פעמי, chair-gated (apply רק אחרי אישור דפנה)
fix_137_committee_case_number.py python #137 — תיקון-נתון חד-פעמי: רשומת internal_committee בודדת (1bf0bae0) שבה ציטוט-מלא זיהם את שדה-המזהה (case_number=85074/0425, case_name=ציטוט שלם) — הפרת INV-ID2 ממסלול missing_precedent_upload (לפני תיקון-הקוד ב-#137). מתקן case_number85074-04-25, case_name→צדדים, ו-token ב-citation_formatted. אומת היחיד עם _canonical_case_number(num)≠num ב-internal_committee (138 ה"מזוהמים" האחרים = מקור-חיצוני/cited_only מקודמים-קידומת, X1 §5 — מחוץ-לתחום). document_id=NULL, 0 ציטוטים-נכנסים → ללא נתיב/קובץ לשנות. guard-התנגשות על (case_number,proceeding_type). אידמפוטנטי, dry-run כברירת-מחדל / --apply. הרצה: HOME=/home/chaim PYTHONPATH=mcp-server/src mcp-server/.venv/bin/python scripts/fix_137_committee_case_number.py --apply. חד-פעמי (בוצע 2026-06-15)
retrofit_case.py python retrofit רטרואקטיבי — מזריק bookmarks לקובץ קיים של תיק ספציפי ומגדיר אותו כ-active_draft ידני (חד-פעמי לתיק)
backfill_case_status_trim.py python צמצום תפריט-הסטטוס 17→10 — ממפה כל cases.status שהוסר (uploading/in_progress/analyst_verified/research_complete/brainstorming/analysis_enriched/ready_for_writing/drafting/qa_failed) לסטטוס-הליבה הקודם-ביותר ברצף (→processing/outcome_set/documents_ready/direction_approved/qa_review), כך ששורות קיימות לא נתקעות על ערך מחוץ ל-SSoT. מציג קודם את פילוח-הסטטוסים המלא. אידמפוטנטי, dry-run כברירת-מחדל / --apply. רץ בקונטיינר (Postgres :5433 משותף): docker exec <c> python /tmp/backfill_case_status_trim.py --apply. חד-פעמי (אחרי deploy של הצמצום)

פסיקה, קורפוס ויומונים

Script Type Purpose Scheduled
ocr_benchmark_mistral.py python בנצ'מרק OCR — Mistral מול Google Vision (מחקר חד-פעמי, הוביל למעבר ל-Mistral). מוריד מסמכים מ-MinIO, קורא טקסט קיים מה-DB, שולח ל-Mistral OCR, מחשב מטריקות (כיסוי/ניקיון/עברית%), שומר דוח ל-data/audit/ocr-benchmark-mistral.md + טקסטים גולמיים ל-data/audit/ocr-benchmark-raw/. הרצה: mcp-server/.venv/bin/python scripts/ocr_benchmark_mistral.py. דורש MISTRAL_API_KEY ו-mcli alias legalminio. ממצא: Mistral מנצח ב-4/5 תיקים בדוגמה ומטפל נכון ב-OCR שבור (1044-03-26 שהחזיר "English garbage" ב-Vision). חד-פעמי (בוצע 2026-06-27)
backfill_missing_precedents.py python הזנת missing_precedents פתוחים לתור-האחזור (X13) — מסווג כל פער-פתוח; עליון-סדרתי→Tier-0(supremedecisions), נט-format→Tier-1; ועדת-ערר/לא-מזוהה→דילוג. יוצר court_fetch_jobs (idempotent). --apply (ברירת-מחדל dry-run). אחרי הרצה: drain-court-fetch קולט. ידני (חד-פעמי/לפי-צורך)
derive_missing_from_cited_only.py python #143 — איחוד cited_only↔missing_precedents (G2): גוזר רשומת missing_precedents 'open' לכל stub cited_only (פסיקה מצוטטת ללא טקסט), כך ש-31 ה-stubs מופיעים בדף "פסיקה חסרה" (היו היו חפיפה≈0). (1) backfill citation_norm (מפתח-dedup designator-aware — court_citation.citation_dedup_key) ל-291 הקיימים; (2) לכל stub → create_missing_precedent(discovery_source='cited_only', linked_case_law_id=stub, notes=מצטטים) עם dedup. linked_case_law_id=זהות-קנונית-ידועה, status='open' עד העלאת-טקסט (→ promote-in-place דרך ON CONFLICT). אידמפוטנטי, dry-run / --apply. הרצה: HOME=/home/chaim mcp-server/.venv/bin/python scripts/derive_missing_from_cited_only.py --apply. חד-פעמי / re-runnable
backfill_digest_missing_precedents.py python #136 — חיבור יומונים-לא-מקושרים ל"פסיקה חסרה": לכל digest עם underlying_citation ו-linked_case_law_id IS NULL (461) מריץ את digest_library.try_autolink הקנוני (G2) — מקשר אם אפשר, אחרת פותח gap: ערר/בל"מ/unknown → missing_precedent (discovery_source='digest', dedup designator-aware), פס"ד בתי-משפט → court_fetch_job (X13). dry-run מציג פילוח-tier (369 ערר + 21 unknown → MP; 71 fetchable → court_fetch). אידמפוטנטי. הרצה: HOME=/home/chaim mcp-server/.venv/bin/python scripts/backfill_digest_missing_precedents.py --apply. חד-פעמי / re-runnable
backfill_plans_registry.py python ייבוא מרשם-התכניות (V38) מקורפוס-ההחלטות — סורק data/cases/*/drafts/decision.md + data/training/cmp/*.md, מאתר פסקאות-תוקף ("פורסמה למתן תוקף"), מחלץ רשומת-תכנית מובנית (plans_extractor, claude CLI מקומי) ועושה upsert_plan(review_status='pending_review') עם provenance. ה-SSOT לזהות+תוקף של תכנית, פעם-אחת במקום גזירה-מחדש מהשומות בכל תיק (G2). idempotent על plan_number מנורמל (G1/G3). --dry-run (ברירת-מחדל, כלום לא נכתב) / --apply / --glob (תת-קבוצה). אחרי הרצה: אישור-יו"ר ב-plan_review/תור-האישור (G10). הרץ: mcp-server/.venv/bin/python scripts/backfill_plans_registry.py. ידני (חד-פעמי + לפי-צורך כשנוספות החלטות)
backfill_precedent_citations.py python #145 — backfill ל-citation_formatted (מראה-מקום) ברשומות case_law ריקות, באמצעות db.format_precedent_citation הדטרמיניסטי (X1 §3 / INV-ID2 — שדה-תצוגה נגזר, לא מעוצב ע"י LLM ש-הפיל אותו, #145). שני מעברים לכל שורה: (1) ללא-LLM — הרכבה מהשדות השמורים (ממלא שורות-ועדה עם parties+docket+date); (2) LLM — אם (1) נמנע ויש full_text, מריץ את מחלץ-המטא (extract_and_apply) שמחלץ רכיבים (parties, citation_prefix) ואז מרכיב — זה ממלא את 171 פסקי-בתי-המשפט מהכותרת. שורות בלי רובריקה (אין צדדים) נשארות ריקות ומדווחות, לא מנוחשות (INV-AH). idempotent — רק שדה ריק (G3). --apply / --limit N / --no-llm. הרץ: HOME=/home/chaim mcp-server/.venv/bin/python scripts/backfill_precedent_citations.py. ידני (חד-פעמי + לפי-צורך)
backfill_nevo_preamble.py python #86.2 — מיגרציית-נתונים: חיתוך preamble/רציו של נבו שדלף לפסיקה שהוטמעה לפני תיקון #86.1. מאתר כל case_law ש-strip_nevo_preamble(full_text) עדיין מקצר (דליפה היסטורית), ומבצע: (1) לכידת ה-מיני-רציו ל-case_law.nevo_ratio (gold-set ל-#86.3); (2) שכתוב full_text החתוך + חישוב-מחדש של content_hash; (3) reindex_case_law (re-chunk+embed, ללא re-OCR/LLM); (4) סימון (לא מחיקה) הלכות ש-supporting_quote שלהן בתוך ה-preamble שהוסר → pending_review + quality_flag nevo_preamble_leak. שומר-בטיחות: שורות עם keep%<--min-keep (ברירת-מחדל 60) מוחרגות מ---apply כחשד over-strip (אלא אם --include-suspicious). dry-run כברירת-מחדל; --apply כותב backup JSON + manifest CSV ל-data/audit/ תחילה. idempotent. רץ עם venv של mcp-server. chair-gated (לאמת manifest לפני apply) מיגרציית-נתונים — dry-run בוצע (19 פסקים, 27 הלכות מזוהמות); apply ממתין לאישור
upload_blam_decisions.py python חד-פעמי (2026-05-26) — העלאת 2 החלטות בל"מ ל-case_law (8126/24 סופר נוח, 8047/23 הרנון) דרך ingest_internal_decision ישיר, עוקף MCP server שטרם נטען מחדש אחרי הוספת proceeding_type. לא להריץ שוב חד-פעמי — להעביר ל-.archive/ בהזדמנות
process_pending_blam.py python חד-פעמי (2026-05-26) — הרצת metadata + halacha extraction על 2 החלטות בל"מ שעלו ב-upload_blam_decisions.py. עוקף MCP (אותו טעם). לא להריץ שוב חד-פעמי — להעביר ל-.archive/ בהזדמנות

תיקיית .archive/ — סקריפטים שהושלמו

סקריפטים חד-פעמיים שהפונקציונליות שלהם הוטמעה ב-MCP server או ב-API. נשמרים ב-git לצורך היסטוריה — אין להריץ אותם.

Script Original Purpose Superseded By
backfill_pattern_frequency.py עדכון תדירות דפוסי סגנון ב-DB web/app.py::_extract_pattern_variants()
batch_upload_training.py העלאת קורפוס אימון (16 קבצים) Web UI: /api/training/upload
benchmark_embeddings.py השוואת מודלי embeddings (voyage-3 vs voyage-4) הושלם — voyage-3-large נבחר
benchmark_new_vs_old.py השוואת Google Vision vs markdown קיים הושלם — בדיקה חד-פעמית לתיק 1130-25
decompose-decisions.py פירוק החלטות סופיות ל-12 בלוקים MCP: write_block(), write_all_blocks()
export-decision-docx.py ייצוא החלטה ל-DOCX MCP: export_docx()
extract-citations.py חילוץ ציטוטי פסיקה מבלוק י MCP service: references_extractor.py
extract-claims.py חילוץ טענות מבלוק ז MCP: extract_claims() + claims_extractor.py
extract_claims_8174.py חד-פעמי — חילוץ טענות חסרות לתיק 8174-24 אחרי timeout של האנליסט (43 טענות עורר נוספו 30/04/26) phase 1: claude_session async + 30min timeout + chunking סמנטי
extract_all_google_vision.py OCR בכמות עם Google Vision MCP: document_upload() pipeline
extract_originals.py חילוץ טקסט מ-PDF עם Claude Opus MCP service: extractor.py
extract_originals_ocr.py חילוץ OCR מלא מ-PDF MCP service: extractor.py
generate-embeddings.py יצירת embeddings לבלוקים ופסיקה אוטומטי — נוצרים עם יצירת בלוקים
link-claims-to-discussion.py קישור טענות לפסקאות דיון MCP service: qa_validator.py
proofread_training_corpus.py ניקוי Nevo מ-DOCX/PDF ל-Markdown MCP service: proofreader.py + Web UI
seed-appeals.py seeding תיקי ערר ראשוניים ל-DB MCP: case_create()
seed-knowledge.py seeding לקחים, ביטויי מעבר, פסיקה MCP: record_chair_feedback(), precedent_attach()
validate-decision.py ולידציה מול block-schema MCP: validate_decision() + qa_validator.py
run_curator_deepseek_test.sh A/B test #1 (2026-05-05) — Hermes Curator על CMP-78 דרך DeepSeek V4-Pro ב-provider:custom, ללא interaction. תוצאה: 6:33 דק׳, 5 ממצאי סגנון/לקסיקון, פי 3 מהיר מ-Sonnet baseline (CMP-80) ופי ~20 זול. הסקריפט נקודתי לתיק 1130-25 — לא להריץ שוב החלפת Curator לאדפטר DeepSeek מקומי (בתהליך)
run_curator_deepseek_test_v2.sh A/B test #2 (2026-05-05) — אותו run אבל עם interaction. תוצאה: 9:08 דק׳, 5 ממצאים, היחיד מ-4 הריצות שזיהה תוצאה עובדתית נכונה (קבלה חלקית). interaction נכשל ב-API ("Agent run id required" בריצה ידנית). החלפת Curator לאדפטר DeepSeek מקומי
run_curator_sonnet_rerun.sh A/B test #3 (2026-05-05) — ריצה חוזרת של Sonnet 4.5 על אותו CMP-78. תוצאה: 12:52 דק׳ (לעומת 20:13 בריצה המקורית — כי בלי לולאת interaction.json). זיהה תוצאה שגויה ("דחייה") בעקביות עם הריצה המקורית — Sonnet עקבי-בטעות, DeepSeek אקראי. בדיקה חד-פעמית — לא להריץ שוב
ingest_incoming_batch.py python קליטת batch של החלטות ועדת ערר מ-data/precedents/incoming/ דרך המסלול הקנוני (ingest_internal_decision) + חילוץ מטא-דאטה לכל תיק (המסלול הפנימי לא מתזמן metadata — INV-ING3). רצף (לא מקבילי, להימנע מעומס CLI). רשימת DECISIONS נערכת ידנית לכל batch. config מ-~/.env. תומך תהליך project_precedent_incoming_workflow.
drain_halacha_queue.py python ריקון תור חילוץ ההלכות (process_pending_extractions kind='halacha') תיק-בודד לסבב (limit=1) עד שהתור ריק (2 סבבים ריקים), עם קצב pl.INTER_PRECEDENT_COOLDOWN_SEC בין תיקים (נשמר אחרי המעבר ל-limit=1 שביטל את המרווח הפנימי-לסבב). רץ רק בחלון-לילה 23:0005:00 שעון ישראל (_in_window, zoneinfo DST-safe — המכונה UTC); מחוץ לחלון ===SKIP===, ונעצר ===STOP=== כשהחלון נסגר (השאר ממשיך בלילה הבא, FIFO+checkpoint). env: HALACHA_DRAIN_WINDOW_START/_END/HALACHA_DRAIN_TZ. שער-סף-ניצול (נוהל-יו"ר): בין כל תיק בודק את ניצול-claude.ai דרך מקור-האמת המשותף legal_mcp.services.usage_limits (USAGE_CEILINGS — אותו שה-supervisor קורא) ועוצר ===STOP=== usage ceiling reached כשנחצה סף-רך (5-שעות ≥75% / שבועי ≥65%, env HALACHA_DRAIN_CEILING_5H/_WEEKLY). הבדיקה בין תיקים → התיק שרץ תמיד מסתיים על המכסה שנותרה ופשוט לא מתחיל חדש — עצירה לפני 429, לא קטילה. fail-OPEN אם ה-endpoint לא-זמין (ה-supervisor מגבה בקטילת-429). kill-switch /operations: בודק is_drain_disabled בעלייה וגם בתחילת כל סבב — כיבוי באמצע-ריצה עוצר את הלולאה בגבול-הסבב הבא (התהליך עצמו נהרג מיד דרך ה-UI-toggle/סופרוייזר). חילוץ-הלכות נשאר על claude_session (לא Gemini). self-heal ל-orphaned processing. ההלכות נוחתות pending_review (שער-יו"ר). חילוץ תיק-בודד שהיו"ר מבקש רץ מיד דרך ה-CEO (precedent_extract_halachot) ואינו מגודר כאן.
legal-halacha-drain.config.cjs pm2/js תזמון חלון-לילה של drain_halacha_queue.py (cron UTC 10 20,21,22,23,0,1,2,3 * * * = superset שמכסה את 23:0005:00 ישראל בקיץ ובחורף; הסקריפט גוזם לחלון המדויק ב-zoneinfo). דקת-הצתה :10 (לא :00) כדי לא לחלוק דקה עם metadata-drain (:00) או supervisor (:05) — מונע deadlock של DDL-המיגרציה כששני דריינים עולים יחד. HALACHA_DRAIN_CRON לעקיפה. ירייה כל שעה גם מחדשת one-shot שמת באמצע (advisory-lock הופך חפיפה לבטוחה). דורש claude CLI. התקנה: pm2 start scripts/legal-halacha-drain.config.cjs && pm2 save.
halacha_drain_supervisor.py python מנהל-בריאות קבוע ל-legal-halacha-drain (אפס צריכת-Claude — קורא DB/לוגים/pm2 ומצית את הדריינר הקיים). טיק יחיד: מכבד is_drain_disabled בעדיפות עליונה — אם כבוי ב-/operations עוצר את הדריינר ולא מצית · מצית כשבטל+תור≠ריק · restart ל-run תקוע (liveness לפי checkpoints-per-chunk, לא mtime-לוג שמתעדכן רק בסיום תיק ~10 דק') · זיהוי rate-limit: ה-PRIMARY הוא quota_exhausted() הסמכותי (wrapper דק מעל מקור-האמת המשותף legal_mcp.services.usage_limitssubscription_usage()+ceiling_status()+USAGE_CEILINGS, אותו שהדריינר קורא, G1/G2 בלי כפילות; endpoint לא-מתועד GET /api/oauth/usage, token מ-~/.claude/.credentials.json + UA claude-code/* חובה אחרת 429 — אותו אחוז-ניצול 5-שעות/שבועי/שבועי-Sonnet שה-UI מציג. ספי-עצירה-רכים USAGE_CEILINGS (נוהל-יו"ר 2026-06-15): עוצר לפני 429 — 5-שעות ≥75%, שבועי+שבועי-Sonnet ≥65% (עקיפה: HALACHA_DRAIN_CEILING_5H/HALACHA_DRAIN_CEILING_WEEKLY); הגעה לסף = בדיוק כמו מיצוי, cooldown עד resets_at של אותו חלון. הנימוק: 429 באמצע-תיק כופה חילוץ-מחדש של תיק שהושלם ומשחית אותו), durable ואינו תלוי בעומק-זנב-הלוג; scan_rate_limit (429 + parse איפוס, מגודר-טריות) רק כ-fallback כש-endpoint לא-זמין — תיקון הבאג שבו 429 שגלל מתחת ל-churn של ה-restart נקרא כ"hung" וגרר restart-storm שבזבז מכסה. שתי תגובות ל-cooldown: בסף-רך (≥75/65, בלי 429 טרי) — hold-soft: אינו קוטל, הדריינר קורא את אותו סף ועוצר לבד בין תיקים אחרי שמסיים את התיק הנוכחי (יש מכסה לסיים); קטילה (hold-stopped, pm2 stop) רק ב-429 טרי אמיתי (log_rl — הקריאות באמת נכשלות). מצית-מחדש כשהמכסה חוזרת (כל החלונות מתחת לסף; fallback claude -p זעיר אם ה-endpoint לא זמין). status מדפיס ניצול/סף-עצירה · חלון catch-up בוקר [05:0007:00 IDT) (CATCHUP_END) שנפתח רק לניקוי backlog שנותר כשהמכסה חזרה — איפוס-5-שעות מאוחר נוחת לרוב מעט אחרי 05:00; מגודר ב-(לא-מוגבל)+(תור≠ריק), והקצה המורחב מועבר לדריינר כך ש-window-self-guard שלו מקבל את סבבי-ה-catch-up · מאמת ש-staging מתחייב. BURST (חלון "רוץ ברצף עכשיו" ידני): מקור-אמת = drain_controls.burst_until ב-DB — אותו ערך ש-/operations קורא/כותב (G1 מקור-יחיד, G2 בלי מסלול מקביל); בעתיד→חלון מורם, אחרת חלון-לילה 23-05; פג-תוקף אוטומטי במועד. תת-פקודות: tick (ברירת-מחדל), burst-on [--until], burst-off, status.
legal-halacha-supervisor.config.cjs pm2/js תזמון כל 15 דק' של halacha_drain_supervisor.py (cron 5-59/15 * * * * = :05,:20,:35,:50, HALACHA_SUPERVISOR_CRON לעקיפה; דקת-הצתה :05 כדי לא לחלוק דקה עם metadata-drain :00 או halacha-drain :10 — מונע deadlock של DDL-המיגרציה). autorestart:false (one-shot per tick). מצב-state ב-~/halacha-drain-monitor/ (מחוץ ל-repo). התקנה: pm2 start scripts/legal-halacha-supervisor.config.cjs && pm2 save.
ingest_digests_batch.py python קליטת batch של יומוני "כל יום" מ-data/digests/incoming/ דרך המסלול העצמאי של קורפוס-הגילוי (digest_library.ingest_digest) — חילוץ-LLM (תג-מושג, כותרת-הלכה, מראה-מקום, שני-תאריכים), embedding יחיד, ו-autolink לפסק המקורי (X12/INV-DIG3). רצף (לא מקבילי). מזהה-יומון+תאריך נגזרים משם-הקובץ; העלון החודשי מדולג. לא מעביר קבצים — ה-DB (content_hash) הוא מקור-האמת היחיד; הרצה חוזרת מדלגת על קיימים (exists). config מ-~/.env.
drain_digests.py python ריקון תור ההעשרה של יומונים (X12): מעבד כל digest בסטטוס pending דרך digest_library.enrich_digest (חילוץ-LLM Sonnet + embedding + autolink). מקבילי (CONCURRENCY=3, env-tunable), idempotent. מוסיף ~/.local/bin ל-PATH כדי שה-claude CLI יימצא תחת cron. בודק דגל drain_controls('legal-digest-drain') ב-startup → no-op כשכבוי מ-/operations.
legal-digest-drain.config.cjs pm2/js תזמון כל שעתיים של drain_digests.py (cron 12 */2 * * *, DIGEST_DRAIN_CRON לעקיפה; דקת-הצתה :12 כדי לא לחלוק דקה עם metadata-drain :00 — מונע deadlock של DDL-המיגרציה) — הועבר מ-crontab של המערכת ל-pm2 כדי שיופיע ויהיה שליט בדף /operations (הרץ-עכשיו/הפעל/כבה). autorestart:false (one-shot per tick). דורש claude CLI + VOYAGE_API_KEY. התקנה: pm2 start scripts/legal-digest-drain.config.cjs && pm2 save.

| renumber_cases.py | python | מיגרציה חד-פעמית (בוצעה 2026-06-12) — תיקון 11 מספרי-תיקים לפורמט קנוני NNNN-MM-YY (הוספת ספרות-חודש; 1046-26→1024-02-26 תיקון-סידורי). רץ על ה-host (לא בקונטיינר): DB pool של האפליקציה + mcli (MinIO) + Gitea API + Paperclip DB. אטומי per-case עם גיבוי ל-data/audit/ ואימות-אחרי. FK-ים על cases.id (UUID) לא נגעו; משכתב כל עמודה עם cases/{old}/ (file_path וגם image_thumbnail_path שהוא storage-key בלי /data), מנרמל זהות חוצת-קורפוס (case_law/style_corpus/style_exemplars/citations — לא תוכן/full_text), מעביר מפתחי-MinIO ב-3 buckets (legal-immutable=WORM copy-only), משנה-שם repo ב-Gitea, ומעדכן ב-Paperclip את שם-הפרויקט + plugin_state.legal-case-number + כותרות-issues (3 המשטחים ש-get_case_issues נשען עליהם — בלי (b)+(c) ה-issues נשארים על המספר הישן ו-run-learning/run-halacha מדלגים בשקט עם "no_issue"; תוקן 2026-06-28 אחרי שהפער התגלה ב-8137-11-24). dry-run כברירת-מחדל; --apply --tier clean\|archive. מיצוי — לא להריץ שוב (ה-MAPPING היסטורי); לתבנית-עתידית: ה-Paperclip-step המעודכן הוא הרפרנס. | חד-פעמי — בוצע |

סקריפטים שנמחקו (git history בלבד)

Script Reason
import-final-decisions.py מיגרציה הושלמה — כל ההחלטות ב-data/training/
compare_extractions.py בדיקה חד-פעמית לתיק 1130-25
decompose-decisions-v2.py כפילות של v1
extract_google_vision.py hardcoded לתיק בודד
extract_google_vision_single.py wrapper חד-פעמי
test-search.py סקריפט דיבאג