對抗式審查
在任何人採取行動之前,找出一個提案會失敗的原因。產出已排序、可執行的擔憂以及一個判決。絕不執行任何實作。絕不超出回合限制而循環。
0. 設定
- 選擇模式。 當呼叫者明確要求時(例如「以報告模式進行對抗式審查」),或當在沒有真人可回答問題的子代理程式、工作者或無頭執行環境中執行時,使用
report模式。跡象包括:任務是以委派提示的形式送達、沒有提問工具、或呼叫者要求一個檔案或有限字數的摘要。在所有其他情況下使用interactive模式。 - 找出要審查的項目。 它可以是下列其中之一:一個檔案路徑、一個差異範圍、一個貼上的計畫,或是「這個對話中剛剛產生的東西」。如果有多個候選項符合,請在輸出的第一行說明選擇了哪一個。如果沒有給定任何項目,且最近也沒有明顯的候選項:在互動模式中,詢問使用者指的是哪個項目,並提供這個對話中最新的輸出、使用者指定的檔案或差異、或是使用者描述的方法作為選項。在報告模式中,則停止並說明沒有提供要審查的項目。
- 設定關鍵性: 原型、內部工具、生產環境、或金流/安全路徑。互動模式:如果不確定且這會影響審查的嚴厲程度,則詢問一次。報告模式:假設為生產環境並說明。關鍵性會設定類別掃描的深度,但絕不移動嚴重性標準。
- 檢查帳本。 找出帳本路徑(參見第11節)。如果此項目已存在帳本,請讀取
references/ledger-format.md。- 如果在最新一輪中,任何ID的最新一行狀態為
pending,表示有一次審查被中斷。請恢復它:跳過第1至第5節,讀取已儲存的記錄,並從第一個狀態為pending的擔憂繼續進行第8節。不要重新執行透鏡或重新排序。在報告模式中,改將它們列在「待決決策」下方。 - 否則,這是後續的一輪。請遵循第11節。
- 如果在最新一輪中,任何ID的最新一行狀態為
1. 先提出最佳情況
在任何擔憂之前,先寫兩三句話說明為什麼這個提案是合理的:它解決了什麼問題以及它尊重了哪些限制。如果這個部分寫不出來,表示提案還沒有被充分理解。請先閱讀更多內容。
2. 生成候選擔憂
在到達某個透鏡時載入其參考檔案。L12 最後執行。
| # | 透鏡 | 使用時機 | 參考資料 |
|---|---|---|---|
| L1 | 事後諸葛:它上線了並導致了中斷;追溯原因 | 總是 | references/lens-questions.md |
| L2 | 反向目標:列出什麼會保證失敗;檢查哪些條件存在 | 總是 | references/lens-questions.md |
| L3 | 隱藏假設:指出每一個;詢問如果它為假會發生什麼事 | 總是 | references/lens-questions.md |
| L4 | 常見遺漏領域的類別掃描 | 總是 | references/category-checklist.md |
| L5 | 針對典型AI錯誤的AI輸出掃描 | 總是,當由AI產生時 | references/ai-output-checklist.md |
| L6 | 確定主張:讓模糊的詞彙可以被檢驗 | 依類型 | references/lens-questions-extended.md |
| L7 | 要求證據:是測量來的、讀到的,還是假設的? | 依類型 | references/lens-questions-extended.md |
| L8 | 其他角色視角:值班工程師、安全、新人、重度使用者、攻擊者 | 依類型 | references/lens-questions-extended.md |
| L9 | 向前推演兩三步 | 總是 | references/lens-questions-extended.md |
| L10 | 質疑框架:是對的問題嗎?有沒有更小的變更? | 總是 | references/lens-questions-extended.md |
| L11 | 分開探討:事實、風險、替代方案、審查品質 | 依類型 | references/lens-questions-extended.md |
| L12 | 從最嚴重的失敗到其根源設計選擇的因果鏈 | 依類型 | references/lens-questions-extended.md |
「依類型」的透鏡,按項目類型:
| 項目類型 | 加入這些透鏡 |
|---|---|
| 小差異或錯誤修正 | 無 |
| 功能差異或多步驟計畫 | L6, L7, L12 |
| 設計、RFC 或選項間的決策 | L6, L7, L8, L11, L12 |
| 其他技能或代理的輸出 | 使用其產出所對應的列 |
讀取擔憂所依賴的真實程式碼、配置或計畫行。建立在猜測程式碼基礎上的擔憂不是證據。
3. 過濾
對每個候選項套用全部四個測試。如果一個候選項未能通過任何一項測試,則將其丟棄。
- 後果: 如果沒有人對此採取行動,實際上會發生什麼事?「沒什麼大不了」意味著丟棄它。
- 反論點: 寫出它不是一個真正問題的最強理由(程式碼已經涵蓋了、它不在此變更範圍內、或者它不會造成損害)。如果那個理由成立,則丟棄它。如果這個擔憂仍然成立,保留反論點並說明它為何失敗。
- 可執行: 必須有一個具體的行動。沒有任何行動則丟棄它。
- 非重複: 丟棄任何已經在此對話中的其他審查步驟、呼叫者的簡報或帳本中報告過的內容。
4. 評定嚴重性
標準是固定的。模式、關鍵性、輪次和時間壓力都不會移動它。
- Critical (關鍵): 陳述一個具體的失效事件:觸發條件、如何失效,以及損害蔓延多遠。觸發條件必須在提案的原文中是可達到的。如果無法指出任何可達到的觸發條件,則該擔憂的最高等級為 High。 參見
references/severity-downgrade-example.md。 - High (高): 一個已命名、真實的情境,在該情境下它會造成傷害。
- Medium (中): 值得修復。不需要失效事件。
將每個擔憂標記為 blocking (阻擋)(必須在繼續工作前修復)或 watch-item (觀察項目)(追蹤它,但不要因此阻擋工作)。
5. 預算
- 完整報告每一個 Critical 和每一個 High。
- 完整報告前三個 Mediums。任何其他 Mediums 用一行列出:數量,然後是每個的簡短標籤。永遠不要默默地丟棄一個 Medium。
- 如果 Critical 加上 High 的數量超過五個,停止詳細審查。 判決為 RETHINK,並建議將提案拆分成較小的部分。僅列出 Critical 和 High 的標題。
6. 擔憂記錄
每個被報告的擔憂都包含以下所有欄位:
### H1: <一行標題>
- Severity: High | Failure event: <觸發條件> -> <如何失效> -> <影響範圍>
- Lens: L3 隱藏假設
- Counter-argument: <最強的反對論點>。Fails because <原因>。
- Evidence: <檔案:行號 | 計畫步驟 | 引用的決策>
- If ignored: <會發生什麼事>
- Action: <具體變更>
- Status: blocking | watch-item
ID 使用嚴重性字母和數字:C1, H1, M1。在任何輪次中,ID 永不改變。Medium 記錄可以將 Failure event 寫為 n/a。
7. 判決
每次審查都以一個精確的判決作結:
- PROCEED (繼續): 沒有阻擋性的擔憂。可以附帶備註。
- AMEND (修正): 方法可行;但需先修復所列出的阻擋性擔憂。
- RETHINK (重新思考): 存在根本性缺陷,或第5節的預算超標。
在判決下方,增加一個 Known risks (已知風險) 標題。列出所有其最新帳本行為 risk-accepted 的擔憂,無論來自哪一輪,包含其 ID、標題和輪次。如果沒有任何此類擔憂,請寫「Known risks: none」。它們永遠不會被視為阻擋。
8. 互動模式
- 顯示最佳情況(第1節)。
- 在問第一個問題之前,寫下擔憂記錄和每個將被審查的擔憂的一行
pending帳本記錄(參見帳本參考)。 - 每輪提出一個擔憂,從最嚴重的開始。使用者選擇 accept (接受)、reject (拒絕)、modify (修改)、risk-accept (接受風險) 或 defer (延後)。
- 如果存在結構化的提問工具(Claude Code 中的
AskUserQuestion,OpenCode 中的question),請使用它,每個問題一個擔憂,並將完整的記錄放在問題文字中,使其保持在畫面上。如果工具限制了選項,則提供 accept、reject、risk-accept 和 defer,並將 modify 視為自由文字輸入。 - Modify:接受使用者的變更,然後將該擔憂視為以其新形式被接受。Reject:該擔憂不適用。Risk-accept:該擔憂是真實的,但使用者願意承擔,沒有人現在修復;不阻擋。Defer:一個觀察項目,待稍後修復。
- 在每個回答之後,立即附加帳本記錄行,然後再提出下一個問題。 不要等到判決。
- 如果存在結構化的提問工具(Claude Code 中的
- 當每個擔憂都有一個解決方案時,在第2輪及之後執行重新檢查(第11節)。然後給出判決和已知風險(第7節)。
- 如果至少有一個擔憂被接受或修改,無論判決如何,都寫出修訂後的計畫(第10節)。
- 將判決行附加到帳本中。停止並等待明確的下一步指示。
9. 報告模式
不問問題。不等待。按以下順序輸出:
- 關鍵性假設(如果有做的話)。
- 最佳情況。
- 所有擔憂記錄,按嚴重性排序,在預算範圍內。
- 判決,以及來自帳本的已知風險。
- OPEN DECISIONS (待決決策): 一個編號列表。將每個項目表述為一個可以由人類回答的決策問題,然後是推薦選項及其權衡取捨:
1. <問題> (關於 C1) Recommend: <選項>。Trade-off: <成本或風險>。
如果呼叫者提供了一個檔案路徑,請將完整報告寫入該檔案。僅返回一個200字或更少的摘要:判決、按嚴重性的計數,以及 OPEN DECISIONS 的標題。附加記錄和解決狀態為 open 的記錄行(參見帳本參考)。然後停止。報告模式永遠不修訂計畫。
10. 修訂後的計畫
僅限互動模式,在每個擔憂都有解決方案之後。只要至少有一個擔憂被接受或修改,無論判決如何,都要寫這個。僅在 PROCEED 且沒有任何擔憂被接受或修改時跳過它。
-
重新陳述整個計畫,並將已接受的變更納入其中。不要只列出解決方案。
-
增加一個整合對照表。將任何已被接受或修改但沒有匹配計畫行的擔憂標記為 MISSING (遺失),並在表格上方說明。
擔憂 解決方案 解決此問題的計畫行 C1 accepted 步驟 3: 增加冪等性金鑰 H2 modified MISSING -
停止。等待明確的下一步指示。此技能絕不執行實作。
11. 輪次與終止
- 帳本路徑:
${XDG_STATE_HOME:-~/.local/state}/adversarial-review/<slug>.md。在第一次寫入之前,先讀取references/ledger-format.md以了解 slug 和行的格式。 - 帳本只能附加。永遠不要編輯或刪除先前的行。
- 一個擔憂只有在解決它的工件(commit SHA 或計畫行)存在且後續的變更沒有觸及它時,才算被解決。
- 每個後續輪次都以一個標題行開始:
Round N | carried open: C2, H1 | new last round: 1 Critical, 2 High - 第2輪及之後,只審查自上一輪以來變更的內容,以及這些變更可能影響的內容。那裡的一個新的 Critical 或 High 必須是新的行為,存在於已變更的素材中,並且實際上會觸發。
- 不要再次提出一個已被記錄在帳本中的擔憂,除非該變更觸及了解決它的東西,或者重新檢查發現它變得更糟。
- 輪次結束重新檢查(第2輪及之後)。 在給出判決之前,針對當前的工件和程式碼,檢查每一個其最新行為
deferred、risk-accepted、pending或open的擔憂。每個擔憂附加一行:仍然適用、不再適用(附上原因)、或變得更糟(提高嚴重性並說明原因)。變得更糟的擔憂需要一個新的決策:在互動模式中審查它,或在報告模式中將其列在 OPEN DECISIONS 下。永遠不要更改舊的行。
退出規則(硬性規定)
這些規則優先於此技能中的所有其他規則。
- 一個後續輪次如果沒有增加新的 Critical 或 High,則結束循環。 判決為 PROCEED。開放的 Mediums 變成觀察項目。仍然開放的、從先前輪次帶過來的 Critical 或 High 不算新的,但它們仍然是阻擋:在互動模式中於此輪解決它們,或在報告模式中在給出判決之前將它們列在 OPEN DECISIONS 下。
- 如果第3輪仍然發現一個新的 Critical, 請質疑工作是如何被分割的,而不是程式碼本身。建議一個不同的拆分方式。
- 從不執行超過四輪。 在第4輪之後,將所有剩餘的阻擋項目作為一個編號的決策列表交給使用者,然後停止。
12. 語氣
- 直接且具體。寫「當...時會失敗」,而不是「這可能潛在地導致問題」。從最重要的擔憂開始。
- 在每個擔憂上命名所使用的透鏡,讓讀者學習這個方法。
- 如果提案很好,直接說出來並給出 PROCEED 判決。
- 不要為了看起來詳盡而憑空捏造擔憂。每個擔憂必須指名一個檔案、行號或計畫步驟;沒有具體位置的通用風險將被丟棄。
- 不要重寫正在審查的程式碼。描述變更;將實際撰寫留給採取行動的人。