pstack 是什麼?拆解 Lauren Tan 的 agent 工作流程與驗證設計
pstack 是 Lauren Tan(poteto)放在 Cursor 官方 plugin repo 的一組 skill。它不教 agent 寫更多 code,而是規定 agent 做事的順序:先理解現有程式、選好設計、驗證結果、review diff,最後才回報完成。這篇前半整理 pstack 的架構和運作方式。
讀完之後,對照自己的工作經驗,我覺得最值得討論的是驗證。PR 能不能自動 merge,關鍵就在這裡。agent 交出來的改動,如果沒有可信的方式證明它是對的,最後還是要有人 review code,review 的速度就會變成整條流程的瓶頸。pstack 把證據標準、測試和數字的檢查、誰有資格說通過,都寫成了 agent 照著跑的規則,整套流程、設計和背後的思維都很值得參考,所以後半篇把這部分拆開來看。
讀完這篇,你會知道:
- pstack 由哪幾層組成,
/poteto-mode怎麼替任務挑流程 - 它怎麼讓 agent 沒辦法悄悄省略步驟
- 為什麼驗證決定了 PR 能不能自動 merge
- pstack 的驗證設計:要看什麼證據、測試和數字怎麼檢查、誰來驗
- 在 Claude Code 怎麼安裝和下指令
pstack 是誰做的,想解決什麼問題?
Lauren Tan 在 README 自我介紹時寫,她待過 Meta、Netflix、Cursor,也是 React core team 成員,參與 React Compiler。她對 AI 寫 code 的立場在 README 開頭就寫清楚了:
「there’s a growing sense that ai writes too much slop code. i agree. i don’t want to ship like a team of twenty slop artists. throughput without quality is not a goal i aspire to. if you want to go fast, go deep first.」(pstack README)
她的思路是先把一個 agent 做到可以信任,再談平行。Flavio Copes 介紹 pstack 的文章把這點講得很直接:agent 像新進工程師,需要學 codebase、學團隊怎麼調查、設計、測試、溝通,差別是 agent 會一直忘記。rules、skills、tools、memory 就是用來補這段記憶的。
README 寫的目標是寫更少的 code,但品質更高。能信任單一 agent 之後,同時開好幾個才有意義。
pstack 由哪幾層組成?
pstack 有三層:一個 router、一組 playbook、一組 principle,另外搭配幾個可以單獨呼叫的 skill 和負責寫 code 的 subagent。
| 層 | 做什麼 | 例子 |
|---|---|---|
| Router | 讀任務,挑一個流程,按步驟叫其他 skill | /poteto-mode |
| Playbook | 規定某類任務的步驟,以及怎樣才算做完 | Bug fix、Feature、Refactoring、Perf issue |
| Principle | 某個情境下該怎麼判斷 | Laziness Protocol、Prove It Works、Fix Root Causes |
| Workflow skill | 單獨可叫的工具,router 也會叫 | /how、/why、/architect、/interrogate |
| Subagent | 實際寫 code 的分身 | poteto-agent、comment-sicko |
日常只需要記一個指令:/poteto-mode。它的 SKILL.md 列出每個 playbook 適用的情境,例如回報的 bug 走 Bug fix,新功能走 Feature,只讀不改的問題走 Investigation。找不到合適的 playbook,或任務是大型遷移時,交給 figure-it-out 現場設計一套流程。router 不把 56 個 skill 全塞進 context,跑到哪一步才讀那一步要的檔案。
pstack 也會依工作性質分派模型,預設 Grok 寫 code,Opus 5.5 負責判斷和文字。/arena 讓多個模型做同一個任務再挑最好的,/interrogate 讓多個模型對同一份 diff 挑錯。這部分在 Cursor 上才完整,因為 Cursor 能在同一個任務裡混用不同廠商的模型。
pstack 怎麼讓 agent 不跳步驟?
pstack 的做法是讓跳步驟這件事看得見,光在 prompt 裡寫「請務必」擋不住。poteto-mode 的 SKILL.md 寫:
「Open a todolist whose first items are the matched playbook’s steps, copied in verbatim, before any task-specific todos. A step you choose not to do stays in the list with a one-line
skip: <reason>.」(poteto-mode SKILL.md)
playbook 的步驟會一字不改地抄進 todo list,排在任務自己的待辦前面。agent 可以決定不做某一步,但那一步會留在清單上,後面附一行原因。你看 todo list 就知道它跳了哪裡、為什麼跳。
principle 也有類似的約束。回覆裡要寫出是哪個 principle 改變了哪個決定,而且只能引用這個 session 真的讀過的 principle。這擋掉了一種常見的狀況:agent 嘴上說「我遵循了最小改動原則」,其實根本沒讀過那份規則。
SKILL.md 的 frontmatter 也有一個細節。56 個 skill 裡有 55 個設了 disable-model-invocation: true,模型不會自己判斷要用哪一個,一定要人手動叫。整套流程很重,不該在你只想改一行字的時候自己啟動。
這幾個做法的共通點,是把「希望 agent 記得」改成「agent 漏掉時看得出來」。principle 清單裡有一條 Encode Lessons in Structure,講的就是這件事:同一句指令寫第二次的時候,改成 lint、metadata 或 script。
Bug fix playbook 實際規定了什麼?
Bug fix playbook 規定 agent 先自己重現 bug,用 runtime 證據找出原因,修完在同一個介面上再跑一次 repro,每一行 ship 出去的 code 都要能追到證據。它也是理解 pstack 驗證觀念最好的入口,開頭就寫:
「Belt-and-suspenders that “might help” is a hypothesis, not a fix. It does not ship. When evidence refutes a hypothesis, revert what it motivated.」(Bug fix playbook)
步驟整理如下:
- 在同一個介面上自己重現。就算 debug 流程說可以請使用者重現,也要自己先試到不能再試
- 二分法找原因。列出假設,每一輪挑能排除最多可能性的那一刀,用 runtime 證據排除
- 規劃修法。跨 function 邊界的話先跑
/architect,再派 subagent 實作 - 在同一個介面上驗證,原本的重現步驟要通過。「不確定」或換了介面驗證都不算通過
- commit 順序是會失敗的 repro 先進 git,修正疊在上面
- 開 PR
最後的回覆要貼出修之前失敗、修之後通過的原始輸出。
agent 修 bug 時很常見的做法,是在出錯的地方加一個 guard,測試綠了就回報修好。Fix Root Causes 這條 principle 規定 guard 只在它處理的狀態本來就合理時才算修正。沒有重現就沒有起點,修完沒有再跑一次 repro 就不算完成。Bug fix 的六個步驟裡,有兩步在講驗證,pstack 把同樣的要求推到了其他情境。
為什麼驗證決定了 PR 能不能自動 merge?
agent 寫 code 越來越快,PR 能不能直接 merge,取決於有沒有人以外的方式證明它是對的。沒有的話,每個 PR 都要等人 review code,agent 再快,產出也會卡在 review 的速度上。這是我讀 pstack 時最有感的地方,指南在驗證那一章開頭講的是同一件事:
「Verification is the slowest step in most agent work, because it’s the step that usually waits on a human. Make the agent able to do it, and you stop being the bottleneck. Skip it, and running more agents only gets you more unchecked work to review.」(pstack guide,Verify the result and open a PR)
這段話把 pstack 的兩個目標接在一起。README 說的「fearless parallelism」,前提是每個 agent 都能自己證明做對了。agent 沒辦法自己驗證的話,開十個 agent 只是讓十份沒檢查過的 diff 排隊等你看,人還是瓶頸。
要讓 PR 不經人工 review 就能 merge,驗證要強到可以取代 review 在做的事。pstack 在這塊做的事,可以分成五個問題:要看什麼證據、測試本身有沒有在驗、量出來的數字可不可信、專案沒有驗證工具怎麼辦、誰有資格說驗證通過。
怎樣才算驗證過?
pstack 不接受「build 過了」當證據。Prove It Works 這條 principle 的說法是:檢查真的東西,不檢查代理指標。
「Verify every task output by checking the real thing directly. Do not infer from proxies, self-reports, or “it compiles.”」(principle-prove-it-works)
代理指標包括檔案修改時間、輸出看起來是新的、agent 自己的回報、快取的截圖。這些都比直接觀察便宜,所以 agent 很自然會拿來用。principle 的理由是,靠錯的推論行動,代價遠高於直接去看一次。它還補了一句:驗證失敗的時候,先懷疑觀察的方法,再懷疑系統。
驗證的方式要跟著改動走:
| 改了什麼 | 怎樣才算驗證過 |
|---|---|
| CLI | 跑真的指令,看輸出 |
| UI | 在跑起來的 app 裡實際操作一遍;要跟參考圖一致時,比對截圖的像素差 |
| Parser 或 migration | 用存下來的真實輸入重跑 |
| 效能 | 比較改動前後的 profile,「感覺變快」不算 |
| Storage | 把寫進去的值讀回來 |
驗證要能檢查,完成條件就要在任務一開始講清楚。指南的例子:
/poteto-mode add json output to this command. text output stays byte-identical, the json parses, both run against the sample project. show me the evidence.
這個 prompt 給了 agent 三個能跑的檢查:文字輸出一個 byte 都不變、JSON 解析得了、兩種格式都在範例專案上跑過。回來的回覆應該附上實際的指令和輸出。指南特別提醒,檢查跑不了的時候,好的回覆會寫「inconclusive」,很有自信但沒附證據的回覆反而是警訊。
證據最好是你自己能檢查的東西:先失敗再通過的測試、改動前後的錄影、trace、截圖。Prove It Works 也說,最強的證明是一支能重跑的 script,跑出來的輸出就是 reviewer 可以自己重跑的東西,不用相信 agent 的說法。
長時間任務也一樣。Autonomous run 這份 playbook 規定第一輪開始前,要把結束條件寫成一個能檢查的條件,例如「沒有舊 caller,而且 parser fixture 全部通過」,「跑四個小時」沒辦法檢查。最後一步寫得很明白:條件達成才停,進度卡住不算停,也不准為了宣告完成放寬條件。
測試怎樣才算有在驗證?
測試通過不代表行為正確,因為測試本身可能什麼都沒驗到。Test Behavior, Not Implementation 這條 principle 給了一個檢查方法:對每個測試想像兩種改動。
- 把行為改壞。 讓 code 回傳錯的值、少做一個副作用,或做兩次。測試還是通過的話,它什麼都沒證明
- 只改內部。 對外看得到的結果全部不變,只重構底下的實作。測試跟著失敗的話,它綁的是實作,每次重構都要重寫,也抓不到 bug
第一種改動抓得到、第二種改動不受影響的測試才留下來,其他的重寫或刪掉。
它也列出幾種常見的「假測試」:assertion 比合約寬鬆、預期值是用被測的 code 算出來的、assertion 檢查的是測試自己造出來的資料。這幾種在 agent 寫的測試裡特別常見,因為 agent 很容易先寫好實作,再用實作的輸出當預期值。
判斷一個 assertion 有沒有在驗行為,看的是合約。如果承諾是「空的購物車不會扣款」,那檢查付款 client 沒被呼叫就是在驗行為,但要搭一個會扣款的 case,證明這個測試看得到呼叫。外部服務收到的 payload 是行為,因為那個服務看得到;呼叫了哪個內部 helper 是實作,因為沒有使用者看得到。
這也是 Bug fix playbook 對 TDD 有保留的原因。/tdd 只在有便宜的本地測試路徑時才用。指南的說法是,硬用脆弱的 mock 寫出來的測試,證明的比跑一次真的指令還少。
量出來的數字要怎麼驗證?
效能數字是最容易不小心弄錯的證據。指南舉了幾個例子:改動後那次跑的時候 cache 已經有資料(warm cache),其中一邊用 debug build,或是計時的那段時間裡工作根本沒跑。每一種都能做出一個很有說服力的加速。
pstack 處理數字的是 Explain the Number 這條 principle,以及它的完整版 /benchmark-checklist。principle 的核心問題是「為什麼不是兩倍?」:說得出是哪個資源或哪段 code 限制了這個數字,例如一個 core、一把 lock、磁碟、網路,甚至是壓測工具本身,才算知道自己量到了什麼。從讀 code 猜出來的不算,要從 profile 或執行時的系統數據拿。
/benchmark-checklist 有七個問題,每一題都要拿實際跑出來的證據回答:
| 問題 | 在檢查什麼 |
|---|---|
| 為什麼不是兩倍? | 找出限制數字的瓶頸,對到 source |
| 有沒有調校過? | 兩邊都用 production 的設定跑,不然比的是設定,不是實作 |
| 有沒有超過物理極限? | 算一下頻寬、core 數,超過了代表量到的是快取、no-op 或 bug |
| 有沒有出錯? | 數失敗和錯誤回應,被拒絕的請求通常很快 |
| 重現得了嗎? | 每邊至少跑 5 次,A、B 交替,報中位數和範圍 |
| 對使用者有差嗎? | 量使用者等待的完整路徑,報 micro 結果佔整體的比例 |
| 工作真的有發生嗎? | 確認請求有到、資料有寫、結果有被用到 |
第三題是一道簡單的算術:一個佔整體 10% 的部分,就算完全拿掉,整體最多只會快大約 11%。agent 回報一個 40% 的加速,而它改的那段只佔 10%,不用重跑也知道有問題。
結論只有四種:變快、變慢、沒有可量測的差異、無法判斷。說不出瓶頸、有一邊沒調校、或是錯誤數和「工作有沒有發生」這兩題沒檢查,就只能報「無法判斷」。
專案沒有驗證工具怎麼辦?
專案沒有驗證工具時,pstack 用 /create-verification-skill 檢查 repo,產生一個專案自己的 verify-<app> skill,讓 agent 能用程式啟動、操作你的 app 並收集證據。「UI 改動要實際操作一遍」這句話的前提就是這個工具,很多專案沒有。
答案優先從 repo 找,只有 code 看不出來的才問人:使用者實際碰到的是什麼介面、app 在本機怎麼啟動、可以用什麼操作它(先找現有的 Playwright 或 Cypress,沒有才用瀏覽器 CDP、PTY 或 HTTP)、能收集什麼證據、兩個 instance 能不能同時跑。產生出來的 skill 有六個部分:
| 部分 | 內容 |
|---|---|
| Launch | 啟動指令,以及怎樣算準備好。要能從空的資料目錄啟動,「能用」才算準備好,process 有回應不算 |
| Doctor | 一個唯讀檢查:process 有沒有起來、版本對不對、port 是不是自己的 |
| Drive | 用這個 repo 真實的 selector 和指令操作 app,優先用 ARIA label 這類穩定的 handle |
| Evidence | 要收什麼證據、放在哪裡 |
| Cleanup | 只關自己啟動的東西,證據要保留 |
| Helpers | 附帶的 script 要能執行,用法寫在 skill 裡 |
Evidence 那段的標準寫得很細:走使用者真的會走的路徑,不用內部 setter 或只給測試用的 endpoint;動作和結果的狀態都要收,不能只截最後一個畫面;畫面看得到的之外,副作用也要驗,例如檔案有沒有寫、資料有沒有進、訊息有沒有送出。用 dry-run 模式時,要實際觀察它略過了什麼,不能只看名字就相信,因為有些 dry-run 還是會連網路。
skill 旁邊還有一份 feature map,每個功能一個檔案,從使用者的角度寫:這個功能是什麼、怎麼進到它、怎麼用工具操作、什麼可觀察的結果證明它正常。前置條件不夠時,這段流程要回報失敗,把原因記下來,不准把流程改弱來讓它通過。
最後一步是交出去之前,自己照著產生的 skill 完整跑一次:啟動、doctor、操作一個功能、收證據、清理,清理完確認證據還在。skill 裡的原話是,沒跑過的 verification skill 只是草稿。
app 會改,feature map 會跟著過時,所以還有 /maintain-verification-skill:對每個功能派一個唯讀的 subagent 讀 source,找出文件跟程式不一致的地方,再實際把每個功能操作一遍。它只能改 verification skill 自己的檔案,不能改產品 code。文件寫的行為 app 已經不做了,要先判斷是文件過時,還是產品壞了。文件過時就修文件,產品壞了就回報,不能改文件把 bug 蓋過去。
測試碰不到的情況怎麼驗證?
測試碰不到的情況,pstack 交給 /create-formal-verification-skill,用 formal verification 檢查一個性質在所有情況下是否成立。有些 bug 只在特定的執行順序下才會出現,例如 race condition、重試、狀態機、parser,測試只檢查有人想到要寫的 case。它在 repo 裡找出「壞掉會傷到使用者、測試又很少碰到」的地方,用合適的工具驗證一個性質:檢查執行順序用 model checker,預設是 TLA+;檢查 code 對每個輸入的行為,就用直接跑在 code 上的 verifier。
它對結果的要求跟前面幾節一致:
- 每個性質都要在一個故意改壞的版本上失敗過一次,沒看過失敗的檢查什麼都沒證明
- 現在的 code 違反性質時,帶著反例回報,不准放寬性質或模型來讓它通過
- 說清楚驗證了什麼、在什麼界限和假設下,通過只代表模型或界限內沒問題
- 記下每個檢查涵蓋哪些檔案和函式,以及最後確認時的 commit,code 改了下一個 agent 才知道要重看
「要能失敗」這條其實適用所有驗證,前面「把行為改壞,測試還過就沒用」講的也是同一件事。
為什麼寫 code 的 agent 不能自己驗證?
寫 code 的 agent 只會檢查它想做的東西,所以 pstack 的 Shipping playbook 規定,每個 PR 上線前都要由一個沒寫這份 code 的 verifier 用使用者的方式跑過,回報 PASS、PASS+NOTES 或 FAIL。playbook 的原文是:
「Only a verdict from an agent that did not write the code counts, because an author checks what it meant to build. Green CI and an approving bot review are not verdicts, because neither runs the change as a user would.」(Shipping playbook)
agent 想做的東西,不一定是它實際做出來的東西,這跟人自己 review 自己的 code 是同樣的盲點。CI 綠燈和 bot 的 approve 也不算,因為兩者都沒有用使用者的方式跑過這個改動。
驗證結果還要對得上現在的 code。stack 裡的 PR rebase 之後,每個 PR 的 SHA 都會變,CI 卻不一定會失敗。playbook 要求比對驗證當時和現在的 git patch-id,patch 變了就要重新驗證。上線時從最底下的 PR 開始往上,遇到第一個沒通過驗證的就停。
證據要是真的、測試要能失敗、數字要能解釋,最後還要有一個沒寫這份 code 的 agent 來看。四件事都做到,驗證才接近 review 在做的事。
在 Claude Code 怎麼安裝和使用?
Cursor 的 plugin repo 也是 Claude Code 的 marketplace,安裝方式:
/plugin marketplace add cursor/plugins
/plugin install pstack@cursor-plugins
Claude Code 會在指令前面加 plugin 名稱當前綴,所以要打 /pstack:poteto-mode。裝好後跑一次 /pstack:setup-pstack 設定每個角色用哪個模型,再開新的 session。
之後的任務用這個格式下:
/pstack:poteto-mode <你看到的現象,或你要什麼>
Done means <agent 可以執行或檢查的條件>.
Keep <不能改變的既有行為>.
這個格式就是前面講的驗證觀念:現象決定要重現什麼,Done means 是完成條件,Keep 是不能被打壞的行為。你不用記得要叫哪個 skill,playbook 會決定順序。
什麼時候適合用 pstack?
pstack 適合「看起來做完」和「真的做完」差很多的任務。下面三個情境都取自 README 的範例 prompt,可以看出 playbook 在每一種情況下替你多做了哪些事。
情境一:難以重現的 bug
/poteto-mode this pr has a subtle bug where the scroll drifts every 750ms even when idle. repro
first, then fix and verify.
這種 bug 最難的部分是重現,修法常常只有幾行。沒有流程約束時,agent 很容易讀完 code 就猜一個原因,加個 guard 回報修好。這個 prompt 會走前面那份 Bug fix playbook,agent 得先在閒置的頁面上把每 750ms 一次的偏移抓出來,才能開始找原因。你拿到的是修之前失敗、修之後通過的輸出,不用再自己捲一次頁面確認。
情境二:說不出原因的效能問題
/poteto-mode a big list takes a second or two to load even though we virtualize. run a cpu trace
and tell me why.
效能問題最常見的錯誤,是讀 code 猜瓶頸,改完覺得變快了。Perf issue playbook 規定每個修正都要對到一次量測:先錄一份 baseline trace,用 /benchmark-checklist 檢查這個數字可不可信,再從 trace 規劃修法。修法依成本由低到高排順序,第一個是「不要做」,也就是先停掉結果沒人用的工作,接著才是不重複做、少做、晚點做、平行做、做得更便宜,前面的方法達標就停。回覆要附 baseline 數字、修完的數字、差距和 trace 檔案的路徑。
情境三:人不在場的大範圍遷移
/poteto-mode i'm stepping away. migrate every caller from the synchronous store to the new async
one, keeping behavior identical. i want to trust it was done right when i'm back.
這種任務改的地方很多,人又不在旁邊看,最怕的是回來看到一個巨大的 diff,不知道從哪裡開始 review。pstack 會把它交給 figure-it-out,替這次遷移設計一套專屬的流程。工作切成一個個小單位,每個單位都要通過檢查才做下一個;舊 API 的 caller 全部遷移完,就在同一波把舊 API 刪掉;每個決定記進 decision log,寫下做了什麼、為什麼、證據是什麼。你回來時看的是一份決策紀錄和一串各自驗證過的 commit,判斷能不能信任它的成本低很多。
什麼時候不該用 pstack?
小改動不該用。改一句文案、調一個設定值,跑整套 playbook 加上多個模型,時間和 token 成本都不划算。Flavio 自己的做法是例行工作用便宜的模型,只在困難的部分動用前沿模型。
規模也要對。pstack 的指南提醒,任務跑得久不代表它是一個 program,Orchestrate 這種多天、多個 stacked PR、一群 subagent 的流程,留給真的需要協調的長期專案。一個 agent 在一個 session 內做得完的事,用一般的 playbook 就夠了。
專案還沒有驗證方式時,也不要期待 pstack 一裝上去就能自動驗證。agent 沒辦法操作你的 app,「實際走一遍流程」就做不到,playbook 最後只能回報 inconclusive。這種情況先跑一次 /create-verification-skill,把驗證工具建起來,後面的 playbook 才有東西可以用。
pstack 本身很重,但它的驗證觀念不需要整套裝起來才用得到。叫 agent 把完成條件寫成能跑的檢查、要它附上看過的證據、說不出證據就回報無法判斷、上線前找另一個 agent 用使用者的方式跑一次,這幾件事寫進自己的 CLAUDE.md 或 skill 就能做到。想讓 PR 自動 merge,要先建立的是一套能取代 review 的驗證流程,pstack 是我目前看到寫得最完整的參考。