7.7 KiB
7.7 KiB
Pod: セッションログをバックエンドにした Pod 単位の永続化
背景
現在の永続化の主軸は session-store の append-only JSONL ログで、SessionId 単位に会話履歴・設定・scope snapshot・usage・拡張 payload を復元できる。一方で Pod 単位のランタイム状態は <runtime_dir>/{pod_name}/ 配下の status.json / history.json / spawned_pods.json などに write-through されているが、runtime dir は再起動で消えてよい領域であり、Pod プロセスの寿命を超える復元ソースとしては扱えない。
特に spawned Pod の管理情報は SpawnedPodRegistry のコメントにもある通り、現状は runtime dir への write-through のみで、再起動した spawner が子 Pod 一覧を rebuild する future work になっている。
このチケットでは、既存の session-store を物理バックエンドとして利用しつつ、Pod 名をキーにした永続状態を追加し、Pod 単位で「最後にどの session を保持していたか」「spawned children をどう復元するか」を扱えるようにする。
方針
- session log は引き続き会話状態の唯一の復元ソースにする。
history.jsonや runtime dir の snapshot を永続正本にはしない。- LLM context に載せる新規 input は、既存方針通り先に worker history / session log に commit されている必要がある。
- Pod 単位の永続化は「Pod identity → session / child registry などへの参照」を保存する薄いメタデータ層として設計する。
- 会話本文を二重保存しない。
- active session だけでなく、compaction / fork / resume によってその Pod が辿ってきた過去 session を順序付きで保持する。これは UI の履歴表示、直近以前への復元、active session 変更の監査に使う。
- session-store の
Storetrait を拡張するか、隣接 trait / module を追加して、FsStore 以外の backend でも同じ形で実装できるようにする。
- FsStore のデフォルト layout は
<data_dir>/pods/配下など、sessions/と同じ data_dir 管理下に置く。- runtime dir (
<runtime_dir>/{pod_name}/) は引き続き socket / pid / status など一時状態専用。
- runtime dir (
- Pod lifecycle 上の write point を明確にする。
- Pod 作成時: pod name と allocated session id を記録。
- first run で
SessionStartが materialize された後: active session / head を更新できる状態にする。 - compaction / fork / resume で active session が変わる場合: Pod state も同時に更新。
SpawnPod/ callback /StopPodによる child registry 変更時: runtime dir だけでなく persistent Pod state にも write-through。
- 復元時は Pod state から active session を解決し、その session log を
restore_from_manifest相当の経路で復元する。- session id を明示した resume は既存通り session を直接指定できる。
- Pod 名 resume は Pod state → active session → session restore の順に解決する。
- live writer 衝突は既存の pod-registry / session_id collision check を維持する。
データ粒度の考え方
- ユーザー視点の会話継続単位と、内部の append-only log 単位を分けて扱う。
- ユーザー視点: Pod / thread / conversation のような安定 ID。compaction しても同じ会話として継続する。
- 内部 log 視点: session segment / revision / epoch のような履歴再構築単位。compaction や fork で新しい log root が必要なら新 ID になる。
- 現状の
SessionIdは内部 log 単位の性質が強い。compaction は履歴を要約済み prefix に置き換えて新しい append-only chain を始めるため、低レベルには「新 session」として扱うのは自然。ただし UX / データモデル上は「同じ Pod conversation の新 revision」と見せる。 - 将来 DB backend を追加する場合も、
Conversation/PodStateとSessionSegmentを分ける形に寄せる。pod_state.active_session_idは現在 append 先の segment を指す。pod_state.session_history[]は Pod 視点で active だった segment の順序付き履歴。- compaction / fork の構造的 lineage は session log の
SessionOriginまたは DB の relation として保持し、Pod state は「この Pod がどれを active にしたか」の操作履歴に留める。
要件
- Pod 名をキーに、少なくとも以下を永続化できること:
- active
SessionId - ordered session history: その Pod が active として保持してきた
SessionIdの時系列リスト- 各 entry には最低限
session_idと遷移理由(new / resume / compact / fork など)を持たせる - compaction / fork の構造的な出自は session log の
SessionOriginを正本とし、Pod state 側は Pod 視点の active session 遷移履歴として扱う
- 各 entry には最低限
- Pod manifest / scope 復元に必要な参照または snapshot の扱い(既存 session log の
pod.scopesnapshot と責務を重複させない) - spawned children の registry(pod name, socket path, delegated scope, callback address, child session id が必要なら含める)
- active
SpawnedPodRegistryが runtime dir のspawned_pods.jsonだけでなく、Pod 永続状態から初期化できること。ListPods/SendToPod/ReadPodOutput/StopPodは、復元後の spawner でも永続化された child registry を基に動作できること。- ただし
ReadPodOutputの read cursor は session-lifetime / in-memory のままでよい。永続化対象にしない。
- ただし
- Pod の compaction により active session id が変わった場合、Pod 永続状態と pod-registry の session id が整合すること。
- 既存の
--session <UUID>resume は壊さない。 - 新しい Pod 名単位 resume / attach の入口を決めること。
- 例:
pod --pod-state <name>ではなく、既存pod.nameと manifest cascade から同名 Pod state を探す形など。 - CLI / TUI の最小導線を本チケット内で確定する。
- 例:
完了条件
session-storeに Pod 単位メタデータを扱う backend API と FsStore 実装がある。- Pod state が active session と ordered session history を保持し、new / resume / compaction / fork の遷移が順序付きで記録される。
- 新規 Pod 起動、resume、compaction、spawn / stop の各タイミングで Pod 永続状態が更新される。
- Pod プロセス再起動後、Pod 名から active session を復元し、会話を継続できる。
- spawner Pod の再起動後、永続化された spawned children 一覧から
ListPodsが復元され、到達可能な child に対して comm tools が使える。 - runtime dir は引き続き一時状態として扱われ、永続正本に依存しない。
- live writer の二重起動は既存 pod-registry / session lock と同等以上に防止される。
範囲外
- 会話履歴そのものの保存形式変更。
- session log の DB 化や remote backend 実装。
- Pod state の自動 GC / retention policy。
- TUI 上の高度な Pod 一覧 UI。最小限の resume / attach 導線を超える UX は別チケット。
ReadPodOutputcursor の永続化。
関連
crates/session-store/: 既存の session append-only backend。crates/pod/src/runtime/dir.rs: runtime dir のhistory.json/spawned_pods.json。crates/pod/src/spawn/registry.rs: spawned children registry。現状は write-through のみで復元未実装。tickets/pod-session-fork.md: active session 切り替え設計との整合が必要。