yoi/tickets/pod-comm-tools.review.md
2026-04-19 06:32:44 +09:00

5.3 KiB
Raw Blame History

Review: pod-comm-tools

実装コミット前レビュー。cargo build -p pod clean、cargo test -p pod --test pod_comm_tools_test 8/8 pass。

総評

チケット要件の中核4 ツールの wire 動作、SpawnedPodRegistry の共有、scope 回収、stale reclaim トリガー)は達成。テスト構成もモックソケットで実 pod バイナリ非依存で速い。ただし以下のうち修正必須項目を解消してから完了にしたい。

指摘と判断

修正必須

1. SendToPod が RUNNING 状態を検知しない(設計合意違反)

状況: connect_and_sendMethod::Run を書いて即切断し、応答 event を読まない。Controller は RUNNING 中の Run に対し Event::Error { code: AlreadyRunning } を返すが、tool 側はそれを見ないので LLM に「送信成功」と返る。

設計合意: pod-comm-tools 議論の結論は「A. SendToPod は Method::Run を使い、Pod が IDLE でなければエラーを返す」。

判断: 修正必要。書き込み後に short timeout で 1 event 読み、Error { AlreadyRunning } を検知したら ToolError::ExecutionFailed に変換する。正常時は TurnStart など先頭 event を見て「受け付けられた」ことを確認して戻る。

チケット文言と実装の整合

2. Pod status (running / idle / stopped) の取得手段がない

状況: チケットは ReadPodOutput/ListPods 出力に running / idle / stopped を含めることを求めているが、Event::History にはステータスが乗っておらず、実装は「接続可=alive / 接続不可=stopped」の 2 値のみ。

判断: 今回のスコープからは外す。Greeting または別 event に PodStatus を載せる改修は Method::GetHistory のレスポンス設計変更を伴うので、別チケット化する。本チケット文言を alive / stopped に揃えて実装と一致させる。

3. StopPod は終了確認を待たない

状況: チケット本文は「Method::Shutdown 送信 → 終了確認受信 → 切断」だが、実装は fire-and-forget。scope の明示 release と scope_lock 上の stale reclaim で整合性は担保されているので実害なし。

判断: チケット文言を「Method::Shutdown 送信(応答は待たない)」に修正。

範囲外として明文化

4. spawned_pods.json からの再起動復旧は未実装

状況: spawned_pod_registry.rs のモジュールコメントに「today only write-through is implemented」と明記されている。spawner プロセス再起動後、ListPods は空リストを返す。

判断: 今回のスコープ外。チケットの範囲外に「spawner 再起動時の spawned_pods.json からの復旧」を明記し、必要になったタイミングで別チケットを切る。

5. ReadPodOutput cursor の非永続性

状況: SpawnedPodRegistry::cursorsHashMap<String, usize> でインメモリのみ。spawner 再起動後、カーソルは 0 にリセットされ、既読だった assistant text が再送される。モジュールコメントに「cursors intentionally do not persist」と明記されている。

判断: 現状のままで OK。設計判断としてレビューで合意し、チケットの「設計で決めること」の回答として本 review に残す。チケット側には残さないgitで追える

軽微

6. extract_assistant_text のメッセージ境界

状況: 複数の assistant message を \n で連結するのみ。メッセージ境界が曖昧になる。

判断: \n\n に変更して境界を明確にする。修正コスト小。

7. blocking flock を async から呼んでいる

状況: release_scope / stale reclaim 経路で LockFileGuard::open(内部で flock(2))を async fn から直接呼ぶ。通常は瞬時だが厳密には tokio runtime を一瞬止める。

判断: 既存コード全体が同じ慣習なので今回は踏襲。気になったら別タイミングで spawn_blocking 化を検討。本チケットでは対応しない。

8. SpawnedPodRegistry::newArc<Self> を返す

状況: コンストラクタが smart pointer を返す API は珍しい。

判断: consumer が全員 Arc で持つ設計なので許容。リファクタは不要。

完了条件との対応

完了条件 状態
SendToPod で spawned Pod にメッセージ送信・Pod が処理 (指摘 #1 の修正後)
ReadPodOutput でカーソルベース差分取得
StopPod で graceful 停止 + scope 返却
ListPods で既知 Pod の状態一覧 + health check ⚠️ alive/stopped のみ(指摘 #2
接続不可 Pod は stopped 扱い + stale 回収トリガー
各ツール正常系・異常系の単体テスト 8/8 pass

完了に向けた作業

  1. 指摘 #1: SendToPod に応答確認を実装
  2. 指摘 #2, #3: チケット本文の文言修正(running/idle/stoppedalive/stopped、Shutdown 応答待ちの記述削除)
  3. 指摘 #4: チケットの「範囲外」に spawned_pods.json 復旧を追記
  4. 指摘 #6: extract_assistant_text の区切りを \n\n