## 何を見つけたか 承認ゲート 1 の後に設計 PR をマージするプラン(`supervise.py new sprint` が書く `design-merge-<N>`)は、PR がベースブランチと衝突した(`mergeStateStatus=DIRTY`、`merge` の終了コード 4)ときに取り込みへ戻らず、そのまま止まる。 スプリント m1426(2026-10-30〜31)で、並行に出した設計 PR 4 本(#2211・#2212・#2213・#2214)が用語集(`docs/glossary/glossary.json`・`docs/glossary.md`)へ語を足し合い、先にマージされた PR との衝突で #2212 のマージが止まった。 - `1-design-1455-state/02-merge.out`: `{"status": "stopped", "summary": "#2212 はベースブランチと衝突している(mergeStateStatus=DIRTY)", "next": "ベースブランチを取り込んで push してから打ち直す"}` - conductor が手で取り込みと用語集の衝突の解消を 2 回行い、マージのプランを打ち直した(`merge-1455.log`・`merge2-1455.log` は `merge(exit=4) → handoff(exit=10)`、`merge3-1455.log` で完了) 用語集の語の追加どうしの衝突は `merged_lib/base_sync.py` が `glossary.py merge` で解けるが(#1913)、設計 PR のマージのプランには取り込みのステップが無い。 ## どこで見つけたか - `plugins/ndf/scripts/supervise_lib/design_merge.py:50` — `*merge_steps(a, next="end")`。`on_conflict` を渡していない - `plugins/ndf/scripts/supervise_lib/sprint_waves.py:427` — `*merge_steps(a, next="end", on_fail="handoff")`。同じく `on_conflict` が無い - 比較: 検査のプランは `templates.py:182`・`templates.py:332` で `on_conflict="base-return"` を渡し、衝突したら取り込みへ戻る(#1917) - 記録: スプリント m1426 の振り返り(PR #2247 の配布を記録した PR #2266) ## なぜこの変更の範囲外なのか #1426 の受け入れ条件 1〜4 は「設計 PR のマージをキューのステージとして流す」ことで、マージが衝突したときの戻り先は条件に無い。#1913 は用語集の衝突を解く副命令と `base-sync` を足したが、設計 PR のマージのプランから呼ぶことは範囲外だった(#1913 の起票者の推定 S6「#1912 と #1917 がこれを呼ぶ」)。根拠: 共通原則の「判断の範囲は目の前の変更・操作に限る」(MVV 版 3)。 ## 直さないと何が起きるか 並行の設計 PR が用語集へ語を足す普通のスプリントで、承認ゲート 1 の後のキュー 1 本が止まり、conductor が手で取り込み・衝突の解消・打ち直しを行う。#1426 が目指した「承認ゲート 1 の後はキュー 1 回と待ち 1 回」が、設計 PR が 2 本以上あるスプリントで崩れる。 ## 起票者の推定 - 直し方は、設計 PR のマージのプランにも `on_conflict` で取り込み(`base-sync`)へ戻るステップを足す形がよい(推した出所: `templates.py:182` の検査のプランの前例) - 衝突が用語集以外に及ぶときは今どおり止まってよい(推した出所: #1913 の受け入れ条件「語の追加どうし以外の衝突は止まる」) ## 由来 PR #2247
Activity