Skip to content

idd-close Step 1.55 branch resolution 誤匹配 — in:body "#N" 非精確比對,且未檢查 PR 早於 issue #305

Description

@kiki830621

Problem

idd-close Step 1.55(merge-completeness gate)解析 issue 的 feature branch 時用:

BRANCH_REF=$(gh pr list --repo "$GITHUB_REPO" --state merged \
    --search "in:body \"#${NUMBER}\"" --json headRefOid -q '.[0].headRefOid')

in:body "#N" 不是精確比對。GitHub 的 search 會做 tokenize,"#10" 命中了一個 body 內根本沒有 #10 的 PR。

Type

bug

Actual

實測於 PsychQuant/perspective-writer,close issue #10 時:

搜尋 gh pr list --state merged --search 'in:body "#10"'
命中 PR #2feat: EXTERNAL-CONSUMER CONTRACT — programmatic calibration…),headRefOid d1c6dfe2
PR #2 body 內實際出現的 issue ref #1#7#20#269#272 —— 沒有 #10
時序 PR #2 merged 2026-08-02;issue #10 created 2026-08-10

於是 gate 拿到一個比 issue 早 8 天合併的無關 PR 的 branch SHA,準備對它跑 check-merge-completeness.sh#10 走的是 direct-commit path、根本沒有 feature branch,正確行為應該是印那行 no merged PR / feature branch → direct-commit path 的 skip note。

實際後果有限(gate 是 warn-only,最壞是產生一則假 orphan 警告),但它污染的正是 gate 用來判斷的輸入,而使用者看到 orphan 警告時無從分辨真假。

Expected

Branch resolution 至少要排除結構上不可能的候選。兩道都便宜:

  1. 時序守衛(強烈建議) —— PR 的 mergedAt 早於 issue 的 createdAt不可能是該 issue 的 branch,直接排除。一次 gh issue view --json createdAt 即可,且完全不依賴 search 的精確度
  2. 精確 ref 比對 —— 取回候選 PR 的 body 後,用 grep -E "#${NUMBER}\b" 二次過濾(word-boundary),濾掉 #100#1 這類 tokenize 假命中

兩道並用可涵蓋不同失效:(1) 擋掉時序不可能者(本案例),(2) 擋掉同期但編號相近的誤命中。

Impact

  • 檔案skills/idd-close/SKILL.md Step 1.55 的 branch resolution 區塊
  • 影響對象:所有走 /idd-close 且 repo 內有 merged PR 的 issue。direct-commit path 的 issue 最容易中招 —— 它們應該走 skip note,卻可能被塞一個無關 branch
  • 嚴重度:低(warn-only gate,不硬擋 close),但錯誤方向是製造假訊號。一個會誤報的 gate,人會學會忽略它 —— 那等於沒有 gate。這正是 Step 1.55 自己的註解在講的事:「a checker whose output makes a passing check look like a skipped one is a checker people stop trusting」

附帶觀察

Step 1.55 的設計已經很小心處理過一個相關陷阱(#184 DA-1:用 headRefOid 而非 branch name,因為 GitHub merge 後會刪 branch)。時序守衛是同一類的「便宜且方向永遠正確」的加固 —— 建議一併補上。


Source: surfaced while running /idd-close #10 on PsychQuant/perspective-writer(2026-08-13);判定為 mis-detection 後跳過,已記入該 issue 的 closing summary ### Merge-completeness

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions