概要
PR がマージ済みでも、Issue の GitHub close 状態 と Project の Close ステータス が一致しないケースがある。
非デフォルト base 宛て PR(EPIC サブ)や EPIC 本体で顕在化する。#738 / #839 / #840 で実際に発生し、手動で整合させた。
観測した不整合(2 方向)
ケース
GitHub issue
Project Status
原因
A. leaf が epic ブランチに merge (#839 /#840 、PR が topic/koshien-epic-738 宛て)
OPEN のまま
Close
applyMergeProgression は Project フィールドを書くだけで GitHub issue を close しない 。非デフォルト base なので GitHub の Closes #N 自動 close も効かない
B. EPIC の統合 PR が develop に merge (#738 、PR #761 が topic/koshien-epic-738→develop)
CLOSED(Closes #738 で自動 close)
Review のまま
selectMergeCandidates が EPIC を除外 するため、EPIC の Project ステータスが merge 後に更新されない
修正方針(tools/autopilot/、.claude/ 非依存 = autopilot 実装可)
Fix A: merge-progression が GitHub issue も close する
daemon.js の applyMergeProgression で、leaf を Close へ前進させたら GitHub issue も close する
(project.closeIssue(repo, issue, token) 新設 = gh issue close。既に閉じていれば no-op で冪等)。
これで非デフォルト base 宛て PR でも issue が確実に閉じる。
Fix B: 「closed issue → Project Status=Close」の整合パス
tick に整合パスを追加(純粋判定 + I/O 分離):
閉じている issue 番号集合を取得(gh issue list --repo <repo> --state closed --limit 1000 --json number。
※ gh project item-list の content には state が無い)。
純粋関数 selectClosedToReconcile(items, closedSet): issue が closed かつ Project Status が Close/終端でない item を返す。
それらに Status=Close + AI Status クリアを適用(EPIC も対象に含める)。実行中(running)の item は触らない。
これで EPIC(feat: スモウルビー甲子園 拡張機能の本格対応(ブロック挙動 + 実サーバー通信)[Epic] #738 型)や、人手で閉じた issue も Project が Close に揃う。
両 Fix で「GitHub issue 状態 ⇄ Project Close」が双方向に整合する。
受け入れ条件
参考(手動で整合させた実例)
概要
PR がマージ済みでも、Issue の GitHub close 状態と Project の Close ステータスが一致しないケースがある。
非デフォルト base 宛て PR(EPIC サブ)や EPIC 本体で顕在化する。#738 / #839 / #840 で実際に発生し、手動で整合させた。
観測した不整合(2 方向)
topic/koshien-epic-738宛て)applyMergeProgressionは Project フィールドを書くだけで GitHub issue を close しない。非デフォルト base なので GitHub のCloses #N自動 close も効かないtopic/koshien-epic-738→develop)Closes #738で自動 close)selectMergeCandidatesが EPIC を除外するため、EPIC の Project ステータスが merge 後に更新されない修正方針(
tools/autopilot/、.claude/非依存 = autopilot 実装可)Fix A: merge-progression が GitHub issue も close する
daemon.jsのapplyMergeProgressionで、leaf を Close へ前進させたら GitHub issue も close する(
project.closeIssue(repo, issue, token)新設 =gh issue close。既に閉じていれば no-op で冪等)。これで非デフォルト base 宛て PR でも issue が確実に閉じる。
Fix B: 「closed issue → Project Status=Close」の整合パス
tick に整合パスを追加(純粋判定 + I/O 分離):
gh issue list --repo <repo> --state closed --limit 1000 --json number。※
gh project item-listの content には state が無い)。selectClosedToReconcile(items, closedSet): issue が closed かつ Project Status が Close/終端でない item を返す。これで EPIC(feat: スモウルビー甲子園 拡張機能の本格対応(ブロック挙動 + 実サーバー通信)[Epic] #738 型)や、人手で閉じた issue も Project が Close に揃う。
両 Fix で「GitHub issue 状態 ⇄ Project Close」が双方向に整合する。
受け入れ条件
selectClosedToReconcileの node:test を追加(cd tools/autopilot && node --test緑)参考(手動で整合させた実例)