docs(tickets): 追加:タスクリストの表示とコンテキスト長インジケータ

This commit is contained in:
Keisuke Hirata 2026-05-04 15:32:40 +09:00
parent c57d4be413
commit 7527b55de4
3 changed files with 129 additions and 0 deletions

View File

@ -15,6 +15,8 @@
- ユーザーマニフェストのモデル設定 wizard → [tickets/tui-user-model-setup.md](tickets/tui-user-model-setup.md)
- spawn 失敗時に Pod の stderr が TUI に表示されない → [tickets/tui-spawn-error-surface.md](tickets/tui-spawn-error-surface.md)
- 巻き戻されたターンの入力テキストを編集領域に復元 → [tickets/tui-empty-turn-restore.md](tickets/tui-empty-turn-restore.md)
- セッションコンテキスト長 / ウィンドウ占有率の常時表示 → [tickets/tui-context-usage-indicator.md](tickets/tui-context-usage-indicator.md)
- Task ストア状態の表示(入力欄上ミニビュー + サイドペイン) → [tickets/tui-task-display.md](tickets/tui-task-display.md)
- Manifest: Tool Output / File Upload 上限の分離とデフォルト緩和 → [tickets/manifest-output-upload-limits.md](tickets/manifest-output-upload-limits.md)
- メモリ機構
- 使用頻度メトリクス + Knowledge 化候補レポート → [tickets/memory-usage-metrics.md](tickets/memory-usage-metrics.md)

View File

@ -0,0 +1,50 @@
# TUI: セッションコンテキスト長 / ウィンドウ占有率の常時表示
## 背景
TUI の status line は現状、Run 単位の `↑net upload / ↓output` トークンしか出していない(`crates/tui/src/app.rs:55-61`、`crates/tui/src/ui.rs:850-895`)。これは「このターンで実際に課金される転送量」を示すには適切だが、「今このセッションがコンテキストウィンドウのどこにいるか」をユーザーが把握する手段がない。
Pod は `Event::Usage` で LLM 1 リクエスト分の `input_tokens`cache 込みの prompt prefix 占有量)を毎回送ってきており(`crates/protocol/src/lib.rs:301-306`、最新値がそのまま「現在のセッションコンテキスト長」になる。受信はしているが、TUI は cache 控除して run 集計に積むだけで保持していない。
ユーザーは compaction やプロンプト重複の発生を体感するために、コンテキスト消費を常に視認したい。
## 方針
3 段階の最小拡張で済ませる:
1. **TUI**: `Event::Usage::input_tokens`cache 控除しない素の値の最新値をセッション状態として持ち、status line に常時表示する。`Event::CompactDone` でリセット。
2. **Protocol**: `Greeting``context_window: u64``context_tokens: u64` を追加。前者はモデルのウィンドウ上限、後者は attach 時点の `Pod::total_tokens()` 推定値(次の Usage 到着まで TUI に表示できる初期値)。
3. **Manifest / Pod**: モデルのコンテキストウィンドウは provider catalog のモデルメタに常設の値として持たせ、必要なら manifest 側で override できる経路を 1 つ用意する。配置catalog エントリの新フィールド or `ModelCapability` 拡張 or `[worker] context_window`は実装着手時に確定。Greeting 構築時には必ず具体値が入る。
`Event::Usage` 自体は既存の wire を踏襲する。新イベントを足さない。
## 要件
- Run 中・Idle 中・Paused 中いずれでも status line に `ctx: <tokens> / <window> (<pct>%)` を表示する。
- セッション初期値: `Event::History``context_tokens` を採用。最初の `Event::Usage` 受信で上書き。
- 更新トリガ:
- `Event::Usage::input_tokens` 受信ごとに最新値で上書きcache 控除しない素の値)。
- `Event::CompactDone` で 0 にリセット(次の Usage で上書き)。`Event::CompactStart` / `Event::CompactFailed` ではリセットしない。
- `Event::TurnStart` / `RunEnd` ではリセットしないrun 集計とは別のセッション単位指標)。
- 既存の run 集計(`request: N | ↑x/↓y | tool: ...`)は残す。`ctx:` は別フィールドとして併置する。
## 完了条件
- TUI 起動から終了まで、status line にコンテキスト消費とウィンドウ占有率が常時出ている。
- compact が走った直後、`ctx:` が一旦 0 に戻り、次のリクエストでセッション開始サイズが入る挙動が見える。
- カタログ未掲載モデルを inline で指定した場合でも、manifest 側 override で値を入れれば同じ表示になる。
## 範囲外
- 履歴ビュー側でのターンごとコンテキスト推移グラフ。
- 課金額USD換算表示。
- compact 閾値 / `compact_request_threshold` との対比可視化threshold バー等)。本チケットは現値の表示までで、警告色の閾値運用は別チケット。
- pod_cli 等他クライアントの同等表示TUI 限定)。
## 影響範囲
- `crates/protocol/src/lib.rs`: `Greeting``context_window: u64` / `context_tokens: u64` 追加。
- `crates/manifest` / `crates/provider/src/catalog.rs`: context window をモデルメタとして宣言する経路。実装着手時に置き場所を確定。
- `crates/pod/src/controller.rs`: `build_greeting` で window と `total_tokens()` を Greeting に詰める。
- `crates/tui/src/app.rs`: `App``session_context_tokens: u64``context_window: u64` を持たせ、`handle_pod_event` で更新。
- `crates/tui/src/ui.rs`: `draw_status``ctx:` フィールドを追加。

View File

