目的
worktree による並列委譲の隔離保証に穴がある。git stash は worktree をまたいで共有される単一の ref であり、並行して走る別 worktree の未コミット作業を静かに奪う。仕様はこの面を名指していない。
観測事実(2026-08-24、実測。両側から独立に報告された)
evolution-full-run で3本の実装を並列委譲した。うち2本が別々の worktree で同時に走っていた:
両者とも「新しいテストが修正前に落ちること」を確認するため git stash push を使った。結果、git stash pop が相手の作業を返した。#1796 側の pop は #1798 の3ファイルを取り出し、自分の hook 変更は消えていた。#1798 側も対称に同じ事象を報告している。
どちらの実装者も独立に復旧した(patch を退避 → 相手へ返す / 自分の変更を再適用)。最終的に失われたものは無い。親が実測で確認済み:
つまり被害はゼロだが、それは実装者2体がたまたま気づいて復旧したからである。片方が気づかずコミットしていれば、相手の作業は静かに消えていた。
前提
refs/stash は worktree ごとに分かれない。worktree が分離するのは working tree と index であって、stash スタックは共有 .git にある単一の ref である。したがって:
- worktree A の
git stash push と worktree B の git stash push は同じスタックに積まれる
- どちらの
git stash pop も、スタックの先頭が誰のものかを問わずに取り出す
git stash pop は成功する。エラーも警告も出ない。取り出した内容が自分のものかどうかは呼び出し側が確認しない限り分からない
仕様側の穴
adapter/claude/CLAUDE.md / adapter/codex/AGENTS.md の Subagent_Delegation は同一ブランチ並列の制約を次のように述べている:
Multiple subagents sharing one branch share .git/index (staging area).
Parallel commits on the same branch cause staging area conflicts.
Use worktree to isolate.
名指されているのは staging area だけである。worktree がそれを分離するのは正しいが、refs/stash は分離されない。つまり「worktree を使えば並列は安全」という読みが、この一文からは自然に出てしまう。
memory/promotion_tally.md に 2026-08-21 の同種クラスタ(親が委譲中のクローンの working tree を触る)があったが、tally 1 のまま 2026-08-24 に expire している。本件は別 worktree の subagent 同士という別経路であり、そちらの再発ではない。
論点
修理の方向は2つあり、どちらを取るかは未確定。
- 禁止:並列委譲下では
git stash を使わない、と規約で述べる。安全な代替(対象ファイルを scratchpad へコピーして退避し、戻すときはコピーバック)は既に存在し、追加コストはほぼ無い。ただし委譲プロンプト経由の手続きは実行保証が無く、rules/model/subtractive-structural-beauty.md Application notes が「置き換えよ」と言う側に落ちる。実際、本セッションの promotion_tally.md には「委譲プロンプトの指示は守られないことがある」というクラスタが tally 2 で生きている。
- 構造化:
git stash push 相当を各 worktree 内で完結する形に落とす(git worktree ごとの一時ブランチ、あるいは git diff > file + git checkout --)。規約ではなく手順そのものを置き換える。
いずれにせよ、staging area だけを名指している現在の一文は、共有される可変 ref を取りこぼしているという点は共通の所見である。少なくともその一文は修理対象。
変更予定ファイル(方向未確定のため暫定)
adapter/claude/CLAUDE.md / adapter/codex/AGENTS.md —— Subagent_Delegation の同一ブランチ並列制約。共有されるのは index だけではないことを述べる
docs/6.-Adapter.md —— 対応するミラー記述があれば追従
skills/task-subagent-prompt/SKILL.md —— 方向1を取る場合、委譲プロンプトへの注入項目として
目的
worktree による並列委譲の隔離保証に穴がある。
git stashは worktree をまたいで共有される単一の ref であり、並行して走る別 worktree の未コミット作業を静かに奪う。仕様はこの面を名指していない。観測事実(2026-08-24、実測。両側から独立に報告された)
evolution-full-run で3本の実装を並列委譲した。うち2本が別々の worktree で同時に走っていた:
workspace/.worktrees/liplus-language-1796(issue bug(adapter): MEMORY_DIR glob fallback resolves to another workspace's memory dir #1796、adapter/claude/hooks/on-session-start.sh)workspace/.worktrees/liplus-language-1798(issue bug(adapter): webhook handling re-arm is dropped in channel and mcp_hook delivery modes #1798、adapter/*/hooks/on-user-prompt.*)両者とも「新しいテストが修正前に落ちること」を確認するため
git stash pushを使った。結果、git stash popが相手の作業を返した。#1796 側の pop は #1798 の3ファイルを取り出し、自分の hook 変更は消えていた。#1798 側も対称に同じ事象を報告している。どちらの実装者も独立に復旧した(patch を退避 → 相手へ返す / 自分の変更を再適用)。最終的に失われたものは無い。親が実測で確認済み:
adapter/claude/hooks/on-session-start.shを含む)、commit401b721c7d8ac8stash@{0}の3ファイルはc7d8ac8の内容と byte-identical(git hash-objectで照合)であり、コミット済みの重複でしかなかったため親が drop 済みつまり被害はゼロだが、それは実装者2体がたまたま気づいて復旧したからである。片方が気づかずコミットしていれば、相手の作業は静かに消えていた。
前提
refs/stashは worktree ごとに分かれない。worktree が分離するのは working tree と index であって、stash スタックは共有.gitにある単一の ref である。したがって:git stash pushと worktree B のgit stash pushは同じスタックに積まれるgit stash popも、スタックの先頭が誰のものかを問わずに取り出すgit stash popは成功する。エラーも警告も出ない。取り出した内容が自分のものかどうかは呼び出し側が確認しない限り分からない仕様側の穴
adapter/claude/CLAUDE.md/adapter/codex/AGENTS.mdのSubagent_Delegationは同一ブランチ並列の制約を次のように述べている:名指されているのは staging area だけである。worktree がそれを分離するのは正しいが、
refs/stashは分離されない。つまり「worktree を使えば並列は安全」という読みが、この一文からは自然に出てしまう。memory/promotion_tally.mdに 2026-08-21 の同種クラスタ(親が委譲中のクローンの working tree を触る)があったが、tally 1 のまま 2026-08-24 に expire している。本件は別 worktree の subagent 同士という別経路であり、そちらの再発ではない。論点
修理の方向は2つあり、どちらを取るかは未確定。
git stashを使わない、と規約で述べる。安全な代替(対象ファイルを scratchpad へコピーして退避し、戻すときはコピーバック)は既に存在し、追加コストはほぼ無い。ただし委譲プロンプト経由の手続きは実行保証が無く、rules/model/subtractive-structural-beauty.mdApplication notes が「置き換えよ」と言う側に落ちる。実際、本セッションのpromotion_tally.mdには「委譲プロンプトの指示は守られないことがある」というクラスタが tally 2 で生きている。git stash push相当を各 worktree 内で完結する形に落とす(git worktreeごとの一時ブランチ、あるいはgit diff > file+git checkout --)。規約ではなく手順そのものを置き換える。いずれにせよ、staging area だけを名指している現在の一文は、共有される可変 ref を取りこぼしているという点は共通の所見である。少なくともその一文は修理対象。
変更予定ファイル(方向未確定のため暫定)
adapter/claude/CLAUDE.md/adapter/codex/AGENTS.md——Subagent_Delegationの同一ブランチ並列制約。共有されるのは index だけではないことを述べるdocs/6.-Adapter.md—— 対応するミラー記述があれば追従skills/task-subagent-prompt/SKILL.md—— 方向1を取る場合、委譲プロンプトへの注入項目として