בהגיע סף-רך (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>
30 KiB
30 KiB