Skip to content

fix(store): agent prompt の take で所有確認後にのみ削除し他 worktree の prompt 消失を防ぐ#258

Merged
kkyosuke merged 1 commit into
mainfrom
fix/agent-prompt-take-ownership
Jun 21, 2026
Merged

fix(store): agent prompt の take で所有確認後にのみ削除し他 worktree の prompt 消失を防ぐ#258
kkyosuke merged 1 commit into
mainfrom
fix/agent-prompt-take-ownership

Conversation

@kkyosuke

Copy link
Copy Markdown
Owner

目的

agent_prompt_store::take が queued prompt を読み込んだ直後、所有権を確認する前に無条件で fs::remove_file していたため、別 worktree の prompt を黙って消す silent data loss の経路があった。これを塞ぐ。

具体的な失敗モード:

  1. ファイル名は canonical path の 64bit DefaultHasher ハッシュ。ハッシュ衝突で別 worktree のファイルが自分の計算名に居座ると、take はそれを削除してしまう(呼び出し元には None を返すが、本来の所有者の prompt は永久に失われる)。
  2. read → remove は 2 syscall。その間に割り込んだ set が削除される(prompt の取りこぼし)。

変更内容

src/infrastructure/agent_prompt_store.rs のみ変更。

take を「所有確認してから削除」に変更:

  • 自分のものworktree == key): prompt を返し、ファイルを削除(one-shot 配信は維持)。
  • 別 worktree のもの(parseable だが key 不一致): 削除せず None を返し、本来の所有者が take できるよう残す。
  • 壊れた/パース不能なファイル: 誰にも配信できないため削除して None
  • 存在しない: そのまま None

json_file::readOk(Some)/Ok(None)/Errmatch で分岐し、削除するのは「自分のもの」か「パース不能」のときだけにした。モジュール冒頭のドキュメントコメントも実態(衝突ファイルは所有者のために残す)に合わせて更新。

テスト・確認方法

in-file テストで全分岐を網羅:

  • set_then_take_round_trips_and_is_one_shot — 正常な所有者一致パス(prompt 返却・ファイル削除)。
  • a_file_queued_for_another_worktree_reads_as_absent_and_is_preserved — key B で take しても A 所有ファイルは 削除されず残ることを確認(本 PR の主眼)。
  • a_corrupt_file_reads_as_absent_and_is_cleared — パース不能ファイルは None を返し削除される。
  • 既存の distinct_worktrees_queue_independently / set_replaces_a_previously_queued_prompt も維持。

品質ゲート(worktree から実行):

  • cargo fmt — 通過
  • cargo clippy --all-targets -- -D warnings — 通過
  • cargo test — 1402 + 統合テスト全て通過(agent_prompt_store の 7 テスト含む)

🤖 Generated with Claude Code

take はファイルを読み込んだ直後に所有権を確認せず無条件で remove_file して
いたため、ハッシュ衝突や別マシンから同期された stale ファイルが自分の計算名に
存在すると、本来の所有 worktree の queued prompt を黙って削除していた(silent
data loss)。

所有権を確認してから削除するように変更する。

- 自分のもの(worktree == key): prompt を返し、ファイルを削除(one-shot 配信)。
- 別 worktree のもの(parseable だが key 不一致): 削除せず None を返し、
  本来の所有者が take できるよう残す。
- パース不能な壊れたファイル: 誰にも配信できないため削除して None。
- 存在しない: そのまま None。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

📊 Test Coverage

🚀 いまのカバレッジ (Lines): 100.00% — この調子でいこう!

🎉✨ パーフェクト!全ファイル Lines カバレッジ 100% を達成しました 🏆🐰

@kkyosuke kkyosuke merged commit a55181a into main Jun 21, 2026
3 checks passed
@kkyosuke kkyosuke deleted the fix/agent-prompt-take-ownership branch June 21, 2026 06:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant