CH3-005 · אובייקט החלטת CIO גרסאי

גרסה 1.0 · 9.8.2026, 14:58 · P1 · Locked & Approved — מאושר לביצוע

v1.0 Locked & Approved

היסטוריית גרסאות

גרסהתאריךשינוייםסטטוס
0.18.8.2026טיוטה ראשונית — מבנה בסיסי: Decision entity, lifecycle (DRAFT→ACTIVE→EXPIRED/SUPERSEDED/CANCELLED), Snapshot, שילוב ב-runAgentScan ו-refreshPortfolioPrices.Review
0.29.8.2026 14:13תיקוני סוקר מקיפים: decision_context, פעולות מורחבות, שדות תלויי פעולה, decision_family_id + CAS, Snapshot CH5, assertDecisionActive בגבול הביצוע, try/catch Enforced/Shadow, שדות עקיבות, approval_required, hard_semi, TTL, cancel reason_code.Review — לא מאושר
0.39.8.2026 14:34תיקוני סוקר v0.3: (1) התאמת decision_context לפרק 2 — INCREASE עבר ל-POSITION, WAIT נוסף לכל ההקשרים. (2) DRAFT→ACTIVE אינו דורש Risk Gate — הסדר: Decision ACTIVE → Risk Gate → Approval → Execution. (3) Decision אינה משתנה לאחר פרסום — risk_gate_passed/reason/result_id ו-approval_id הוסרו מהישות ועברו ל-RiskVerdict ו-ApprovalRecord נפרדות. (4) supersedeDecision אטומי מלא + קריטריון קבלה לקריאות מקבילות. (5) אין מיגרציית נתונים semi_hard→hard_semi ב-CH3-005. (6) כלל Legacy ל-Trades היסטוריים. (7) הפרדת cancel_reason_code ממעברי מצב. (8) תיקון עיצוב טבלאות.Review v0.3
1.09.8.2026 14:58אושר סופית לביצוע. כל שבעת התיקונים הוטמעו ונבדקו. סטטוס: Locked & Approved.Locked & Approved

🔒 v1.0 Locked & Approved — מאושר לביצוע

כל שבעת התיקונים המהותיים הוטמעו ונבדקו. אין הערות תוכניות נוספות. המפרט נעול ומאושר לביצוע. CH3-005: סגור.

1 · בעיה ויעד

החלטת ה-CIO מפוזרת כיום בין שדות Trade (symbol, side, quantity, price, score, reasoning) ואינה מהווה אובייקט עצמאי גרסאי. אין יכולת להקפיא Snapshot של כל הקלטים ברגע ההחלטה (מחירי ייחוס, נתוני שוק, ניתוח סוכן, הגדרות מערכת). אין מנגנון להחליף החלטה ישנה בחדשה תוך שמירת היסטוריה. אין הפרדה ברורה בין "ההחלטה" (מה ה-CIO החליט) לבין "הפקודה" (מה בוצע בפועל). חסר decision_context (ENTRY/POSITION/EXIT) ופעולות ניהול פוזיציה (REJECT, REDUCE, INCREASE, EXIT_REVIEW, REJECT_EXIT). שדות החובה אינם תלויי פעולה — quantity ו-reference_price נדרשים גם ב-WAIT/HOLD שבהן אינם רלוונטיים, וב-BUY חסרים שדות חובה כגון הפסד מרבי ויחס סיכון-סיכוי. אין decision_family_id יציב לצד decision_id ייחודי לכל גרסה, והחלפת גרסה אינה אטומית — קיים סיכון לשתי גרסאות ACTIVE. ה-Snapshot אינו מתאים לפרק 5 (חסר snapshot_id, גרסת Schema, Hash, input_refs) ושומר "פלט LLM מלא" ללא סינון Secrets. assertDecisionActive נאכף רק ב-refreshPortfolioPrices ולא בגבול הביצוע המשותף (tradeExecution/executeTrade). ה-try/catch מסוכן: במצב Enforced כשל ביצירת Decision עלול לחזור בשקט ליצירת Trade ישירה. חסרים שדות עקיבות וגרסאות (schema_version, policy_version, model_version, prompt_version, agent_profile_version, correlation_id). אין approval_required ואין הפרדה בין החלטה לבין תוצאת Risk Gate ואישור משתמש שנוצרים לאחריה. מצב העבודה נקרא semi_hard במקום hard_semi, ואינו מודגש כפרופיל משנה. cancelDecision משתמש בטקסט חופשי במקום reason_code קנוני. בנוסף: INCREASE מופיע תחת ENTRY בניגוד לפרק 2 (צריך להיות תחת POSITION), ו-WAIT חסר בחלק מההקשרים. מעבר DRAFT→ACTIVE דורש Risk Gate שעבר, בניגוד לסדר הנכון: Decision ACTIVE → Risk Gate → Approval → Execution. שדות Risk Gate ו-Approval מתעדכנים בתוך Decision לאחר פרסום, בניגוד לעיקרון האי-שינוי — צריכות לחיות ברשומות נפרדות. supersedeDecision אינו מוגדר כאטומי מלא. אין כלל לעסקאות ישנות ללא decision_id. TIMEOUT ו-SUPERSEDED מופיעים כ-cancel_reason_code למרות שהם מעברי מצב (EXPIRED ו-SUPERSEDED בהתאמה).

