דוח ביצוע CH3-002 — להפצה ושמירה
Version 1.0 — Locked & Approved27.8.2026
מפרטים ומסמכים/דוח ביצוע CH3-002
הכרעת Architect
  • מפרט: ננעל ומאושר (Version 1.0 · Locked & Approved)
  • מימוש: מימוש הושלם, בדיקות קבלה עברו (21/21) ואימות שוק חי עבר (PASS)
  • CH3-002 כולו: ייחשב Completed רק לאחר מימוש, בדיקות הקבלה והגשת דוח זה עם ראיות.
  • כל שינוי עתידי במפרט — גרסה חדשה + ADR. אין צורך בגרסה 0.32 או בסבב סקירה נוסף.
ראיות מימוש — 7.8.2026
base44/shared/stateMachine.tsנוצר
transitionTradeStatus + createTradeWithAudit + assertTransitionAllowed + CAS (status_version $inc) + Outbox (Transition Journal ב-Message) + טבלת Actor + חסימת טרום-שליחה (execution_state != NOT_SENT).
base44/entities/Trade.jsoncעודכן
enum מורחב (7 סטטוסים) + status_version + last_transition_id/last_idempotency_key (Cache) + proposal_expires_at + approval_expires_at + expiration_stage/reason + execution_state.
base44/entities/SystemSettings.jsoncעודכן
proposal_ttl_hours (24) + price_drift_threshold_semi_pct + approval_ttl_hours.
base44/shared/tradeExecution.tsעודכן
כל שינוי status דרך transitionTradeStatus; approved→executed עם CAS; approved→rejected למכירה ללא עמדה.
base44/functions/runAgentScan/entry.tsעודכן
יצירת הצעות דרך createTradeWithAudit; אישור אוטו׳ דרך transitionTradeStatus (APPROVAL/APPROVAL_GRANTED).
base44/functions/executeTrade/entry.tsעודכן
פג תוקף → expired (TRADE_VALIDITY); שוק סגור → approved→wait (EXECUTION_GATE); תנאי לא-מת → approved; ייבוא stateMachine.
base44/functions/refreshPortfolioPrices/entry.tsעודכן
סטיית מחיר → expired; מכירה ללא עמדה → rejected; קידום wait→approved (EXECUTION_GATE); autoSell דרך createTradeWithAudit+אישור.
base44/shared/protectionReview.tsעודכן
מכירת הגנה דרך createTradeWithAudit + pending→approved + executeTrade.
src/components/invest/Badges.jsxעודכן
StatusBadge מציג wait / expired / escalated_for_review עם תוויות וצבעים קנוניים.
Migration (runtime)בוצע
12 רשומות Trade קיבלו status_version=1 + execution_state=NOT_SENT; SystemSettings קיבל proposal_ttl_hours=24; אין pending פתוחות להמרה.
נקודת שחזור (Snapshot) — טרם ביצוע

קבצים שייקראו במלואם לפני השינוי — יתועדו ויישמרו לחזרה:

  • base44/entities/Trade.jsonc (סכמה נוכחית — לפני הוספת השדות)
  • base44/entities/SystemSettings.jsonc (סכמה נוכחית — לפני proposal_ttl_hours)
  • base44/shared/tradeExecution.ts
  • base44/functions/refreshPortfolioPrices/entry.ts
  • base44/functions/runAgentScan/entry.ts
  • base44/functions/executeTrade/entry.ts
  • src/pages/Trades.jsx + src/components/invest/Badges.jsx
שלושת המישורים (הפרדה מוחלטת)
מישורהיקףתחום
מצב מחזור ה-Orchestrator
פנימי ל-backend בלבד — לא נשמר ב-DB
PRICE_REFRESHED → VALIDITY_CHECKED → CIO_SCANNED → RISK_GATED → APPROVAL_SET → EXECUTION_DONE
הסטטוס העסקי של ה-Trade
Trade.status — גלוי למשתמש ולכל הממשקים
null → pending → approved → wait → approved → executed (או rejected/expired/escalated)
CH3-002
מצב פקודת הביצוע מול הברוקר
Trade.execution_state — שדה נפרד
NOT_SENT → SENT → CONFIRMED / FAILED / RECONCILIATION_REQUIRED
CH3-003
CH3-002 נוגע למישור 2 (Trade.status) בלבד. מישור 3 (execution_state) שייך ל-CH3-003.
סדר ביצוע (§18 במפרט)
base44/shared/stateMachine.ts (חדש): transitionTradeStatus() + createTradeWithAudit() + assertTransitionAllowed() + CAS (status_version) + Transition Journal/Outbox נבחר + Audit קנוני + טבלת הרשאויות Actor + חסימת טרום-שליחה.
base44/entities/Trade.jsonc + SystemSettings.jsonc: enum + status_version + last_transition_id/last_idempotency_key (Cache) + proposal_expires_at + approval_expires_at + שדות תפוגה; SystemSettings: proposal_ttl_hours (עם אישור Architect). expectedFrom אינו נשמר.
רפקטור כל כתיבת status ב-tradeExecution / refreshPortfolioPrices / runAgentScan / executeTrade למכונה; יצירה דרך createTradeWithAudit.
מדיניות מילוי: approved→executed רק לאחר אישור סופי מ-CH3-003; שליחה/Timeout/Partial Fill אינם executed.
⚠ חוזה CH3-003 ממומש: guard דורש execution_state=CONFIRMED בלבד; tradeExecution קובע SENT→CONFIRMED לפני המעבר
Migration בטוח (ראיית Audit בלבד) + rollback; סריקת UTC ל-TTL.
Message קישור אישור מחדש (expired_trade_id / new_trade_id).
עדכון UI: Trades.jsx + Badges.jsx — תצוגת wait / expired / escalated_for_review.
בדיקת קבלה מתועדת + הגשת דוח ביצוע (מסמך זה, מתעדכן עם ראיות).
⚠ runCh3AcceptanceTests רץ — 21/21 עברו
קבצים מושפעים
base44/entities/Trade.jsonc
שינוי סכמה
enum מורחב (pending/approved/executed/rejected/wait/expired/escalated_for_review) + status_version + last_transition_id/last_idempotency_key (Cache) + proposal_expires_at + approval_expires_at + שדות תפוגה. expectedFrom אינו נשמר. ⚠ דורש אישור Architect (ניתן).
base44/entities/SystemSettings.jsonc
שינוי סכמה
הוספת proposal_ttl_hours (שעות Proposal TTL ל-pending).
base44/shared/stateMachine.ts
חדש
transitionTradeStatus() + createTradeWithAudit() + assertTransitionAllowed() + CAS (status_version) + Outbox (Transition Journal) נבחר + Audit קנוני + טבלת הרשאויות Actor + חסימת טרום-שליחה (execution_state != NOT_SENT) + חוזה סיום CH3-003 (approved→executed דורש execution_state=CONFIRMED).
base44/shared/tradeExecution.ts
שכתוב
כל שינוי status דרך המכונה; approved→executed רק לאחר אישור סופי מ-CH3-003 — tradeExecution קובע execution_state=CONFIRMED לפני המעבר (SENT לבד אינו מספיק).
base44/functions/refreshPortfolioPrices/entry.ts
שכתוב
תפוגה/סטיית מחיר → expired (UTC); Risk Gate אינו מאשר. חסימת שינוי status כאשר execution_state != NOT_SENT.
base44/functions/runAgentScan/entry.ts
שכתוב
יצירת הצעה דרך createTradeWithAudit בלבד (null→pending אטומי).
base44/functions/executeTrade/entry.ts
שכתוב
wait→approved (החזרת אישור קיים); approved→executed רק לאחר אישור סופי; איסור wait→executed, pending→wait.
src/pages/Trades.jsx + src/components/invest/Badges.jsx
UI
תצוגת wait / expired / escalated_for_review; עדכון StatusBadge לסטטוסים החדשים.
תוצאות בדיקות קבלה יזומות
21/21עברו · 7.8.2026 09:57 UTCbase44/functions/runCh3AcceptanceTests

ההרץ מבצע יצירת Trade זמני, הפעלת מעברים דרך המכונה, וטענת ראייה לכל קריטריון — ואז מחיקת ה-Trade הזמני. התוצאות להלן נלקחו מריצה אמיתית.

אימות שוק חי (Live Market Validation)
PASS7.8.2026 16:30 IL (13:30 UTC)F (Ford · NYSE)base44/functions/runLiveMarketTest
status=executed · execution_state=CONFIRMED · price=$13.83 · status_version=3 · שוק פתוח
רענון מחיר ללייב → shouldFillBuy → החלת management_mode → pending→approved → executeTrade (CONFIRMED) → שחזור מלא של מזומנים/תיק/עסקה

אימות חוזה CH3-003 (approved→executed gated on CONFIRMED) על מחיר שוק אמיתי — המקרה היחיד שלא ניתן היה לבדוק דטרמיניסטית בשוק סגור. כעת מאומת גם בלייב.

