用 Claude Code 同 Codex 之前,先整好三個規格檔案
我花咗一年時間從 Claude Code 同 Codex 得到反覆無常嘅結果。三個職責清晰嘅規格檔案解決咗呢個問題。
用 AI 編程代理幾乎每日工作將近一年,困擾我嘅唔係幻覺程式碼或者搞錯咗 API,而係結果嘅不一致性。同一個任務,措辭稍有唔同,某日跑出嚟乾淨利落,第二日卻一塌糊塗。會話越長情況越差,因為代理會把廿條訊息之前達成嘅共識忘得一乾二淨。
根本原因係結構性嘅。我冇一套跨會話向代理傳達意圖嘅框架,所以每次對話都從零開始,漂向難以預測嘅方向。
改變結果嘅三個層次
將指令拆分成三個職責分明嘅檔案,一致性問題幾乎喺一夜之間得到解決。
第一層 CLAUDE.md 喺每次會話時自動載入。佢存放專案層級嘅常數:建置命令、技術棧版本、目錄結構、編碼規範,以及行為邊界(必須做、先確認再做、絕對唔做)。
第二層 SPEC.md 記錄某個具體功能嘅「做乜」同「點解做」。目的、需求、成功標準、技術限制、範疇邊界。唔涉及任何實作細節。
第三層 plan.md 將規格拆解成每個耗時兩至五分鐘嘅可執行任務,附上明確嘅檔案路徑、測試優先嘅執行順序,以及提交檢查點。
點解將所有嘢塞進一個檔案唔得
研究 LLM 指令跟隨能力嘅論文將呢個現象稱為「指令詛咒」(Curse of Instructions)。單一上下文入面嘅指令數量越多,模型對每條個別指令嘅遵守率就跌得越厲害。我親自試過:將項目規則、功能規格、任務清單全塞進一個檔案,代理大約忽略咗後半段將近一半嘅指令。
按職責分離解決咗呢個問題。代理從第一層讀取全域規則,從第二層讀取功能意圖,從第三層讀取執行步驟。每個檔案都夠短,讓模型可以完整關注到。
CLAUDE.md 保持精簡效果最好
由於呢個檔案喺每次會話都會載入,佢只需要包含普遍適用嘅內容。建置命令、棧版本、目錄結構、命名規範。加上三層行為邊界:必須做、先確認再做、絕對唔做。
效果最好嘅做法係從最小化開始,每當發現代理反覆犯同一個錯誤時再增量加規則。一開始就試圖寫出面面俱到嘅 CLAUDE.md,反而會導致臃腫,觸發我本來想避免嘅遵守率下跌。
幾個具體嘅陷阱:唔好把 API 金鑰或程式碼片段放入去,佢哋會好快過期。唔好重複 linter 已經喺強制執行嘅規則。把任何只針對單一功能嘅內容移入第二層。
規格檔案專注於「做乜」同「點解」,把「點做」留畀代理
同傳統 PRD 嘅分別係,呢啲規格係為代理消費而結構化嘅。五個部分就夠:目的、需求、成功標準、技術限制、邊界。
把實作決策交畀代理。佢可以分析現有程式碼庫,揀選合適嘅方案。當我試圖規定「點做」嘅時候,代理要麼盲目照做導致同現有模式衝突,要麼直接無視。
手寫規格之外嘅另一個方式:讓代理嚟訪問你。設定兩條規則,每次只問一個問題,盡量用選擇題。呢樣產出嘅規格,比我自己從頭寫嘅版本遺漏更少。
把完成嘅規格存到 docs/specs/YYYY-MM-DD-topic.md 然後 commit 入 Git。咁樣代理可以透過 git diff 追溯規格變更歷史,程式碼審查者亦有咗一份記錄程式碼變更背後意圖嘅文件。
會話拆分係最容易畀人忽視嘅做法
規格撰寫過程中嘅腦力激盪同問答消耗咗大量嘅上下文視窗。從同一個會話直接跳入實作,意味著代理會逐漸失去對早期上下文嘅存取能力。
我將工作重組成三個會話:會話 1 產出 SPEC.md,會話 2 建立 plan.md,會話 3 起逐條執行任務。準確度嘅提升喺第一週內就感受得到。
令呢套方法發揮作用嘅三個習慣:喺每個任務裏寫明確嘅檔案路徑,讓代理唔再猜測;把 TDD 順序(測試、實作、驗證、提交)固定喺 plan.md 裏;以及上下文使用量達到大約 50% 時開啟新會話。
成熟度模型指向「規格即來源」
Martin Fowler 嘅團隊最近定義咗一套基於代理嘅軟件開發成熟度模型,分三個級別。級別一:寫規格、實作、丟掉規格。級別二:把規格作為同程式碼並行演進嘅活文件嚟維護。級別三:規格成為唯一事實來源,程式碼係生成嘅產物。
我認識嘅大多數團隊同個人還未到級別一。佢哋發一次性提示詞,然後期待結果。
從級別一升到級別二只需要一個習慣:把規格檔案 commit 入 Git。從級別二升到級別三意味著喺改程式碼之前先更新規格。今日能夠邁出嘅最小一步,係為你嘅項目建立一個 CLAUDE.md,並喺下一個功能開始前寫一份 SPEC.md。
訂閱通訊
獲取關於我最新項目、文章同埋 AI 和 Web 開發實驗嘅更新。