跳到主要內容

【2026 最新】Claude Code 規格修正殘留怎麼清?4 步清理「不要加番茄醬」的 PR 殘影

最後更新: ·
Claude Code 規格修正殘留四步清理教學首圖

你先說「漢堡不要加番茄醬」,後來改成「其實要加」。Claude Code 把功能做對了,卻在 Spec、README 或 PR description 留下一句「without ketchup」。成品看似完整,讀者卻得替 AI 考古:這句是現行需求、已撤回的限制,還是只是模型想證明自己有聽話?這就是本文所說的 Claude Code 規格修正殘留

這不是虛構痛點。2026 年 8 月一則 r/ClaudeAI 討論就用「不要番茄醬」描述這種規格修正殘留;截至 8 月 26 日 07:05(UTC+8),頁面約 280 分、65 則留言,數字會隨投票變動。留言提供的是經驗,不是通用證明。本文因此不報一組不存在的勝率,而是交付一套可以放進 Repo、能以同一組案例重跑的清理流程。

先記住核心判準:Current State(現在正確狀態)不等於 Decision Log(必要決策史)。前者讓人今天照著做;後者只回答「為什麼曾做這個重要決定」。修正對話本身,不屬於任何一邊。

  • Spec/README:只描述現在有效的行為與驗收條件。
  • PR description:描述這次變更交付什麼、怎麼驗證、還有什麼風險。
  • ADR/Decision Log:只保留影響長期架構、成本、相容性或安全的決策與理由。
  • Changelog:記錄已對使用者發布、且時間點本身有價值的改變。

Claude Code 規格修正殘留為什麼會出現?

第一個風險來源很直白:長對話同時裝著舊需求、新需求、嘗試、道歉與修正。Anthropic 的 Claude Code 最佳實務甚至明確建議,同一問題修正超過兩次時,應該用 /clear 重新開始,並把學到的內容改寫成更精確的提示。重點不是「清掉模型記憶」這個模糊說法,而是減少當前對話裡互相競爭的版本。

第二個風險來源更容易被忽略:新對話不等於無記憶。官方的 Claude Code 記憶說明指出,CLAUDE.md 與 auto memory 都會在一般新對話載入,而且它們是脈絡,不是強制設定。用 /memory 可以瀏覽記憶位置,用 /context 可以檢查本次實際載入了什麼。若「不要番茄醬」早已進了持久記憶,只換聊天視窗仍可能把它帶回來。

第三個風險來源是文件角色不清。Google 的 Timeless Documentation原則要求一般文件聚焦目前版本,把過往改動留給 release note 或具日期的文章。當團隊沒有先定義 Spec、ADR 與 Changelog 的邊界,「重要」就可能被誤解成「全部留下」。

Claude Code 規格修正殘留的四步清理流程:重寫現況、分流決策、乾淨審查、回歸驗收
四步不是四選一:先把正確狀態寫乾淨,再用獨立審查與機械掃描守住出口。圖/AlphaLab

第 1 步:把 Current State 原地重寫,不替修正過程留收據

不要把新需求接在舊句後面。請直接改寫那個句子的主詞、動作、輸入、輸出與驗收條件,讓第一次看到文件的人不需要先知道前一版。Anthropic 的提示工程建議是「清楚、直接、明確說出想要的輸出」;其中「說要做什麼,而非只說不要做什麼」是輸出格式的具體建議,不是禁止所有否定句的宇宙定律。

五種常見殘留,該怎麼改?

  1. Spec:「按鈕原本不是藍色,現在改藍色」改成「主要按鈕使用 #2563EB,並通過 AA 對比度檢查」。
  2. README:「不再使用 npm,改用 pnpm」改成「安裝依賴:pnpm install;最低版本由 packageManager 欄位決定」。
  3. PR description:「需求最後不是 without ketchup」改成「此 PR 的預設配方包含番茄醬;測試覆蓋有、無配料兩條路徑」。
  4. API 文件:「端點不再同步」改成「建立工作回傳 202 與 job ID;客戶端輪詢狀態端點」。若這是相容性決策,再另外寫 ADR。
  5. 安全規則:「不得把密碼寫進 log」不是殘留,而是仍有效的限制。可以改成更可驗證的正向狀態:「所有憑證欄位在記錄前一律遮罩;測試斷言 log 不含原值」。