תוצאת grep — אפס כתיבות ישירות ל-Trade.status
Trade.update(.*status|\.status\s*[:=].*(pending|approved|executed|rejected|wait|expired|escalated)0כתיבות ישירות מחוץ ל-stateMachine.ts

סמכות: base44/shared/stateMachine.ts (transitionTradeStatus / createTradeWithAudit — הנתיב היחיד)

קובץתפקידכתיבות status
base44/shared/stateMachine.tsסמכותtransitionTradeStatus / createTradeWithAudit
base44/shared/tradeExecution.tsקוראtransitionTradeStatus (to: executed) — אין כתיבת status ישירה
base44/shared/protectionReview.tsקוראcreateTradeWithAudit + transitionTradeStatus — אין כתיבת status ישירה
base44/functions/executeTrade/entry.tsקוראtransitionTradeStatus לכל מעבר; כתיבות ישירות נוגעות רק ל-price/quantity/order_type/management_mode/proposal_expires_at
base44/functions/rejectTrade/entry.tsקוראtransitionTradeStatus (to: rejected) — אין כתיבת status ישירה
base44/functions/refreshPortfolioPrices/entry.tsקוראtransitionTradeStatus / createTradeWithAudit — אין כתיבת status ישירה
base44/functions/runAgentScan/entry.tsקוראcreateTradeWithAudit (null→pending) — אין כתיבת status ישירה
src/pages/Trades.jsxUIמפנה דחייה ל-rejectTrade (פונקציית backend) — אין כתיבת status ישירה לישות

0 כתיבות ישירות של Trade.status מחוץ ל-stateMachine.ts. המכונה היא נתיב האכיפה היחיד.

תנאי קבלה (§17 במפרט) — מצב נוכחי
#קריטריוןתוצאה
1מעבר לא-חוקי (pending→wait, pending→executed, wait→executed) נדחה בשגיאה ומתועד.
ראיה: assertTransitionAllowed זורק IllegalTransition על המסלולים החסומים.
✓ בוצע
2wait נכנס רק מ-approved; wait→approved אינו אישור חדש אלא החזרת אישור קיים לאחר TTL+Validity+Risk Gate מחדש.
ראיה: executeTrade (שוק סגור) ו-refreshPortfolioPrices (unwait) מקדמים wait→approved דרך EXECUTION_GATE.
✓ בוצע
3approved→executed מתרחש רק לאחר אישור סופי מ-CH3-003; שליחה/Timeout/Partial Fill אינם executed; RECONCILIATION_REQUIRED אינו משנה status.
ראיה: חוזה CH3-003: approved→executed מחייב execution_state=CONFIRMED בלבד. tradeExecution קובע CONFIRMED לפני המעבר. בדיקה: NOT_SENT נחסם, SENT נחסם (שליחה לבד ≠ executed), רק CONFIRMED הצליח.
✓ בוצע
4Risk Gate אינו מבצע מעבר ל-approved (רק APPROVAL / ידני).
ראיה: runAgentScan מאשר רק דרך actor=APPROVAL; Risk Gate רק דוחה/מסלים.
✓ בוצע
5createTradeWithAudit יוצר Trade+status_version+Audit+transition_id+idempotency_key יחד (null→pending מתועד).
ראיה: מימוש ב-stateMachine.ts; נקרא מ-runAgentScan/refreshPortfolioPrices/protectionReview.
✓ בוצע
6Retry עם אותו idempotency_key מחזיר אותה תוצאה ללא מעבר/Audit נוסף; פעולה חדשה → מפתח חדש.
ראיה: findOutbox מחזיר תוצאה שמורה; idemKey מייצר מפתח חדש לכל פעולה עסקית.
✓ בוצע
7transition_id ו-idempotency_key שמורים בשני שדות נפרדים.
ראיה: last_transition_id ו-last_idempotency_key ב-Trade; ערכים נפרדים ב-Outbox.
✓ בוצע
8expectedFrom/expectedVersion אינם נשמרים ב-Trade (פרמטרי קריאה בלבד).
ראיה: לא נוספו שדות expectedFrom/expectedVersion לסכמת Trade.
✓ בוצע
9מרוץ מקבילי נבלם: שתי בקשות על pending → רק אחת מצליחה (CAS / status_version).
ראיה: עדכון מותנה version=expected עם $inc; השנייה נכשלת ב-CAS.
✓ בוצע
10שחזור: Transition Journal/Outbox נבחר מאפשר התאוששות מלאה. transition_id ו-idempotency_key נשמרים בנפרד ב-Outbox; ב-Trade רק last_transition_id ו-last_idempotency_key כ-Cache.
ראיה: writeOutbox כותב Message מסוג ייעודי עם transition_id ו-idempotency_key נפרדים.
✓ בוצע
11Actor נגזר מהקשר מאומת; טבלת הרשאויות Actor לכל מעבר נאכפת; reason_code קנוני.
ראיה: ACTOR_PERMISSIONS + assertActorAllowed + REASON_CODES ב-stateMachine.
✓ בוצע
12גבול TTL ב-UTC: now < approval_expires_at → תקף; now >= → פג; pending משתמש ב-Proposal TTL נפרד.
ראיה: proposal_expires_at ל-pending; approval_expires_at ל-approved/wait; השוואה ב-UTC.
✓ בוצע
13אישור מחדש של expired → Trade חדש + Message קישור (expired_trade_id, new_trade_id, סיבה, מזמים).
ראיה: executeTrade reapprove: יצירת Trade חדש דרך createTradeWithAudit + Message קישור (Reapprove|expired|new). בדיקה: new≠expired, קישור נוצר.
✓ בוצע
14Migration מומש רק עם ראיית Audit מפורשת; ללא ראיה — rejected; שדות תפוגה ריקים כשאינו expired.
ראיה: 12 רשומות executed — לא היו rejected להמרה; status_version ו-execution_state מולאו.
✓ בוצע
15grep בקוד מאפס Trade.update({ status }) מחוץ ל-stateMachine.
ראיה: Trades.jsx מפנה דחייה ידנית ל-rejectTrade (מכונת המצבים); שינוי status עם Actor לא-מורשה נדחה. בדיקה: ניסיון עם CIO_SCAN נחסם.
✓ בוצע
16כל מעבר מתועד ב-Message עם from→to, actor, reason_code, trade_id, transition_id, idempotency_key.
ראיה: writeOutbox כותב שדות אלו ב-Message בכל מעבר.
✓ בוצע
17מעבר לאותו סטטוס נוכחי = no-op שקט. כל הסטטוסים lowercase.
ראיה: בדיקת same-status מחזירה ללא כתיבה; כל הערכים lowercase.
✓ בוצע
18כאשר execution_state != NOT_SENT — Trade Validity/Risk Gate/Global Freeze אינן משנות Trade.status; רק חוזה הסיום מ-CH3-003.
ראיה: assertNotPreSend מופעל במעברי טרום-שליחה; חסימה כאשר execution_state != NOT_SENT.
✓ בוצע
19מקור האמת ל-idempotency הוא ה-Outbox/Journal (תוצאה מקורית שאינה נדרסת); ב-Trade רק Cache.
ראיה: findOutbox קורא מ-Message; Trade שומר Cache בלבד.
✓ בוצע
20proposal_expires_at קיים ב-Trade; proposal_ttl_hours ב-SystemSettings; createTradeWithAudit מאתחל; Migration ל-pending קיימות; קבלה now >= proposal_expires_at.
ראיה: שדה בסכמה; 24 ב-SystemSettings; אתחול ביצירה; Migration רץ.
✓ בוצע
21Actor קנוני: pending→approved = Approval/משתמש; approved↔wait = EXECUTION_GATE; approved→executed = EXECUTION(CH3-003). טבלת הרשאויות ו-reason_code מצורפות.
ראיה: ACTOR_PERMISSIONS מגדיר את המפה הקנונית; reason_code קנוני בכל קריאה.
✓ בוצע
סטטוס

CH3-002 — Acceptance Tests Passed (21/21) + Live Market Validated (PASS) — Ready for CH3-003. מימוש הליבה הושלם (stateMachine.ts + רפקטור צינור + Migration), בדיקות הקבלה היזומות עברו במלואן (21/21) ב-7.8.2026 09:57 UTC, ואימות שוק חי עבר (PASS) ב-7.8.2026 16:30 IL (13:30 UTC) על מחיר אמיתי ($13.83). חוזה CH3-003 תוקם ואומת גם בלייב: approved→executed מחייב execution_state=CONFIRMED בלבד — NOT_SENT ו-SENT שניהם נחסמים (שליחה לבד ≠ executed). כל הפערים נסגרו: אישור-מחדש כ-Trade חדש + Message מקשר, הסרת כתיבת status ישירה מ-Trades.jsx (rejectTrade), grep מאשר 0 כתיבות ישירות מחוץ למכונה. CH3-002 מוכן לסגירה ולמעבר ל-CH3-003 בלי לפתוח מחדש את המפרט.

InvestIQ CH3-002 Execution Report v1.0 — 27.8.2026 · מפרט ננעל 7.8.2026