ישות Decision עצמאית, גרסאית, עם decision_context (ENTRY/POSITION/EXIT), פעולות מורחבות, שדות חובה תלויי פעולה, decision_family_id יציב וגרסאות אטומיות (CAS). Snapshot קפוא מתאים לפרק 5 (snapshot_id, schema_version, Hash, input_refs, סינון Secrets). assertDecisionActive נאכף בגבול הביצוע המשותף (tradeExecution/executeTrade). try/catch: Enforced=חסימה על כשל, Shadow=נפילה למסלול הישן. שדות עקיבות מלאים (schema/policy/model/prompt/agent_profile version, correlation_id). approval_required + Risk Gate ו-Approval כרשומות נפרדות המקושרות ל-Decision. hard_semi כפרופיל משנה (לא מצב רביעי). TTL תלוי הקשר (אסטרטגיה, סוג עסקה), נפרד מ-Approval/Proposal TTL. cancel_reason_code קנוני + טקסט חופשי משלים. INCREASE תחת POSITION, WAIT בכל ההקשרים (ENTRY/POSITION/EXIT). DRAFT→ACTIVE אינו דורש Risk Gate — הסדר: Decision ACTIVE → Risk Gate → Approval → Execution. Decision אינה משתנה לאחר פרסום — Risk Gate ו-Approval חיים ברשומות נפרדות (RiskVerdict, ApprovalRecord) המפנות ל-decision_id + decision_version. supersedeDecision אטומי מלא — גם בקריאות מקבילות נשארת גרסה ACTIVE אחת. כלל Legacy לעסקאות ישנות ללא decision_id. הפרדה בין cancel_reason_code לבין מעברי מצב (TIMEOUT→EXPIRED, SUPERSEDED→מעבר SUPERSEDED). אין מיגרציית נתונים semi_hard→hard_semi ב-CH3-005 — משימה נפרדת.

