feat(halacha): עצירה-רכה של הדריינר בסף-ניצול (75/65) + מקור-אמת יחיד למכסה #265

Merged
chaim merged 1 commits from worktree-halacha-soft-ceiling-stop into main 2026-06-15 04:11:44 +00:00
Owner

מה ולמה

המשך ל-#259. שם הספים (75/65) נאכפו ע"י קטילת הדריינר (pm2 stop) באמצע חילוץ. היו"ר הבהיר: ב-75% יש מכסה לסיים את התיק שרץ — אז לתת לו להסתיים ולא להתחיל חדש, במקום לקטול. בנוסף "סדר בקוד": לוגיקת-המכסה הייתה כפולה.

השינוי

  • חדש legal_mcp/services/usage_limits.py (stdlib-only) — מקור-אמת יחיד: subscription_usage / USAGE_CEILINGS / ceiling_status. מיובא גם מ-system-python (supervisor) וגם מה-venv (drain); __init__ ריקים → import בטוח מחוץ ל-venv.
  • supervisor — מייבא מהמודול (הסרת ~50 שורות העתקים); quota_exhausted/quota_available→wrappers דקים. ענף cooldown: קטילה (hold-stopped) רק ב-429 טרי (log_rl); סף-רך → hold-soft בלי pm2 stop.
  • drainlimit=4→1 (בדיקת-סף בין כל תיק); שער-סף ב-run_in_executor, fail-OPEN כש-endpoint None (supervisor מגבה ב-429-kill); שמירת קצב 30ש' בין תיקים (limit=1 ביטל את המרווח הפנימי).
  • SCRIPTS.md עודכן.

אימות end-to-end (endpoint חי)

בדיקה תוצאה
drain, CEILING_5H=30<45% ===STOP=== usage ceiling reached (5h=45%/30 ...) — 0 תיקים, לא נגע ב-lock
supervisor status=online+סף-רך action=hold-soft, stop_drain נקרא 0
429 טרי (patch) action=hold-stopped, stop_drain נקרא 1
py_compile 3 קבצים OK

נדחה

court_fetch_service/usage_status (העתק שלישי, async/aiohttp, גשר-מארח רגיש-דיפלוי, רק 3 קבועים) — איחוד עתידי ב-PR נפרד; לא נוגעים כאן.

Invariants

  • G1 נרמול-במקור (endpoint יחיד) · G2 אין מסלול-בקרה מקביל (מודול משותף יחיד; drain+supervisor קוראים אותו דבר) · X16 עמידות (עצירה לפני 429 מונעת חילוץ-מחדש משחית) · G12 לא רלוונטי.

הערה ליו"ר (post-merge)

host-side scripts — אחרי מיזוג צריך git checkout origin/main של 3 הקבצים בעץ הראשי (stale, 68 מאחור) כדי שהטיק הבא של pm2 ירוץ עם הקוד החדש. בנוסף מחיקת שארית מקומית scripts/monitor_halacha_queue.py (לא-מתויקת).

🤖 Generated with Claude Code

