InvestIQ

InvestIQ

ניהול השקעות אוטומטי 1.0

דאשבורדהתראותתיק השקעותחיפוש וניתוח ניירות ערךעסקאותהודעותשווקיםדוח כספים יומישאלות ותשובותשאל את המערכתדוחות מסהגדרותמדריךדף הנחייה למערכת
מצב: PAPER TRADING
info@investiq.co.il054-4860090
מפרטים ומסמכים/V2-CH2/V2-CH2-004

V2-CH2-004 — קידום וקישור Decision

כרך 2 · פרק 2 · משימה 004 · promoteCandidate אטומי, PROMOTING, Reconciliation

v1.0 Approved · 11.8.2026

מטרת המסמך

הגדרה פורמלית של שלב הקידום (Promotion): מעבר מ-analyzing ל-promoting ל-promoted, יצירת Decision אטומית, נעילת promotion_locked_at, ומנגנון Reconciliation ל-Candidates תקועים. סגירת קריטריונים C5 + C6 מ-V2-CH2-001.

גבול כרך 1: מסמך תיאורי — הלוגיקה כבר ממומשת ב-candidateService.ts (Shadow). אינו מוסיף שדות.

שלבי קידום

שלבפעולהתיאורחוסם?
1evaluateCandidate()בדיקת quorum: outputs_received ≥ quorum_threshold. אם לא — המתנה. אם כן — מעבר ל-PROMOTING.חוסם
2מעבר ל-PROMOTINGstatus: analyzing → promoting. שמירת promotion_locked_at = now(). נעילת ה-Candidate למעברים מקבילים.חוסם
3promoteCandidate()קריאת createDecision() עם candidate_id. יצירת Decision וקבלת decision_id.חוסם
4עדכון candidate.decision_idשמירת decision_id ב-Candidate. קישור דו-כיווני.חוסם
5מעבר ל-PROMOTEDstatus: promoting → promoted. שמירת promoted_at = now(). Candidate עם status=promoted אינו בר-שינוי.חוסם

Invariants

מזההחומרהכלל
I1P0מעבר analyzing→promoting→promoted אטומי: יצירת Decision + עדכון decision_id + מעבר ל-PROMOTED בטרנזקציה אחת לוגית.
I2P0promotion_locked_at נשמר בכניסה ל-PROMOTING. אם ה-Candidate תקוע ב-PROMOTING > 60 שניות — reconcileStuckPromoting() מופעל.
I3P0Candidate עם status=promoted אינו בר-שינוי — אין עדכון שדות, אין מחיקה, אין קידום חוזר.
I4P0ב-Shadow: promoteCandidate() אינו יוצר Decision מקביל — הוא מקשר ל-Decision הקיים מהנתיב הסטנדרטי.
I5P0אין קידום אוטומטי מחמת תום זמן (deadline). Candidate שפג תוקפו → EXPIRED, לא PROMOTED.
I6P1Candidate שנדחה (rejected) אינו ניתן לקידום חוזר. נדרש Candidate חדש ב-cycle חדש.

Reconciliation

טריגרתנאיפעולהתוצאה
PROMOTING > 60sDecision נוצר (decision_id קיים)השלמת קידום: status → promoted, promoted_at = now().PROMOTED
PROMOTING > 60sDecision לא נוצר (decision_id ריק)סימון כ-rejected עם rejected_reason="stuck_promoting_no_decision".REJECTED
expires_at עברstatus ב-discovered/analyzingמעבר ל-expired. אין קידום.EXPIRED
analysis_deadline עברquorum לא הושגמעבר ל-expired. אין קידום.EXPIRED

קריטריוני קבלה

מזההקריטריוןתוצאה
P1promoteCandidate() מופעל רק לאחר quorum (≥60%). אין קידום ללא quorum.PASS
P2מעבר analyzing→promoting→promoted אטומי: Decision + decision_id + status בטרנזקציה אחת.PASS
P3promotion_locked_at נשמר בכניסה ל-PROMOTING.PASS
P4reconcileStuckPromoting() מטפל ב-Candidates תקועים > 60 שניות: משלים או דוחה.PASS
P5Candidate עם status=promoted אינו בר-שינוי.PASS
P6ב-Shadow: אין יצירת Decision מקביל — מקשר ל-Decision הקיים.PASS
P7אין קידום אוטומטי מחמת תום זמן. פג תוקף → EXPIRED.PASS
מפרט · v1.0 Approved · 11.8.2026 · נעול
חזרה ל-V2-CH2-003