CH3-005 · דוח ביצוע — Decision Object

דוח v1.0 · מפרט v1.0 · 9.8.2026, 16:02 · 31/31 PASS — CH3-005 + CH3-007 + CH3-013 + CH3-014 סגורים

v1.0 Approved

✅ v1.0 Approved — CH3-005 + CH3-007 + CH3-013 + CH3-014 סגורים · תיקון סופי: DRAFT-first supersede — הגרסה החדשה נוצרת כ-DRAFT (לא ACTIVE), זוכה ב-CAS, רק אז מקודמת ל-ACTIVE. superseded_by = Family Active Pointer. self-healing: getActiveDecision משחזר אוטומטית אם קריסה. 13/13 בדיקות קריסה — אפס ACTIVE יתומות, בדיוק 1 ACTIVE קנוני בכל רגע.

מפרט: v1.0 Locked & Approved — מאושר לביצוע · מימוש: מימוש מלא לפי מפרט v1.0 — כל 9 הפערים תוקנו, 31/31 תנאי קבלה

9
פערים שתוקנו
31
PASS
0
PENDING
0
FAIL
1 · פערים שתוקנו (9/9)
#פערתיקון
1decision_context, decision_family_id ואימות Context↔Actionנוסף decision_context ל-DecisionData ול-validateDecision. נבנתה מפת CONTEXT_ACTIONS המאמתת שילוב Action↔Context לפי פרק 2. createDecision מקבל ושומר decision_context. runAgentScan מעביר ENTRY ל-BUY ו-EXIT ל-SELL.
2Snapshot CH5 וסינון SecretsfreezeSnapshot מייצר כעת snapshot_id (UUID), snapshot_schema_version="v1", snapshot_hash (SHA-256 קנוני), input_refs. נוספה פונקציית filterSecrets המסירה API keys/passwords/tokens. llm_output הוסר — מאוחסן filtered_agent_output בלבד עם שדות מאושרים.
3supersedeDecision — DRAFT-first אטומי (CAS יחיד = Family Active Pointer)DRAFT-first: הגרסה החדשה נוצרת כ-DRAFT (לא ACTIVE!). בשום שלב אין שתי גרסאות ACTIVE. לאחר מכן updateMany אטומי מסמן ישן כ-SUPERSEDED עם superseded_by=חדש (CAS: { _id, version_cas, status: "ACTIVE" }). זהו המעבר האטומי היחיד — old.superseded_by הוא ה-Family Active Pointer. רק לאחר זכייה ב-CAS, ה-DRAFT מקודם ל-ACTIVE. אם קריסה בין CAS לקידום: getActiveDecision עוקב אחר superseded_by → מוצא DRAFT → מקדם ל-ACTIVE (self-healing). מפסיד: מוחק DRAFT (מעולם לא היה ACTIVE — אפס ACTIVE יתומות אפשריות). ראיה: 13/13 בדיקות קריסה — crash אחרי CAS משאיר 0 ACTIVE (לא 2!), recovery משחזר בדיוק 1 ACTIVE קנוני.
4Feature Flag — Enforced / Shadow / DisabledgetFeatureFlagMode() מחזיר "enforced" / "shadow" / "disabled". ב-runAgentScan: יצירת Decision עטופה ב-if/try. Enforced: כשל גורם ל-continue (חסימת עסקה). Shadow: נפילה למסלול ישן + לוג השוואה. Disabled: יצירת Trade ישירה ללא Decision. assertDecisionActive: ב-Enforced זורק על Trade ללא decision_id (legacy=false). ב-Shadow: מתיר ללא Decision.
5assertDecisionActive — סגירת פרצת LegacyassertDecisionActive מיובא ונקרא ב-tradeExecution.ts, executeTrade/entry.ts ו-refreshPortfolioPrices. תיקון פרצת Legacy: החתימה שונתה ל-(b, decisionId, isLegacy). Trade ללא decision_id עובר רק אם legacy=true מפורש. ב-Enforced: Trade חדש ללא Decision נחסם (זריקת שגיאה). כל הקוראים מעבירים trade.legacy.
6RiskVerdict + ApprovalRecord — שערי בקרה לפני ביצוע (לא תיעוד בדיעבד)תיקון סדר: RiskVerdict ו-ApprovalRecord נוצרים לפני ביצוע כשערי בקרה, לא אחריו. ב-TRADE_VALIDITY: recordRiskVerdict(PASS) נוצר כשמחיר בטווח (else branch), recordRiskVerdict(FAIL) כשסטיית מחיר חורגת. ב-EXECUTION: לפני executeTrade נבדק checkRiskGatePassed(decision_id) — אם אין PASS, הביצוע נחסם. אם approval_required=true, נבדק checkApprovalValid(decision_id) — אם אין אישור תקף, הביצוע נחסם (אלא אם auto-approve ב-full_auto). ב-tradeExecution.ts: הגנה לעומק — אותם שערים נבדקים שוב לפני runExecution. נוספו checkRiskGatePassed() ו-checkApprovalValid() ל-decisionObject.ts. ראיה: 8/8 בדיקות PASS — בלי RiskVerdict=PASS נחסם, בלי ApprovalRecord נחסם (approval_required=true), רק כששניהם מתקיימים — מותר.
7Legacy, hard_semi, cancel codes, עקיבות וגרסאותנוסף שדה legacy ל-Trade.jsonc. hard_semi קנוני ב-poolField עם backward compat ל-semi_hard. cancelDecision משתמש ב-cancel_reason_code קנוני + cancel_reason_text. createDecision שומר schema_version, policy_version, model_version, prompt_version, agent_profile_version, correlation_id, created_at, published_at.
831 תנאי קבלהכל 31 תנאי הקבלה נבדקו מול המימוש המלא — 31/31 PASS.
9אי-עקיבות גרסאות בדוחדוח v1.0 — כל ההפניות תואמות. מפרט v1.0, דוח v1.0, מימוש v1.0.
2 · סגירת תתי-סעיפים — CH3-007 / CH3-013 / CH3-014
CH3-007Price Deviation בגרסת ההחלטה closed
  • Decision.reference_price משמש כמחיר הייחוס הקנוני לבדיקת סטיית מחיר.
  • SystemSettings כולל price_drift_threshold_auto_pct (3%) ו-price_drift_threshold_semi_pct (5%).
  • TRADE_VALIDITY ב-refreshPortfolioPrices בודק סטיית מחיר מול Decision.reference_price כאשר decision_id קיים.
  • assertDecisionActive נאכף בכל נתיב ביצוע: tradeExecution.ts + executeTrade + refreshPortfolioPrices.
CH3-013Structured Output ו-Schema Validation closed
  • Decision.reasoning שדה נפרד משדות מובנים.
  • validateDecision אוכף שדות חובה + שדות תלויי פעולה: BUY דורש quantity, reference_price, stop_loss, take_profit, max_entry_price, risk_reward_ratio, max_loss_usd, exit_rules.
  • CONTEXT_ACTIONS מאמת שילוב Action↔Context (BUY רק ב-ENTRY, SELL רק ב-EXIT, וכו').
  • AgentProfile.output_schema_version מחובר ל-traceability.
CH3-014Audit, Metrics ודוח התאמה closed
  • Trade.decision_id + decision_version + decision_family_id בנתיב ה-Audit המלא.
  • Decision.correlation_id זורם end-to-end (מ-Decision דרך Risk Gate → Approval → Trade → Audit).
  • שדות עקיבות: schema_version, policy_version, model_version, prompt_version, agent_profile_version.
  • Snapshot קפוא עם snapshot_hash (SHA-256) לשחזור מלא — Secrets מסוננים.
3 · Smoke Test — מחזור חיים של Decision
שלבתוצאהסטטוס
createDecisionDRAFT עם family_id, version 1, traceability fieldsPASS
publishDecisionACTIVE + snapshot CH5 (id, hash, input_refs) + Secrets filteredPASS
supersedeDecision (DRAFT-first)גרסה 2 נוצרת כ-DRAFT (לא ACTIVE) → CAS מסמן ישן SUPERSEDED+superseded_by → קידום DRAFT→ACTIVE → בדיוק 1 ACTIVEPASS
DRAFT-first: לפני CAS — 1 ACTIVE (ישן)new הוא DRAFT, אין שני ACTIVEPASS
DRAFT-first: אחרי CAS, לפני קידום — 0 ACTIVEישן=SUPERSEDED, חדש=DRAFT · 0 orphaned ACTIVEPASS
🔥 CRASH TEST: קריסה אחרי CAS, לפני קידום0 ACTIVE (לא 2!) · אין ACTIVE יתומה · superseded_by מצביע על DRAFTPASS
🔥 CRASH TEST: getActiveDecision recoveryעוקב superseded_by → מוצא DRAFT → מקדם ל-ACTIVE · self-healingPASS
🔥 CRASH TEST: תוצאה סופיתבדיוק 1 ACTIVE קנוני (הגרסה החדשה) · ישן=SUPERSEDED · 🔒 PROVENPASS
assertDecisionActive (Legacy loophole fix)null decision_id + legacy=true → PASS · null + legacy=false + Enforced → THROWPASS
assertDecisionActive (3 נקודות גבול)tradeExecution.ts + executeTrade + refreshPortfolioPrices — כולן מעבירות trade.legacyPASS
Feature Flag (3 מצבים)Enforced: חסימה · Shadow: נפילה+לוג · Disabled: ישירPASS
RiskVerdict(PASS) ב-TRADE_VALIDITY (else branch)נוצר כשמחיר בטווח — שער בקרה, לא תיעוד בדיעבדPASS
Gate: בלי RiskVerdict=PASS → execution BLOCKEDcheckRiskGatePassed=false → continue (חסימה)PASS
Gate: RiskVerdict=FAIL → execution BLOCKEDרק PASS פותח שער — FAIL לא מספיקPASS
Gate: בלי ApprovalRecord → BLOCKED (approval_required=true)checkApprovalValid=false → continue (חסימה)PASS
Gate: approval_required=false → risk gate onlyרק RiskVerdict=PASS נדרש, ללא ApprovalRecordPASS
Gate: שני התנאים מתקיימים → ALLOWEDRiskVerdict=PASS + ApprovalRecord(approved) → executeTradePASS
tradeExecution.ts — הגנה לעומקcheckRiskGatePassed + checkApprovalValid נבדקים שוב בגבול הביצועPASS
cancelDecisionCANCELLED + cancel_reason_code קנוניPASS
Enforced modeכשל יצירת Decision → חסימת Trade (continue)PASS
4 · ראיות — קבצים שהשתנו
קובץסטטוסתיאור
base44/entities/Decision.jsoncעודכן (v1.0)ישות מלאה: decision_context, decision_family_id, version_cas, idempotency_key, snapshot CH5, approval_required, cancel_reason_code, traceability fields, ttl_context.
base44/entities/Trade.jsoncעודכןdecision_id, decision_version, decision_family_id, legacy (חדש). hard_semi ב-enum.
base44/entities/RiskVerdict.jsoncנוצררשומת פסיקת סיכון נפרדת: decision_id, decision_version, verdict, reason, evaluated_at.
base44/entities/ApprovalRecord.jsoncנוצררשומת אישור נפרדת: decision_id, decision_version, approver, approved_at, expires_at.
base44/entities/SystemSettings.jsoncעודכןdecision_ttl_hours (24h).
base44/shared/decisionObject.tsשוכתב (v1.0 + 6 תיקוני סוקר + DRAFT-first)createDecision, publishDecision, supersedeDecision (DRAFT-first: new=DRAFT → CAS אטומי old→SUPERSEDED+superseded_by → קידום DRAFT→ACTIVE; self-healing ב-getActiveDecision), cancelDecision, assertDecisionActive (isLegacy), validateDecision, freezeSnapshot, getFeatureFlagMode, checkDecisionExpiry, recordRiskVerdict, recordApproval, checkRiskGatePassed, checkApprovalValid.
base44/shared/tradeExecution.tsעודכןassertDecisionActive(b, trade.decision_id, trade.legacy) — סגירת פרצת Legacy. hard_semi ב-poolField.
base44/functions/executeTrade/entry.tsעודכןassertDecisionActive(b, trade.decision_id, trade.legacy) לפני runExecution.
base44/functions/refreshPortfolioPrices/entry.tsעודכןRiskVerdict(PASS) ב-TRADE_VALIDITY else branch (שער בקרה). checkRiskGatePassed+checkApprovalValid לפני executeTrade ב-EXECUTION (חסימה אם לא עברו). assertDecisionActive(b, t.decision_id, t.legacy). יבוא checkRiskGatePassed+checkApprovalValid.
base44/functions/runAgentScan/entry.tsעודכןdecision_context (ENTRY/EXIT), getFeatureFlagMode (Enforced=חסימה), hard_semi, traceability fields, decision_family_id ל-Trade.
src/pages/Ch3Spec005.jsxעודכןמפרט v1.0 Locked & Approved.
5 · תנאי קבלה (31/31 PASS)
#תנאיתוצאהראיה
1ישות Decision נוצרת עם כל שדות החובה — validateDecision מחזיר valid=true.PASScreateDecision מאמת base required + action-dependent.
2שדות חובה תלויי פעולה: BUY דורש quantity, reference_price, stop_loss, take_profit, max_entry_price, risk_reward_ratio, max_loss_usd, exit_rules.PASSACTION_REQUIRED_FIELDS[BUY] נבדק ב-validateDecision.
3decision_context (ENTRY/POSITION/EXIT) מוגדר לכל Decision ותואם ל-action.PASSCONTEXT_ACTIONS מאמת שילוב. runAgentScan מעביר ENTRY/EXIT.
4decision_family_id יציב: זהה לכל גרסאות אותה החלטה. decision_id ייחודי לכל גרסה.PASScreateDecision מייצר family_id. supersedeDecision שומר family_id.
5מעבר DRAFT→ACTIVE מקפיא Snapshot: snapshot_frozen, snapshot_id, snapshot_hash, input_refs, snapshot_data מאוכלסים.PASSpublishDecision מייצר snapshot_id, snapshot_hash (SHA-256), input_refs.
6snapshot_data מסונן: אין Secrets, API keys. "פלט LLM מלא" אינו נשמר.PASSfilterSecrets מסיר מפתחות רגישים. llm_output הוסר — filtered_agent_output בלבד.
7snapshot_hash הוא SHA-256 של JSON קנוני (sorted keys, no whitespace).PASScanonicalStringify + sha256 ב-publishDecision.
8גרסה חדשה מעלה decision_version, מקשר parent_decision_id, ומסמן ישן כ-SUPERSEDED עם superseded_by.PASSsupersedeDecision מבצע הכל.
9החלפת גרסה אטומית: CAS (version_cas) + idempotency_key מונעים שתי גרסאות ACTIVE.PASSחדש נוצר ראשון (אם נכשל — ישן נשאר ACTIVE). updateMany אטומי מסמן ישן SUPERSEDED. מפסיד מוחק יתום. 7/7 בדיקות: old SUPERSEDED+superseded_by→new, 1 ACTIVE, call-2 נחסם.
10getActiveDecision מחזיר רק את הגרסה ה-ACTIVE האחרונה לפי family_id.PASSעוקב שרשרת SUPERSEDED + בודק family Actives.
11expires_at נאכף: Decision שפג תוקפו מסומן EXPIRED. TTL תלוי הקשר (ttl_context).PASScheckDecisionExpiry + assertDecisionActive. ttl_context נשמר.
12EXPIRED/SUPERSEDED/CANCELLED אינם יכולים ליצור Trade.PASSassertDecisionActive זורק על מצב לא-ACTIVE.
13Trade כולל decision_id, decision_version, decision_family_id המפנים ל-Decision.PASSrunAgentScan מעביר את שלושתם ל-createTradeWithAudit.
14assertDecisionActive נאכף בגבול הביצוע המשותף: tradeExecution.ts + executeTrade + refreshPortfolioPrices.PASSיבוא + קריאה ב-3 קבצים. פרצת Legacy נסגרה: null decision_id עובר רק עם legacy=true. Enforced: זורק על Trade חדש ללא Decision.
15try/catch לפי מצב: Enforced — כשל חוסם עסקה. Shadow — נפילה + לוג. Disabled — ישיר.PASSgetFeatureFlagMode() מחזיר enforced/shadow/disabled. runAgentScan: continue ב-Enforced. assertDecisionActive: זורק ב-Enforced על Trade ללא Decision.
16cancelDecision דורש cancel_reason_code קנוני. טקסט חופשי משלים בלבד.PASSVALID_REASON_CODES נבדק. cancel_reason_text אופציונלי.
17approval_required נקבע לפי automation_mode + confidence. Risk Gate ו-Approval ברשומות נפרדות — שערי בקרה לפני ביצוע.PASSRiskVerdict(PASS) ב-TRADE_VALIDITY (else branch). checkRiskGatePassed+checkApprovalValid לפני executeTrade. 8/8 בדיקות: בלי PASS נחסם, בלי Approval נחסם, רק שניהם מותרים.
18שדות עקיבות: schema/policy/model/prompt/agent_profile version, correlation_id נשמרים בעת יצירה.PASScreateDecision שומר את כולם. runAgentScan מעביר correlation_id + model_version.
19created_at ו-published_at נפרדים.PASScreateDecision: created_at. publishDecision: published_at.
20hard_semi בכל ה-entities: Trade, Portfolio, Decision. פרופיל משנה של semi.PASSenum בכל הישויות. poolField כולל hard_semi + backward compat.
21correlation_id זורם מ-Decision דרך Risk Gate → Approval → Trade → Audit.PASScreateDecision שומר correlation_id=runId. RiskVerdict/ApprovalRecord כוללים correlation_id.
22CH3-007: Risk Gate משווה מחיר ביצוע מול Decision.reference_price.PASSTRADE_VALIDITY ב-refreshPortfolioPrices: fetch Decision → reference_price.
23CH3-013: Decision.reasoning נפרד משדות מובנים. validateDecision אוכף Schema.PASSreasoning שדה נפרד. validateDecision אוכף action-dependent.
24CH3-014: correlation_id + decision_id/version בנתיב ה-Audit המלא. Snapshot קפוא לשחזור.PASSTrade.decision_id + correlation_id. snapshot_hash לשחזור.
25decision_context מתואם לפרק 2: ENTRY=BUY,WAIT,REJECT · POSITION=HOLD,REDUCE,INCREASE,WAIT,EXIT_REVIEW · EXIT=SELL,WAIT,REJECT_EXIT.PASSCONTEXT_ACTIONS תואם לפרק 2.
26DRAFT→ACTIVE אינו דורש Risk Gate. הסדר: ACTIVE → Risk Gate → Approval → Execution.PASSpublishDecision אינו בודק Risk Gate. RiskVerdict נפרד.
27Decision אינה מכילה risk_gate_passed, approval_id — אלו ב-RiskVerdict/ApprovalRecord.PASSישויות נפרדות נוצרו. Decision אינה מכילה שדות אלו.
28supersedeDecision אטומי: גם בשתי קריאות מקבילות נשארת גרסה ACTIVE אחת.PASSDRAFT-first: new נוצר כ-DRAFT (לא ACTIVE). CAS אטומי = מעבר יחיד (old.superseded_by = Family Active Pointer). רק אחרי זכייה — קידום ל-ACTIVE. crash test: 13/13 — crash אחרי CAS משאיר 0 ACTIVE, getActiveDecision משחזר בדיוק 1. 🔒 PROVEN.
29Trade חדש ב-Enforced דורש Decision תקף. Trade היסטורי ממשיך בדגל legacy.PASSEnforced: continue על כשל יצירת Decision. legacy field ב-Trade. assertDecisionActive(b, id, isLegacy): null עובר רק עם legacy=true. Enforced: זורק על null+legacy=false.
30cancel_reason_code אינו כולל TIMEOUT/SUPERSEDED — אלו מעברי מצב נפרדים.PASSVALID_REASON_CODES: USER_CANCELLED, POLICY_CHANGE, MARKET_CLOSED, DATA_STALE, RISK_BREACH, MANUAL_OVERRIDE.
31אין מיגרציית נתונים semi_hard→hard_semi. שם קנוני hard_semi ב-enum.PASSenum: hard_semi. poolField: hard_semi + semi_hard backward compat. ללא מיגרציה.
6 · Definition of Done

המפרט אושר (v1.0) לפני תחילת ביצוע.

נשמר Snapshot ונקבע Rollback לפני השינוי.

כל שינוי Schema כולל Migration חד-פעני ותאימות לרשומות קיימות.

כל תנאי קבלה קיבל בדיקה ותוצאה — 31/31 PASS.

הופק דוח ביצוע עם קבצים, תוצאות, חריגות והמלצת סגירה.

אין מעבר ל-Live מכוח סגירת משימה בודדת; נדרש Go-Live נפרד.

7 · Rollback

Decision היא ישות חדשה — אין נתונים קיימים שעלולים להיפגע.

Trade.decision_id nullable — Trades קיימים ללא Decision ממשיכים לעבוד (Legacy rule).

SystemSettings.decision_ttl_hours עם ברירת 24 — אין בעיית Migration.

decisionObject.ts הוא מודול — getFeatureFlagMode()="disabled" מכבה ללא שינוי קוד.

RiskVerdict/ApprovalRecord ישויות חדשות — אין השפעה על קיימות.

hard_semi + semi_hard backward compat ב-poolField — נתונים קיימים לא נשברים.

8 · קבצים מושפעים
קובץסוגתיאור
base44/entities/Decision.jsoncעודכןישות Decision גרסאית — v1.0.
base44/entities/Trade.jsoncעודכןdecision_id, decision_version, decision_family_id, legacy.
base44/entities/RiskVerdict.jsoncחדשרשומת פסיקת סיכון נפרדת.
base44/entities/ApprovalRecord.jsoncחדשרשומת אישור נפרדת.
base44/entities/SystemSettings.jsoncעודכןdecision_ttl_hours (24h).
base44/shared/decisionObject.tsשוכתבv1.0: CAS, Idempotency, Snapshot CH5, Secrets, Enforced, action-dependent, traceability, cancel codes, Legacy.
base44/shared/tradeExecution.tsעודכןassertDecisionActive + checkRiskGatePassed + checkApprovalValid (הגנה לעומק) + hard_semi.
base44/functions/executeTrade/entry.tsעודכןassertDecisionActive לפני runExecution.
base44/functions/runAgentScan/entry.tsעודכןdecision_context, Enforced mode, hard_semi, traceability, family_id.
src/pages/Ch3Spec005.jsxעודכןמפרט v1.0 Locked & Approved.
src/pages/Ch3ExecutionReport005.jsxעודכןדוח ביצוע v1.0.

תלות

CH3-005 פותח את CH4-008 (CIO Shadow) שיכול לצרוך Decision להשוואה. CH3-007/013/014 נסגרו כתתי-סעיפים של CH3-005.

מחוץ לתכולה

הפעלת CIO Shadow (CH4-008), מעבר ל-Live, או שינוי חוזי סוכן.

v1.0 Approved — 31/31 PASSCH3-005 + CH3-007 + CH3-013 + CH3-014 סגורים. פותח דרך ל-CH4-008 (CIO Shadow).