Skip to content

idd-verify 檔案存在性檢查樣板在 zsh 下因 glob no-match 整條 abort,把存在的檔案誤報為缺失 #328

Description

@kiki830621

Problem

Original text:
「Codex 其實已完成(12:37 寫入 19KB — 剛才的 glob 失敗讓 ls 整條 abort 看不到)。讀 Codex verdict,等 4 個 lens agents」
— Source: /idd-all #182 run(PsychQuant/che-ical-mcp,2026-08-31)的 verify phase 現場觀察

idd-verify 執行中,coordinator 用一條命令同時檢查 lens findings glob 與 codex 輸出檔:

ls -la "$VERIFY_DIR"/findings_*.md "$VERIFY_DIR"/codex.md 2>/dev/null

當時 4 個 lens agents 尚未寫檔(findings_*.md 零 match),但 codex.md 已存在(codex-call 已完成並寫入 19KB)。zsh 的預設 nomatch 行為對無 match 的 glob 會讓整條命令 abortno matches found),2>/dev/null 又吞掉了那行錯誤 → 存在的 codex.md 也沒被列出。搭配 pgrep 顯示 codex-call 程序已退出(實為正常完成),coordinator 得到兩個相互印證的假訊號,誤判「codex-call 死亡且沒寫輸出」。

本次靠 launcher 的 task output file 留有 [codex-call] wrote 13723 chars 一行才排除誤判。若沒有這條旁證,這個 false negative 的下游是:把已完成的 Codex lens 當 failure 標進 master report(「cross-model pass incomplete」process gap)、或觸發不必要的 retry — 都是靜默方向的錯。

Type

bug

Root cause 歸屬(skill 文件層)

臨場命令是 executor 寫的,但 idd-verify/SKILL.md 至少兩處樣板性地教這個寫法:

  1. 鐵律段:「必須 ls $VERIFY_DIR/findings_*.md 確認 5 個檔案 + non-empty」
  2. Step 0 bootstrap task wait_for_claude_agents:「4 lens Agent calls return 後 ls $VERIFY_DIR/findings_*.md 確認 4 檔 non-empty」

Claude Code 的 Bash 跑在 zsh;zsh 對 no-match glob 的 abort 行為是這個 plugin 生態已踩過的坑家族(safari-browser 的 unquoted-variable 教訓同源:zsh 與 bash 的字串/glob 語意差異)。glob 檢查在「檔案還沒生出來」的等待場景是常態路徑,不是 edge case — 樣板本身站在 footgun 上。

對照:Step 2.5a 的 bash 範例(EXPECTED_FILES array + [ -s "$f" ] 逐一檢查)是正確寫法 — 問題只在鐵律段與 task 描述的 shorthand 樣板與它不一致。

Expected

  • 檔案存在性檢查在 zsh 下對「部分檔案尚未存在」給出正確的 per-file 結果,不因單一 glob no-match 而讓其他存在的檔案也顯示為缺失。
  • SKILL.md 的鐵律段/task 樣板與 Step 2.5a 的正確寫法一致。

Actual

鐵律段樣板誘導 glob 合併檢查 → zsh nomatch abort → 存在的檔案被誤報為不存在 → 誤導 coordinator 判斷(本例:誤判 Codex 死亡;同構風險:Step 2.5 Recovery Protocol 被 false trigger,浪費一輪 agent spawn 或誤標 process gap)。

修法建議

  1. 鐵律段與 wait_for_claude_agents task 描述改為顯式路徑迴圈(即 Step 2.5a 既有樣板),或至少改寫為 zsh-safe 形式(每個 pattern 分開跑、或 setopt null_glob / ls ... 2>/dev/null || true 並明注「zsh nomatch 防禦」)。
  2. 可考慮在 SKILL.md 的 scratch-file 段(idd-verify 的 /tmp/verify_${NUMBER}_* 檔名跨 session 碰撞 — 不同 repo 的同號 issue 互踩 findings 檔 #288 附近)加一行環境註記:Claude Code Bash = zsh,glob no-match 會 abort 整條命令 — 與 idd-verify 的 /tmp/verify_${NUMBER}_* 檔名跨 session 碰撞 — 不同 repo 的同號 issue 互踩 findings 檔 #288 同屬「檢查樣板的靜默失敗方向」家族。

Impact

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