2 · Decision Context
Contextתיאורפעולות
ENTRYכניסה לפוזיציה חדשה, המתנה או דחיית כניסהBUY, WAIT, REJECT
POSITIONניהול פוזיציה קיימת — החזקה, הקטנה, הגדלה, המתנה או סימון לבדיקת יציאהHOLD, REDUCE, INCREASE, WAIT, EXIT_REVIEW
EXITיציאה מפוזיציה, המתנה או דחיית יציאה מוצעתSELL, WAIT, REJECT_EXIT
3 · פעולות (Actions)
פעולהContextתיאורשדות חובה נוספים
BUYENTRYכניסה לפוזיציה חדשה (Long)quantity, reference_price, currency, stop_loss, take_profit, max_entry_price, risk_reward_ratio, max_loss_usd, exit_rules
WAITENTRYדחיית כניסה — ממתין לנתונים/אירוע נוסף לפני כניסהreasoning
REJECTENTRYדחיית הזדמנות שנותחה — לא נכנסreasoning
HOLDPOSITIONהחזקת פוזיציה קיימת ללא שינויreasoning
REDUCEPOSITIONהקטנת פוזיציה קיימת (מכירה חלקית)quantity, reference_price, currency
INCREASEPOSITIONהגדלת פוזיציה קיימתquantity, reference_price, currency, stop_loss, take_profit
WAITPOSITIONדחיית פעולת ניהול — ממתין לנתונים/אירוע נוסףreasoning
EXIT_REVIEWPOSITIONסימון פוזיציה לבדיקת יציאה יזומהquantity, reference_price, reasoning
SELLEXITיציאה מלאה מפוזיציהquantity, reference_price, currency
WAITEXITדחיית יציאה — ממתין לנתונים/אירוע נוסףreasoning
REJECT_EXITEXITדחיית המלצת יציאה — החזקת הפוזיציהreasoning
4 · שדות חובה בסיסיים (תמיד)
שדהסוגתיאור
decision_idstringמזהה ייחודי לגרסה זו. UUID.
decision_family_idstringמזהה משפחה יציב — זהה לכל גרסאות אותה החלטה. אינו משתנה בין גרסאות.
decision_versionnumberמספר גרסה, מתחיל ב-1. עולה בכל שינוי.
statusenumDRAFT, ACTIVE, EXPIRED, SUPERSEDED, CANCELLED
actionenumBUY, SELL, HOLD, WAIT, REJECT, REDUCE, INCREASE, EXIT_REVIEW, REJECT_EXIT
decision_contextenumENTRY, POSITION, EXIT — הקשר ההחלטה
symbolstringסמל הנכס
marketenumTASE, NYSE, NASDAQ, LSE, TSE, HKEX
confidencenumberרמת ביטחון 0–10 מה-CIO
agent_namestringשם סוכן ה-CIO שהפיק את ההחלטה
agent_idstringהפניה ל-AgentConfig.id
decision_cycle_idstringמזהה מחזור הניתוח שיצר את ההחלטה
data_as_ofdate-timeמתי הנתונים היו עדכניים
5 · שדות חובה תלויי פעולה
פעולהContextשדות נוספים (מעבר לבסיס)
BUYENTRYquantity, reference_price, currency, stop_loss, take_profit, max_entry_price, risk_reward_ratio, max_loss_usd, exit_rules
WAITENTRYreasoning
REJECTENTRYreasoning
HOLDPOSITIONreasoning
REDUCEPOSITIONquantity, reference_price, currency
INCREASEPOSITIONquantity, reference_price, currency, stop_loss, take_profit
WAITPOSITIONreasoning
EXIT_REVIEWPOSITIONquantity, reference_price, reasoning
SELLEXITquantity, reference_price, currency
WAITEXITreasoning
REJECT_EXITEXITreasoning
6 · שדות אופציונליים
שדהסוגתיאור
asset_typeenumstock, etf, fund, bond, index, reit, commodity, crypto
namestringשם חברה/נכס
currencyenumUSD, ILS, EUR, JPY, HKD — חובה בפעולות עם quantity
stop_trigger_pricenumberמחיר טריגר (Stop)
order_typeenummarket, buy_limit, buy_stop, stop_loss, take_profit, trailing_stop, stop_limit
trailing_pctnumberאחוז גלישה (Trailing)
cancellation_termsstringתנאים שבהם ניתן לבטל את ההחלטה לפני תום תוקף
reasoningstringנימוק ה-CIO — נפרד מהשדות המובנים (CH3-013). חובה ב-HOLD/WAIT/REJECT/REJECT_EXIT
scorenumberציון המלצה 0–10
management_modeenumauto, hard_semi, semi, manual — hard_semi הוא פרופיל משנה של semi (סף 9.5), לא מצב רביעי
analysis_output_idsarrayהפניות לרשומות AnalysisOutput (CH4-003)
max_loss_usdnumberהפסד מרבי בדולר — חובה ב-BUY
risk_reward_rationumberיחס סיכון-סיכוי — חובה ב-BUY (למשל 1:2)
exit_rulesstringכללי יציאה מוגדרים — חובה ב-BUY (סטופ, טייק, זמן, תנאי מימוש)
7 · שדות עקיבות וגרסאות
שדהסוגתיאור
schema_versionstringגרסת סכמת Decision הנוכחית (למשל "v1")
policy_versionstringגרסת Policy/SystemSettings ברגע ההחלטה
model_versionstringמודל LLM שהפיק את ההחלטה (למשל "gemini_3_flash")
prompt_versionstringגרסת תבנית ה-Prompt ששימשה
agent_profile_versionnumberגרסת AgentProfile בעת ההחלטה
correlation_idstringמזהה עקיבות end-to-end — עובר דרך Decision → Risk Gate → Approval → Trade → Audit
created_atdate-timeמועד יצירת DRAFT (נפרד מ-created_date של הישות)
published_atdate-timeמועד מעבר DRAFT→ACTIVE (פרסום)
8 · שדות גרסאות ומשפחה (Atomic CAS)
שדהסוגתיאור
parent_decision_idstringמזהה הגרסה הקודמת — מקשר את שרשרת הגרסאות
superseded_bystringמזהה הגרסה החדשה שהחליפה את הנוכחית
version_casnumberמונה אופטימי (CAS) להחלפה אטומית — מונע שתי גרסאות ACTIVE
idempotency_keystringמפתח Idempotency לפעולת החלפת גרסה — מונע כפילות
9 · Snapshot (CH5 Alignment)
שדהסוגתיאור
snapshot_idstringמזהה ייחודי ל-Snapshot זה. UUID.
snapshot_schema_versionstringגרסת סכמת ה-Snapshot עצמה (למשל "v1")
snapshot_frozenbooleanהאם ה-Snapshot הוקפא — נקבע ב-DRAFT→ACTIVE ואינו ניתן לשינוי
snapshot_hashstringSHA-256 של JSON קנוני (sorted keys, no whitespace) — מבטיח שלמות ויכולת השוואה
snapshot_datastringJSON קפוא מסונן — Secrets ומידע רגיש הוסרו. אין "פלט LLM מלא" ללא סינון.
input_refsarrayמערך הפניות למקורות קלט: { type, id, version } — AnalysisOutput, MarketData, AgentProfile, SystemSettings
10 · Approval ו-Risk Gate (נפרדים מ-Decision)

