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>
81 KiB
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.query → claude -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+ספ-התחום ולוודא קיום G1–G12 — לפני שכותבים. + 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/טיוטת החלטה.dotx → skills/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_committee→completed (מטא דטרמיניסטי, מחוץ ל-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_number→85074-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:00–05: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:00–05: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_limits — subscription_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:00–07: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 |
סקריפט דיבאג |