## מה ולמה המשך ל-#259. שם הספים (75/65) נאכפו ע"י **קטילת** הדריינר (`pm2 stop`) באמצע חילוץ. היו"ר הבהיר: ב-75% **יש מכסה לסיים** את התיק שרץ — אז לתת לו להסתיים ולא להתחיל חדש, במקום לקטול. בנוסף "סדר בקוד": לוגיקת-המכסה הייתה כפולה. ## השינוי - **חדש `legal_mcp/services/usage_limits.py`** (stdlib-only) — מקור-אמת יחיד: `subscription_usage` / `USAGE_CEILINGS` / `ceiling_status`. מיובא גם מ-system-python (supervisor) וגם מה-venv (drain); `__init__` ריקים → import בטוח מחוץ ל-venv. - **supervisor** — מייבא מהמודול (הסרת ~50 שורות העתקים); `quota_exhausted`/`quota_available`→wrappers דקים. ענף cooldown: קטילה (`hold-stopped`) רק ב-**429 טרי** (`log_rl`); סף-רך → **`hold-soft` בלי `pm2 stop`**. - **drain** — `limit=4→1` (בדיקת-סף בין כל תיק); שער-סף ב-`run_in_executor`, **fail-OPEN** כש-endpoint None (supervisor מגבה ב-429-kill); **שמירת קצב 30ש'** בין תיקים (`limit=1` ביטל את המרווח הפנימי). - **SCRIPTS.md** עודכן. ## אימות end-to-end (endpoint חי) | בדיקה | תוצאה | |---|---| | drain, `CEILING_5H=30`<45% | `===STOP=== usage ceiling reached (5h=45%/30 ...)` — 0 תיקים, לא נגע ב-lock ✅ | | supervisor `status=online`+סף-רך | `action=hold-soft`, `stop_drain` נקרא **0** ✅ | | 429 טרי (patch) | `action=hold-stopped`, `stop_drain` נקרא **1** ✅ | | `py_compile` 3 קבצים | OK ✅ | ## נדחה `court_fetch_service/usage_status` (העתק שלישי, async/aiohttp, גשר-מארח רגיש-דיפלוי, רק 3 קבועים) — איחוד עתידי ב-PR נפרד; לא נוגעים כאן. ## Invariants - **G1** נרמול-במקור (endpoint יחיד) · **G2** אין מסלול-בקרה מקביל (מודול משותף יחיד; drain+supervisor קוראים אותו דבר) · **X16** עמידות (עצירה לפני 429 מונעת חילוץ-מחדש משחית) · **G12** לא רלוונטי. ## הערה ליו"ר (post-merge) host-side scripts — אחרי מיזוג צריך `git checkout origin/main` של 3 הקבצים בעץ הראשי (stale, 68 מאחור) כדי שהטיק הבא של pm2 ירוץ עם הקוד החדש. בנוסף מחיקת שארית מקומית `scripts/monitor_halacha_queue.py` (לא-מתויקת). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
chaim added 1 commit 2026-06-15 04:11:37 +00:00
feat(halacha): עצירה-רכה של הדריינר בסף-ניצול + מקור-אמת יחיד למכסה
All checks were successful
G12 Leak-Guard / leak-guard (pull_request) Successful in 5s
Lint — undefined names / undefined-names (pull_request) Successful in 11s
4ac661b0a6
בהגיע סף-רך (5-שעות ≥75% / שבועי ≥65%) הדריינר מסיים את התיק שרץ ועוצר
לבד בין תיקים (===STOP===) — במקום שהסופרוויזר יקטול אותו ב-pm2 stop באמצע
חילוץ. ב-75% יש מכסה לסיים את התיק; הקטילה נשמרת רק ל-429 טרי אמיתי.

- חדש legal_mcp/services/usage_limits.py (stdlib-only): מקור-אמת יחיד —
  subscription_usage / USAGE_CEILINGS / ceiling_status. מיובא גם מ-system-python
  (supervisor) וגם מה-venv (drain). __init__ ריקים → import בטוח מחוץ ל-venv.
- supervisor: מייבא מהמודול (הסרת ההעתקים המקומיים, ~50 שורות פחות);
  quota_exhausted/quota_available הפכו wrappers דקים; ענף cooldown — קטילה
  (hold-stopped) רק אם log_rl (429 טרי), אחרת hold-soft בלי pm2 stop.
- drain: limit=4→1 (בדיקת-סף בין כל תיק); שער-סף ב-run_in_executor, fail-OPEN
  כש-endpoint None (הסופרוויזר מגבה ב-429-kill); שמירת קצב 30ש' בין תיקים
  (pl.INTER_PRECEDENT_COOLDOWN_SEC — limit=1 ביטל את המרווח הפנימי-לסבב).
- SCRIPTS.md עודכן (limit=1, שער-סף, hold-soft, מקור-אמת משותף).

אומת end-to-end (endpoint חי): (1) drain עם סף מורד → ===STOP=== usage ceiling
בלי לעבד תיק; (2) supervisor status=online+סף-רך → action=hold-soft, stop_drain
נקרא 0; (3) 429 טרי → hold-stopped, stop_drain נקרא 1. py_compile עובר.

court_fetch_service/usage_status (העתק שלישי, async/aiohttp, רגיש-דיפלוי) נדחה
במכוון לאיחוד-עתידי — לא נוגעים בגשר-המארח כאן.

Invariants: G1 (נרמול-במקור — endpoint יחיד), G2 (אין מסלול-בקרה מקביל — מודול
משותף יחיד, drain+supervisor קוראים אותו דבר), X16 (עמידות — עצירה לפני 429
מונעת חילוץ-מחדש משחית). G12 לא רלוונטי.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chaim merged commit 07ecb6a366 into main 2026-06-15 04:11:44 +00:00
chaim deleted branch worktree-halacha-soft-ceiling-stop 2026-06-15 04:11:44 +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#265