Problem
domain の kernel モデルはイベントの発生を one-hot なフラグで表す。
rust/fsl-core/src/domain_lowering.rs::event_assignments(1929 行)は、発火した
イベントのフラグを true、それ以外の全イベントフラグを false に代入する:
Ok(names.into_iter().map(|name| Statement::Assign {
target: LValue::Var(event_flag(name)),
value: Expr::Bool(emitted.contains(name)), // 発火 1 件のみ true
span,
}).collect())
これは「1 ステップ = 1 イベント」という実行モデルと整合的で、状態空間も最小に保たれる。
導入時の制約(有界検証で状態爆発を避ける)は現在も有効である。
問題は、この表現が 「過去にこのイベントが起きた」を表せないことにある。saga は
まさにそれを必要とする。
帰結 1: await ステップのガードが構造的に恒偽(#640(b))
saga_guards(同ファイル 2617 行)は、最初のステップに starts_on のフラグを、
awaits を持つステップに待機イベントの選言を積む。one-hot なので両者は同時に真に
なり得ない。生成物がそのまま証拠になる:
action saga_payment_flow_await_payment_capture() {
requires event_PaymentCaptureRequested
requires (event_PaymentCaptured or event_PaymentFailed or event_PaymentTimedOut)
...
}
素の fslc verify は action '...' is never enabled within depth N を出す
(#641 マージ後は domain check からも見える)。
帰結 2: 終端状態の隠蔽
#640(a) 修正(PR #661)で無ガードの観測アクションが消えた結果、domain testgen の
生成物に deadlock_terminal シナリオが新たに出現した。観測アクションが常に発火
可能だったため、モデルの終端状態がこれまで隠されていたことを意味する。
(deadlock は既定で検査対象外のため corpus の verdict は変わっていない。)
帰結 3: 迂回アクションの存在理由そのもの
#640(a) で削除した saga_<name>_observe_<event> は、そもそも「effect が所有する
イベントの発生を saga 側から見る」ための迂回だった。フラグが履歴を表現できていれば
必要のない構造である。
なぜ局所修正で直しにくいか
saga ステップアクションは引数を持たない(lower_saga_actions は Vec::new() を
渡す)。したがって相関キーで永続 status マップ(<effect>_status[correlation])を
引けない。「saga が開始済み」を永続状態で表すには、ステップアクションの署名か
フラグ表現のどちらかを変える必要がある。
docs/DESIGN-domain.md の Future Work 自身が "richer history-aware saga state"
を残課題として挙げている。
決めるべきこと(コードより先に)
- saga ステップに相関引数を持たせ、effect の永続 status を直接引く
- イベントフラグを履歴化する(発生済みフラグを sticky にする、または最後のイベント
とは別に「発生済み」集合を持つ)
- saga の開始/進行を専用の永続 saga 状態として明示的にモデル化する
いずれも状態空間と意味論に影響する。測定を伴う設計判断であり、実装から始めない。
未検証
- 各案の状態空間コスト(one-hot vs 履歴表現)は未計測
- 3 案の表現力差(compensation / 多段 saga / 並行 saga)は未評価
関連
Problem
domainの kernel モデルはイベントの発生を one-hot なフラグで表す。rust/fsl-core/src/domain_lowering.rs::event_assignments(1929 行)は、発火したイベントのフラグを
true、それ以外の全イベントフラグをfalseに代入する:これは「1 ステップ = 1 イベント」という実行モデルと整合的で、状態空間も最小に保たれる。
導入時の制約(有界検証で状態爆発を避ける)は現在も有効である。
問題は、この表現が 「過去にこのイベントが起きた」を表せないことにある。saga は
まさにそれを必要とする。
帰結 1: await ステップのガードが構造的に恒偽(#640(b))
saga_guards(同ファイル 2617 行)は、最初のステップにstarts_onのフラグを、awaitsを持つステップに待機イベントの選言を積む。one-hot なので両者は同時に真になり得ない。生成物がそのまま証拠になる:
素の
fslc verifyはaction '...' is never enabled within depth Nを出す(#641 マージ後は
domain checkからも見える)。帰結 2: 終端状態の隠蔽
#640(a) 修正(PR #661)で無ガードの観測アクションが消えた結果、
domain testgenの生成物に
deadlock_terminalシナリオが新たに出現した。観測アクションが常に発火可能だったため、モデルの終端状態がこれまで隠されていたことを意味する。
(deadlock は既定で検査対象外のため corpus の verdict は変わっていない。)
帰結 3: 迂回アクションの存在理由そのもの
#640(a) で削除した
saga_<name>_observe_<event>は、そもそも「effect が所有するイベントの発生を saga 側から見る」ための迂回だった。フラグが履歴を表現できていれば
必要のない構造である。
なぜ局所修正で直しにくいか
saga ステップアクションは引数を持たない(
lower_saga_actionsはVec::new()を渡す)。したがって相関キーで永続 status マップ(
<effect>_status[correlation])を引けない。「saga が開始済み」を永続状態で表すには、ステップアクションの署名か
フラグ表現のどちらかを変える必要がある。
docs/DESIGN-domain.mdの Future Work 自身が "richer history-aware saga state"を残課題として挙げている。
決めるべきこと(コードより先に)
とは別に「発生済み」集合を持つ)
いずれも状態空間と意味論に影響する。測定を伴う設計判断であり、実装から始めない。
未検証
関連
docs/DESIGN-domain.mdRuntime Replay / Future Work