Decision אינה משתנה לאחר פרסום. שדה יחיד ב-Decision:

שדהסוגתיאור
approval_requiredbooleanנקבע ביצירה לפי automation_mode + confidence. אינו משתנה לאחר פרסום.

רשומות חיצוניות המפנות ל-decision_id + decision_version (אינן משנות את ה-Decision):

ישותתיאורשדות
RiskVerdictרשומת פסיקת סיכון נפרדת. נוצרת לאחר פרסום Decision (ACTIVE). אינה משנה את ה-Decision.decision_id, decision_version, verdict (PASS/FAIL), reason, evaluated_at, evaluator (agent_id)
ApprovalRecordרשומת אישור נפרדת. נוצרת לאחר RiskVerdict (PASS). אינה משנה את ה-Decision.decision_id, decision_version, approver, approved_at, expires_at, approval_status
11 · TTL
שדהסוגתיאור
expires_atdate-timeתוקף ההחלטה. ב-Paper: 24h ברירת מחדל. ב-Live: תלוי הקשר (אסטרטגיה, סוג עסקה, נכס).
ttl_contextstringהקשר ה-TTL: "paper_default", "scalping", "swing", "position", "manual_override". נפרד מ-Approval TTL ו-Proposal TTL.
12 · Cancel Reason Codes (קנוניים)
קודתיאור
USER_CANCELLEDביטול ידני על-ידי משתמש
POLICY_CHANGEשינוי Policy הפך את ההחלטה ללא-רלוונטית
MARKET_CLOSEDהשוק נסגר לפני ביצוע
DATA_STALEנתוני הקלט אינם עדכניים
RISK_BREACHדליפת סיכון זוהתה לאחר ההחלטה
MANUAL_OVERRIDEעקיפה ידנית — דרוש תיעוד נפרד
13 · מכונת מצבים
מ-אלשחקןטריגרתנאי שמירה
DRAFTACTIVECIO (runAgentScan)publishDecision — החלטה פורסמהכל שדות החובה (base + action-dependent) מלאות · confidence מוגדר · reference_price קיים (לפעולות מתאימות) · Snapshot הוקפא. אין לדרוש Risk Gate בשלב זה — הסדר: Decision ACTIVE → Risk Gate → Approval → Execution
ACTIVEEXPIREDSystem (TTL)expires_at חלףאוטומטי — checkDecisionExpiry. TTL תלוי הקשר.
ACTIVESUPERSEDEDCIO (runAgentScan)DRAFT-first: גרסה חדשה נוצרה כ-DRAFT, CAS אטומי מסמן ישן SUPERSEDED+superseded_by, רק אז קידום DRAFT→ACTIVEparent_decision_id מקשר לגרסה הקודמת · CAS version_cas + idempotency_key · old.superseded_by = Family Active Pointer · בשום שלב שתי גרסאות ACTIVE · קריסה: getActiveDecision משחזר
ACTIVECANCELLEDUser / SystemcancelDecision עם reason_codecancellation_terms מתקיימים · reason_code קנוני (לא טקסט חופשי)

מצבים טרמינליים: EXPIREDSUPERSEDEDCANCELLED

14 · כללים

רק Decision במצב ACTIVE יכול לזרום ל-Risk Gate → Approval → Execution.

Snapshot מוקפא במעבר DRAFT→ACTIVE: snapshot_frozen=true, snapshot_id, snapshot_hash, snapshot_schema_version, input_refs ו-snapshot_data מאוכלסים. לא ניתן לשנותם לאחר ההקפאה.

snapshot_data חייב סינון Secrets: אין לשמור "פלט LLM מלא" ללא הסרת מידע רגיש (API keys, פרטי חשבון, סיסמאות).

גרסה חדשה: decision_version עולה, parent_decision_id מקשר לקודמת, הקודמת מסומנת SUPERSEDED עם superseded_by. פעולה אטומית ב-CAS (version_cas) + idempotency_key — מונע שתי גרסאות ACTIVE של אותה משפחה.

decision_family_id יציב: זהה לכל גרסאות אותה החלטה. decision_id ייחודי לכל גרסה. חיפוש גרסה פעילה — לפי decision_family_id + status=ACTIVE.

expires_at נאכף: TTL תלוי הקשר (ttl_context). ב-Paper: 24h ברירת מחדל. ב-Live: לפי אסטרטגיה וסוג עסקה. נפרד מ-approval_ttl_hours ו-proposal_ttl_hours.

Trade מקבל הפניה ל-decision_id ו-decision_version — לא מעתיק את שדות ההחלטה לתוכו.

רק הגרסה ה-ACTIVE האחרונה של Decision תקפה לביצוע. גרסאות קודמות (SUPERSEDED) אינן ברות-ביצוע.

EXPIRED/SUPERSEDED/CANCELLED אינן יכולות ליצור או לשנות Trade.

CIO Shadow (CH4-008) קורא רשומות Decision לצורך השוואה — קריאה בלבד.

Decision נוצר על-ידי ה-CIO (runAgentScan) לפני יצירת Trade proposal.

Risk Gate מקבל את reference_price מה-Decision לבדיקת סטיית מחיר (CH3-007).

Decision עם confidence < auto_execute_threshold אינו יכול לעבור אישור אוטומטי.

cancelDecision מקבל cancel_reason_code (קנוני) + cancel_reason_text (חופשי, משלים). טקסט חופשי לבדו אינו מספיק.

assertDecisionActive נאכף בגבול הביצוע המשותף: tradeExecution.ts ו-executeTrade — לא רק ב-refreshPortfolioPrices. כל נתיב ביצוע עובר דרך גבול זה.

try/catch לפי מצב תכונה: Enforced (DECISION_OBJECT_ENABLED=true) — כשל ביצירת Decision חוסם את העסקה, אין נפילה למסלול ישן. Shadow (DECISION_OBJECT_ENABLED="shadow") — נפילה ליצירת Trade ישירה מותרת + לוג השוואה. Disabled (false) — יצירת Trade ישירה ללא Decision.

שדות חובה תלויי פעולה: validateDecision(data) בודק שדות נוספות לפי action. למשל BUY דורש quantity, reference_price, stop_loss, take_profit, max_entry_price, risk_reward_ratio, max_loss_usd, exit_rules. HOLD/WAIT/REJECT/REJECT_EXIT דורשים reasoning בלבד.

approval_required: נקבע לפי automation_mode + confidence. Risk Gate ו-Approval נשמרים כרשומות נפרדות (risk_gate_result_id, approval_id) המקושרות ל-Decision — הם נוצרים לאחר ההחלטה.

hard_semi (לא semi_hard): פרופיל משנה של semi (סף 9.5), לא מצב עבודה רביעי. מצבי העבודה: auto, semi, manual. hard_semi מופעל כש-automation_mode=semi_auto ו-confidence ≥ 9.5.

correlation_id זורם מ-Decision דרך Risk Gate → Approval → Trade → Audit — מאפשר שחזור מלא של מחזור החיים.

schema_version, policy_version, model_version, prompt_version, agent_profile_version נשמרים בעת יצירת ה-Decision — מאפשרים שחזור הקשר מלא.

Decision אינה משתנה לאחר פרסום (ACTIVE). risk_gate_passed, risk_gate_reason, risk_gate_result_id, approval_id אינם שדות ב-Decision — הם חיים ברשומות RiskVerdict ו-ApprovalRecord נפרדות המפנות ל-decision_id + decision_version.

supersedeDecision DRAFT-first אטומי: הגרסה החדשה נוצרת כ-DRAFT (לא ACTIVE). המעבר האטומי היחיד הוא updateMany שמסמן ישן כ-SUPERSEDED עם superseded_by→חדש (CAS). old.superseded_by הוא ה-Family Active Pointer — מקור אמת אחד. רק לאחר זכייה ב-CAS מקודם ה-DRAFT ל-ACTIVE. בשום שלב אין שתי גרסאות ACTIVE. אם קריסה אחרי CAS אך לפני קידום: 0 ACTIVE (לא 2), ו-getActiveDecision משחזר אוטומטית דרך superseded_by → מקדם DRAFT ל-ACTIVE (self-healing).

Trade חדש במצב Enforced חייב Decision תקף (ACTIVE, לא פג תוקף). Trade היסטורי שנוצר לפני מועד ההפעלה מסומן בדגל legacy או כלל Legacy מפורש — ממשיך לעבוד ללא Decision.

