前幾天看到 Google 開源了一套 skill,叫 Elephant-Goldfish。它把寫規格和讀規格拆成兩種記憶長度。
Elephant-Goldfish Model(下面簡稱 EGM)是一套給 AI coding agent 用的規格先行 plugin。來源是 Dave Rensin 的文章 Elephants, Goldfish, and the New Golden Age of Software Engineering,後來做成開源 plugin,放在 google/elephant-goldfish-model。Apache 2.0。頁尾寫得很清楚:這不是 Google 官方支援的產品。
大象是記憶很長的那一端。這段對話從需求聊到取捨,專案背景、否決過的方案、為什麼現在不做,都留在這裡。設計先寫出來。Code 先不動。
金魚是記憶很短的那一端。新開一個 session,前面那段聊天它沒有。你只把寫好的設計丟給它。它讀得懂,才往下寫 code。還得猜,就回到長記憶那邊把文件補完。
這個 skill 就是在做這件事。長記憶負責把規格寫到短記憶看得懂。短記憶不參加設計,只讀規格、找洞,或照規格做。同一段對話不要又設計、又實作、又自己判自己及格。
flowchart TB E["大象:長記憶\n跟人把取捨談完,寫出設計"] D["設計文件"] G["金魚:短記憶\n沒有前面的聊天,只讀文件"] C["照文件寫 code"] E --> D --> G G -->|讀得懂| C G -->|還得猜| E
Plugin 把這件事拆成幾個指令。/egm-brainstorm 先把半成品的想法壓一壓,用幾個彼此衝突的角度找弱點。/egm-draft 把對過的想法寫成設計文件,一節一節寫,不在聊天視窗裡倒出一大篇。/egm-review 再叫一批零上下文的 reviewer 來讀:是不是做太複雜、能不能用現成的東西、沒參加討論的人看不看得懂、實作計畫有沒有把檔案和契約寫到不必再做設計決定。通過以後,才拿這份文件去寫 code。
他們還有一個 /egm-drift-report,定期看已經 check-in 的設計和現在的 code 有沒有分家。金魚的通過標準寫得很硬。一個不熟這份 codebase 的人,只靠文件,第一次就該寫出行為相同的 code。不能猜預設值,不能猜錯誤時該怎麼處理,也不能猜資料長什麼樣子。要猜,文件就不及格。
我用現在這套方式開發已經一陣子了。需求先跟 Hermes 談完,該做的決定做完,寫成一張別人拿了就能做的票,再派給沒參加那段討論的 coding agent。前幾篇都在講這個:跟一群 AI 一起工作、模型夠聰明,Loop 才真的轉得起來、Hermes 和 Orca 的化學作用。看完他們怎麼拆記憶,熟悉感就上來了。我心裡那句是:這不就是我已經在做的事嗎。
不能說它的架構跟我完全一樣。他們把規格寫進 repo 裡的設計文件,我寫在 YouTrack 的票上。他們有一整排審稿人格,我沒有裝那一排指令。可是做法是同一件事:先有一份脫離對話也能執行的規格,再讓一個沒有那段記憶的人去讀。讀的人還得猜,規格就還沒寫完,先別寫 code。
這很像 design pattern。大家做久了,各自踩過類似的坑,會不約而同往同一個方向收。沒有人規定必須這樣做。名字是事後才貼上去的。下面拿他們的拆法,對我現在的角色。
我現在實際在做的
flowchart TB O["Owner:長記憶"] T["TPM / Hermes:長記憶"] Y["YouTrack 票"] C["Coder:短記憶\n只拿票,在自己的 worktree 寫"] R["Reviewer:短記憶\n只對票和 PR"] P["PR"] O <--> T T --> Y Y -->|Orca 派工| C C -->|工程問題| T C -->|產品決定| O C --> P Y --> R P --> R
我幾乎不直接打開 Codex 或 Grok Build,丟一句「幫我加一個匯出」。我跟 Hermes 談。Hermes 在這裡就是那段很長的對話:它讀現有的 code,把症狀、根因、這次改什麼、不改什麼、怎樣才算做完,寫進 YouTrack。票夠了,才派工。
派出去的 coding agent 沒參加那段討論。它拿到的是票,不是聊天紀錄。Worktree 把它和別人正在改的檔案隔開,但它腦裡沒有我們剛才吵過的那些取捨。票如果沒寫完,它會回來問。問的如果是產品決定,通常是票還沒準備好。
這就是我說的金魚測試,只是我之前沒有用這個名字。接手的人能不能只靠票把事情做完、驗證、交回來。不能,就先別派。
之前寫過一個例子。使用者按重新整理就被登出,看起來像 token 過期,拆開其實是兩條獨立的路,都會把人踢出去。只修其中一條,問題還會再出現。這種東西如果沒寫進票裡,沒參加討論的人只會修到他第一眼看到的那條。EGM 會說,這份文件金魚讀不懂。我的說法比較土:這張票還不能派。
Review 我另外找一顆沒寫這份 code 的模型來看 PR。貴的模型放在討論和審查。規格關起來以後,寫 code 的那顆可以換成夠用的。這件事 上一篇 講過,這裡不展開。
人還是要在場。登入要不要上一整套 NextAuth,搜尋建議能不能寫死「機器學習」,這種決定我不想讓寫 code 的那個自己選。它列得出可行方案。值不值得現在做,是另一件事。
對一下
上一篇 Hermes 和 Orca 的化學作用 把工作拆成四個角色。用這次的動物來對:TPM 和 Owner 是大象,Reviewer 和 Coder 是金魚。
| 角色 | 記憶 | 動物 | 它在做什麼 |
|---|---|---|---|
| Owner | 長 | 大象 | 決定做什麼、現在不做什麼。取捨留在這裡 |
| TPM | 長 | 大象 | 跟我把票談到能派工,記得前面否決過的方案 |
| Reviewer | 短 | 金魚 | 沒坐在那段討論裡。讀票、PR、相關程式 |
| Coder | 短 | 金魚 | 沒坐在那段討論裡。拿票寫 code |
| EGM | 我現在 | |
|---|---|---|
| 記得一切的那個 | 長對話,先寫設計文件 | Hermes 長對話,先把票寫到能派工 |
| 什麼都不記得的那個 | 新 session,只讀設計文件 | 沒參加討論的 coding agent,只讀票 |
| 不及格 | 金魚還得猜,文件就沒寫完 | 實作者還在問產品決定,票就沒準備好 |
| 規格放哪 | repo 裡的 docs/designs/ | YouTrack。長期規則留在 repo,這次的決定留在票上 |
| 誰拍板 | 人 | 人。需要我決定的,票先停 |
| 寫 code 的時候 | 照已核准的文件做,不再重開設計 | 照票做,不重做一次產品分析 |
做法一樣,指的是工作怎麼拆。檔案放哪、有沒有裝 plugin,是另一回事。
他們把金魚做成一群正式的 reviewer,在寫 code 之前就用標準打文件:太複雜沒有、術語沒定義沒有、要改哪些檔、錯誤時怎麼處理,有沒有寫到實作者不必再做設計決定。我的金魚主要是那個沒在場的實作者。另外一顆模型,多半是 PR 出來以後才看。順序不一樣。壓力一樣。同一段對話不要又設計、又實作、又自己判自己及格。
他們每一節都有一個核准閘,寫完要人點下一步。這部分我不會抄。規格要在派工前收斂。收斂完,就讓它去寫,不要每段再問我一次。確認迴圈我已經踩過,工作沒有變清楚,只是變慢。
他們的 drift scan 我現在沒有對等的工具。我的補償比較笨:repo 裡的說明會落後,對的時候以票和實際 code 為準,不拿一份舊文件當現況。哪天規格真的 check-in 進 repo,那個掃描才有東西可掃。在那之前,掃一份會過期的說明,不如重查票。
簡單的 bug 我也不走完整套。EGM 自己也說,能一次做完的修復,不必硬走 design-first。Pattern 不是儀式。
為什麼我會覺得眼熟
一個 session 又訪談、又寫規格、又寫 code,它會把自己剛才的假設當成事實。Context 一長,重要的契約被埋掉。測試全綠,只是它驗證了自己的誤解。隔一週換一個 agent 回來改,聊天紀錄已經不在了。當時為什麼不選另一條路,沒人說得清。
我是在 YouTrack、Hermes、worktree 裡撞到這些,才把「討論的人」和「寫 code 的人」拆開。Google 裡另一群人用設計文件和零上下文的 reviewer 撞到同一面牆,於是有了大象和金魚。兩邊都還沒看到對方的檔名,形狀已經像了。
Design pattern 的意思就在這裡。工廠方法先有做法,書是後來的名字。很多人各自做過「物件要怎麼建立」,發現有幾種收法比較不容易炸,才有人寫下來。EGM 是他們給這個收法的名字。我的票、他們的設計文件,是同一個 pattern 的兩種實作。
我不會把 plugin 裝成我的開發流程,也不會用 docs/designs/ 換掉 YouTrack。我在意的是那個收斂。
—
本文是讀過 google/elephant-goldfish-model 的 skill,以及 Dave Rensin 的文章 之後寫的對照,不是安裝教學。Plugin 以 Apache 2.0 授權,作者註明這不是 Google 官方支援的產品。我自己的流程仍以 YouTrack 的票和當時的工具行為為準。