判斷口訣是:刪掉舊選項後,現在的接受條件是否仍完整?若完整,舊選項多半是殘影;若刪掉後會失去安全邊界、範圍界線或相容性承諾,它就是現行約束,應改寫成可測條件,而不是硬刪。

可直接貼給 Reviewer 的重寫 Prompt

<role>
你是 final-state 文件編輯器,只處理目前有效的規格。
</role>

<task>
依據提供的 acceptance criteria 與 final diff,重寫指定文件。
</task>

<rules>
1. 直接陳述目前行為,不敘述對話、嘗試、撤回或「原本/後來」。
2. 保留仍有效的安全、範圍與相容性限制,改寫成可驗證條件。
3. 只有影響長期架構、成本、相容性或安全的理由,才標記為 ADR 候選。
4. 不從聊天記憶補需求;證據不足就回報 NEEDS_DECISION。
</rules>

<output>
先輸出乾淨文件,再列出 ADR_CANDIDATES 與 NEEDS_DECISION。
</output>

第 2 步:把 Decision Log 與 Current State 分流

決策紀錄的價值不是證明「我們曾改口」,而是讓未來的人知道某個昂貴選擇為何存在。AWS 的 ADR 指南建議記下 context、decision 與 consequences;已接受的 ADR 不直接改寫,而是由新 ADR supersede。Microsoft 的 架構決策紀錄指引也把 ADR 視為 append-only,並提醒只記重要決策。

  • SPEC.md:現在必須成立的需求、介面、範圍與驗收。
  • README.md:使用者今天如何安裝、執行與排錯。
  • docs/decisions/NNN-*.md:長期且需要理由的選擇;舊 ADR 保留狀態,新 ADR 指向被取代者。
  • CHANGELOG.md:真正發布給使用者的行為變更,不是聊天逐字稿。
  • PR description:Problem、Solution、Verification、Risk 四段,內容以 final diff 為準。

這也能防止 CLAUDE.md 災難性記憶的另一種變體:每次糾正都被升格為永久規則。若規則只適用單一路徑,放進 path-scoped rule;若只是這次任務的決定,留在 Spec 或 PR;若程式碼本身已能說明,就不要再寫一份會過期的散文。

第 3 步:讓 Reviewer 只看 final diff,再加殘留掃描

同一個對話既當作者又當審稿人,容易沿用同一套假設。Claude Code 官方建議用 subagent 做驗證,也建議完成 Spec 後開新對話執行;但若你的目標是隔離持久脈絡,光用 /clear 還不夠,因為一般新對話仍會載入 CLAUDE.md 與 auto memory。

Reviewer 的最低輸入只有三樣:final diff、目前 acceptance criteria、檔案角色。不要把聊天紀錄一起餵回去。若需要更強的 CI 隔離,官方的 程式化執行文件提供 claude --bare -p:它會略過 CLAUDE.md、auto memory、hooks、plugins、MCP 等自動發現內容;範例再用 --no-session-persistence 不保存 Reviewer 對話,並用 --tools "" 移除工具。Bare mode 不使用訂閱登入或系統 keychain,Anthropic API 使用者需另外設定 ANTHROPIC_API_KEY;因此它是可選的 CI 路徑,不是人人都能直接使用的免費按鈕。

git diff --cached | claude --bare -p \
  --no-session-persistence --tools "" '
只審查這份 final diff。逐檔判斷:
1. 是否完整描述目前接受條件;
2. 是否殘留已撤回選項、修正過程或對話口吻;
3. 否定句是否為仍有效且可驗證的安全/範圍限制;
4. 是否有必須進 ADR、卻未留下的長期決策。
每個問題回傳 file:line、分類與最小修正;沒有問題就輸出 PASS。'

接著加一層確定性的掃描。它不需要理解語意,只負責把高風險詞送去人工或 Reviewer 判斷。像「原本」「後來改成」「不再」「without ketchup」、舊技術名與已撤回功能名,都可以依專案放進清單。掃描器的命中不是罪證:例如「付款頁不在本 PR 範圍」與「log 不含密碼」可能正是必須保留的現行界線。

