昨天把檢查搬進 CI,讓測試、型別、Lint 和 Migration 都有了自動化的把關機制,但程式通過 CI,不代表一個工作單元真的完成了。開發結束後,還有文件回填、決策記錄、Issue 收尾等工作,這些事情沒有測試可以直接驗證,也不會因為忘記更新就讓 CI 失敗。
CI 擋得住程式錯誤,卻擋不住這些逐漸累積的資訊落差。
今天要處理的,就是如何讓工作單元從「程式完成」真正走到「交付完成」。
這個專案的 CLAUDE.md 開頭,第一段就是「這個 repo 現在是什麼」。每個 session 啟動後,第一眼就會讀到這段內容。
而這段文字的結尾,還有一句我之前特別加上的提醒:
This section is the first thing every session reads. When a work unit changes what the system can do, change this paragraph in the same commit — it was left saying "a skeleton, deliberately" through four delivered work units.
今天我回頭檢查了一次。從這句提醒寫下來之後,又交付了兩個工作單元,結果是:
CLAUDE.md 寫的 |
實際 |
|---|---|
| Backend is 61 tests, frontend 16 | 113 / 34 |
| Not built yet: 版本歷程檢視(#3) | 已交付 |
| Not built yet: 決議項指派(#5) | 已交付 |
| (沒有提到) | CI 已經建好,warning 是硬性閘門 |
一段專門用來防止過期的警語,自己過期了。
這不是第一次遇到文件沒有更新的問題。比較值得追問的是:明明已經在文件裡寫了提醒,為什麼還是沒用?
這不是單純的紀律問題,而是提醒本身有一個前提:讀到文件的人,必須能察覺內容已經過期,但這個前提在這裡並不成立。
當我讀到 Backend is 61 tests 時,腦中浮現的其實是目前的測試數量。我知道實際上已經有 113 個測試,因此那行舊數字不會特別引起我的注意。我讀到的不是文件上的文字,而是自己對系統現況的理解。 這件事之前其實已經驗證過一次,當時我開了兩個 session,分別扮演 SA 和 PG。最後發現 CLAUDE.md 已經連續四個工作單元沒有更新的,是那個沒有參與過實作的 PG。
它能發現問題,正是因為它沒有實作過程中的上下文,不會用自己的記憶補足文件缺少的資訊。
持有上下文的人,反而容易看不見文件已經過期。而在一般開發流程中,負責修改、閱讀文件的人,通常就是最熟悉系統的人。
所以解法不能只是「更努力地記得」,也不能再加一句更醒目的提醒。這兩種做法都還是依賴同一個人主動察覺問題。
既然提醒無法保證文件更新,我決定把「檢查文件」變成工作單元交付時的獨立步驟,而且必須留下實際產出。
這也是我刻意不使用 Closes #123 的原因。
Closes # 很方便,只要 PR merge,Issue 就會自動關閉。但這也代表,Issue 的關閉只是 merge 的副作用。程式碼合併了,Issue 就關了。中間不需要有人重新確認原本的需求,也不需要整理實際交付了什麼、過程中做了哪些調整。因此,我改成手動關閉 Issue,並要求在關閉留言中附上一份交付盤點。
這份盤點不是單純記錄「完成了哪些工作」,而是要重新對照原本的規劃與實際成果,找出開發過程中出現的落差。
累積幾個工作單元後,我發現真正值得回填的內容,大致可以分成四類:
實際範圍和原本規劃有什麼差異?
例如第一張 Issue 原本只規劃開草稿、編輯和送出,卻漏掉必要的會議 API,導致使用者根本無法進入編輯畫面。
驗收條件有沒有事後才發現寫錯?
最近一張 Issue 要求既有 74 條測試都不能修改,但補上認證後,有 10 條測試失敗。這些測試原本不帶 Token 也能讀取資料,代表部分測試其實建立在原有缺陷上。
有沒有哪一條測試一開始就是綠燈?
測試通過不代表測試有效。如果一開始就綠燈,就還沒證明它能抓出違反規則的情況。回填時要記錄如何確認測試真的有效,而不只是記錄通過結果。
同樣的問題之前發生過幾次?
這個專案曾有一個樣式檔,連續兩張 Issue 都遇到相同問題。第一次只是順手繞過,第二次才開始意識到這可能是需要正式處理的流程問題。
其中最值得注意的是第四類。前面三類主要是在記錄單次交付的經驗;第四類則能讓我們發現重複出現的問題,進一步調整開發流程,而不是每次都用臨時方式解決。
沿用前幾天的原則:有明確判準、可以讓機器判斷的事情,就交給機器;需要人做判斷的事情,才留給人。
像是測試數量、尚未完成的功能清單,這些資訊都有更可靠的來源。測試數量可以直接執行測試取得,功能進度則可以從 Issue 狀態確認。與其在文件裡重複記錄,不如直接連結到原始來源,避免資訊不同步。
但範圍為什麼改變、驗收條件是否合理、測試是否真的有效,以及問題是不是重複發生,都需要理解開發過程,無法只靠一條自動化規則判斷。
這些才是收尾盤點真正需要人花時間處理的部分。
整理之後,我發現一個很明顯的差異:
容易過期的,通常是被複製到文件裡的事實;比較不容易過期的,則是當時做出的判斷。
測試數字和功能清單描述的是不斷變動的現況;但為什麼這次修改範圍、為什麼某個測試必須調整,這些是當時的決策及其原因。
因此,我現在的原則是:文件多記錄判斷,少複製會變動的事實。需要查現況時,就回到原始來源。
這次整理交付流程,讓我重新思考了幾件事:
明天: 這一整套——CLAUDE.md、收尾清單、CI 閘門,以及測試分層的規則——目前都只在我自己的機器上。指令只有自己用,還稱不上團隊規範。要讓它真正成為開發流程的一部分,下一步就是讓其他人也能安裝、使用,並且持續遵循。