BridgeCraft logobridgecraft
週報作品集關於聯絡登入
聯絡

bridgecraft

從資料視覺化到 AI Agent,一直在找下一個 meta

文章主題指南週報Labs作品集系統架構關於聯絡RSS

© 2026 BridgeCraft — Waiting7777. All rights reserved.

← 所有文章

Test-driven 是錯的 — 為什麼我的 QA Agent 看 spec 不看 test

2026年10月20日 · Waiting7777 · 6 分鐘閱讀

AI Agents自動化測試Claude
📂 AI Agents 系列📂 自動化測試 系列📂 Claude 系列

這是 QA Pipeline 系列的第 2 篇。前一篇 〈15 個 Agent 跑兩週的全景〉 把整條 pipeline 的結構畫出來了。這一篇要回答一個更根本的問題:agent 在比對什麼 vs 什麼?

業界絕大多數「自動修 bug 的 agent demo」答案是:test 跑失敗 → LLM 讀 test 錯誤 → 改 code 讓 test 過。這條路在 demo 影片裡很漂亮、在 production 會出大事。

一個「修成功了但其實修錯了」的案例

我們的 E2E 裡有一個 test 大概長這樣:

test("shows inline error when analytics endpoint returns 429", async ({ page }) => {
  await page.locator("text=分析").or(page.locator("text=Analytics")).click()
  await expect(page.getByRole("alert")).toBeVisible()
})

這個 test 一開始紅了。錯誤訊息是 Playwright 的 strict mode violation — .or() locator 解析出兩個 element,而不是一個。

傳統 agent 的反應:

「哦 strict mode 不讓你這樣寫。改成 .or().first()、或者 wrap 一層、或者關掉 strict mode。」

改完 test 過了、PR 開了、merge 了。

但原本的 test 意圖是測 429 rate limit 的 UI,而改法繞過了 strict mode、根本沒測到 429。這個 test 從「紅」變成「綠但沒效」。line coverage 還是滿分。

這是我們最早踩過的坑,Linear AUT-1。當時的 closed_reason 留了一句:「Promise.race replaces .or() chain — PR #52 was wrong approach」— PR #52 就是那個「把 test 改綠但沒測到東西」的錯誤 fix。後來重做是因為比對到 spec 才發現 test 改法跟 requirement 脫節。

test 也會說謊,但 spec 不會

這不是 agent 笨、是把 test 當 SSOT 的設計本身就有 bug。test 是人寫的、人會寫錯、人會為了讓 CI 綠而妥協。讓 LLM 讀 test 修 code,等於讓它把一個可能錯的假設當成真理。

所以我做了另一個選擇:SSOT 是 spec,不是 test。

三方比對:spec × source × test