cancel_reason_code חל רק על מעבר ACTIVE→CANCELLED. TIMEOUT שייך למעבר ACTIVE→EXPIRED (לא CANCELLED). SUPERSEDED שייך למעבר ACTIVE→SUPERSEDED (לא CANCELLED). אין להשתמש בהם כ-cancel_reason_code.

שם קנוני: hard_semi. שינוי נתונים קיימים (semi_hard → hard_semi ברשומות Trade/Portfolio) אינו חלק מ-CH3-005 — משימת מיגרציה נפרדת לאחר בדיקת As-Is.

15 · שינויי סכמה
ישותשינוישדות
Decisionישות חדשה/מעודכנתכל השדות הנ״ל: base required + action-dependent + optional + traceability + versioning + snapshot + approval + TTL + cancel
Tradeהוספת שדותdecision_id (string), decision_version (number), decision_family_id (string)
SystemSettingsהוספת שדהdecision_ttl_hours (number, default 24 — Paper בלבד)
Trade + Portfolioשינוי enum (שם קנוני בלבד)management_mode: hard_semi. אין מיגרציית נתונים קיימים ב-CH3-005 — משימה נפרדת לאחר As-Is
16 · מודול משותף

base44/shared/decisionObject.ts

פונקציהתיאור
createDecision(data)יוצר DRAFT. מקבל decision_context, action, symbol וכו׳. מאמת שדות חובה לפי action (validateDecision). יוצר decision_family_id (אם ראשון במשפחה) ו-decision_id.
publishDecision(decisionId)DRAFT→ACTIVE. מקפיא Snapshot (snapshot_id, snapshot_schema_version, snapshot_hash, input_refs, snapshot_data מסונן Secrets). קובע expires_at לפי TTL תלוי הקשר. מציב published_at.
supersedeDecision(familyId, newData, cas, idempotencyKey)DRAFT-first אטומי: יוצר גרסה חדשה כ-DRAFT (לא 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 יתומות). בשום שלב אין שתי גרסאות ACTIVE.
cancelDecision(decisionId, reasonCode, reasonText?)ACTIVE→CANCELLED. reason_code קנוני (חובה) + reason_text חופשי (משלים, אופציונלי).
expireDecision(decisionId)ACTIVE→EXPIRED. נקרא על-ידי checkDecisionExpiry.
getActiveDecision(familyId)מחזיר את הגרסה ה-ACTIVE האחרונה לפי decision_family_id + status=ACTIVE. זורק אם אין ACTIVE או אם יש יותר מאחת.
assertDecisionActive(decisionId)זורק שגיאה אם ה-Decision אינו ACTIVE, פג תוקפו, או שה-Snapshot אינו קפוא. נקרא בגבול הביצוע המשותף: tradeExecution.ts + executeTrade — לא רק ב-refreshPortfolioPrices.
validateDecision(data)מאמת שדות חובה לפי action: BUY דורש quantity, reference_price, stop_loss, take_profit, max_entry_price, risk_reward_ratio, max_loss_usd, exit_rules. HOLD/WAIT דורשים reasoning. וכו׳. confidence בטווח 0–10.
freezeSnapshot(decision)לוכד קלטים כ-JSON מסונן (Secrets הוסרו): נתוני שוק, פלט סוכן מסונן, מצב תיק, הגדרות. יוצר snapshot_id, snapshot_hash (SHA-256 קנוני), input_refs, snapshot_schema_version.
checkDecisionExpiry()batch: מסמן ACTIVE שפג תוקפם כ-EXPIRED. TTL תלוי הקשר (ttl_context). נקרא על-ידי scheduled workflow.
getFeatureFlagMode()מחזיר את מצב התכונה: false (Disabled), "shadow" (Shadow), true (Enforced). קובע התנהגות try/catch.
17 · תלויות
כיווןמשימהתיאור
unblocksCH4-008 (CIO Shadow)CIO Shadow צריך Decision model להשוואה. ללא CH3-005, CH4-008 חסום.
relatedCH3-006 (Expiration Metadata)משתמש ב-Decision.expires_at + ttl_context ל-stage/reason קנוניים.
relatedCH3-007 (Price Deviation)Risk Gate משווה מחיר ביצוע מול Decision.reference_price.
relatedCH3-013 (Structured Output)Decision.reasoning מופרד משדות מובנים. validateDecision אוכף Schema.
relatedCH3-014 (Audit)correlation_id + decision_id/version בנתיב ה-Audit המלא.
relatedCH5-003 (DecisionContextSnapshot)Snapshot CH5: snapshot_id, schema_version, hash, input_refs — מתואם עם CH5-003.
relatedCH5-005 (Versioned Stores)schema_version, policy_version, model_version — מתואם עם גרסאות ידע.
18 · קריטריוני קבלה (31)