#!/usr/bin/env bash
set -u
input="$(cat)"
if [[ "$(jq -r '.stop_hook_active // false' <<<"$input")" == "true" ]]; then
  exit 0
fi

hit=0
while IFS= read -r -d '' file; do
  [[ -f "$file" ]] || continue
  if rg -n -i \
    -e '原本|後來改成|不再|without ketchup' \
    -e 'OLD_API_NAME|REJECTED_FEATURE' "$file"; then
    hit=1
  fi
done < (git diff HEAD --name-only -z -- '*.md' \
  ':!docs/decisions/**' ':!CHANGELOG.md')

if [[ "$hit" -eq 1 ]]; then
  echo '請逐筆判斷:殘留、有效限制,或 ADR 證據。' >&2
  exit 2
fi

把腳本存成 .claude/hooks/spec-residue.sh 並執行 chmod +x,再把下面設定合併進 .claude/settings.json

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/spec-residue.sh"
          }
        ]
      }
    ]
  }
}

這樣就把腳本接到 Claude Code Stop hook。exit code 2 會阻止 Claude 停下,並把 stderr 當作繼續修正的理由。範例掃描 HEAD 之後的 Markdown 成品,排除本來就應容納歷史的 ADR 與 Changelog;PR body 仍要由另一個 CI 檢查。Stop hook 每一輪都會跑,所以腳本也處理 stop_hook_active,避免無限循環。官方目前另有最多 8 次連續延續的保護,但那不是你可以省略 CI 停止條件的理由。

原地重寫、乾淨 Reviewer、禁用詞掃描三種方法的能力邊界比較
三種方法解不同問題:重寫負責產生成品、Reviewer 判斷語意、掃描器提供確定性警報。圖/AlphaLab

第 4 步:用 10-case Eval 驗收,不靠「看起來很乾淨」

Anthropic 的 評估工具設計建議要求測例具體、可量測、貼近任務,並納入邊界案例。以下 10 題故意混入兩種陷阱:該刪的修正史,以及看似否定句、其實必須保留的現行限制。請讓 A「原地重寫」、B「乾淨 Reviewer」、C「禁用詞掃描」都跑同一份 fixture,再比較輸出,觀察 Claude Code 規格修正殘留是否重現;不要替任何一組偷偷補更多上下文。

  1. Spec:按鈕由紅改藍;舊色不再有任何意義。
  2. README:套件管理器由 npm 改 pnpm;只留下現在能執行的指令。
  3. PR:漢堡最後要加番茄醬;不得留下「without ketchup」敘事。
  4. API:同步工作改成非同步 job;現行 response 與輪詢流程要正確。
  5. 資料庫:MySQL 改 PostgreSQL;遷移成本與回滾理由必須進 ADR。
  6. 登入:OAuth 改 magic link;安全與帳號相容性決策必須可追溯。
  7. 端點:/v1/send/v2/messages;README 不得混用舊路徑。
  8. 範圍:付款頁明確不在本 PR;這個負面邊界必須保留。
  9. 安全:log 必須遮罩密碼與 token;掃描器不得把它當成可刪殘留。
  10. 回滾:新 ADR 取代舊 ADR;Current State 只寫現況,決策鏈仍完整。
Claude Code 規格修正殘留 10-case Eval 的案例矩陣與三項指標公式
10-case 是回歸 smoke test,不是對所有模型版本的泛化證明;先固定資料與評分規則,再累積自己的版本趨勢。圖/AlphaLab

三個指標與停止條件

  • 語意正確率=符合目前 acceptance criteria 的案例數 ÷ 10。
  • 修正殘留率=Current State 仍出現已撤回歷史的案例數 ÷ 10。
  • 必要決策可追溯率=正確寫入 ADR/Decision Log 的必要決策數 ÷ 所有必要決策數。

對這組小型回歸測試,建議停止條件設成:語意正確 10/10、殘留 0/10、必要決策全部可追溯,而且禁用詞掃描沒有未處理命中。命中可以被標成「有效限制」並附一行理由,但不能悄悄忽略。Reviewer 與程式掃描結論衝突時,回到 acceptance criteria,由人決定;不要讓另一個模型用更流暢的句子掩蓋不確定性。

