對此程式碼庫執行一次對抗性審計,並完成它。先報告與交付;只有在使用 --fix 或使用者選定修復後才修改原始碼。
你是對手。每個透鏡從不同角度問一個問題:什麼樣的輸入、時機、使用者或攻擊者會讓此程式碼給出錯誤答案、遺失資料、洩漏資料或讓使用者陷入困境?
此資料夾存放審計所需的一切。請從此檔案所在的目錄解析下列路徑:
lenses/<lens>.md:每個透鏡一個檔案。其Fires:行說明透鏡何時執行(always,或when <condition>)。每個探針可以是無條件(總是回答)或標記為(when <condition>)(當條件成立時回答,否則關閉為不適用)。接著是透鏡產出的成品,以及其完成行。scripts/scan.py:指紋辨識儲存庫、路由透鏡、並列出專案自身的分析器。scripts/signals.tsv:每個偵測與種子模式;scripts/tools.tsv:它知道的每個分析器。專案可在docs/agents/audit-signals.tsv中加入自己的行。scripts/verify.py:檢查發現檔案是否與透鏡檔案一致。scripts/cochange.sh:一起變更的檔案。DELIVER.md:交接備註、審計地圖及其票務。UNTANGLE.md:結構性重構,用於--untangle及結構性票務。
1. 範圍
- 引數:一個路徑(預設:儲存庫根目錄);
--lens a,b只執行那些透鏡;--since REF審計自某個引用(如 PR 基礎,或上次審計的提交)以來的變更;--fix;--untangle [area|ticket]直接跳到UNTANGLE.md;--out DIR(預設.audit/)。 - 當無法得到答案時(CI,
claude -p),未回答的問題會以開放問題的形式保留在HANDOFF.md中,交付只會送至本地追蹤器,且原始碼保持不變,除非票務在approved:行上。 - 建立輸出目錄,其中包含一個
*的.gitignore,使審計不觸碰任何受追蹤的檔案。當開始新的執行(絕不在恢復時),首先將舊執行的RUN.md、REPORT.md及findings/移動到<out>/history/<其日期>/,以便新執行能與其比較。 - 恢復:如果
<out>/HANDOFF.md存在,則從其next階段繼續,保留執行檔案於原位。其approved:行上的票務無需再次詢問即可進行原始碼變更;依照DELIVER.md所述,處理前沿的第一項票務,每次工作階段一張票。任何其他票務需先回報使用者。如果history/中存在較早的執行,則提議--since <其提交>並向前攜帶refuted.md。
以下每個階段結束時,都按照 DELIVER.md 所述重新寫入 <out>/HANDOFF.md。
2. 掃描與偵察
執行 python3 scripts/scan.py <path> [--since REF] [--lens a,b] > <out>/SCAN.md,使 SCAN.md 成為腳本的原始輸出:技術棧、套件、哪些透鏡觸發及原因、熱點、執行計畫、要執行的分析器、每個探針的候選站點(最熱門的檔案優先)以及特殊情況計數。
執行工具下列出的、命令可用的每個分析器,將其輸出儲存到 <out>/tools/<tool>.txt。它們的警告是每個列名透鏡的線索,與掃描站點相同;缺失或失敗的工具會在 RECON.md 中註明,絕不安裝。
然後撰寫 <out>/RECON.md,完成腳本無法看到的內容。只有在每個標題都有答案或 none 時才算完成:
- 邊界:外部資料進入的每個地方(HTTP、Webhook、資料庫讀取、檔案、環境變數、深度連結、推送負載、模型輸出、使用者輸入)。
- 持久性:本地儲存、伺服器資料庫、快取、佇列,以及每個事實歸屬於哪一個。
- 關鍵路徑:金錢、驗證、資料刪除、遷移、任何與安全相關的事項、主要使用者迴圈。
- 命令:構建、測試、lint、執行;測試目前是否通過。
- 內部規則:
CLAUDE.md/AGENTS.md;GLOSSARY.md(或GLOSSARY-MAP.md)中的領域語言,用於發現與修復中的所有名稱;ADR,其接受的風險保持不變,除非風險已改變;docs/agents/中的問題追蹤器。 - 條件:對於每個觸發的透鏡,哪些條件性探針在此成立,附上證據。
- 透鏡覆寫:掃描跳過但偵察顯示需要的透鏡,或因錯誤訊號而觸發的透鏡,附上原因。
撰寫 <out>/RUN.md:提交、日期、引數、最終透鏡清單。
3. 獵尋
遵循掃描的計畫:序列在此逐一執行每個透鏡;平行為每個透鏡提供一個子代理,而分片透鏡則為每個列出的套件提供一個子代理。限制並發的主機以波浪方式執行,將站點最少的透鏡配對;沒有子代理的主機則全部序列執行。
子代理開始時沒有技能,也沒有此對話的任何內容,因此每個簡報都是獨立的。它包含:透鏡檔案、此檔案(用於方法和發現格式)、RECON.md、SCAN.md 中該透鏡的部分、範圍以及輸出路徑 <out>/findings/<lens>[-<package>].md。獵人是唯讀的葉節點:他們閱讀程式碼、執行測試、腳本和應用程式,僅撰寫他們的發現檔案和重現腳本,然後返回主上下文,由主上下文單獨分派。
方法
- 事前驗屍:上線三個月後,關於此區域的頭條一星評論。寫下它,然後找出導致它的程式碼。
- 反向思考:你如何讓此功能盡可能糟糕地失敗?檢查每種方式的程式碼區塊。
- 假設清單:對於關鍵路徑上的每個函式,列出其假設。哪些是由型別或約束強制執行的,哪些是依賴於運氣的?
- 切斯特頓圍欄:在將一個防護、特殊情況或奇怪的行稱之為錯誤之前,先找出其存在的原因(
git log -L、blame、PR)。有合理原因的圍欄不是一個發現。 - 候選是線索:掃描站點是開始閱讀的地方。零站點的探針仍需回答,而站點僅在有具體情境時才成為發現。
發現格式
### <LENS>-<n> <60 字元內的宣稱>
- where: path:line
- probe: <來自透鏡檔案的探針 ID>
- scenario: <具體輸入、狀態或時機> → <使用者或系統看到的錯誤結果>
- severity: critical | high | medium | low
- detectability: loud (崩潰、警報、測試失敗) | quiet (有人可能注意到的錯誤答案) | silent (沒人會注意到)
- verdict: CONFIRMED (<重現它的測試、腳本、查詢或螢幕截圖>) | PLAUSIBLE (有推理,未執行)
- fix family: <變更的種類,而非修補程式>
嚴重性:critical 會遺失或損壞資料、違反安全或隱私、金錢計算錯誤或危及安全;high 在常見路徑上顯示錯誤答案或讓使用者陷入困境;medium 在罕見路徑上如此或降低品質;low 是衛生問題。嚴重性由今天在已出貨配置中誰能觸發它來決定:critical 或 high 情境需指明該人員(任何訪客、任何已登入使用者、持有 X 的攻擊者);僅操作員或死配置能達到的路徑降一級。
編輯:發現、重現、報告和票務會被分享。用 <REDACTED> 取代任何機密、令牌或個人資料,並指向其存放位置,而非引用它。
發現檔案以透鏡的成品開頭。每個探針至少以一個發現或一行 clean: 結尾:clean: <probe> — <evidence>,或者對於條件不成立的條件性探針:clean: <probe> — n/a: <why>。當獵人的完成行成立且 python3 scripts/verify.py <out> --root <path> --lens <lens> 通過時,獵人完成。
4. 驗證
- 合併重複:跨透鏡的發現,當兩個發現共享位置和機制時,保留更嚴重的區塊,加入
- also: <其他 ID>行,然後刪除其他區塊,使每個問題只出現一次。 - 駁斥:每個 critical 或 high 發現都有一個全新的駁斥者;其餘按透鏡批次處理。駁斥者僅獲得發現區塊,從不獲得獵人的推理。對於
PLAUSIBLE的發現,它嘗試推翻宣稱:上游的防護、資料庫中的約束、不可達的路徑、有理由的圍欄。對於CONFIRMED的發現,它檢查重現:它是否因所述原因而失敗,且是透過真實使用者或攻擊者可達到的程式碼?當主機提供不同模型時,駁斥者使用該模型,因為共享偏見使同模型的一致性成為弱證據。 - 根據證據提升:存活並被重現 →
CONFIRMED;存活於推理 →PLAUSIBLE;被推翻 → 放入<out>/refuted.md並附上原因。 - 覆蓋率評論家:一個全新的子代理獲取
RECON.md的關鍵路徑和每個透鏡的clean:行,並指出每個證據薄弱的關鍵路徑(需要軌跡或測試的一句話)或沒有透鏡觸及到的。每個路徑在報告前送回匹配的透鏡進行第二次檢視。
重現是一個緊密的回饋迴圈,僅在此發現上變紅,而在其他發現上不變:在最近接縫處的失敗測試、腳本、查詢。只要成本低於十分鐘,就在 <out>/repro/ 中建立一個,僅針對本地、分支、沙箱或測試模式系統。被一個在下個季度仍將成立的推理(接受的風險、故意的權衡)所推翻的發現,應歸入 ADR,在交付時提出,以便後續審計在偵察中讀取。
5. 報告
撰寫 <out>/REPORT.md:
- 摘要:按嚴重性和透鏡的計數,以及要優先進行的三項修復及其原因。
- 修復:按根本原因將發現分組,每個修復寫在其解決的發現之上;尋找一個修復背後的多個發現,這通常看起來與它們完全不同。標記每個為
structural(耦合、重複、遺失的型別、淺層模組、錯置的接縫)或local(一個地方、一個變更),並使用深度模組詞彙描述結構性修復:模組、介面、深度、接縫、適配器、槓桿、局部性、刪除測試。 - 未分組的發現,按嚴重性排名,然後按可偵測性(無聲優先),然後按可達性。
- 覆蓋率:每個透鏡的
clean:行、跳過的透鏡及其原因、已執行或缺失的分析器,以及覆蓋率評論家送回來的內容。 - 自上次審計以來,當
history/中有較早的執行時:已修復、仍開放、新增、以及復發(之前已修復,現在又回來)。
- 使伺服器成為 `scan_count` 的唯一寫入者,使用 `where scan_count > 0` 原子遞減,使客戶端無法漂移、重複花費或重置。 [structural, critical]
- MONEY-2 `ScanQuota.swift:40` 在上傳前本地遞減,並在重試時再次遞減。
- MONEY-3 重新安裝應用程式會將本地儲存中的 `scansUsed` 重置為 0。
- STATE-5 每週配額在設備本地星期一重置,因此向西飛行會獲得第二週。
執行 python3 scripts/verify.py <out> --root <path>;報告在通過時是最終版本。當主機呈現結構化發現(一個 ReportFindings 工具)時,也報告每個倖存的發現,最嚴重的優先。
調整此專案的漏斗:一個其站點全部被駁回或 clean 的種子行,或一個沒有種子指向的發現,是提議加入專案 docs/agents/audit-signals.tsv 的行。在報告中列出提議;它們僅在使用者接受時才被寫入。
6. 交付與交接
閱讀 DELIVER.md。將報告繪製成審計地圖,每個修復一張票,附帶類型與阻擋邊,放在儲存庫的問題追蹤器上(若未配置則為本地 .scratch/;在發布到遠端追蹤器前先確認)。然後詢問要開始哪些修復作為一輪燒烤:將每個編號為一個問題,附上你的建議答案,措辭使得「是」表示接受。使用 --fix 時,採用所有建議。在 HANDOFF.md 的 approved: 行上記錄已批准的票務編號。
根據票務的形狀進行路由。命名的技能是 mattpocock-skills;在可用時使用技能工具呼叫一個,否則內嵌執行其步驟:
| 票務形狀 | 路由 |
|---|---|
| 需要先做決定:接縫位置、與之矛盾的 ADR、模糊的領域術語、要接受的風險 | grill-with-docs,記錄答案為 ADR 和詞彙表條目 |
| 結構性,一個模組,值得在承諾前與使用者探討 | improve-codebase-architecture 在該區域 |
| 結構性,競爭的介面設計 | codebase-design,其雙重設計模式 |
| 結構性,路徑清晰且適合一次工作階段 | UNTANGLE.md,以票務和 REPORT.md 作為起點清單 |
| 結構性,超過一次工作階段 | wayfinder,繪製決策票務朝向目標 |
| 許多修復要切片給代理無人值守工作 | to-tickets(追蹤子彈切片、阻擋邊、寬重構為擴張-收縮),然後 implement |
| 本地修復 | tdd:重現是第一個紅燈測試,位於與使用者商定的接縫處;完整套件保持綠燈 |
PLAUSIBLE 且 critical,尚無重現 | diagnosing-bugs 第 1 階段:先建立緊密迴圈 |
當前沿為空時,使用 --since <審計提交> 重新審計。審計的目標是一次驗證沒有倖存的 critical 或 high 發現的重新審計。
完成條件
- 每個觸發的透鏡都有一個滿足其完成行的發現檔案,且
verify.py在整個輸出上通過。 - 每個倖存的發現都有位置、探針、情境、嚴重性、可偵測性和判定;每個被推翻的都在
refuted.md中。 REPORT.md將每個發現置於修復之下或未分組清單中,地圖包含每個修復的一張票,且HANDOFF.md指名下一張票。