1.ישות Decision נוצרת עם כל שדות החובה (base) — validateDecision מחזיר valid=true.

2.שדות חובה תלויי פעולה: BUY דורש quantity, reference_price, stop_loss, take_profit, max_entry_price, risk_reward_ratio, max_loss_usd, exit_rules. HOLD/WAIT/REJECT דורשים reasoning בלבד.

3.decision_context (ENTRY/POSITION/EXIT) מוגדר לכל Decision ותואם ל-action.

4.decision_family_id יציב: זהה לכל גרסאות אותה החלטה. decision_id ייחודי לכל גרסה.

5.מעבר DRAFT→ACTIVE מקפיא Snapshot: snapshot_frozen=true, snapshot_id, snapshot_hash, snapshot_schema_version, input_refs, snapshot_data מאוכלסים.

6.snapshot_data מסונן: אין Secrets, API keys, פרטי חשבון. "פלט LLM מלא" אינו נשמר ללא סינון.

7.snapshot_hash הוא SHA-256 של JSON קנוני (sorted keys, no whitespace) — ניתן להשוואה.

8.גרסה חדשה מעלה decision_version, מקשר parent_decision_id, ומסמן ישן כ-SUPERSEDED עם superseded_by.

9.החלפת גרסה אטומית DRAFT-first: הגרסה החדשה נוצרת כ-DRAFT, CAS אטומי מסמן ישן SUPERSEDED+superseded_by, רק אז קידום ל-ACTIVE. בשום שלב שתי גרסאות ACTIVE. אם קריסה — self-healing.

10.getActiveDecision מחזיר רק את הגרסה ה-ACTIVE האחרונה לפי family_id.

11.expires_at נאכף: Decision שפג תוקפו מסומן EXPIRED. TTL תלוי הקשר (ttl_context), נפרד מ-Approval/Proposal TTL.

12.EXPIRED/SUPERSEDED/CANCELLED אינם יכולים ליצור Trade.

13.Trade כולל decision_id, decision_version, decision_family_id המפנים ל-Decision.

14.assertDecisionActive נאכף בגבול הביצוע המשותף: tradeExecution.ts + executeTrade — לא רק refreshPortfolioPrices.

15.try/catch לפי מצב: Enforced — כשל חוסם עסקה. Shadow — נפילה למסלול ישן + לוג. Disabled — ישיר.

16.cancelDecision דורש cancel_reason_code קנוני. טקסט חופשי משלים בלבד.

17.approval_required נקבע לפי automation_mode + confidence. Risk Gate ו-Approval נשמרים כרשומות נפרדות.

18.שדות עקיבות: schema_version, policy_version, model_version, prompt_version, agent_profile_version, correlation_id נשמרים בעת יצירה.

19.created_at ו-published_at נפרדים — האחד ליצירת DRAFT, השני לפרסום ACTIVE.

20.hard_semi (לא semi_hard) בכל ה-entities: Trade, Portfolio, Decision. מודגש כפרופיל משנה.

21.correlation_id זורם מ-Decision דרך Risk Gate → Approval → Trade → Audit.

22.CH3-007: Risk Gate משווה מחיר ביצוע מול Decision.reference_price.

23.CH3-013: Decision.reasoning נפרד משדות מובנים. validateDecision אוכף Schema.

24.CH3-014: correlation_id + decision_id/version בנתיב ה-Audit המלא. Snapshot קפוא לשחזור.

25.decision_context מתואם לפרק 2: ENTRY=BUY,WAIT,REJECT · POSITION=HOLD,REDUCE,INCREASE,WAIT,EXIT_REVIEW · EXIT=SELL,WAIT,REJECT_EXIT.

26.DRAFT→ACTIVE אינו דורש Risk Gate. הסדר: Decision ACTIVE → Risk Gate → Approval → Execution.

27.Decision אינה מכילה risk_gate_passed, risk_gate_reason, risk_gate_result_id, approval_id — אלו חיים ב-RiskVerdict ו-ApprovalRecord נפרדות המפנות ל-decision_id + decision_version.

28.supersedeDecision DRAFT-first אטומי: גם בשתי קריאות מקבילות נשארת בדיוק גרסה ACTIVE אחת לכל משפחה. הגרסה החדשה נוצרת כ-DRAFT (לא ACTIVE), כך שקריסה אחרי CAS אינה משאירה ACTIVE יתומה. getActiveDecision משחזר אוטומטית.

