chore(tasks): #77+#78 done; #76 deferred with root-cause diagnosis

#78 (committee-upload wakeup) + #77 (case_number identity) shipped.
#76 (Paperclip create-task button): root-caused to ee=companyId guard —
button enabled on title only but submit requires a company; not safely
patchable via injection. Deferred with workaround + upstream note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-02 12:27:45 +00:00
parent 901ec9f869
commit 76fae77393

View File

@@ -2485,10 +2485,10 @@
{
"id": "76",
"title": "תיקון כפתור \"צור משימה\" ב-Paperclip — מאופשר אך submit חוזר בשקט",
"description": "במודאל \"משימה חדשה\" של Paperclip, הקלדת כותרת בעברית מציגה את הטקסט והכפתור \"צור משימה\" שחור/מאופשר (לא disabled) — אך לחיצה לא שולחת שום בקשה ואין שגיאה בקונסול. אומת מול access-log: אין POST ל-.../issues. כלומר ה-onChange כן נורה (b=true, הכפתור מאופשר), אבל ה-onClick handler חוזר מ-guard פנימי לפני ה-mutate. חוסם יצירת משימה ידנית לכל סוכן/לוח, לא רק לתור החילוץ.",
"details": "Paperclip צד-שלישי (PM2, לא Docker). bundle: ~/.npm/_npx/*/node_modules/@paperclipai/server/ui-dist/assets/index-*.js. אבחנה מהבדיקה: submit handler בנוסח `function xi(){ const je=m.current.trim(); if(!ee||!je||He.isPending) return; He.mutate({...}) }` — הטקסט (je) קיים, אז ה-guard שנכשל הוא `ee` (ערך נדרש נוסף — לזהות מהו: company/board/project/agent target). שלב 1: לאתר ב-bundle את ה-handler המדויק ומה `ee` מייצג, ולמה הוא falsy במודאל הזה (אולי target company/project לא נקבע כש-prefill מגיע מתוך לוח \"תור חילוץ\"). שלב 2: תיקון קבוע דרך מנגנון ההזרקה הקיים — shim ב-~/.paperclip/hebrew/translate-he.js (נטען בכל טעינה, שורד restart דרך start-paperclip.sh wrapper) שמשלים את הערך החסר / מאזין לאירוע ה-submit. שלב 3: apply דרך `bash ~/.paperclip/hebrew/apply-hebrew.sh` + Ctrl+Shift+R, ולבדוק יצירת משימה. עוקף זמני שתמיד עובד: API ישיר — `~/legal-ai/scripts/pc.sh POST /companies/<cid>/issues '{...}'`. הערה: בזרימה הרגילה מניעים סוכנים בעיקר דרך תגובה על issue (CEO מנתב) — להחליט אם המודאל בכלל נחוץ.",
"description": "כפתור \"צור משימה\" במודאל \"משימה חדשה\" של Paperclip: הטקסט מופיע, הכפתור שחור/מאופשר, אך לחיצה לא שולחת בקשה ואין שגיאה. אובחן סופית (2026-06-02).",
"details": "אבחנה סופית מתוך הבאנדל (index-BWGhimVr.js): ה-submit הוא `function xi(){const je=m.current.trim();if(!ee||!je||He.isPending)return;...He.mutate({...companyId:ee...})}`. `je`=כותרת (קיים), `He`=mutation. ה-guard שנכשל הוא **`ee`**, ש-`ee` משמש כ-`projects.list(ee)` וכ-`companyId:ee` במוטציה — כלומר **`ee` = מזהה החברה**. השורש: הכפתור מאופשר לפי הכותרת בלבד (`disabled:!b`, b=כותרת), אבל ה-submit דורש גם חברה (`!ee`). כשהמודאל נפתח בהקשר שבו החברה לא אותחלה, המשתמש לוחץ כפתור 'מאופשר' וה-handler חוזר בשקט — בלי POST, בלי שגיאה. בחירת הסוכן (callback Ro) לא מגדירה את החברה — היא נקבעת רק דרך בורר חברה נפרד (pr/oe). ההזרקה שלנו (translate-he.js) זוכתה: reverseComments נוגע רק ב-[id^='comment-'], לא במודאל; isUserContent מדלג על contentEditable. **לא ניתן לתקן בבטחה דרך injection**: אי-אפשר לכתוב ל-state של React מבחוץ; shim שמגרד DOM ויוצר issue דרך API הוא שביר (צריך IDs מה-DOM) ועלול ליצור משימות פגומות — גרוע מהבאג. **Workaround**: לוודא שהחברה נבחרה במודאל (בורר החברה) לפני לחיצה על 'צור משימה'; או לפתוח 'משימה חדשה' מתוך הקשר חברה/לוח. מסלול אמין תמיד: API ישיר `pc.sh POST /companies/{id}/issues`. **תיקון יסודי = upstream Paperclip** (הכפתור צריך להיות disabled כשאין חברה, או החברה צריכה להיגזר מהלוח/סוכן הנבחר). הערה: #78 (חילוץ פסיקה אוטומטי) מסיר את הצורך במודאל הזה בזרימת חילוץ-הפסיקה; הזרימה הרגילה מניעה סוכנים דרך תגובות (CEO מנתב).",
"testStrategy": "לאחר ה-shim: לפתוח \"משימה חדשה\", להקליד כותרת עברית, ללחוץ \"צור משימה\" → לוודא POST /issues ב-access-log + ה-issue מופיע בלוח. לבדוק גם בלוח רגיל (לא תור חילוץ) ובשתי החברות.",
"status": "pending",
"status": "deferred",
"dependencies": [],
"priority": "high",
"subtasks": [],
@@ -2500,11 +2500,11 @@
"description": "בטופס העלאת פסיקה (precedent-upload-sheet), עבור החלטות ועדת-ערר ה-frontend ממפה את שדה \"מראה המקום\" אל case_number (`case_number: citation.trim()`), כך שהמזהה הייחודי מקבל את המראה-מקום הארוך במקום מספר תיק נקי (למשל '8027-25'). בנוסף case_number כלל לא קיים ב-PrecedentUpdateRequest — אז מסך העריכה לא יכול לתקן אותו בדיעבד. citation_formatted נשאר ריק בהעלאה (מתמלא רק בחילוץ מטא). תוצאה ב-8027-25: case_number=מראה-מקום, case_name=מראה-מקום, מראה-מקום ריק עד החילוץ.",
"details": "קבצים: web-ui/src/components/precedents/precedent-upload-sheet.tsx:121-123 (committee path ממפה citation→case_number); web/app.py:5147-5163 (PrecedentUpdateRequest חסר case_number); mcp-server/.../internal_decisions.py (id_field=case_number, display_name_fallback=case_number); precedent_metadata_extractor.py:247-253 (guard: case_name מתוקן רק אם ריק או ==case_number, לכן לא תיקן). תיקון מוצע: (1) בטופס committee — שדה נפרד \"מספר תיק (מזהה ייחודי)\" שממפה ל-case_number, ולמפות \"מראה המקום\" ל-citation (→citation_formatted), במקום לדחוס הכל ל-case_number; (2) להוסיף case_number ל-PrecedentUpdateRequest כדי שהעריכה תוכל לתקן בדיעבד (update_case_law כבר מתיר אותו); (3) להריץ `npm run api:types`. ראה כללי השם שהוגדרו: מזהה ייחודי = שם הקובץ/מספר תיק; מראה-מקום בשדה שלו; שם קצר = שם הצד.",
"testStrategy": "להעלות פסיקת ועדת-ערר עם מספר תיק + מראה-מקום נפרדים → לוודא case_number=מספר התיק, citation_formatted=מראה-מקום, case_name=שם קצר. לפתוח עריכה ולוודא שניתן לתקן case_number.",
"status": "pending",
"status": "done",
"dependencies": [],
"priority": "high",
"subtasks": [],
"updatedAt": "2026-06-02T00:00:00.000Z"
"updatedAt": "2026-06-02T12:17:44.302Z"
},
{
"id": "78",
@@ -2512,18 +2512,18 @@
"description": "אחרי העלאת פסיקה, הבקאנד מסמן metadata+halacha כ-pending וקורא ל-pc_wake_for_precedent_extraction להעיר את ה-CEO. הקריאה נבלעת בשקט (try/except 'non-fatal') — אם PAPERCLIP_BOARD_API_KEY חסר מחזיר {ok:false,skipped:no_api_key}, או שה-wakeup API נכשל — והתוצאה: ה-CEO לא מתעורר, לא רץ חילוץ מטא ולא חילוץ הלכות, וה-UI מציג 'ממתין לחילוץ' לנצח. קרה ב-8027-25 (תוקן ידנית עם precedent_process_pending). זה גם הסיבה ששדות המטא (תקציר/headnote/תגיות/citation) היו ריקים.",
"details": "קבצים: web/app.py:5250-5262 (wakeup best-effort, exception נבלעת); web/paperclip_client.py:816-820 (skip שקט כש-no api key) ו-~905-907 (כשל API נבלע). תיקון מוצע: (1) להציף את הכשל למשתמש — סטטוס מובחן (extraction_wakeup_failed / 'ממתין-לעיבוד-ידני') ב-UI במקום 'pending' אילם; (2) fallback אוטומטי — אם ה-wakeup נכשל, או job מתוזמן (כמו sync-case-status) שמנקז את התור עם precedent_process_pending, או retry; (3) לאמת אם PAPERCLIP_BOARD_API_KEY מוגדר בקונטיינר (Coolify env) — אם לא, להוסיף. עיין reference: project_precedent_auto_extraction. לא לבלוע exceptions בשקט (feedback_silent_swallow).",
"testStrategy": "להעלות פסיקה חדשה ולוודא שחילוץ מטא+הלכות רץ אוטומטית (CEO מתעורר), או שבכשל wakeup מופיע סטטוס שגיאה ברור + מסלול ניקוז אוטומטי. לבדוק שאין 'pending' אילם.",
"status": "pending",
"status": "done",
"dependencies": [],
"priority": "high",
"subtasks": [],
"updatedAt": "2026-06-02T00:00:00.000Z"
"updatedAt": "2026-06-02T12:07:22.194Z"
}
],
"metadata": {
"version": "1.0.0",
"lastModified": "2026-06-01T04:43:40.475Z",
"taskCount": 75,
"completedCount": 68,
"lastModified": "2026-06-02T12:17:44.302Z",
"taskCount": 78,
"completedCount": 70,
"tags": [
"legal-ai"
]