這些是你為 Repo 設定的驗收門檻,不是本文測得的 Claude Code 全域效能。10 題只能證明這批已知回歸沒有重現;模型、CLI 與專案規則變更後,都應重跑並增加新的失敗案例。若你正把這類閘門擴成完整工作流,可接著讀 AGENTS.md 規則與驗收閘門,或從 AI Agent Harness 實作理解為何模型之外還需要確定性控制。

最小落地版本:今天只做這四件事

  1. 在 Repo 寫清楚四種文件角色,尤其是 Current State 與 Decision Log 的分界。
  2. 把 Spec 與 PR description 原地重寫成現在式,再用 /memory/context 檢查持久脈絡。
  3. 開新 Reviewer,只給 final diff 與 acceptance criteria;需要 CI 級隔離時才評估 --bare
  4. 把禁用詞掃描與 10-case Eval 接進 PR gate;所有未處理命中歸零才合併。

這套做法與 Specification-First 收斂流程可以直接接在一起:前者先把目標寫清楚,本文的 gate 再確保修正後留下的是成品,而不是聊天歷史。想系統化學習 Claude Code 與 Agent 工作流,也可以到 AlphaLab 課程;其他工具與實作整理在 AI 專區

Claude Code 規格修正殘留 FAQ

1. 用 /clear 就能清乾淨嗎?

只能清目前對話脈絡。一般新對話仍可能載入 CLAUDE.md 與 auto memory,所以還要用 /memory/context 檢查持久內容,並重新審查 final diff。

2. 所有「不要」都應刪掉嗎?

不是。仍有效的安全、隱私、相容性與範圍限制必須保留,最好改寫成可測狀態,例如「log 中憑證一律遮罩」。要刪的是已撤回選項與修正敘事。

3. 為什麼不把每次修正都寫進 Changelog?

Changelog 面向已發布的使用者變化,不是內部對話紀錄。未發布就被撤回的選項通常沒有使用者價值,只會讓文件更難判讀。

4. 何時一定要寫 ADR?

當選擇影響長期架構、回滾成本、相容性、安全或跨團隊協作,而且未來的人無法只靠程式碼理解理由時。小文案與一次性樣式修正通常不需要。

5. 新 subagent 一定是乾淨 Reviewer 嗎?

它有獨立對話脈絡,適合驗證,但仍可能受到專案設定或提供的檔案影響。真正的隔離程度要看啟動方式;需要 CI 可重現性時,再評估 --bare 與明確輸入。

6. 禁用詞掃描可以取代 AI Reviewer 嗎?

不行。它能穩定找字串,卻分不出殘留與有效限制;Reviewer 能判斷語意,但也可能漏看。兩者疊加才同時得到可解釋判斷與確定性警報。

7. 10-case 全過就代表以後不會再發生嗎?

不代表。它只是固定的回歸 smoke test。每次出現新型殘留,就把去識別化案例補進 fixture;模型、CLI 或 Repo 規則改版後重跑。

8. PR description 應該完全不提歷史嗎?

可以提與審查直接相關的背景,例如相容性風險與 migration,但不要重播需求拉鋸。只留下能幫 Reviewer 判斷 final diff、驗證方法與風險的資訊。

接著閱讀

左右滑動查看更多推薦

結論:成品描述現在,紀錄只保存必要的為什麼

Claude Code 規格修正殘留之所以污染 PR,不是因為「不要加番茄醬」那句話曾經錯,而是它被放進了不該承載歷史的文件。先原地重寫 Current State,再把少數重要理由放進 Decision Log;用只讀 final diff 的 Reviewer 做語意檢查,以字串掃描補確定性,最後用同一組 10-case Eval 決定能不能停。這樣留下來的不是 AI 服從過程的收據,而是一份下一位工程師今天就能照著工作的乾淨成品。

ALPHALAB 社群

有問題?來 Telegram 聊

和 Terry、編輯、其他網友一起討論這篇文章。提問、分享觀點,回覆更即時。

加入 Telegram 討論

📩 訂閱 AlphaLab 電子報

每週最多三封:一封 Weekly 週報與最多兩封關鍵 Alpha Signal。

我們不會 spam,隨時可退訂。