aggregate_claims_to_arguments עם force=True אינו נעול — שתי ריצות חופפות מייצרות טיעונים כפולים #461

Open
opened 2026-08-05 12:02:46 +00:00 by chaim · 0 comments
Owner

What & Why

argument_aggregator.aggregate_claims_to_arguments(case_id, force=True) עושה DELETE FROM legal_arguments WHERE case_id=$1 ואז מוסיף מחדש — בלי נעילה על התיק. שתי ריצות חופפות משתלבות: השנייה מוחקת אחרי שהראשונה כבר הכניסה חלק, או ששתיהן מוסיפות אותה קבוצה.

שחזור (2026-08-05, תיק 1069-04-26)

הריצה דיווחה total: 141:

"by_party": {"appellant":81,"committee":32,
             "permit_applicant·כתב תשובה ערר גפטו":14,
             "permit_applicant·כתב ערר":9,"respondent·כתב ערר":5}

אבל ב-DB היו 154 שורות. חותמות-הזמן מראות שתי קבוצות נכתבו פעמיים:

קבוצה בפועל דווח נכתב ב-
permit_applicant·כתב ערר 17 9 10:49:34 וגם 11:40:26
respondent·כתב ערר 10 5 10:50:11 וגם 11:41:12

הצבירה נמשכת ~45 דקות (כמה קריאות מודל), כך שחלון החפיפה רחב מאוד — כל wakeup של סוכן או לחיצה ב-UI בתוך פרק הזמן הזה מספיקים.

למה זה מזיק: legal_arguments מזין את פאנל "טיעונים ועמדות", את party_claims_summary, את protocol_analyzer (בסיס-ההשוואה לדיון) ואת case_digest_radar. כפילות שקטה מנפחת את כולם, ו-total המדווח לא תואם את מה שנמצא בפועל — כלומר גם אי אפשר לזהות זאת מהפלט.

קרוב-משפחה של #444 (ריצת-heartbeat כפולה דורסת טיוטה) — אותו שורש: פעולה ארוכה ללא בלעדיות.

Acceptance Criteria

  • צבירה מחזיקה בלעדיות פר-תיק לכל אורך הריצה (למשל pg_advisory_xact_lock על ה-case_id, או שורת-נעילה ב-DB).
  • ריצה שנייה על אותו תיק בזמן שהראשונה פעילה אינה כותבת — היא מחזירה status:"busy" עם הודעה ברורה, לא ממתינה בשקט ולא כותבת חלקית.
  • ה-DELETE וההוספות של ריצה אחת אטומיים ביחס לריצה אחרת.
  • total המוחזר שווה בדיוק ל-COUNT(*) בפועל בתיק בסיום — טסט-רגרסיה שאוכף את זה.
  • טסט: שתי קריאות force=True במקביל על אותו תיק → אחת מצליחה, השנייה busy, וב-DB אין כפילויות.
## What & Why `argument_aggregator.aggregate_claims_to_arguments(case_id, force=True)` עושה `DELETE FROM legal_arguments WHERE case_id=$1` ואז מוסיף מחדש — **בלי נעילה על התיק**. שתי ריצות חופפות משתלבות: השנייה מוחקת אחרי שהראשונה כבר הכניסה חלק, או ששתיהן מוסיפות אותה קבוצה. ## שחזור (2026-08-05, תיק 1069-04-26) הריצה דיווחה `total: 141`: ```json "by_party": {"appellant":81,"committee":32, "permit_applicant·כתב תשובה ערר גפטו":14, "permit_applicant·כתב ערר":9,"respondent·כתב ערר":5} ``` אבל ב-DB היו **154** שורות. חותמות-הזמן מראות שתי קבוצות נכתבו פעמיים: | קבוצה | בפועל | דווח | נכתב ב- | |---|---|---|---| | `permit_applicant·כתב ערר` | 17 | 9 | 10:49:34 **וגם** 11:40:26 | | `respondent·כתב ערר` | 10 | 5 | 10:50:11 **וגם** 11:41:12 | הצבירה נמשכת ~45 דקות (כמה קריאות מודל), כך שחלון החפיפה רחב מאוד — כל wakeup של סוכן או לחיצה ב-UI בתוך פרק הזמן הזה מספיקים. **למה זה מזיק:** `legal_arguments` מזין את פאנל "טיעונים ועמדות", את `party_claims_summary`, את `protocol_analyzer` (בסיס-ההשוואה לדיון) ואת `case_digest_radar`. כפילות שקטה מנפחת את כולם, ו-`total` המדווח לא תואם את מה שנמצא בפועל — כלומר גם אי אפשר לזהות זאת מהפלט. קרוב-משפחה של #444 (ריצת-heartbeat כפולה דורסת טיוטה) — אותו שורש: פעולה ארוכה ללא בלעדיות. ## Acceptance Criteria - [ ] צבירה מחזיקה בלעדיות פר-תיק לכל אורך הריצה (למשל `pg_advisory_xact_lock` על ה-case_id, או שורת-נעילה ב-DB). - [ ] ריצה שנייה על אותו תיק בזמן שהראשונה פעילה **אינה** כותבת — היא מחזירה `status:"busy"` עם הודעה ברורה, לא ממתינה בשקט ולא כותבת חלקית. - [ ] ה-DELETE וההוספות של ריצה אחת אטומיים ביחס לריצה אחרת. - [ ] `total` המוחזר שווה בדיוק ל-`COUNT(*)` בפועל בתיק בסיום — טסט-רגרסיה שאוכף את זה. - [ ] טסט: שתי קריאות `force=True` במקביל על אותו תיק → אחת מצליחה, השנייה `busy`, וב-DB אין כפילויות.
chaim added the type:bugpriority:p2-normalstatus:readysize:sarea:mcp labels 2026-08-05 12:02:46 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ezer-mishpati/legal-ai#461