qa-planner 每次 session 讀三樣東西:

  1. Spec(docs/superpowers/specs/routes/、docs/superpowers/plans/、docs/plans/)— 真相
  2. Source code(src/**)— 實際行為
  3. Test(e2e/**、src/**/__tests__/**)— 驗證層

然後把三方不一致的情況分成 6 類:

三方狀態分類fixer 動作
spec ≠ source,test 跟 source 一致code-bug改 source
spec ≠ test,source 跟 spec 一致test-bug改 test
spec 有、source 有、test 沒有coverage-gapexplorer/fixer 寫新 test
spec 有要求、source 有實現、test 過但不穩flakyfixer 找 root cause
source 跟 spec 有歧異、可能是效能退化perf-regression不修,丟回人
spec 本身不清楚needs-spec-review不修,丟回人

最後兩類最重要。當 spec 不清楚、agent 直接停手。這是整個系統穩定的基石。

過去兩週 53 個真實 bug 裡:

  • code-bug 12 個(23%)— 改 source
  • test-bug 6 個(11%)— 改 test
  • coverage-gap 27 個(51%)— 補 test
  • flaky 3 個(6%)— 修穩定性
  • needs-spec-review 5 個(9%)— 完全沒碰 code

那 5 個 needs-spec-review 就是「agent 判斷:我不確定 spec 要什麼,這個我不處理」的安全出口。這一層沒有、agent 就會開始瞎猜、然後把「猜錯的東西」寫進 PR。

實際的 qa-fixer 分類決策

這段直接是 .claude/agents/qa-fixer.md 的原文(經過少許格式整理):

## Scope

| Issue Type    | What You Fix                        | Where                |
|---------------|-------------------------------------|----------------------|
| code-bug      | Source code to match spec           | src/**               |
| test-bug      | Test code to match spec             | e2e/**, src/**/__tests__/** |
| coverage-gap  | Write new tests for untested spec   | e2e/**, src/**/__tests__/** |
| flaky         | Root cause in code OR test          | src/** or e2e/**     |

**Do NOT fix:** `perf-regression` or `needs-spec-review`
— these require human judgment.

注意最後一行。fixer 拿到 needs-spec-review issue 會直接跳過、把它 re-assign 成 "Awaiting Human Review" 留給人。這不是 fallback、是 primary safety property。

一個 needs-spec-review 真實案例

兩週資料裡最新的一筆是 AUT-61:api-types::verify-code-type-vs-usage-type。

前因:qa-analyzer 在跑 AUT-60 的時候發現,某個 API 的 TypeScript 型別裡有個 field 叫 type,但另一個呼叫方用的是 usage_type。兩邊各自 work、但互相牴觸。這是 code-bug 還是 spec-bug?analyzer 不知道。

如果是傳統 agent:LLM 會挑一邊改、寫 migration、發 PR、可能動到生產資料流。

我們的 agent 判斷:這不是 agent 該做的決策。Linear 新 issue 狀態直接 set 成 Awaiting Human Review、打 needs-spec-review + needs-human-review label、不開 PR。

隔天早上我 15 秒看完 Linear 知道要跟後端確認型別對應、找 PM 問業務語意、最後決定保留兩個欄位、寫 spec 補充。這個決策流程是對的,agent 的角色是把這件事推上人類的桌子、不是自己亂動。

有人會問:讓 LLM 生 spec 不行嗎

不行。理由是:

Spec 是需求,不是程式碼。需求來自產品、法規、使用者研究,LLM 沒有這些 context。讓 LLM 生 spec 等於讓它自己出題自己改 — 你會得到一個完全自洽但跟市場脫節的系統。

我的 pipeline 不自動產 spec。spec 只有人寫、agent 只比對。這個職責分界不能鬆。

Spec 放哪裡 — 最低成本的做法

很多團隊 spec 散落在 Notion、Figma、Slack、PM 腦袋裡。agent 讀不到、人讀一讀也記不住。

我做的事簡單:spec 寫成 markdown、丟進 repo。具體路徑:

  • docs/superpowers/specs/routes/ — 按 route 整理的結構化 spec(acceptance criteria、邊界條件、錯誤 UI)
  • docs/superpowers/plans/ — SDD(Software Design Document)級別的模組設計
  • docs/plans/ — 功能級別的 plan 文件

每個 qa-planner prompt 裡這三個路徑是 hardcoded 的。planner 開場第一步就是 Glob 這三個目錄撈所有 .md。

這個決定有幾個副作用比原本 spec 文件化本身更有價值:

  • Spec review 跟 code review 一起做 — PR 改到 spec 的 requirement,reviewer 馬上看到
  • Spec diff 可追溯 — 什麼時候加的需求、git blame 查得到
  • PM 也 commit 進 repo — 業務邏輯變更有 PR trail

反對意見清單

幾個我被問過的質疑:

「如果 spec 本身就錯呢?」 這就是 needs-spec-review 存在的原因。agent 偵測到 spec 矛盾或歧義、不猜、丟回人。spec 錯不會自動傳到 code。

「我沒時間寫 spec」 那你其實也沒時間寫好 test。test-driven 團隊的 test 品質 = 寫 test 投入的時間,這條路你要嘛面對、要嘛品質被迫下降。spec-driven 把「寫 requirement」這件事上移一層、讓 test 從 SSOT 降級成 assertion layer,負擔反而輕。

「LangGraph / CrewAI / Claude Agent SDK 哪個比較好做這個?」 不是框架問題,是哲學問題。任何框架都能做、只要你把 SSOT 換成 spec。這個變更是一行 prompt(「planner 讀 spec 不讀 test」),框架選什麼無所謂。

Takeaway

用最短的話講完整篇:

Test 是假設的驗證。Spec 是假設本身。當它們不一致的時候,不要改驗證、要回去看假設。

下一篇 #3 講我系統裡最有趣的一層 — 跨 session memory、讓 agent 從 fix 裡抽 pattern、再用這個 pattern 回頭掃整個 repo。那是把 spec-driven 從 linear 變指數的關鍵。


如果你團隊正在考慮導入 QA agent、或者已經在踩「LLM 修 test 但越修越糊」的坑,Twitter @waiting7777 聊聊。

每週一篇 — 技術趨勢背後的商業邏輯

分享:

Waiting7777

WoW Arena 冠軍轉前端,用電競 meta 思維拆解技術趨勢。

關於作者

相關文章

Orca 七個月拿下 10 萬顆星:我拆了它的 GitHub 數據,看到 agent 開發真正的瓶頸AI Agents開發者工具+1

Orca 七個月拿下 10 萬顆星:我拆了它的 GitHub 數據,看到 agent 開發真正的瓶頸

一個由 agent 寫出來、拿來管 agent 的開源 IDE。19,000 個 commit、979 次 release 背後,最值得看的數字是 2,525 個放了一個月還沒人處理的 PR。

2026年10月20日 · Waiting7777 · 7 分鐘閱讀

繼續閱讀 →
跑了兩週 Agent QA Pipeline — 真實數字、踩到的坑、重來我會怎麼做AI Agents自動化測試+1

跑了兩週 Agent QA Pipeline — 真實數字、踩到的坑、重來我會怎麼做

這是 post-mortem,不是 case study。做對的三件事、做錯的三件事、以及為什麼這套東西接下來要抽成 `claude-qa-pipeline` OSS。

2026年10月20日 · Waiting7777 · 6 分鐘閱讀

繼續閱讀 →
你的 100% Coverage 是假的 — 用 test-audit 抓出沒被真正測到的分支自動化測試開發者工具

你的 100% Coverage 是假的 — 用 test-audit 抓出沒被真正測到的分支

AI 寫的 code 跑出漂亮的覆蓋率數字,但 error path 根本沒人測過,這工具專門抓這個。

2026年10月20日 · Waiting7777 · 3 分鐘閱讀

繼續閱讀 →

這篇文章對你有幫助嗎?

每週一篇 — 技術趨勢背後的商業邏輯

AI 產業在變什麼、工程師該注意什麼——拆清楚寄到你的信箱。