29.Trade חדש ב-Enforced דורש Decision תקף. Trade היסטורי ממשיך באמצעות דגל legacy או כלל Legacy מפורש.

30.cancel_reason_code אינו כולל TIMEOUT או SUPERSEDED — אלו מעברי מצב נפרדים (EXPIRED ו-SUPERSEDED בהתאמה).

31.אין מיגרציית נתונים semi_hard→hard_semi ב-CH3-005. השם הקנוני hard_semi מופיע ב-enum, אך רשומות קיימות אינן משתנות.

19 · קבצים מושפעים

base44/entities/Decision.jsonc — ישות חדשה/מעודכנת: כל השדות הנ״ל (ללא risk_gate_passed/reason/result_id, approval_id — אלו ברשומות נפרדות).

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/Trade.jsonc — הוספת decision_id, decision_version, decision_family_id, legacy (boolean). שם קנוני hard_semi ב-enum (ללא מיגרציית נתונים ב-CH3-005).

base44/entities/Portfolio.jsonc — שם קנוני hard_semi ב-enum (ללא מיגרציית נתונים ב-CH3-005).

base44/entities/SystemSettings.jsonc — הוספת decision_ttl_hours (24h — Paper בלבד).

base44/shared/decisionObject.ts (חדש/מעודכן) — כל הפונקציות הנ״ל + CAS + Idempotency + Snapshot CH5 + Secrets filtering.

base44/shared/tradeExecution.ts — הוספת assertDecisionActive בגבול הביצוע המשותף.

base44/functions/executeTrade/entry.ts — הוספת assertDecisionActive לפני ביצוע.

base44/functions/runAgentScan/entry.ts — יצירת Decision לפני Trade. try/catch לפי Feature Flag (Enforced/Shadow).

base44/functions/refreshPortfolioPrices/entry.ts — assertDecisionActive + checkDecisionExpiry + CH3-007.

src/pages/Ch3Spec005.jsx — עמוד מפרט זה.

20 · סדר ביצוע

1. עדכון Decision entity: הוספת כל השדות (base + action-dependent + traceability + versioning + snapshot + approval + TTL + cancel).

2. עדכון Trade entity: הוספת decision_id, decision_version, decision_family_id, legacy. שם קנוני hard_semi ב-enum (ללא מיגרציית נתונים).

3. עדכון Portfolio entity: שם קנוני hard_semi ב-enum (ללא מיגרציית נתונים).

3a. יצירת RiskVerdict entity: decision_id, decision_version, verdict, reason, evaluated_at.

3b. יצירת ApprovalRecord entity: decision_id, decision_version, approver, approved_at, expires_at.

4. עדכון SystemSettings: הוספת decision_ttl_hours (24h — Paper).

5. עדכון base44/shared/decisionObject.ts: כל הפונקציות + CAS + Idempotency + Snapshot CH5 + Secrets filtering + action-dependent validation.

6. עדכון base44/shared/tradeExecution.ts: assertDecisionActive בגבול הביצוע המשותף.

7. עדכון base44/functions/executeTrade/entry.ts: assertDecisionActive לפני ביצוע.

8. עדכון base44/functions/runAgentScan/entry.ts: יצירת Decision לפני Trade. try/catch לפי Feature Flag (Enforced=חסימה, Shadow=נפילה).

9. עדכון base44/functions/refreshPortfolioPrices/entry.ts: assertDecisionActive + checkDecisionExpiry + CH3-007.

10. בדיקות קבלה: יצירת גרסה, הקפאת Snapshot, Hash, תוקף, ביטול עם reason_code, החלפה אטומית (CAS), חסימת EXPIRED, Enforced vs Shadow.

11. תצלום לפני/אחרי והפקת דוח ביצוע CH3-005.

21 · Rollback

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

Trade.decision_id הוא nullable — Trades היסטוריים ללא Decision ממשיכים לעבוד באמצעות דגל legacy. Trade חדש ב-Enforced חייב Decision תקף.

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

decisionObject.ts הוא מודול חדש — הסרתו מחזירה ליצירת Trade ישירה.

Feature Flag: DECISION_OBJECT_ENABLED=false מכבה זמנית ללא שינוי קוד. Shadow מאפשר השוואה ללא חסימה.

שם קנוני hard_semi ב-enum. אין מיגרציית נתונים ב-CH3-005 — נתונים קיימים עם "semi_hard" נשארים, קוד מטפל בשני הערכים. מיגרציה במשימה נפרדת.

v1.0 Locked & Approvedמאושר לביצוע. פותח דרך ל-CH4-008 (CIO Shadow). כל שינוי עתידי — גרסה חדשה + ADR.