測試失敗後,若只把最後一行錯誤貼給 Codex,只會得到幾個範圍很大的猜測。相同的 TypeError 可能來自輸入資料缺欄位、呼叫端傳錯物件、測試替身回傳不同格式,也可能來自正規化函式沒有處理邊界資料。
錯誤文字提供第一個定位座標,完整原因還需要透過重現與程式證據確認。
一個可執行的除錯任務,需要包含失敗命令、錯誤輸出、重現資料、預期行為,以及本次允許檢查與修改的範圍。
Codex 取得這些資訊後,才能沿著堆疊追查呼叫路徑,判斷失敗在哪一層形成,再用相同命令驗證修正結果。
堆疊追蹤(Stack Trace)會顯示錯誤類型、訊息與經過的函式。它能指出程式在哪裡失敗,無法單獨說明資料為何走到該位置。
只截取 Cannot read properties of undefined,Codex 看不到哪個值是 undefined,也不知道這項輸入是否符合需求。
提供錯誤時,先保留第一個與專案程式有關的堆疊位置,以及前後幾行測試輸出。接著補上實際執行命令、測試名稱、最小輸入和預期結果。
若問題需要特定作業系統、環境變數或資料檔才能發生,也要說明使用的測試環境,敏感值則改用安全的測試資料。
內容過長的 log 可以先縮小。保留第一個失敗案例、完整錯誤訊息、相關堆疊與造成失敗的輸入,移除重複成功紀錄及無關服務輸出。
原始紀錄要留在本機或持續整合(Continuous Integration, CI)平台,方便後續將 Codex 的判斷與完整輸出互相核對。
除錯第一步,是用相同命令重新產生問題。若 Codex 無法重現,就要先比較程式語言編譯版本、套件鎖定檔、工作目錄、環境設定與測試資料。此時直接修改程式,可能只會處理到另一個相似症狀。
成功重現後,要求 Codex 整理「觀察到的事實」與「待驗證的原因假設」。事實包含實際輸入、錯誤位置、經過的函式與失敗測試。假設則需要附上驗證方法。
例如 normalizeLabels() 收到 undefined 是事實,呼叫端漏了預設值則是需要繼續查證的假設。
Codex 可以沿著堆疊由下往上閱讀。先看拋錯的那一行,再看資料從哪個呼叫端進入,最後確認公開入口如何建立輸入。
每找到一段關係,都應附上檔案路徑、函式名稱與相關程式。這些證據能讓開發者檢查分析是否走在實際執行路徑上。
目標、上下文、限制與完成條件為提示中的基本資訊。除錯任務可以把「同一個案例不再重現,且相關測試通過」寫進完成條件,讓代理人有清楚的驗證終點。
找到一行會拋錯的程式,還不能直接把它當成根因。
假設 labels.map() 收到 undefined,可以在該行加上空陣列預設值,也可以在資料讀取層補齊欄位。兩種做法都能讓例外消失,代表的資料責任與影響範圍並不相同。
Codex 應先檢查資料型別、公開契約、既有測試與相鄰呼叫端。
假設專案允許 issue 缺少 labels,正規化層就需要安全處理。若輸入契約要求欄位必須存在,問題就需要回到資料建立或驗證流程檢查。
需求案例、型別定義與現有使用方式要一起支持結論。
分析報告至少要回答四件事:錯誤在哪裡發生、哪一筆資料觸發、資料如何走到該位置,以及哪項規則說明目前行為有誤。
無法取得證據的部分應標示為待確認。這能避免 Codex 用看似合理卻無事實根據的敘述填補專案裡沒有的資訊。
根因確認後,請 Codex 先提出修改計畫,列出預計變更的檔案、函式、測試與驗證命令。
計畫應能說明每項修改如何對應根因。若它準備重寫整個資料模型、移動多個模組或更新套件,需要先停下來說明擴大範圍的理由。
最小修正(Minimal Fix)指的是改動足以滿足已確認規則,並保留現有相容行為。它不追求最少字元。
例如將 labels 缺值處理放進正確的正規化邊界,並用回歸測試固定行為,會比在多個呼叫端各加一段特殊判斷方便維護。
同一輪避免順手改名、重新排版、抽取共用函式或清理鄰近程式。這些變更會擴大差異,讓審查者難以判斷哪一行真正解決問題。
若分析途中發現其他缺陷,先記入除錯紀錄,再建立獨立任務處理。
今天我們延續上一個練習。業務測試已確認:issue 缺少 labels 欄位時,要視為未分類,四種標籤統計都不增加,而且該 issue 仍保留在排名結果中。
執行測試後得到以下失敗輸出:
FAIL test/issue-report.test.ts
issue report
✕ keeps an issue without labels in the ranked result
TypeError: Cannot read properties of undefined (reading 'map')
at normalizeLabels (src/labels/normalize-labels.ts:18:17)
at buildIssueReport (src/report/build-issue-report.ts:27:20)
at test/issue-report.test.ts:64:18
這段輸出先提供三項線索:失敗案例和未標籤議題有關,錯誤發生在 normalizeLabels(),呼叫端是 buildIssueReport()。目前還不能確認預設值應放在哪一層,也不能確定其他呼叫端是否受到相同問題影響。
第一輪只讓 Codex 分析,不開放產品程式修改:
請先讀取 AGENTS.md、失敗測試與以下堆疊涉及的程式:
test/issue-report.test.ts
src/labels/normalize-labels.ts
src/report/build-issue-report.ts
失敗命令:npm test -- issue-report.test.ts
錯誤:TypeError: Cannot read properties of undefined (reading 'map')
位置:normalizeLabels -> buildIssueReport -> issue-report.test.ts
已確認的業務規則:issue 缺少 labels 時視為未分類,四種標籤統計
都不增加,該 issue 仍須保留在排名結果中。
這一輪請保持唯讀:
1. 使用相同命令重現錯誤,記錄實際結果。
2. 沿呼叫路徑追蹤 labels 的來源與型別。
3. 列出觀察事實、原因假設,以及支持或排除各假設的證據。
4. 提出最小修正計畫,列出預計修改檔案與驗證命令。
不要修改程式、測試、設定或套件。若無法重現,請停止並整理環境差異。
收到分析結果後,先核對 Codex 是否真的執行指定命令,堆疊路徑是否能在程式中找到,以及 labels 的資料契約是否允許缺值。
它若只看到 .map() 就建議加入 || [] 這類提供初始值的改動,仍缺少放置位置與相容影響的證據。
接著檢查最小修正計畫。若所有 issue 的標籤都經過 normalizeLabels(),且該函式的責任包含把外部資料轉成內部格式,這裡處理缺值就有清楚依據。
若另有輸入驗證層已承諾補齊欄位,就需要先查明該流程為何失效。
確認根因與修改位置後,再給 Codex 第二輪指令:
我已確認根因分析與修改位置。請依剛才的最小修正計畫執行:
1. 只修改直接相關的正規化實作,讓缺少 labels 的 issue 使用空標籤集合。
2. 保留既有大小寫正規化、前後空白處理與單一 issue 內去重行為。
3. 不得修改、刪除、略過或放寬失敗測試。
4. 不得改動排名規則、輸出格式、套件、設定或 README。
修改後先執行 npm test -- issue-report.test.ts。
確認原失敗案例通過後,依 AGENTS.md 執行標籤統計相關測試、完整 Test、Lint、Type Check、Build 與 Formatter 檢查。
最後顯示 git status、git diff、所有驗證命令與結果。
未提供或無法執行的檢查要明確記錄。不要建立 commit。
原失敗案例通過,表示同一組輸入沒有再次觸發例外,也符合測試裡的預期輸出。
接著執行標籤相關測試,確認大小寫、空白、重複標籤、零值與排序維持原有行為。完整測試、Lint、Type Check 和 Build 則從其他角度檢查影響。
回歸測試(Regression Test)需要在修正前失敗,修正後通過,而且失敗原因要對準這次缺陷。
若測試只斷言「沒有拋錯」,它沒有確認未分類議題仍保留在排名中,也沒有檢查四種統計保持零值。原先由開發者確認的業務斷言應保持完整。
還可以檢查相鄰輸入:labels: []、只有空白標籤、包含重複標籤,以及正常的多標籤議題。這些案例若已有測試,就直接執行。缺少測試時,先確認是否屬於本次根因的直接邊界,再決定是否補入,避免把一個錯誤修正擴張成整套測試改寫。
最後閱讀差異,確認變更位於計畫中的檔案,沒有修改測試期待值,也沒有把所有錯誤吞掉。過度寬廣的 try/catch 會讓例外消失,卻可能留下錯誤資料。
驗證應同時核對沒有例外、統計正確與排名資料保留。
任務完成後,將這次除錯整理成一段短紀錄。內容包括失敗命令與錯誤摘要、確認過的根因、修改檔案與函式、回歸測試、完整驗證結果,以及仍未涵蓋的風險。若 CI 後續再次執行,也可以補上工作名稱與提交版本。
本次紀錄可以寫成:「normalizeLabels() 直接對缺少的 labels 執行 .map(),使未分類 issue 產生 TypeError。修正將缺值正規化為空集合,保留既有標籤處理規則。原失敗測試、標籤相關測試與專案檢查結果如下。」後面接上真實命令與結果。
預防方式要對應根因。這次可保留缺欄位的業務測試,並在資料型別或輸入契約中表達 labels 可以缺少輸入值。
若同類外部資料還有其他選填陣列,可以另開盤點任務,先找出位置與風險,再決定是否需要一致的正規化規則。
一份可追溯的除錯結果,應讓審查者從錯誤輸出一路看到重現證據、根因判斷、最小差異與驗證紀錄。
Codex 負責加快搜尋、執行與整理,開發者則確認資料契約、接受修正位置,並判斷目前證據是否足以進入後續流程。