Appearance
Day 22|讓 Bug Hunter 自己找問題,再交證據給我
前言
經過前幾天的培養,新同事終於可以當我的代理人,開始獨立處理事情了。之前得由我一步步下指令,今天可以讓它照流程自己跑,最後列出結果,再讓我幫忙審核就好。
這一步也是為了將來輪值做準備。輪值時我可能不在身旁,新同事得靠自己處理,總不能每一步都停下來等我,畢竟我可不想在半夜的時候被叫起來上廁所。
回歸正傳,前面幾天我們已經學會怎麼探索問題、判斷是不是 bug、打信心指數,以及去除重複的問題。今天把這些步驟串起來,交給一位代理人(Agent)執行。
我們只需要給它一句話,它就會跑完整個流程,交回候選問題和證據,讓我這個資深的前輩審核。不過,今天先讓它找問題、交證據,開單的權限還沒給它,後面再說。
開始之前
bug-hunter 開跑前會先檢查三件事,缺一項就先停下來補齊:
- charter(探索任務書)檔案存在且可讀:沒有 charter,代理人不知道要巡查哪個範圍、邊界在哪裡。若沒有,先叫 exploration-charter 產生一份 charter。
output/known-false-positives.yaml與output/issues-index.yaml存在:前者記錄已確認的誤報,後者記錄已有的問題,讓它知道哪些該過濾、哪些是重複發現。- 先讀設定與交接規則:Bug Hunter 要讀取配套
sdet-skills專案裡的references/config-resolution.md與references/agent-handoff.md。前者告訴它這個專案使用哪些門檻與預算,後者說明交接時要保留哪些欄位(project、session、finding_id),免得下一位同事接手後不知道這筆問題從哪來。
這裡會用到前面幾天留下的東西:charter 是 Day 15 的產物,問題索引與誤報名單則是這幾天陸續累積的紀錄。現在把它們一起交給新同事,讓它接著做。
如果沒有 charter 內容,可以使用 /exploration-charter 產生 charter,或者閱讀第 15 天的文章。
/sdet-skills:exploration-charter 探索 https://with-bugs.practicesoftwaretesting.com 的登入到購物車流程,尋找數量與購物車狀態相關的 bug它會產出一份新的 charters/toolshop-login-cart.yaml,欄位長相跟 Day 15 那份一樣:goal、scope、oracles、out_of_bounds、test_account、max_steps。唯一缺少的是一行 notes,那是 Day 15 那份特別留給 Day 19 更正用的,但不影響今天要跑的 bug-hunter。
動手試試
我們用下面這句 Prompt,讓新同事照先前建立的 charter去找問題:
用 charters/toolshop-login-cart.yaml 跑一輪 bug-hunter順帶一提,這兩個 skill 的呼叫方式不一樣。本書將 exploration-charter 設計成 user-invoked,要由使用者輸入斜線指令呼叫;bug-hunter 則是 model-invoked,允許模型依任務需要呼叫,所以前面才會直接用一句話請它開跑。
這樣安排,是為了讓未來的值班代理人 duty-oncall 能自己呼叫 bug-hunter。總不能半夜還要有人坐在旁邊,幫它輸入斜線指令吧。
但這也表示,什麼時候該用 bug-hunter,得讓模型判斷。skill 的 description 就要寫清楚適用情境,減少叫錯人的機會。
跑完之後
這次跑了約 30 分鐘,它交回一份 candidates.yaml,內容長這樣(節錄第一筆):
yaml
- id: C-05
fingerprint: "product-detail|quantity-field-not-reset-across-products|route-product-to-product"
verdict: bug
oracle_used: 內部一致性
basis: >
使用者未在新商品頁碰過數量欄,該欄卻沿用上一個商品輸入的值……
同一 app 的另一條路徑(從列表頁進商品)同樣情境下顯示正確的 1,前後矛盾。
confidence: high # 0.25+0.25+0.20+0.10 = 0.80
factors:
- "3 次跨商品重現(p1→p2、p3→p4、p4→p5) +0.25"
- "oracle=內部一致性(同一 app 兩條路徑結果矛盾) +0.25"
- "證據齊(截圖/DOM 讀值/sessionStorage/步驟) +0.20"
- "分類 product-bug、basis 指得到證據檔 +0.10"
occurrences: 3
evidence: output/evidence/.../packages/C-05-qty-leaks-across-products.md這裡的 verdict: bug 是 Hunter 的初步判定,意思是它找到了判斷依據。這筆仍然是候選問題,還要交給明天上線的 Verifier 獨立驗證。
每一筆都要帶上 oracle 依據、信心指數的計分明細、指紋和證據路徑,缺一樣就還不能收工。不過,同一輪也記下了兩項執行流程上的問題,寫在執行紀錄(run log)的 process_notes 裡:
- 兩趟 hunter subagent 都出現『回報已完成但實際留有大缺口/未存證據』;下輪應在 hunter 收工前先驗『每候選是否指得到已存在的證據檔』再收。
- subagent 反覆把 typo 打信心指數 0.95;分數以 references/confidence.md 重算,未採信。第一條是它說做完了,結果證據沒存,這不就跟我們偶爾也會犯的錯一樣嗎?第二條是它給自己的信心分數打太高,沒有照規則算,所以不能直接採用,得重新計算。
前面的範例只節錄了 candidates 裡的第一筆。整份 candidates.yaml 的結構如下,不同處理結果會分開放:
yaml
candidates: [] # 依信心指數排序,尚未開單
merged: [] # 指紋已存在,併入舊單的
related: [] # 疑似相同根本原因,交人判
suppressed: [] # 命中誤報名單,附命中哪條
needs_spec: [] # 無 oracle,附「該問誰」
stopped_because: 達標 | max_steps | 無進展最後一行記錄這輪為什麼停下來,實際填入其中一個原因。上面的 [] 是空清單,跑完後再填入對應的紀錄;沒有符合的項目就維持空清單。
背後怎麼做
一句話就能開跑,是因為 skill 已經把下面這八步排好了,新同事照著做就行:
| # | 步驟 | 使用的規則 |
|---|---|---|
| 1 | 探索 | Day 16 到 19 的自主探索 |
| 2 | 標狀態 | 狀態只從 pass / fail / blocked / flaky / anomaly / inconclusive 六種裡挑 |
| 3 | 初篩分類 | Day 13 的七類分類 |
| 4 | 判定 | Day 18 的 oracle |
| 5 | 打分 | Day 20 的計分規則 |
| 6 | 去重 | Day 21 的指紋 |
| 7 | 濾誤報 | Day 21 的誤報名單 |
| 8 | 封裝與交付 | Day 11 的證據包 |
「標狀態」「初篩分類」「判定」看起來很像,其實各管各的:狀態記錄測試跑得怎樣,分類區分問題出在哪裡,oracle 判定則回答有沒有依據認定它是 bug。所以前面說狀態只能六選一,後面仍然會出現 bug、needs-spec 這些判定結果,它們填的是不同欄位。
第 4 到 7 步就是四道關卡,少一道就不算跑完一輪。第 1 步還有一件容易忘記的事:先讀同一份 charter 過去幾輪的紀錄,看看哪些已經驗過,把這輪的時間留給還沒探索的地方。
四道關卡要串著看:先用 oracle 判斷這個現象違反了什麼,再依規則計算信心分數,接著查指紋,看是不是舊問題,最後比對誤報名單,看是不是已經有人確認過的誤報。
沒有判斷依據,就先別急著說它是 bug。 還沒人說清楚怎樣才算對,標成 needs-spec;手上的證據還不夠,現在下不了結論,標成 inconclusive。
尤其是 needs-spec,要等有人釐清預期行為,再重新判斷。不能先把它算成 bug,也不能直接塞進誤報名單,當作沒這回事。
今天學到什麼
今天,我們把前幾章的探索、判斷、打分與去重步驟,串成 Bug Hunter 能自行執行的流程。只要給它一份探索任務,它就會交回候選問題,以及對應的操作步驟和證據。
不過,自動執行不代表結果可靠。這次它仍然漏存證據,也曾把信心分數打得過高。因此,驗收時必須檢查它實際留下了什麼,不能只相信它說「完成了」。
Hunter 交回的問題還需要獨立驗證。明天會加入 Bug Verifier,讓另一位沒有參與探索的代理人,照證據包中的步驟重新操作,確認同樣的現象是否再次出現。
作者備忘錄 (Author's Notes) — 正式出版前應移除
本區塊為作者內部檢討區,用於追蹤內容品質與後續改進方向。正式出版前應移除或轉為附錄。
章節大綱
- 前言 — 承接 Day 16–21:探索、判定、信心、去重各自能用,但每步都要人下指令,今天包成代理人,只找不開單。
- 為什麼需要把它包成代理人 — 順序不能錯(分類先於打分、oracle 先於去重);順序即規格,寫進 skill 擋跳步;發動成本從五條指令降到一條,鋪墊 Day 30 排程值班。
- 實驗:一句話發動,30 分鐘交回一輪 —
candidates.yaml節錄一筆完整結構(fingerprint/verdict/confidence 因子拆解/evidence);同輪留下兩筆壞紀錄:宣稱做完卻未存證據、自評 0.95 被重算否定。 - 八個步驟與四道關卡 — 表列八步對應 Day 16–21 各篇;第 4–7 步是四道關卡,少一道不算跑完;鐵則:沒有 oracle 命中不得判 bug。
- 輸出檔案:candidates.yaml 的五個欄位,零筆也要出現 — candidates/merged/related/suppressed/needs_spec/stopped_because;空欄仍要出現,證明關卡真的跑過;
stopped_because記錄停止理由,未達步數上限不是缺點。 - 撰寫原則:要改,從哪裡下手 — model-invoked 用法補在 Prompt 指令段落(對照 Day 15 的 user-invoked);三塊可改內容(description/八步/五欄位)各自的邊界,鐵則不得單改;改完要拿同份 charter 跑一輪對照 run log。
- 小結 — 流程圖收斂:讀舊紀錄→探索→標六態→初篩→四道關卡→封裝交付;強調「順序就是規格」「代理人化不修毛病,只讓毛病變成每輪要驗的固定項」。
- 下一步 — 預告 Day 23:找的人不能是判的人,確認偏誤問題,下一步找第二位同事盲驗。
- 參考資料 — Gawande checklist manifesto、Bach session-based test management、Claude Code subagents 文件、Conway's law、延伸資料 SKILL.md。
結構特徵:從「單站分別能用」過渡到「代理人化」,敘事重點是順序即規格與代理人化不解決既有毛病(只是讓毛病曝光在固定檢查點),延續全書「先出包再建機制」節奏,同時是 Day 16–21 的收束點。
參考資料
- Atul Gawande(2009)《The Checklist Manifesto: How to Get Things Right》 - 把步驟寫成清單,防的不是新手不會做,是熟練者跳步,正是「八步不得跳號」的理由
- James Bach(2000)《Session-Based Test Management》,STQE Magazine - 用 charter 界定一段可稽核的探索,本篇的輸入格式就是這個傳統
- Claude Code Docs — Create custom subagents - 用 name/description/tools/system prompt 定義一位專職代理人
- Melvin E. Conway(1968)《How Do Committees Invent?》,Datamation - 交付物的形狀會長得像產生它的流程,五個欄位對應四道關卡不是巧合
- 延伸資料:
sdet-skills專案的skills/agents/bug-hunter/SKILL.md(八步與鐵則)、references/confidence.md、references/bug-fingerprint.md- 八步、四道關卡與計分規則的真檔,非本書 repo 收錄