Problem
scripts/lib/assert-helpers.sh 的 assert_true(eval 家族)對「含任意捕捉輸出」的 assertion 有隱性陷阱:被測 script 的輸出若含字面 $VAR(如 process-attachments.sh 的提示訊息印出 $CLAUDE_PLUGIN_ROOT/scripts/...),把輸出插值進 eval 字串後,eval 會重展開該變數 — 在 set -u 的 test runner 下直接炸 unbound variable → assertion 誤判 FAIL(false negative on the assertion itself)。
實際發生:#186 TDD 期間,fixture f4b 用 assert_true "..." "printf '%s' \"$OUT\" | grep -q '...'",$OUT 含 script 印的字面 $CLAUDE_PLUGIN_ROOT → eval 炸 → 花一輪 debug 才定位(test.sh 最終改用 file + require 直接執行家族避開)。
Type
enhancement(test-infra hardening / docs)
Expected
assert-helpers.sh header 對 eval 家族(assert_true)標明禁忌:「不要把捕捉的任意輸出插值進 eval 字串 — 用 file + require grep -q ... file 或 assert_grep」。可選:加一個 assert_output_grep <name> <needle> <file> convenience helper 把安全形式變 first-class。
Actual
header 只記載兩個 assertion 家族的存在理由(#156)與 -- end-of-options 紀律(#154/#160),沒有 eval-content 警告;下一個寫 runner 的人會再踩一次。
Refs
#186(觸發現場:scripts/tests/process-attachments/test.sh f4b 的修正 commit 989e117 內含 NB 註解);#154/#160(同屬 test-harness quoting/escaping class)
Source: surfaced during /idd-implement #186 reproduction (Step 5.7)
Problem
scripts/lib/assert-helpers.sh的assert_true(eval 家族)對「含任意捕捉輸出」的 assertion 有隱性陷阱:被測 script 的輸出若含字面$VAR(如 process-attachments.sh 的提示訊息印出$CLAUDE_PLUGIN_ROOT/scripts/...),把輸出插值進 eval 字串後,eval 會重展開該變數 — 在set -u的 test runner 下直接炸 unbound variable → assertion 誤判 FAIL(false negative on the assertion itself)。實際發生:#186 TDD 期間,fixture f4b 用
assert_true "..." "printf '%s' \"$OUT\" | grep -q '...'",$OUT含 script 印的字面$CLAUDE_PLUGIN_ROOT→ eval 炸 → 花一輪 debug 才定位(test.sh 最終改用 file +require直接執行家族避開)。Type
enhancement(test-infra hardening / docs)
Expected
assert-helpers.sh header 對 eval 家族(
assert_true)標明禁忌:「不要把捕捉的任意輸出插值進 eval 字串 — 用 file +require grep -q ... file或assert_grep」。可選:加一個assert_output_grep <name> <needle> <file>convenience helper 把安全形式變 first-class。Actual
header 只記載兩個 assertion 家族的存在理由(#156)與
--end-of-options 紀律(#154/#160),沒有 eval-content 警告;下一個寫 runner 的人會再踩一次。Refs
#186(觸發現場:scripts/tests/process-attachments/test.sh f4b 的修正 commit 989e117 內含 NB 註解);#154/#160(同屬 test-harness quoting/escaping class)
Source: surfaced during /idd-implement #186 reproduction (Step 5.7)