Development Workflow支線 B
觀測每一次開發:retro 的摩擦與收割
有的成了一行設定,有的成了廢欄位,有的還在等時間推移
前言
模型每更新一次,規則檔就值得再縮一次,這件事官方跟社群都在建議。
能減少的多半是通用規則,但一間公司的規則檔裡,有一大半是內部知識:
開發流程在哪幾步會卡、使用者做事的偏好、哪些事講過一次就不想再講。
這些有可能是使用者自己的習慣,也有可能是一個為公司開發流程增進效率的好建議。
但描述改不改,靠什麼判斷?可能改進什麼,改完之後,怎麼知道模型下次會自己推得出來?
原生 /doctor 能掃你的 CLAUDE.md,指出哪些內容模型讀程式就推得出來:目錄樹、技術棧、太長的檔案。
但它不知道,模型很愛用選項式的提問工具,而那個工具有時會把前面的解釋整段蓋掉,使用者得再問一次才看得到。
這種事只發生在對話裡,掃檔案掃不出來。
摩擦最深刻的當下是在對話。
所以有了 retro。
每輪 /develop 收尾時,AI 翻整趟流程記下三件事:
使用者出手糾正了什麼、哪道步驟失敗重試過、哪條規則它讀了卻做了別的事。
寫成一份報告,進 git。
報告不會自動改任何東西。它累積,隔一陣子由人一次分析,決定哪些教訓升級成規則、哪些規則該刪,改完把報告清掉,這叫收割。
選項式提問那件事,就是使用者抱怨了好幾次、進了報告之後,才變成流程檔裡的一句「一律純文字提問」。
retro 的用意是讓證據替推導說話:一段描述究竟是自嗨、有用抑或是白白燒 token 的大殺器。
幾個月下來一百多份報告,模板改到第五版。
我也正慢慢摸索,而此文算是我目前的心路。
要觀測什麼、哪些值得量化,而哪些可能也只是自嗨的工具。
有用的
不懼怕刪除
描述太多我想刪,但刪錯描述怎麼辦?
心想著成本才沒多多少,還是就留一下好了,這點在心裡縈繞不斷,真理就是能動就好,沒事就是好事。
軟體工程師從小聽到大的句子,在程式或許是技術債,但對多數老闆來說根本沒影響。
可是在大模型獲得的描述裡,就是得額外推理的真金白銀,會提早讓我達到五小時上限的 token 殺手。
想省、想快、想精準,想有勇氣刪掉描述,
想打破這個預設,需要的是更低的代價。
若刪錯一條規則,下一趟就會在那出事,而使用者會出手糾正,retro 則記下一列:他糾正了什麼、當時做了什麼。
而留錯一條規則,它不會出事,只會安靜地影響旁邊每一條,而且不會有人知道。
一邊是有紀錄的摩擦,一邊是慢性的稀釋。
所以我在憲章訂立了其中一條:刪錯的代價是一次摩擦,留錯的代價是永遠。
馬斯克說過:你刪掉沒摩擦,就代表你刪的不夠多。
所以改了預設:先刪,出事再補。
數個月下來,流程檔總行數比巔峰少了四成多,砍掉的有數千行。
摩擦落成機制,不是落成更多的字
每趟開發結束後固定跑一次 retro,會把摩擦一條一條記下來。
記下來之後,最直覺的處理是加一句規則提醒它下次別這樣。
「上次這件事出過問題,所以下次不要。」
有個摩擦被記了三次:
Windows 和 Linux 的換行符號不一樣,git 在 Windows 上 checkout 會自動把檔案換成 Windows 的格式,
而我們用來編排 subagent 的 workflow 腳本一被換掉就啟動失敗。
三趟 run 各自卡在這裡,三份 retro 各自記了一筆。
其中一份照著反射動作提了修法:在規則檔加一行,叫模型跑之前先把腳本轉回 Linux 的換行。
我們在收割那天剛好把眾多報告攤開,才看見這是同一件事第三次發生。
人類這時的介入不是依照建議執行,而是直接落成機制:
.gitattributes 裡的一行,強制那個目錄永遠用 Linux 的換行,再也不管誰的環境怎麼設。
事後沒再發生過問題,且規則檔裡一個字都沒加。
retro 雖然有提修法,但那不是它的價值。
它的價值是把每一次都記下來,收割的時候重複才看得見,
人類才有依據判斷如何讓未來開發更順暢。
沒用的
工程師抓 bottleneck 就想量化各種指標,指標就可以依據來做決策。
我也不例外,老實說我只是想各種試看看,由於沒啥成本,就想用各種角度來評量,
什麼是更快、更好、更準確。
但我發現我量化到最後大部分都沒用,所以就來回改了好多版直到今天。
數字有了,還是不知道要做啥
一開始,我想用 KPI 回答前面的問題:這套流程到底有沒有變好?
所以要求 AI 每趟填數字,譬如重做了幾次、派了幾個 agent、設計改了幾輪。
希望累積一段時間後,就能看出哪裡浪費時間、哪次修改真的有效。
好笑的是,每次回顧,表面報告指標都是好,背地仍是摩擦紀錄,屬實是面子工程。
譬如有個欄位記「派錯工的次數」,每份都是零;
另一個又記「完成項目附上驗證證據的比例」,每份都是百分之百。
結果同一份報告裡,使用者照樣在糾正理解、要求重改設計。
我想知道流程好不好,量到的卻只是其中幾個步驟有沒有做。
分析的定義改了五次,最終還是回答不了原本的問題。
我直接把這批 KPI 拔了,這好像只是我自爽的無意義記數,又或者說我根本沒抓到可以記什麼。
人類看不懂,AI 跟著胡謅,純純的耗 token 工具。
要它證明自己有用,它就會說有用
第二個死掉的指標,想解決的是規則本身到底有沒有用。
所以模板加了一張表,標成規則的描述對於此次的開發「有作用」或「讀了沒差」,
讓安靜但有用的規則留下證據,將來大掃除時不被誤刪。
一個月下來,二十幾份報告填了將近兩百列「有作用」,「讀了沒差」只有十幾列。
然後下一次收割,有作用的規則照樣被刪,十幾列讀了沒差的也沒有一條因此被刪。
說到底表填了,就是沒有意義,最終刪不刪還是人自己判斷的。
問 AI 「這條規則對你有沒有用」,人類沒辦法讓它有區別能力,所以它會說有用。
開始記成本
如今我已改成直接在開發最尾端自動跑一個腳本,記錄此開發中所有的消耗 token 紀錄,
從最上層的 main context,到過程中派遣 workflow 的 subagent,他們所有的 input/output,以及執行的時間,統統以表格列出。
這張表沒有判斷,只跑程式抄數字,AI 可沒胡扯的空間。
與其窮舉對應關係,不如宏觀看待整體調整,在歷史留下趨勢。
它能回答錢去了哪裡。
譬如我們把幾趟 run 的表加起來看,模型真正寫出來的 output 不到百分之一,
九成以上的 token 是每個 agent 一次又一次把同樣的規則檔和程式重新讀進腦袋。
錢不是花在寫程式,是花在讀 context。
單趟開發也看得出來,主 context 在不同任務裡的峰值可以差到三倍,一目了然的顯示哪種任務撐爆 agent 的腦袋。
這些數字以前沒有,現在有了我馬上就能知道必須盡量刪掉無謂的描述:
因為每句話在每個 agent 的派工都會再讀一次。
不過它不能回答的是這套流程有沒有變好,因為每趟任務尺度都不同,沒有基準可以比。
但至少我們第一次讓成本可查。
什麼叫做好
迭代到最後,一個問題隨之浮出。
「我要怎麼定義『好』。」
我甚至覺得這好像開始觸及哲學。
在機率的大語言模型中,
我要怎麼衡量開發快這件事,每次的任務尺度都不同,如何有一個基準?
我要怎麼衡量需求準這件事,滿足 90% 測試覆蓋率,但怎麼處理你未想到的 edge cases?
我要怎麼衡量精粹的記憶這件事,你都是用真金白銀在堆任務,但主 context 裡放什麼,決定你省不省錢。
如何用最少的錢做最快又最準的事。
(可老實說,模型下一次的更新加降價可能就是效果最明顯的答案,或許我在這邊做的調校僅是杯水車薪。
但我希望,至少能夠留下註腳,以及嘗試在 retro 的過程中尋找無論如何都迭代不了的步驟。)
快、準、省,是我想要的結果,但光講這三個字,那就只是在許願。你需要定義它並且不被 AI 唬弄。
多寫一段提醒,可以說是為了準;少讀一份文件,也可以說是為了快跟省。
每個改法都能找到理由,最後又回到各說各話。
所以我把判斷規則的準則換個思路,寫成一份憲章。
依照官方的建議,所謂的最小知識原則。
它本來就會的不用教,repo 查得到的不用抄,同一條閱讀路徑上已經講過的不用重講。
要留下來,必須是下面三類之一。
第一類,Fact:模型讀的當下推不出來的事實。
一條描述概括:讀程式、讀設定、讀同一條路徑上的檔案,推不推演得出來。
目錄樹、技術棧清單就不算,檔案明明就在那裡,再抄一份只是多養一份會過期的描述。
譬如:這個路徑下的資料夾是舊版 service 的參考點,基本上新版不用理會。
這件事 repo 裡沒有任何地方寫著,不講它不會知道。
第二類,Decision:我們在幾個合理選項之間做好的取捨。
譬如幾份互不衝突的工作,依序做或同時做,都能完成。
但我們可以預設寫下「需併行處理」這個選擇,免得每一趟重新決定。
不過隨著模型持續的進化,他們已更有智慧決定這類事,這一類應該是最會被先淘汰的。
第三類,Correction:模型預設的行為,跟我們要的不一樣。
模型曾經用了選項式提問,使用者卻看不到前面的說明,只好再叫它貼一次。
這種情況發生過好幾次,才有依據要求它改用純文字提問。
不能只因為我猜它可能犯錯,就先塞一句「不准這樣」。
憲章要求的是一趟實際紀錄,證明它做了什麼,跟我們要的差在哪裡。
retro 在這裡才接上憲章。
它留下使用者的糾正、當時的動作、牽涉的規則,
收割時讓當下最強的模型依據憲章判斷這是不是一條值得加入的 Correction。
如果規則已經寫了,模型卻反覆沒做到,就要查它有沒有讀到、放的位置對不對、能不能用工具攔下來。
同一句話再加粗一次,解決不了這些問題。
另外,憲章把舉證責任放在保留方。
意思是若要新增規則,你就必須證明為什麼要新增。
刪錯之後若在某趟開發出了問題,retro 會留下那次糾正,下次就有依據補回;
若一句話三類都不屬於,刪吧各位,反正下次的 retro 它將被拎起。
到這裡,快、準、省仍然是目標,而每次收割終於有了能逐句執行的準則。
我還不能因此宣稱整套流程進步了多少,但至少能說清楚:這句為什麼留、那句為什麼刪,哪個改動有實際摩擦作為依據。
就讓成本繼續記著,摩擦繼續收著,憲章繼續讓未來有一致性的判斷,retro 則讓人類盡可能的得知過程紀實。
最終,留下一套由內部知識所建構起的統一開發流。
這一步,還有必要嗎?
我們曾有一個專門寫開發筆記的 agent,每次開發完就派它去更新文件。
目的是額外記下程式當下為什麼這樣寫的抉擇,讓下一趟的 agent 不用重新猜。
七十多份筆記放了幾個月,六十多份 retro 提到過它。
沒有一份問過它該不該存在。連我自己也是。
我看著 retro 的派工次數及時間,同時思索:寫筆記這一步,能不能少花點時間。
某次收割時拿新版憲章一量,靈機一動竄出腦袋:
事實讀程式就推得出來,沒增加效率;
程式一改筆記就得跟著改,多一層要維護;
每趟收尾都要等它寫完,開發跟著慢。
三個標準一個都沒過,最後連根拔除這個 agent,將抉擇搬進程式碼註解。
這一步驟不再出現,沒有任何異常。