Reactive Coeffects:空間次元の依存応答
本論文は Reactive Coeffects で spatial composability を解決する——コンポーネントの依存が出現、消失、置換された後、システムがライフサイクルと依存接続を自動調整できるか。中核思想:コンポーネントは自分が何を必要とするか(coeffect 仕様)を宣言し、ランタイムはコンテキスト変化時に仕様に従ってコンポーネントに通知する。
Coeffect Context と set は effect
[論文原文の結論 §3.2.1] Coeffect context Σ ≔ (k : K) ⇀ 𝒱_k は依存キーから型付き値への有限偏関数である。get と set が二つのコア操作(Def 23)であり、set(k, v) 自体が effect である——coeffect 操作は effect であり、coeffect の提供は自動的に追跡可能性と回復可能性を継承する。これが Revertible Effects と Reactive Coeffects の協調点である:依存を宣言(provide)することは、同時に可逆 effect を行うことである。
Coeffect Specification と三状態変化
[論文原文の結論 §3.2.2] Coeffect specification d ⊆ K はコンポーネントが宣言する依存キー集合;satisfaction predicate σ ⊧ d ≔ ∀k ∈ d. k ∈ dom(σ)。σ を σ' に変える任意の effect は d に従い activating / deactivating / neutral(Def 26)に分類される:
- activating:変化前 σ は d を満たさず、変化後 σ' は満たす——コンポーネントは活性化されるべき;
- deactivating:変化前は満たし、変化後は満たさない——コンポーネントはアンロードされるべき;
- neutral:変化の前後で満たす、または前後で満たさない——コンポーネントは状態切替不要(ただし依存インスタンスは差し替わっている可能性がある)。
データベース A + RAG B の完全事例
具体的な事例(論文全体を貫く標準例):
プラグイン A(データベースプラグイン):set('database', dbService) 依存を提供
プラグイン B(RAG プラグイン): d_B = {'database'} を宣言 依存を必要- A の出現:A は
ctx.set('database', dbService)でデータベースサービスを提供;σ に'database'キーが出現。B が宣言したd_B = {'database'}は不満足から満足に——activating、B は通知され自動的に活性化され、ctx.get('database')から dbService を取得する。 - A の消失または置換:A の fiber が Unloading に入り、
'database'キーが σ から除去される。B のd_Bは満足から不満足に——deactivating、B は通知され自動的にアンロードされる(B 自身の inverse accumulator が適用され、B が保持する資源が解放される)。 - 新 A の準備完了:新版データベースプラグイン A' が
ctx.set('database', newDbService)で提供。B のd_Bは再び不満足から満足に——activating、B は新依存で再活性化し、newDbService を取得する。
整プロセスにおいて、B のコードは「もし A がいなくなったら……」という能動検出を書く必要がない——ランタイムが coeffect 仕様に従い自動通知する。
Committed View vs Target View
[論文原文の結論 §4.1, §4.2] Cordis 実装には、二つの重要な依存解決ビューがある:
- Committed View(ω):現在コミット済みの依存解決、fiber 名から provider への写像を記録。コンポーネントが episode 全体で読むのはこのビューであり、コンポーネントの今回ライフサイクル中の依存が不変であることを保証する(Ordering 定理 参照)。
- Target View:fiber が置かれるべき依存解決状態、
refreshが設定変化時に再計算する。target と committed が不一致になると、ライフサイクル遷移(活性化、アンロード、再読み込み)が発火する。
[論文原文の結論 §4.2] 重要な詳細:target view が記録するのは provider identity(fiber uid)であり、value が等しいかではない。論文は明記する:「makes the comparison usable, since a different fiber providing an equal value would otherwise compare equal」——value だけを比較すれば、同じ value を提供する異なる fiber が「依存は変わっていない」と誤判定され、再活性化が発火せず、consumer が旧 fiber のスナップショットを使い続け provider が差し替わったことに気づかない。Cordis 実装の fiber.target は依存解決結果の uid ダイジェストを保持する(§5.1.3)。
Isolation と Interception
[論文原文の結論 §3.2.3] 二つの直交する派生機構:
- Isolation:isolation realm table
ρ : K ⇀ Rにより、同じ key k が異なる context で異なる realm r に解決され、結果として異なる値にバインドされる。ctx.isolate(k, r)は k における ρ の写像だけを上書きする新コンテキストを派生する(derived realization、親テーブルは変更しない)。 - Interception:coeffect にメタデータ
ι : K → ℙ_kを掛け、provider 関数がメタデータを受け取り挙動を調整する。ctx.intercept(k, ν)は k のメタデータに ν をマージするコンテキストを派生する。
両者の違い:Isolation は「key がどの binding に解決されるか」を置き換える(インスタンス交換)、Interception は「binding が使われる方式」を変更する(制約追加、インスタンス交換なし)。Isolation は derived realization(inverse 不要、子コンテキストを破棄するだけ)、set は in-place realization(元に戻すために inverse が必要)。
シナリオ対照
| シナリオ | Isolation を使用 | Interception を使用 |
|---|---|---|
| マルチテナント / 異なる Workspace | 同じ key 'db' を各テナントで各インスタンスに解決 | — |
| サブ Agent の独立環境 | 同じ 'filesystem' を各サブ Agent で独立インスタンスに | — |
| テストダブル | mock realm で上書き | — |
| ファイルシステムの読み取り専用権限 | — | readonly メタデータを付与 |
| 異なるプラグインが異なるモデルを使用 | 'model' key を各々隔離 | — |
| コミュニティプラグインの厳格なアクセス方針 | — | capability 制限メタデータを付与 |
Reactive Coeffects は「依存変化の感知」を解決するが、コンポーネントインスタンス自身の読み込み/アンロード/再読み込みプロセスはまだ状態機械で管理する必要がある。ライフサイクルとアンロード順序 を参照。