Day 1 問了一個問題:你用 AI 做出一個能跑的小工具,有人問哪裡可以下載,你敢給他嗎?
那時我舉的例子,是 usage(我做的開源小工具,顯示 Claude Code、Codex 這些 AI 工具用了多少額度)把一天 38.74 美元的花費,算成 465.22 美元。修正前那一週,CI(每次推上去自動跑的檢查)跑了 17 次,全部通過。錯是一位使用者拿他自己電腦上 Codex 的真實使用紀錄,跑出來的。
今天不寫感想,用這 29 篇裡發生過的事來回答。
把 29 篇的事件排在一起,有一句話一再出現:「當時是綠的」,也就是測試或 CI 全部通過、亮綠燈:
這幾個綠燈都沒說謊。它們檢查的東西,都真的過了。問題是它們看的,跟使用者會遇到的,不是同一件事:測試跑的是專案資料夾裡的原始碼,使用者開的是打包好的 App,檔案少打包一個,只有 App 會壞(Day 8、Day 23);翻譯測試數的是每種語言條目齊不齊,使用者讀的是條目裡的字(Day 16);CI 的電腦用 UTC 時間,使用者在台灣(Day 21);測試用的是自己做的假選單,使用者按的是真的右鍵(Day 28)。
29 篇裡,問題最先被誰看到(每篇算一次,看那一篇主要事件最先看到問題的是誰):

系列的上線段(把 App 交給陌生人用),Day 22 到 Day 26 連續五篇,都是陌生人先發現的。他們做的事很普通:下載打包好的 App、照 README 安裝、照 App 的提示打指令、對著面板按右鍵。這些路,我自己平常不走。我平常是在專案資料夾裡直接跑原始碼,沒照陌生人的步驟走過一次(Day 27)。
Day 28 是另一種。usage 的面板按右鍵會出現 Reload,點了面板就變空白(Day 26)。6 月 22 日上線的修正要把它拿掉,可是從沒拿掉,139 個版本沒有人回報。這次是 AI 照工作單交回一張待驗清單,我照著它在真的面板上按了一次右鍵,才看到的。
Day 1 的錯,是使用者發現的。Day 28 的錯,是照清單重查發現的。Day 29 拿清單驗這次的修正,又在回覆使用者之前,找出三件還沒做到的事。
敢。但「敢」的根據,不是下面這幾件事:
根據是這三件事,剛好對應這個系列的三段:
這三件事都不保證不出錯。陌生人先發現的那 7 次,換成今天的清單,也不見得每一次都擋得住。它們給的是:出錯的時候,查得出是哪一行沒驗,或清單還缺哪一行;補上那一行,下次驗的時候就多一行可以對。這份清單的 34 行,每一行都是這樣來的。
Day 1 我說,這 30 天要寫的是:一個由 AI 寫出來的東西,改了一千多次,怎麼還能被信任。29 篇寫下來,答案不是「它不會出錯」,是「它出錯時,查得出漏了哪一行」。
系列一共分五段,上面三件事來自前四段。下面這張圖,是每一段各留下了什麼:

30 篇講完,能直接拿去用的是三樣東西。
一張工作單(Day 28 那張,每一格標著來自哪一篇):
改哪裡:___(猜的就寫「猜的」,附上讓你這樣猜的證據:哪一行程式、哪段錯誤訊息)(Day 2、Day 6)
症狀怎麼量:在___量到___,正常應該是___;修完再量同一個地方,貼出前後;
量不到就說量不到,交回來給我量,不要改量別的(Day 6)
哪裡不准動:___,因為動了會___壞掉(Day 3)
已經決定的(不要自己改):___,因為___(Day 7)
做完怎麼算對:從下面的 34 行裡,挑這次屬於的那幾組貼進來
停損:同一處改超過 3 次,檢查還是不過,就停,回報卡在哪(Day 5)
你自己決定的:工作單沒寫、你自己拿主意的地方,全部列出來(Day 7)
一份「做完怎麼算對」清單,34 行,照情境分 10 組(Day 4 到 Day 28 每篇加的行):
【每一次改動】
- 你自己驗:跑了什麼、結果是什麼,指令和結果貼在回報裡(Day 4、Day 5)
- 我自己按:打開___,按___,應該看到___(Day 4)
- 驗不到的:先說哪一類你驗不到(例如要用滑鼠點、要看真實畫面),再列出這次落在裡面的項目(Day 4)
- AI 交回來的「驗不到的」:每一項寫上誰來做、做完貼什麼;沒人做完,就不准回覆使用者「修好了」(Day 28)
- 回報的測試數字旁邊寫上基準:「pytest:N passed(基準 ____)|跑的範圍:____」;N 比基準少不准寫完成,全套跑不完就寫只跑了哪些,剩下的我自己跑(Day 12)
- 新加或改過的測試:每一個用一句白話說它最後檢查什麼,標出是「使用者看得到的結果」還是「程式內部有沒有做某個動作」。修 bug 的測試至少要有一個是前者,Day 9 那條「拿掉修正要紅」就拿這一個來跑(Day 27)
【修 bug】
- 在___量到___,正常應該是___;修完再量同一個地方,貼出前後數字(Day 6)
- 修 bug 附的測試:先拿掉修正跑一次,要紅,而且紅在___(bug 發生時的樣子);放回修正再跑,要綠。兩次的輸出都貼在回報裡。拿掉修正還是綠,就補一個會紅的測試(Day 9)
- 修 bug 補測試:列出這次修正改了哪幾處,每一處分開拿掉、各跑一次測試,貼出結果。每拿掉一處都要變紅;有一處拿掉還是綠的,就補一個會紅的檢查。那一處如果管的是程式執行時去哪裡找檔案,這個檢查就是打開打包好的 App(Day 23)
- 修使用者回報的錯誤:照他寫的步驟重跑一次,貼出這次成功的輸出,再回覆他「修好了」(Day 25)
【推上去、發版】
- 推上去之前:打開 CI 設定檔,每一項檢查在本機用同樣的指令跑一遍,每項貼最後一行結果;本機跑不了的列出來,推上去之後列出這個版本在 GitHub 上的每一項檢查和結果(Day 11)
- 推上去之後:列出這個版本在 GitHub 上跑的每一項檢查(名字、在哪個系統跑、結果),貼在回報裡;有一項紅就不算完成,先貼那顆紅燈錯誤訊息的第一段(Day 10)
- 發版前:同一個版本的每一項檢查都綠了才准發;新加的檢查第一次就紅,當天查清楚、修綠,不准當成「本來就紅」(Day 10)
- CI 的上限檢查(例如每個檔案最多幾行)要過;超過時只准把程式搬走或合併,不准調高上限數字(Day 15)
- 出貨前開一次:拿使用者會拿到的那一份(安裝檔/部署後的網址/裝好的指令),照使用者的開法打開___,應該看到___;出現錯誤就不准出貨(Day 8)
- 寫進出貨流程:上面這一步每次自動跑,不靠人記得(Day 8)
- 發版:發出去後馬上把使用者會下載的那個檔下載回來,先確認這次新加的檔案在裡面(貼出 unzip -l 那幾行),再打開打包好的 App,確認能正常啟動;只在自己的專案資料夾跑過不算數(Day 22)
- 同一天要發第二版以上:說明這一版為什麼不能等到當天收工再一起發(Day 22)
【算數字、改檔案、改預設值】
- 算數字的功能:拿一筆真實資料,跟一個不是這段程式算的數字對(官方數字、別的工具、手算),回報兩邊的值和差距;差距的原因要附證據,不准只寫推測(Day 13)
- 會改檔或改設定的功能:成功訊息不算數,AI 回報要附改動前後的比對;測試要拿一份真實環境裡用過的檔案跑一次,不能只用自己想像的寫法(Day 14)
- 會改用預設值的功能:測試要各餵一次「少一個」和「內容是空的」,兩種都要紅;測試說明寫要抓什麼症狀,就親手做出那個症狀跑一次(Day 16)
- 有更新快照的改動:回報要貼出快照多出來的那幾行;新功能在快照裡要看得到數字;把新功能故意改壞一次,快照要紅;新畫面用真實資料打開看一次(Day 19)
【跨作業系統、日期時間】
- 支援多個作業系統的專案:型別檢查每個作業系統各跑一次(mypy --platform),回報要寫明在哪個作業系統上跑的(Day 17)
- 改到日期、時間的程式:「拿掉修正要紅、放回要綠」,要在切不動時區、而且不是 UTC 的環境跑;只在 CI 或自己的 Mac 上過,不算數。回報要寫明在哪個作業系統、哪個時區跑的(Day 21)
【文字、翻譯、說明文件】
- 有繁體中文介面的專案:繁中文字用 OpenCC(s2twp)掃過,標出來的每一句不是改掉,就是連同原文寫進例外清單;這個掃描寫成測試(Day 18)
- 改了有翻譯版的文件:每個語言版本都要改到,AI 回報要列出每一版改了哪幾行;同步檢查通過不算數(Day 20)
- 改了檢查的範圍:同一個改動裡,把說明檔裡描述這個檢查的句子一起改(Day 20)
- 寫給使用者看的訊息(錯誤提示、空白畫面的說明):寫出這句會在什麼情況出現、看到的人是怎麼裝的。叫人跑指令的,確認裝 App 的人也跑得了;App 裡有按鈕做得到的,就叫他按按鈕(Day 24)
- 改了安裝方式、加了按鈕或新入口:把介面文字裡提到舊做法的句子全部找出來,貼出搜尋結果,一起改(Day 24)
【安裝】
- 動到安裝方式(安裝說明檔、打包格式、README 的安裝指令):照 README 一字不差跑一次安裝,貼出最後 10 行輸出(Day 25)
【畫面】
- 畫面是網頁的 App:在打包好的 App 上,對每個畫面按右鍵、把選單每一項點一次,再按 Cmd+R、兩指左右滑;每一步貼出畫面截圖。程式自己會重新載入畫面的地方,要在真的網頁元件上跑一次,貼出載入後畫面上的文字;只用假物件數它被叫了幾次,不算數(Day 26)
- 結束、重開這類出口:列出 App 裡每一個能結束它的地方,各在哪個畫面上。全部在同一個畫面上的,寫出那個畫面壞掉時使用者怎麼結束 App(Day 26)
【搬程式、刪程式】
- 貼出要動的那幾行的 git blame 結果,標題有 fix 或 issue 編號的 commit 列出來,逐一確認它們修的東西在新位置還在(Day 23)
【別人或另一個 AI 送來的改動】
- 說明裡要貼修正前、修正後各一次的實際結果(數字、畫面截圖或輸出);只勾「手動驗證過」,不算數(Day 27)
一段交給 AI 的驗收提示詞(Day 29):
下面是驗收清單。
1. 先告訴我這次的改動屬於哪幾組,每一組說一句為什麼。
2. 那幾組的每一行,逐行回報:做了沒、結果、證據(指令和輸出);跟這次無關的行,寫「不適用」和一句原因。
3. 沒做的,寫原因,再寫誰來做、做完要貼什麼。
4. 最後一行寫:可以回覆使用者「修好了」嗎?可以/不行,不行的話差哪幾行。
不用一開始就 34 行全用。從你最常做的那一組開始;出過一次事,就加一行。
每一篇的標題、所屬的段落,和那一篇的問題最先被誰發現:
明天還有一篇番外:這個修正已經跟著新版發出去,可是 #42 回報的兩件事只修好一件。回覆使用者時,要怎麼寫?
謝謝你讀到這裡。