@ -0,0 +1,77 @@
# TUI に Task ストア状態を表示する
## 背景
`tickets/session-todo.md` で導入した `tools::TaskStore``TaskCreate / List / Get / Update` ツール群は Pod 側に実装済みで、compaction や resume を跨ぐ永続化も整っている。一方で TUI 側にはまだ表示パスが無く、LLM が Task を作成・更新しても、ユーザーは tool_call ブロックを目で追う以外に状態を把握できない。
`tickets/session-todo-reminder.md` は LLM 側のナッジ(`<system-reminder>` 注入に専念しており、UI 側からのフィードバックループはスコープ外。Task ツール群を「ユーザーから見える進捗ステータス」として機能させるためには、TUI に常時見える表示が要る。
## 前提
- `TaskStore` / `TaskSnapshot` / `TaskEntry` / `TaskStatus` および `TaskStore::from_history``tools` クレートに公開済み
- `TaskStore::from_history``TaskCreate` / `TaskUpdate` の tool_call 引数と、compact 時に挿入される `[Session TaskStore snapshot]` system message から決定的に状態を再構成する
- TUI は protocol 経由で tool_call の `name` と最終 `arguments` を受信済み(`ToolCallBlock { name, arguments }`。system message も `Block::SystemMessage` として観測している
- TUI のレイアウトは `crates/tui/src/ui.rs``history / separator / status / input` を縦に積む構成
## 方針
- **TaskStore は TUI 側で再構成する**。Pod から専用 Event を push せず、すでに TUI に届いている tool_call と system message から `TaskStore::from_history` 相当のロジックを回す
- protocol 表面を増やさない、Pod 側の push 経路も増やさない
- resume / 再接続時はサーバから来る history replay 経路に乗っかれば自動で復元される
- 単一情報源historyに揃うため、Pod と TUI で snapshot がズレない
- TUI 上の表示は 2 ヶ所
- **入力欄直上のミニビュー3〜4 行)**: 常時表示。active`pending` + `inprogress`)優先で最大 2〜3 件を `状態マーク + subject` 1 行ずつ、加えて件数サマリ 1 行
- **サイドペイン(全件)**: トグルキーで右側に開閉。`pending` / `inprogress` / `completed` / `deleted` を区別して全件列挙、`description` も含める
- `tools` クレートに依存させる(または replay 部分のみを薄いヘルパとして切り出して共有する。LLM コンテキスト加工原則との整合は自明history の純粋な再現変換であり context への割り込みではない)
## 要件
### TUI 側の TaskStore 取り回し
- `App` に最新 `TaskStore`(または `TaskSnapshot`)を保持するフィールドを追加する
- 受信パスで以下を観測して TaskStore に反映する
- `ToolCall` 完了時、`name == "TaskCreate"` / `"TaskUpdate"` なら `arguments``TaskStore::from_history` と同じパースで適用
- `SystemMessage` 観測時、本文が `[Session TaskStore snapshot]` で始まるなら `parse_compact_snapshot_text` 相当で snapshot に置き換え
- 初回 history replay の際も同じ経路を通せば、TUI 起動時点の状態が自動的に復元される
- 部分的引数streaming 中は適用しない。tool_call が完了して `arguments` が確定したタイミングだけ反映する
### TUI ミニビュー
- 入力欄の直上に固定で 3〜4 行の領域を確保
- active`pending` + `inprogress`)を優先して最大 2〜3 件、`状態マーク + subject` を 1 行ずつ表示。`subject` が改行を含む場合は先頭行のみ
- 件数サマリ 1 行(`pending` / `inprogress` / `completed` / `deleted` の内訳)
- active 0 件のときの見せ方は実装時に決める(サマリ行のみ残すか、領域ごと畳むか)
### TUI サイドペイン
- トグルキーで右側に開閉する横分割レイアウト(割当キーは実装時に決める)
- 開いている間は全件を表示。各エントリは `taskid` / `status` / `subject` / `description` を含める
- スクロール対応(タスク数が画面高を超えてもよい)
### レイアウトと一貫性
- ミニビューとサイドペインは同じ最新 TaskStore を見る(表示間でズレないこと)
- 既存の history / status / input の幅・高さ計算が壊れないこと
- completion popup`@` / `#` / `/`)と表示位置が干渉しないこと
## 完了条件
- LLM が `TaskCreate` / `TaskUpdate` を呼ぶと、TUI が tool_call 完了タイミングで状態を反映し、ミニビューに即時反映される
- トグルキーでサイドペインが開閉し、`completed` / `deleted` を含む全件が確認できる
- resume / 再接続時、history replay 経路から TaskStore が自動復元され、ミニビューとサイドペインに反映される
- compact 後の history末尾に snapshot system messageでも、それを起点に正しく再構成される
- ミニビュー / サイドペインの導入で既存レイアウトhistory / status / input、completion popupが崩れない
## 範囲外
- protocol への新規 Event 追加。本チケットでは行わない(必要が出たら別途検討)
- TUI からの Task 編集(追加・更新・削除)。表示専用、編集経路は LLM ツール経由のみ
- 表示密度モードDetail / Normal / Overviewへの連動。ミニビューは常時、サイドペインはトグル制
- LLM 側のナッジ(`tickets/session-todo-reminder.md` で別途実装)
- サイドエージェント / sidechain の TaskStore 表示main Pod の TaskStore のみ対象)
## 参照
- 実装: `crates/tools/src/task.rs``TaskStore::from_history` / `parse_compact_snapshot_text` / `TaskStatus` / `TaskEntry`)、`crates/tui/src/ui.rs`、`crates/tui/src/block.rs``ToolCallBlock` / `SystemMessage`
- 設計指針: `AGENTS.md`「LLM コンテキストの加工原則」history からの決定的再構成は許容変換)
- 関連チケット: `tickets/session-todo.md`Task ツール本体)、`tickets/session-todo-reminder.md`LLM 側ナッジ)