前幾天一路讓 Codex 從讀 Repository、找問題、跨檔案修改,到最後真的去看 Diff、跑測試、對照需求,我原本覺得做到這裡,一個 Coding Agent 的工作差不多就結束了,畢竟程式已經改完、測試也過了,接下來只要 Commit 然後 Push 上 GitHub 就好。
但真的回到平常開發流程之後,我才發現中間其實還少了一段,而且這段反而很容易決定其他人到底敢不敢接受這次修改,也就是 Pull Request。
以前自己開 PR 的時候,我常常會寫個「fix bug」或「update function」就送出去,如果只是自己的小專案可能還好,但只要開始多人協作,過幾天回來看連自己都不一定記得當初到底改了什麼,更不用說 Reviewer 還得重新把整份 Diff 看一遍,才能自己拼出這次修改的目的。
所以今天我想測的就不是 Codex 還會不會繼續寫程式,而是它能不能把前面做過的事情整理成一份真的可以交給別人 Review 的 Pull Request。
這次我沒有再丟新的功能需求,而是直接把前一天已經完成的修改留在 Repository 裡,接著讓 Codex 根據目前的 Git Diff、原本的需求以及測試結果,整理出這次 Pull Request 應該包含的內容。
我希望它至少能回答幾件事情,包括這次為什麼要改、實際改了哪些地方、哪些檔案受到影響、測試做了什麼,以及 Reviewer 特別需要注意什麼。
這其實跟單純叫 AI 摘要 Diff 有一點差別,因為 Diff 只能告訴它「哪幾行變了」,卻不一定能說明為什麼會這樣改,例如同樣看到日期轉換函式被修改,如果沒有回頭對照 Issue,它可能只會寫成「更新日期處理邏輯」,但真正有用的資訊應該是某種輸入格式原本會造成解析錯誤,這次修改讓前後端使用一致的格式,而且沒有改動其他日期欄位的行為。
當 PR 寫到這個程度,Reviewer 才不用自己從程式碼裡猜故事。
前幾天我比較常檢查 Codex 有沒有改錯,但今天檢查 PR 描述的方式不太一樣,我開始拿它寫的內容回頭一條一條對照 Requirement、Diff 和 Test,看它有沒有把實際修改講完整。
結果有一個很有趣的地方,Codex 很容易把主要修改寫得很清楚,但一些為了配合主要修改而動到的小地方可能就會被省略,例如某個共用函式一起調整、某個測試資料跟著更新,或是設定檔有一個小變化,這些東西在程式執行上可能沒問題,可是如果 PR 完全沒提,Reviewer 看到 Diff 的時候還是會停下來想「為什麼這裡也改了」。
所以我後來多加了一個要求,不只是摘要主要功能,而是先列出所有 Changed Files,再替每個檔案寫一句修改原因,最後才整理成正式的 PR Description。
這一步其實滿實用,因為它會強迫 Codex 再看一次自己到底碰過哪些地方,也讓我比較容易發現一些原本沒有注意到的修改。
做到這裡之後,我開始覺得 Pull Request 不只是給別人看的說明,它其實也可以當成 Coding Agent 最後一次整理自己工作的機會。
如果 Codex 沒辦法清楚說明某個檔案為什麼需要修改,那我就會回頭確認這個變更到底是不是真的必要;如果它寫著「已完成所有測試」,我就會去看它到底跑了哪些測試;如果 PR 裡提到某個需求已經處理,我也可以直接拿 Acceptance Criteria 回來對照。
這跟昨天做的驗證有一點接在一起,只是昨天是從程式碼出發,看修改有沒有真的完成,今天則是把整次工作壓縮成一份別人可以快速理解的紀錄。
我目前會希望 Codex 產出的 PR 至少包含四塊,修改背景、主要變更、驗證方式、需要 Reviewer 留意的地方,內容不需要很長,但每一段都要能從 Repository 裡找到依據,不能自己補一個聽起來合理但實際沒有做過的測試。
做到 Day 12,我對 Coding Agent 的期待其實已經跟第一天差很多了。
第一天我只是想知道它能不能讀懂一個陌生 GitHub 專案,後來慢慢加入 Bug、跨檔案修改、Refactor、測試、Repository 規則和驗證,今天則開始碰到團隊開發裡很日常的一件事情:怎麼把完成的工作交給下一個人看。
程式能跑只解決了一部分問題,其他人能不能快速理解這次改動、知道風險在哪、知道怎麼驗證,同樣會影響這個修改最後能不能真的 Merge 進去。
明天我想直接把角色反過來,不讓 Codex 當寫程式的人,而是讓它站到 Reviewer 的位置,拿一個已經完成的 Pull Request 給它看,看看它到底能不能找到真正值得提出的問題,而不是只留下幾句很安全的「程式碼整體看起來良好」。