5.9 KiB
5.9 KiB
永続化層のセマンティック整理
背景
現在の永続化は SessionId 単位の append-only JSONL log を中心に構成されている。これは実装上は扱いやすい一方で、今後 Pod 単位永続化、compaction、fork、DB backend 追加などを進めるにあたり、以下の概念が混ざり始めている。
- ユーザー視点の「同じ会話 / 作業の継続単位」
- Pod 視点の「現在 active な会話状態」
- append-only log の物理的 / 復元上の単位
- compaction によって生成される新しい履歴系列
- fork の起点となる履歴中の境界
- runtime dir に置かれる一時状態と、data dir / DB に置く永続正本
特に、現在は compaction によって新しい SessionId が発行される。これは append-only log の低レベル単位としては自然だが、ユーザー視点では「同じ会話が継続している」とも見えるため、Session という名称・粒度が今後の設計上あいまいになり得る。
このチケットでは、実装変更に入る前に、永続化層のドメイン概念・名称・責務境界を整理する。
目的
- 永続化層で扱う概念を、ユーザー視点 / Pod 視点 / storage 視点に分けて定義する。
SessionIdが今後も適切な中心概念か、あるいは別概念に分解すべきかを判断する。- compaction / fork / resume / Pod state / spawned child registry が、どの粒度のデータに属するかを決める。
- 将来 DB backend を追加しても歪みにくいデータ構造を設計する。
- 既存の session-store JSONL 実装から段階的に移行できる命名・API 境界を決める。
検討事項
- 会話継続単位と append-only log 単位を分けるべきか。
- 例: user-visible conversation/thread と、internal log segment の分離。
- compaction の扱い。
- compaction 後の履歴を新しい低レベル log として扱うのは自然か。
- その場合、ユーザー視点では同じ会話の継続としてどう表現するか。
- fork の扱い。
- fork は新しい会話単位を作るのか、同一会話内の branch とするのか。
- fork 起点を entry hash / turn boundary / checkpoint など、どの抽象度で表すか。
- Pod state の責務。
- Pod 名から active な会話 / log を復元するために何を持つべきか。
- Pod が過去に辿った session / log の順序付き履歴をどこに持つべきか。
- runtime state と persistent state の境界。
history.json/status.json/spawned_pods.jsonを永続正本として扱わない方針の確認。
- session log の
pod.scopeextension entry を撤廃するか(要検討)。- 現状: session log に
PodScopeSnapshotを extension として append し、session 復元時に scope も復元できる。 - Pod 単位永続化(
tickets/pod-persistent-state.md)が入ると、scope の正本を Pod state に持つほうが責務が明確で、session log との重複も解消できる。 - ただし scope は session 内で動的に変化し得るため、「最新 snapshot は Pod state 」「変化履歴は session log の event として残す」のような分割もあり得る。conversation timeline 上の scope 変化を session 単独で再現する必要があるかが論点。
- 撤廃の選択肢: (a) session log から完全に削除し Pod state を唯一の正本にする / (b) snapshot 保持責務だけ Pod state に寄せ、scope 変更 event は session log に残す / (c) 現状維持で Pod state は session への参照のみ。
- 現状: session log に
- DB backend を想定した場合のテーブル / relation 相当の構造。
- append-only entry log
- lineage / origin
- active pointer
- Pod / child Pod registry
- index / listing / GC の余地
- 既存 API / CLI 名称の移行方針。
--sessionの扱い- debug 用 ID とユーザー向け ID の分離
一案: Thread / Segment / Checkpoint に分ける案
これは現時点の決定ではなく、検討材料の一案として置く。
Pod: agent 実行主体 / process identity。Thread: ユーザー視点の会話・作業継続単位。compaction しても同じ Thread と見なす。Segment: append-only log の物理的 / 復元上の単位。現在のSessionIdに近い。compaction / fork で新しい Segment が生まれる。Entry: Segment 内の 1 永続化イベント。Checkpoint: fork / rollback / UI 選択などの起点を表す抽象境界。内部的には Segment + EntryHash を指してもよいが、表層 API では entry pointer を直接露出しすぎない。
この案では:
- compaction = same Thread, new Segment
- fork = new Thread または branch, new Segment
- resume = same Thread の active Segment に append
- Pod state = active Thread / spawned children / 必要な runtime 復元メタデータを保持
- lineage = Segment origin または Checkpoint reference として保持
この案を採用するかは本チケット内で改めて比較・判断する。
完了条件
- 永続化層の主要概念と名称が文書化されている。
- compaction / fork / resume / Pod state のデータ粒度が決まっている。
- 現在の
SessionId/ session-store API をどう扱うか、維持・alias・rename・段階移行の方針が決まっている。 - DB backend を追加する場合の概念モデルが、最低限テーブル / relation 相当で説明できる。
tickets/pod-persistent-state.mdや fork 関連チケットに反映すべき前提が整理されている。
範囲外
- このチケット単体での大規模 rename 実装。
- DB backend の実装。
- UI の履歴表示 / branch 表示の詳細 UX。
- GC / retention policy の実装。
関連
tickets/pod-persistent-state.mdtickets/pod-session-fork.mdcrates/session-store/crates/pod/src/pod.rs