X15 — Agent Platform Port: Paperclip כמעטפת ניתנת-להחלפה מאחורי Port יחיד. מגדיר INV-PORT1/G12 (Ports&Adapters + Dependency Rule + Anti-Corruption Layer), מצאי-דליפה baseline (mcp-server נקי; דליפה ב-app.py + 10 פרומפטים + web-ui), מפת-תיקון R0–R4, ומנגנון-אכיפה נגד דליפה-עתידית (leak-guard + תבנית-PR). X16 — Durable Pipeline Execution: LangGraph כספרייה בתוך הסקריפט (לא תחליף-פלטפורמה) ל-final_halacha/final_learning. מגדיר INV-DUR1 (checkpointing+replay, מימוש משותף), SqliteSaver תחת data/checkpoints, גרעיניות מדורגת P0–P3, שימור-חוזה-CLI. מיישם/מחזק: G2 (X15), G3 (X16). תכנון בלבד — ללא שינוי-קוד. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.2 KiB
X16 — עמידות-פייפליין (Durable Pipeline Execution)
כפוף ל-00-constitution.md. מחזק את INV-G3 (idempotency) ב-checkpointing+replay לפייפליינים הדטרמיניסטיים המקומיים. נושק ל-07-learning.md ו-X11-citation-corroboration.md.
0. הבעיה
שני הפייפליינים המקומיים החד-פעמיים — final_halacha_pipeline.py (כפתור run-halacha, אימות-הלכות, X11) ו-final_learning_pipeline.py (כפתור run-learning, למידת-סגנון, 07-learning) — חולקים צורה זהה: סקריפט מקומי, 3–4 שלבים בטור, idempotent, פאנל-LLM ארוך בסוף (CSV-gated, "can take minutes").
היום הם ליניאריים וחסרי-זיכרון: קריסה באמצע (ניתוק ל-DeepSeek/Gemini, restart של קונטיינר, OOM) → הרצה-מחדש מ-שלב 0. השלבים idempotent ולכן זה בטוח, אבל משלמים שוב: מחלצים, בונים corroboration על כל הקורפוס, ושופטים מחדש הלכות שכבר נשפטו — דקות וקריאות-LLM לפח.
הקשר-סיכון אמיתי: דליפת task-master (יתומים ppid=1, ~3GB) מסכנת OOM ל-Postgres ([project_taskmaster_mcp_memory_leak]). אם OOM הורג ריצת-פאנל ארוכה — היום מתחילים מאפס.
הבחנה מ-idempotency: idempotency = "בטוח להריץ שוב". durable execution = "בטוח להריץ שוב בלי לשלם שוב". זה שכלול, לא תחליף.
1. ההכרעה
להטמיע LangGraph כספרייה בתוך הסקריפט (לא כפלטפורמה מחליפה ל-Paperclip): מנוע-העמידות
היחיד שהוא state-of-the-art ב-checkpointing+replay+time-travel, בשימוש כ-import בתוך
הסקריפט המקומי. Paperclip לא מושפע — הכפתור עדיין מעיר את Hermes שמריץ את אותו ה-CLI.
גבול-תחום מפורש (מתחבר ל-G12/X15): LangGraph נכנס רק כמנוע-פנימי של הסקריפטים המקומיים. אסור להשתמש בו כתחליף-פלטפורמה או כ-orchestrator של הסוכנים — זה ייצור מסלול מקביל ל-Paperclip (הפרת G2) ויערבב עמידות עם פלטפורמה. HITL/ניתוב-יו"ר נשאר מאחורי ה-Port (ראו §4 Phase 3).
מקורות: Temporal — Durable Execution · Saga / workflow-checkpointing pattern · Martin Kleppmann, DDIA (idempotence & exactly-once) · LangGraph checkpointer/replay docs.
2. ה-invariant
INV-DUR1 — עמידות לפייפליינים דטרמיניסטיים
כלל: פייפליין דטרמיניסטי רב-שלבי משמר את התקדמותו ב-checkpoint מתמיד אחרי כל שלב
שהושלם; הרצה-חוזרת של אותה יחידת-עבודה מדלגת על שלבים שכבר הושלמו ומתחילה מנקודת-הכשל
המדויקת. מימוש-העמידות הוא משותף לכל הפייפליינים (scripts/_pipeline_runtime.py) —
לא מימוש-לכל-סקריפט (G2). חוזה-הכניסה (ה-CLI) נשמר ללא-שינוי.
מקורות: Temporal (Durable Execution) · Kleppmann DDIA (exactly-once) · Saga pattern
(workflow checkpointing) | סטטוס: verified
אכיפה: _pipeline_runtime.py עם LangGraph + checkpointer; thread_id דטרמיניסטי
לכל יחידת-עבודה (תיק); בדיקת kill-and-resume שמאמתת ששלבים שהושלמו אינם רצים-מחדש.
הפרה ידועה: היום final_halacha_pipeline.py / final_learning_pipeline.py ליניאריים
— קריסה = הרצה-מחדש מלאה (חוזרים על extract/corroboration/panel).
3. ארכיטקטורה
scripts/_pipeline_runtime.py ← מודול-עמידות משותף יחיד (G2)
• build_graph(steps) StateGraph: node לכל שלב
• SqliteSaver data/checkpoints/<pipeline>.sqlite (לא Postgres המשותף)
• run(thread_id, resume) מדלג-אוטומטית על nodes ב-checkpoint
הכרעות-תכנון:
- Checkpointer = SQLite (
langgraph-checkpoint-sqlite), לא Postgres. קובץ תחתdata/checkpoints/: מקומי (תואם "local-only"), פשוט, ונמנע מהאזהרה ב-CLAUDE.md נגד migrations מ-2 worktrees על Postgres המשותף (localhost:5433). PostgresSaver = אופציה עתידית אם נדרש ריכוז/observability. thread_id = f"<pipeline>:{case_number}". הרצה-חוזרת של אותו תיק מזהה checkpoint לא-גמור וממשיכה אוטומטית; תיק שהושלם = no-op. idempotency + דילוג-checkpoint מתחברים.- גרעיניות (מדורגת):
- גס (P0/P1): כל שלב = node. קריסה בין-שלבים → המשך מהשלב שנפל. הפאנל node יחיד שרץ-מחדש — אך הוא כבר CSV-backed + idempotent (מדלג פנימית על מה שנשפט).
- עדין (P2, אופציונלי): פירוק הפאנל ל-map מעל ההלכות/הלקחים (LangGraph
Send), כל פריט = יחידת-checkpoint → resume תוך-פאנל בלי לשפוט מחדש ברמת-LLM. נשען על ה-CSV הקיים כמקור "כבר-נשפט".
- סמנטיקת-כשל מפורשת. היום הכל "non-fatal, continue". עם LangGraph: nodes "מייעצים" (extract, corroboration) — catch+record-status וממשיכים; node "קריטי" (panel) — raise בכשל-קשה → עצירה ב-checkpoint → resume.
- שימור-חוזה-הכניסה. ה-CLI (
--case/--limit/--dry-run) זהה; run-halacha/run-learning → Hermes → אותוpython ...pipeline.py --case Xלא משתנה. מוסיפים--fresh(ברירת-מחדל: auto-resume אם יש checkpoint לא-גמור לתיק).
4. גלגול מדורג
| Phase | תחום | מאמץ |
|---|---|---|
| P0 | deps ל-mcp-server/pyproject (langgraph + langgraph-checkpoint-sqlite, venv מקומי בלבד → אפס השפעת-קונטיינר). _pipeline_runtime.py עם SqliteSaver. עטיפת 4 שלבי-halacha כ-nodes (גס). CLI זהה. test: kill אחרי [1] → resume → assert [0],[1] לא רצו שוב |
~1 יום |
| P1 | אותו runtime על final_learning_pipeline (3 שלבים) — מימוש-עמידות אחד לשניהם (G2) |
חצי יום |
| P2 | (אופציונלי) פירוק-פאנל ל-map per-item — resume תוך-פאנל | 1–2 ימים |
| P3 | (עתידי) LangGraph interrupt() ל-HITL של היו"ר (split→chair, INV-G10) — רק מאחורי ה-Port (X15/G12) |
— |
5. ראו גם
- 07-learning.md · X11-citation-corroboration.md
- X15-agent-platform-port.md — הגבול מול הפלטפורמה (G12).
- scripts/SCRIPTS.md — הסקריפטים המושפעים.