用 LLM 跑 Spec Review — 兩段式 Prompt 把模糊需求釣出來

Spec review checklist 跑久了會累、會漏掉。LLM 在「列出可能性」這件事比人類強 — 但判斷哪些重要還是人類的工作。這篇講怎麼設計兩段式 prompt,讓 LLM 出粗草、QA 收細工。

為什麼要用 LLM

人工 spec review 的盲點:

  1. 熟悉的 domain 反而會跳過 — 你太熟,覺得「這當然會處理」,但實作可能沒
  2. 疲勞時漏看 — 連續 review 第 3 份 spec 就會掃過去
  3. 缺少非 happy-path 想像力 — 寫 spec 的人本來就少寫異常

LLM 的補位:

  • 沒有「太熟」的盲點 — 它會把你忽略的問題都列出來
  • 不會累
  • 訓練資料涵蓋大量異常情境

配合:LLM 出 30 個問題,你用 [[spec-review-checklist]] 判斷哪 10 個真的重要。

兩段式 Prompt 設計

直接問「找漏洞」效果差 — LLM 會給你一坨泛泛的建議。先澄清、再挑戰才有用。

Stage 1:先列「需澄清」問題

你是資深 QA。以下是一份產品需求 spec。

【Spec】
<貼整份 spec、user story、或 PRD>

【任務】
不要急著找漏洞。先列出這份 spec 中**所有需要澄清的點**。
重點問:
1. 模糊用詞(「適時」、「自動」、「合理的」)→ 該追問什麼?
2. 沒明說的前提(角色、權限、依賴功能)
3. 數字 / 限制沒寫的(長度、數量、時間、金額)
4. 沒列舉完的(「等」、「之類」、「包含但不限於」)
5. 多人協作沒寫的(衝突、race、同時改)

【輸出格式】
| 編號 | spec 原文(引用片段) | 澄清問題 | 為什麼這重要 |
|------|---------------------|----------|-------------|

只列「需問」不列「假設」。如果你已經知道答案、就不算需澄清的。

【限制】
- 至少 15 個問題
- 用繁體中文
- 不要編造 spec 沒提到的東西

為什麼這個 Stage 重要:把 spec 的「模糊面積」量化。看到 30 個澄清問題 → 你心理就有底「這份 spec 還不能進開發」。

Stage 2:基於 Stage 1,列邊界與漏洞

基於剛才那份 spec 和你列出的澄清問題,現在進入第二輪。

假設 PM 對你剛才所有問題都回答「依預設值處理」、「跟舊功能一致」、「使用者體驗合理即可」。

請列出在「PM 這樣回答的情況下」,這個功能上線後最可能爆炸的 15 個情境。
每個情境包含:
1. 觸發條件(具體值)
2. 預期會發生什麼
3. 我們應該補哪些 test case

【特別關注】
- 邊界值(0、負數、極大、空值、null)
- 狀態機(不合法的狀態轉換)
- Race condition(兩個請求同時)
- 錯誤處理(網路 / DB / 第三方 fail)
- 資料一致性(多寫入點、cache 失效、歷史資料)
- 跨平台(瀏覽器、裝置、語系)
- 安全(injection、權限繞過、敏感資料外洩)

【輸出格式】
## 場景 N: <一句話描述>
- 觸發:具體操作 + 資料
- 風險:會發生什麼
- 影響:使用者 / 營收 / 法遵
- 建議測試:1-3 個 test case 標題

【限制】
- 用繁體中文
- 不要重複 Stage 1 已提的問題
- 找「會爆炸」的,不是「UX 可以更好」的

為什麼分兩段

  • 一段式 prompt LLM 會混在一起 → 「這裡模糊」「這裡會爆」攪和、難分類
  • 兩段式 → 第一輪做 spec 品質檢查、第二輪做風險探測

實際範例

Spec(簡化版)

功能:會員等級系統
- 使用者依累積消費分為 銅 / 銀 / 金 / 鑽 四級
- 升等規則:累積消費滿一定金額自動升等
- 等級享有不同折扣:銅 0%、銀 5%、金 10%、鑽 15%
- 等級降級:一年內消費未達標自動降級
- 使用者可以查詢自己的等級歷史

Stage 1 LLM 輸出(節錄)

