yoi/tickets/session-todo.md

112 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# セッション内 Task ツール
## 背景
長めのタスクを LLM に進めさせる際、Claude Code / OpenCode が備える「セッション内 TODO / Task リスト」相当の機構が無いため、エージェントが自分の作業計画を構造化された形で保持・更新できない。Reasoning や text 出力の中で擬似的に TODO を書くことはできるが、
- compact を跨ぐと完全に消える
- ツール結果ではないため、状態の作成・更新・削除の規約が決まらず、意図と乖離した「やったつもり」を起こしやすい
- 安定した識別子が無いため、後から特定 entry を更新できない
この用途のために、セッション内に正規化された Task リストを保持し、compact を跨いで保存される専用ツールを導入する。
「LLM がツールを使わなくなった場合のサボり防止」を目的とした注意機構(`<system-reminder>` の自動注入)は本チケットの範囲外。`tickets/session-todo-reminder.md` で別途扱う。
## 方針
- **保存先は `tools` 層の session-lifetime 状態**。`Tracker` と同じ生存スコープで `Pod` が所有。`Arc<Mutex<TaskStore>>` ベースの store を tool に注入する
- **Task は差分操作**。全置換ではなく `TaskCreate` / `TaskUpdate` によって TaskStore を逐次更新する
- **永続化は専用レーンを持たない**。`tool_call.arguments` がセッションログに既に乗っているため、resume 時には履歴 replay の中で `TaskCreate` / `TaskUpdate` を順に再適用すれば状態が復元される
## Task データモデル
各 Task entry は以下の4フィールドを持つ。
- `taskid`: store が自動採番する整数 ID。`TaskCreate` ごとに単調増加する
- `status`: `pending | inprogress | completed | deleted`
- `subject`: 1行程度の短い件名
- `description`: 詳細説明
状態遷移の通常ルートは `pending -> inprogress -> completed` とする。完了ではなく一覧から取り下げたい場合は、物理削除ではなく `TaskUpdate``status = deleted` を設定する。
## 要件
### `TaskCreate` ツール
- 入力は `subject` / `description` のみ
- TaskStore の末尾に新規 entry を push する
- `taskid` は TaskStore が自動で割り当てる。LLM は指定できない
- 初期 `status``pending`
- 戻り値は作成された Task と、更新後の TaskStore スナップショット概要を summary に含める
### `TaskList` ツール
- 入力なし
- 現在の TaskStore スナップショットを返す
- `taskid` / `status` / `subject` / `description` を含める
- `completed` / `deleted` も含め、store に残っている Task をすべて列挙する
### `TaskGet` ツール
- 入力は `taskid`
- 指定された Task を1件返す
- 存在しない `taskid` はエラーにする
### `TaskUpdate` ツール
- 入力は `taskid` と、更新する `status` / `subject` / `description` のいずれか
- 少なくとも1フィールドは更新指定が必要
- `taskid` は変更できない
- `status``pending | inprogress | completed | deleted` のいずれか
- 存在しない `taskid` はエラーにする
- 削除は `status = deleted` への更新として表現し、entry は store から取り除かない
- 戻り値は更新された Task と、更新後の TaskStore スナップショット概要を summary に含める
### Resume 時の復元
- `Pod::resume` / restore の履歴 replay 中に `TaskCreate` / `TaskUpdate``tool_call.arguments` を観測したら、TaskStore に順に再適用する
- `TaskCreate` は replay 時も自動採番を行う。ログ上の call 順序が保持されるため、通常の replay では元の `taskid` が再現される
- `TaskUpdate` は replay 済みの TaskStore に対して適用する
- 専用 LogEntry / Persistence 型は追加しない(`Tracker` と同じ方針)
- `tool_call.arguments` のフォーマットが現在の schema と乖離した場合(旧バージョンのログ)は、その call を無視してよい
### Compact 跨ぎ
- compact 起動時、Pod は現在の TaskStore **全スナップショット**を compact worker context に渡す
- compact worker は summary を書く際、TaskStore を参照できる。未完了 Task を summary 文に取り込める情報源として参照する(強制ではない)
- compact worker に Task 編集権限は与えない(作成・更新・削除はしない)
- compact 後の新セッションでも TaskStore は空にせず、compact 前の TaskStore **全件**を維持する。`completed` / `deleted` も含めて保持する
- compact 後の新セッション開始時、Pod は **`mark_read_required` と同じ system message 注入レーン**に TaskStore 全スナップショットを1メッセージとして注入する
- compact 完了後、Pod は新セッションの継続前に必ず `TaskList` を発火させ、LLM が compact 後の TaskStore 状態を tool result として再確認できるようにする
## 完了条件
- `TaskCreate` / `TaskList` / `TaskGet` / `TaskUpdate` が builtin tool として登録され、Pod で利用できる
- LLM が `TaskCreate` を呼ぶと TaskStore に pending Task が末尾追加され、自動採番された `taskid` が返る
- LLM が `TaskUpdate` を呼ぶと既存 Task の `status` / `subject` / `description` が更新される
- `TaskList` / `TaskGet` で TaskStore の状態を確認できる
- セッションを resume すると、履歴中の `TaskCreate` / `TaskUpdate` replay により TaskStore が復元される
- compact を跨いでも、TaskStore 全件が維持され、新セッション冒頭の system message と `TaskList` 発火により再提示される
- 単体テストで TaskCreate / TaskUpdate / TaskList / TaskGet の挙動、replay 復元がカバーされる
## 範囲外
- 注意機構(`<system-reminder>` の自動注入による「サボり防止」)→ `tickets/session-todo-reminder.md`
- Task の階層・優先度・タグ
- TUI / GUI での Task 状態の可視化(ツール呼び出しのイベントは既に流れているので、クライアント側で表示するかは別軸)
- Task の永続化を専用 LogEntry に分離する設計(現方針は tool_call replay と compact 時 snapshot 維持で復元、追加レーン不要)
- 複数 Pod 間で Task を共有する仕組み
## 参照
- 設計指針: `CLAUDE.md`(最小の構造化 / 概念の追加は不在が問題になってから)
- 参考実装: Claude Code の TodoWrite、OpenCode の todo tool
- 関連: `crates/tools/src/tracker.rs`session-lifetime 状態の前例)、`crates/pod/src/compact/worker.rs`auto-injection レーン)
- 後続: `tickets/session-todo-reminder.md`(注意機構)
## Review
- 状態: Approve (再レビュー済み、blocking 解消・non-blocking 対応反映)
- レビュー詳細: [./session-todo.review.md](./session-todo.review.md)
- 日付: 2026-05-03