מפת-התוויות העברית הקשיחה ב-onWebhook הייתה מקור-האמת השני לאותו enum
של סטטוסי-תיק, והספיקה לסטות: חסרו בה analyst_verified ו-research_complete
(שנוספו ל-case_status_model.py ב-30.6), והיו בה חמישה מפתחות מתים —
uploading, brainstorming, drafting, in_progress ו-qa_failed. #604 תיקן את
המפה הראשונה (CASE_STATUS_TO_ISSUE_STATUS); זו השנייה.
- statusLabels נמחקת; התווית נגזרת מ-GET /api/status-model דרך labelFor()
הקיימת — אותו SSOT שהג'וב sync-case-status כבר צורך (G2).
- resolveStatusLabel() חדשה ב-sync-target.ts (המודול הטהור): מרכיבה את
labelFor ומחזירה גם את **סיבת** הנפילה-לגולמי, כדי שההיגיון יהיה
בר-בדיקה — worker.ts אינו ניתן ל-import בטסט (runWorker ברמת-המודול).
- אין בליעה שקטה (כלל-הנדסה §6): סטטוס שנטען ואינו במודל → logger.warn עם
מספר-התיק והסטטוס; מודל שלא נטען כלל (כשל-רשת או LegalApi חסר) → שני
logger.error נבדלים. בכל המקרים התגובה עדיין מתפרסמת והערת-ה-CEO עדיין
נורית — תווית חסרה אינה מפילה webhook.
- oldStatus מתורגם אף הוא לתווית (היה מודפס כמפתח-אנגלית בתוך משפט עברי).
- legalApi עשה hoist ליד pluginCtx ומועבר מפורשות ל-handleCaseStatusWebhook
— אותו מופע, לא שני.
- AC2: הוסרו שתי רשימות-הסטטוסים הקשיחות הנוספות ב-worker.ts — ה-enum
המיושן ב-legal_case_update (חסם 8 סטטוסים חוקיים והתיר את in_progress
שאינו case.status; המניפסט כבר מגדיר את השדה כמחרוזת חופשית, והוולידציה
האמיתית היא server-side) והמנייה בתיאור legal_case_list.
Invariants: G2 (מקור-אמת אחד לתוויות, בשני הצרכנים) · G1 (נרמול-במקור —
הפלאגין מושך מה-SSOT במקום להחזיק העתק סטטי) · G12 (legal-ai לא נגע כלל;
אפס סמל ספציפי-Paperclip נכנס אליו) · X7 INV-INT9 (onWebhook עדיין אינו
כותב issue.status — המשבצת השמורה נשארת שמורה) · כלל-הנדסה §6.
tsc --noEmit נקי · biome check src/ נקי · node --test 39/39.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
הג'וב sync-case-status יכתוב מעתה גם על שורש-issue ב-in_review. blocked
ו-CLOSED_ISSUE_STATUSES (done/cancelled — הגנת #446) נותרים כפי שהם.
ההערה מעל הסט מתעדת את ההכרעה, את מחירה (issue ממתין-ליו"ר עשוי לרדת
מתור-הביקורת תוך 15 דק') ואת מסלול-החזרה.
Refs ezer-mishpati/legal-ai#626
שלושה כשלים בג'וב sync-case-status, שהשביתו אותו בשקט מאז 22.7:
1. המפה הקשיחה CASE_STATUS_TO_ISSUE_STATUS נותקה מ-case_status_model.py
(מקור-האמת בצד legal-ai): חסרו analyst_verified ו-research_complete
שנוספו ב-851a4fb, ונשארו בה 3 מפתחות מתים (uploading/brainstorming/drafting).
סטטוס חסר נפל ל-`continue` — בלי לוג ובלי שגיאה. כעת המיפוי נגזר מ-
GET /api/status-model דרך resolveIssueStatus/labelFor: terminal→done,
הסטטוס הראשון בסדר→todo, השאר→in_progress. סטטוס חדש בצד legal-ai לא
דורש עוד עריכה כאן (G2 — מקור-אמת אחד).
2. companies[0] בלבד — מתוך שתי החברות, אחת מעולם לא נסרקה (נמדד: 135 מול
67 issues מקושרי-תיק). כעת נסרקות כל החברות, וה-companyId של המועמד
שנבחר הוא זה שנכתב אליו — לא החברה הראשונה גורפת.
3. דילוג שקט על סטטוס לא-מוכר → ctx.logger.warn עם שם-הסטטוס ומספר-התיק.
אימות מול השרת החי: 0 סטיות מול המפה הישנה על כל 10 הסטטוסים שכיסתה,
+2 שכוסו לראשונה. סימולציה על הנתונים החיים: דילוג-שקט 3→0, שורות-לוג 3→6,
כתיבות בפועל 0→0 — כלומר אין נסיגה ל-flip-flop של #446.
לוגיקת בחירת-היעד (#446) לא שונתה: pickSyncTargetIssue, isWritableStatus,
CLOSED_ISSUE_STATUSES ו-NON_WRITABLE_STATUSES זהות; ל-SyncCandidate נוסף שדה
companyId בלבד (passthrough). 8 הטסטים הקיימים עוברים ללא שינוי באסרשנים,
+7 חדשים.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
הג'וב sync-case-status כתב על כל issue מקושר-לתיק שסטטוסו שונה מהיעד — השומר
היחיד היה 'issue.status !== targetStatus'. לכן הוא החזיר sub-tasks שנסגרו
(done) ל-in_progress, כפי שתועד ב-CMPA-140 / תיק 8125-09-24.
בחירת-היעד חולצה ל-src/sync-target.ts: נבחר שורש יחיד (parentId === null)
שאינו done/cancelled ואינו in_review/blocked; אפס או יותר-מאחד → לא נכתב
דבר, ונרשם לוג עם הסיבה. שני הקבועים מובחנים בכוונה — CLOSED_ISSUE_STATUSES
הוא ההגדרה היחידה של 'סגור' (מראה של legal-ai/web/paperclip_client.py:561),
ו-NON_WRITABLE_STATUSES הוא 'מצב בבעלות Paperclip/בהמתנה-לאדם': כתיבת
in_progress על issue ב-in_review מזמינה auto-block תוך דקה
(legal-ai/docs/paperclip-quirks.md §3) וגונבת אותו מתור-הביקורת של היו"ר.
הלולאה הכפולה הוחלפה במעבר אחד + קיבוץ למפת case_number→מועמדים; הקיבוץ
נדרש כדי לבחור 'השורש היחיד', וכתוצר-לוואי O(NxM)→O(M) קריאות state.get.
מבחן-רגרסיה (node --test, ללא תלויות חדשות) משחזר את 11 ה-issues שנמדדו
לתיק 8125-09-24 ומוכיח את הדלתא: הכלל הישן היה כותב על CMPA-140, החדש לא.
בבעלות ריפו זה בהחלטת פאנל — העברת הלוגיקה ל-legal-ai נפסלה כי היא מוסיפה
UPDATE ישיר ל-DB של Paperclip, בהפרת INV-INT4 (GAP-24/25).