# 引用 澄清問題 為什麼重要
1 「累積消費」 是「歷年累積」還是「滾動 12 個月」?退費要扣回去嗎? 影響升等邏輯與資料模型
2 「累積消費滿一定金額」 各級門檻具體數字?台幣?要含稅? 沒寫等於無法實作
3 「自動升等」 即時 vs 次日批次?升等時通知方式? 影響使用者體驗 + 推播設計
4 「銅 0%」 折扣是全品項?特價品也算?跟其他優惠券能疊嗎? 折扣疊加是常見 bug 來源
5 「一年內消費未達標」 一年定義?1/1-12/31 還是滾動?降級到哪一級(降一級或全降銅)? 影響降級頻率與爭議
6 「使用者可以查詢自己的等級歷史」 多久?分頁?匯出?欄位有什麼? UX + 隱私 + 效能
... ... ... ...

價值:拿這份去問 PM,強制 spec 補完整。如果 PM 嫌煩、就回他「我不問現在,將來 5 個 bug 都得回到這個點解」。

Stage 2 LLM 輸出(節錄)

## 場景 1: 升等與退費衝突
- 觸發:使用者買 5000 元升金,退費 1000 後累積剩 4000(金門檻 4500)
- 風險:等級該不該降回銀?折扣已用過怎處理?
- 影響:客訴 + 客服人工處理成本
- 建議測試:
  - test_upgrade_then_refund_below_threshold
  - test_used_discount_with_demoted_user
  - test_refund_partial_within_24h

## 場景 2: 升等同時下單(race condition)
- 觸發:使用者下單觸發升等的瞬間、用同個 session 再下另一單
- 風險:第二單按舊等級結帳、但 DB 已升等 → 折扣不一致
- 影響:少收錢 or 多收錢,客訴
- 建議測試:
  - test_concurrent_upgrade_and_order
  - test_idempotent_upgrade_check

## 場景 3: 跨年降級時間
- 觸發:使用者 12/31 23:59 下單,剛好達標
- 風險:1/1 00:00 跑批次降級,未保護剛達標的人
- 影響:剛升等馬上降、極差體驗
- 建議測試:
  - test_year_boundary_purchase
  - test_demote_grace_period

## 場景 4: 等級顯示不一致
- 觸發:升等後沒清 cache、客戶端看到舊等級
- 風險:顯示銀但結帳金折扣(或反之)
- 影響:客訴、信任度
- 建議測試:
  - test_cache_invalidation_after_upgrade
  - test_concurrent_browsing_after_upgrade
...

價值:直接拿來變 test case backlog。

進階:第三輪反問

如果 spec 比較大,可以加 Stage 3:

你剛才列出的 15 個風險,請挑出**最容易被開發團隊忽略**的 5 個,
並說明為什麼「資深開發也會忽略」。

接著對這 5 個各寫一段「給 PM / 開發看的說服文字」,
解釋為什麼這次 sprint 一定要處理、不能等下版。

用途:你帶這段去 sprint planning,當作「QA 否決進開發」的理由。

品質檢核:LLM 輸出後必做

  1. 濾掉 LLM 編造的欄位 / API — 「呼叫 POST /api/users/upgrade」可能根本不存在,依實際 code 為準
  2. 濾掉重複 — 不同編號講同件事,合併
  3. 濾掉「UX 可以更好」 — 那是設計 review,不是品質 review
  4. 補上 LLM 漏的 domain 規則 — 例如金管會、個資法、特定產業規範
  5. 排序:依「被觸發機率 × 影響大小」打分數

反模式

  1. 直接把 LLM 輸出貼到 spec review 會議 — 沒篩過、品質參差 → 信用扣分
  2. 用 LLM 輸出去質問 PM — 對話會變很臭。自己內化、用自己的話問
  3. LLM 輸出當 ground truth — 它會編造,要對 code / spec
  4. 每份 spec 都跑 — 簡單 spec 不需要、有些只需 Stage 1。依複雜度決定

工作流建議

[PM 寫 spec]
  ↓
[QA 自己讀一遍、心裡有底]
  ↓
[Stage 1 LLM 跑 → 你篩 → 整理 5-10 個關鍵問題]
  ↓
[Spec review 會議:用問題形式問 PM]
  ↓
[PM 補 spec]
  ↓
[Stage 2 LLM 跑 → 你篩 → 轉成 test case backlog]
  ↓
[Sprint planning:用 backlog 估點 / 加 QA 工時]

整個流程省下「會議中現場思考」的壓力,把判斷力留到實質的取捨上。

最後

LLM 在 spec review 的角色是「有耐心的列舉者」、不是「判斷者」。用對位置 = 你變得更敏銳;用錯位置 = 你變懶又不準。永遠保留人工最後一道篩