fix(halacha): rate-limit refusal ≠ empty answer — לא checkpoint chunk בכשל (#144) #267

Merged
chaim merged 1 commits from worktree-halacha-no-empty-checkpoint into main 2026-06-15 04:23:02 +00:00
Owner

הבעיה (#144)

חילוץ-מחדש תחת rate-limit השאיר תיקים עם פחות הלכות (3→1→0). שורש-הליבה: כש-claude -p מחזיר exit=0 עם הודעת-מגבלה/שגיאה כ-result (refusal NOTICE), claude_session.query החזיר אותה כהצלחהhalacha_extractor._extract_chunk קיבל []/non-list וסימן את ה-chunk כ-done-עם-0-הלכות; resume דילג עליו לתמיד → תת-חילוץ קבוע.

התיקון (G1 — אבחנת-מקור · INV-G3/X16 — checkpoint=הושלם-באמת)

  1. ליבה (b)claude_session.query: is_error או _looks_like_limit_notice הופכים תוצאת-מגבלה לכשל-חולף → retry → raise אם מתמיד. כך ה-chunk נשאר un-checkpointed ו-resume משחזר. תוצאת-JSON אמיתית (מתחילה ב-[/{) לעולם לא מסומנת בטעות. (תיקון רוחבי — כל המחלצים נהנים.)
    • תוצאה חשובה: משלא מסמנים chunk-בכשל, גם ה-force-delete של חילוץ-מחדש כבר לא הרסני-לצמיתות — ריצה שנקטעת אחרי המחיקה משאירה chunks un-checkpointed → resume משחזר את ההלכות.
  2. (c) churn-detect במתזמר — Δdone<0 (regress completed→pending) או Δhal<-2 (אובדן-הלכות מעבר לרעש-קונסולידציה) → אזהרה גלויה + churn_ok ב-JSON. הסימפטום 3→1 לא נשאר שקט.
  3. reconcile חד-פעמיscripts/reconcile_under_extracted_halacha.py: completed עם 0 הלכות למרות ≥3 מקטעי-נימוק → מאפס checkpoints + request_halacha_extraction (נתיב קנוני, G2). dry-run הראה 15 מועמדים (33572-08-18 עם 61 מקטעים, 4843/23 עם 54, ...). שמרני (≥3 → לא נוגע ב-remand לגיטימי; אפס אובדן כי 0 הלכות ממילא). יורץ אחרי הפריסה (כדי שהחילוץ-מחדש ירוץ עם תיקון-הליבה חי).

מחוץ-לתחום (נדחה מנומק)

אטומיות-מלאה (staging_run_id, extract-then-swap) — דורשת מיגרציית-סכמה + שינוי hot-path של dedup. נדחתה: PR #257 כבר מיתן את ה-trigger (cooldown על 429-טרי), ו-(b)+resume מונעים אובדן-קבוע. נרשם כ-follow-up.

בדיקות

  • test_claude_session_limit_notice (חדש) — מזהה refusal-prose, לא מזהה JSON-array/object, edge cases.
  • כל 354 בדיקות mcp עוברות. undefined-names + leak-guard נקיים. (rebased על origin/main העדכני — אין קונפליקט עם #265/#266.)

Invariants

  • G1 — אבחנת-מקור (כשל-מגבלה ≠ תשובה-ריקה)
  • INV-G3 / X16checkpoint משקף השלמה-אמיתית; resume לא מדלג על chunk שנכשל
  • INV-G4 — churn לא-שקט (אזהרה + churn_ok)
  • G2 — reconcile דרך נתיב-ההזמנה הקנוני; G12 — leak-guard נקי

🤖 Generated with Claude Code

## הבעיה (#144) חילוץ-מחדש תחת rate-limit השאיר תיקים עם **פחות** הלכות (3→1→0). שורש-הליבה: כש-`claude -p` מחזיר `exit=0` עם הודעת-מגבלה/שגיאה כ-`result` (refusal NOTICE), `claude_session.query` החזיר אותה **כהצלחה** → `halacha_extractor._extract_chunk` קיבל `[]`/non-list וסימן את ה-chunk כ-done-עם-0-הלכות; `resume` דילג עליו לתמיד → **תת-חילוץ קבוע**. ## התיקון (G1 — אבחנת-מקור · INV-G3/X16 — checkpoint=הושלם-באמת) 1. **ליבה (b)** — `claude_session.query`: `is_error` או `_looks_like_limit_notice` הופכים תוצאת-מגבלה ל**כשל-חולף** → retry → raise אם מתמיד. כך ה-chunk נשאר **un-checkpointed** ו-`resume` משחזר. תוצאת-JSON אמיתית (מתחילה ב-`[`/`{`) לעולם לא מסומנת בטעות. *(תיקון רוחבי — כל המחלצים נהנים.)* - **תוצאה חשובה:** משלא מסמנים chunk-בכשל, גם ה-force-delete של חילוץ-מחדש **כבר לא הרסני-לצמיתות** — ריצה שנקטעת אחרי המחיקה משאירה chunks un-checkpointed → resume משחזר את ההלכות. 2. **(c) churn-detect** במתזמר — `Δdone<0` (regress completed→pending) או `Δhal<-2` (אובדן-הלכות מעבר לרעש-קונסולידציה) → אזהרה גלויה + `churn_ok` ב-JSON. הסימפטום 3→1 לא נשאר שקט. 3. **reconcile חד-פעמי** — `scripts/reconcile_under_extracted_halacha.py`: `completed` עם 0 הלכות למרות **≥3 מקטעי-נימוק** → מאפס checkpoints + `request_halacha_extraction` (נתיב קנוני, G2). **dry-run הראה 15 מועמדים** (33572-08-18 עם 61 מקטעים, 4843/23 עם 54, ...). שמרני (≥3 → לא נוגע ב-remand לגיטימי; אפס אובדן כי 0 הלכות ממילא). **יורץ אחרי הפריסה** (כדי שהחילוץ-מחדש ירוץ עם תיקון-הליבה חי). ## מחוץ-לתחום (נדחה מנומק) אטומיות-מלאה (`staging_run_id`, extract-then-swap) — דורשת מיגרציית-סכמה + שינוי hot-path של dedup. נדחתה: **PR #257** כבר מיתן את ה-trigger (cooldown על 429-טרי), ו-(b)+resume מונעים אובדן-קבוע. נרשם כ-follow-up. ## בדיקות - `test_claude_session_limit_notice` (חדש) — מזהה refusal-prose, לא מזהה JSON-array/object, edge cases. - כל **354** בדיקות mcp עוברות. `undefined-names` + `leak-guard` נקיים. (rebased על origin/main העדכני — אין קונפליקט עם #265/#266.) ## Invariants - ✅ **G1** — אבחנת-מקור (כשל-מגבלה ≠ תשובה-ריקה) - ✅ **INV-G3 / X16** — `checkpoint` משקף השלמה-אמיתית; resume לא מדלג על chunk שנכשל - ✅ **INV-G4** — churn לא-שקט (אזהרה + `churn_ok`) - ✅ **G2** — reconcile דרך נתיב-ההזמנה הקנוני; **G12** — leak-guard נקי 🤖 Generated with [Claude Code](https://claude.com/claude-code)
chaim added 1 commit 2026-06-15 04:22:33 +00:00
fix(halacha): rate-limit refusal ≠ empty answer — לא checkpoint chunk בכשל (#144)
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 5s
Lint — undefined names / undefined-names (pull_request) Successful in 10s
6cc100f9f8
תיקון-ליבה (b): כש-claude CLI מחזיר exit=0 עם הודעת-מגבלה/שגיאה כ-result, query
זיהה אותה כהצלחה → _extract_chunk קיבל []/non-list וסימן chunk כ-done-ריק; resume
דילג עליו לתמיד → תת-חילוץ קבוע (3→1→0). עכשיו is_error/_looks_like_limit_notice
הופכים אותה לכשל-חולף → retry → raise → chunk נשאר un-checkpointed → resume משחזר
(כך force-delete כבר לא הרסני-לצמיתות).

+ churn-detect במתזמר (Δdone<0 / Δhal<-2 → אזהרה+churn_ok ב-JSON).
+ scripts/reconcile_under_extracted_halacha.py — שחזור completed-עם-0-הלכות-ו≥3
  מקטעי-נימוק (dry-run הראה 15 מועמדים); נתיב-הזמנה קנוני (G2), שמרני (לא remand).

הערה: אטומיות-מלאה (staging_run_id) נדחתה — PR #257 מיתן את ה-trigger, ו-(b)+resume
מונעים אובדן-קבוע (force-delete מתאושש דרך resume).

בדיקות: test_claude_session_limit_notice. כל 354 עוברות. guards נקיים.
Invariants: G1, INV-G3/X16 (checkpoint=הושלם-באמת), INV-G4 (churn לא-שקט), G12.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chaim merged commit 49cbd8bb3a into main 2026-06-15 04:23:02 +00:00
chaim deleted branch worktree-halacha-no-empty-checkpoint 2026-06-15 04:23:02 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ezer-mishpati/legal-ai#267