分類: 工具與實踐

  • Claude Design 實戰拆解:brainstorming/spec/plan 三層流程的必要性與代價

    重點摘要

    • Claude Design 不是一個工具,是 Claude Code 裡由 brainstormingwriting-planssubagent-driven-development 三個技能組成的結構化開發流程,把「想 → 寫規格 → 拆任務 → 做 → 審查」變成可追蹤的步驟。
    • 最大價值是「砍掉不該做的事」——在我的失智症陪伴專案裡,這個流程幫我在寫 code 前砍掉了背景音樂、獨立話題卡、每日心情打卡三個功能,省下至少 3-4 小時重工。
    • 設計原則會在對話中浮出來——使用者一句「照顧者腦子清晰的,可以有期待的方式知道」變成整個系統的「可預期」原則,驅動 45 條提示語都用同一個模板。
    • 但它不適合所有情境——單檔 HTML 原型用 subagent-driven-development 會被 39 次 subagent dispatch 拖到超慢,實測比 inline 慢 3-5 倍。
    • 判斷標準:想事情時用 brainstorming、寫一致內容時用 spec、多檔複雜時用 subagent;單檔改一個函式就直接 inline。
    • 最深的反省:Claude Design 其實就是把 SDD「菜譜化」。人人可以照做,但如果不懂菜譜背後的「為什麼」,遇到菜譜涵蓋不了的變化就卡住。AI 時代最危險的是「永遠繞著菜譜轉、卻以為自己會了」——你的能力上限會被 AI 給的菜譜深度封頂。
    • 用中華一番「大魔術熊貓豆腐」案例說明:對手下黑手、大豆意外變納豆、把汙染當靈感——這三個 AI 結構上做不到的元素。文末附 7 個對抗菜譜化的具體做法,最關鍵是「保留一塊 AI 絕不介入的創作領域」。

    「Claude Design」這個名字其實沒有官方定義,它是 Claude Code 裡一組設計驅動的工作流程技能(superpowers:brainstorming / writing-plans / subagent-driven-development)的總和。我最近用它做了一個失智症陪伴 APP 的重大功能迭代,這篇文章把它在實戰中「什麼時候救了我」跟「什麼時候反而拖慢我」完整拆給你看。

    Claude Design 是什麼?三層流程一次看懂

    Claude Design 是一套讓 AI 助手在動手寫 code 前先「想清楚 → 寫規格 → 拆任務」的結構化流程。它不是任何新工具,而是 Claude Code 內建的三個技能組合使用:

    階段 技能名稱 產出 目的
    1. 發想 brainstorming 設計 spec(Markdown) 用多輪一問一答釐清需求、砍掉不該做的、浮出設計原則
    2. 規劃 writing-plans 實作計畫(含驗證步驟) 把 spec 拆成 10-20 個可個別 commit 的小任務
    3. 執行 subagent-driven-development 每個 task 一個 commit 派 subagent 做、派 subagent 審 spec、派 subagent 審 code quality

    重點不是「三個步驟」這個形式本身,而是每一步強迫你跟 AI 在不同粒度上達成共識:brainstorming 達成「做什麼」、spec 達成「做成什麼樣」、plan 達成「怎麼拆」、subagent 執行時還能雙重審查。

    沒用 Claude Design vs 用 Claude Design 的實際差異

    同樣是「加一個照顧者支援功能」的需求,兩種做法的差別在哪?這是我實測後的對照:

    面向 直接叫 AI 寫 走 Claude Design 流程
    需求釐清 憑 AI 猜,常常做錯方向 多輪問答,需求明確後才動手
    功能範圍 容易做太多(AI 傾向加功能) 在 brainstorming 階段就砍掉不必要項目
    一致性 做到一半風格會漂移 spec 用表格固定內容模板
    可追蹤 一個大 commit 或多個散亂 commit 每 task 一個 commit,可個別 revert
    重工成本 常常寫完才發現方向錯 方向錯在 spec 階段就發現
    速度 單點快、整體容易重工 前期慢、後期穩;不適合微任務

    實戰案例一:砍功能,省下 3-4 小時重工

    Claude Design 最值錢的貢獻不是寫 code,是阻止你寫不該寫的 code。在我的失智症陪伴 APP 迭代過程中,brainstorming 流程實際上幫我砍掉了三個功能:

    砍掉案例 1:背景音樂

    我一開始提議加背景音樂(失智症音樂療法有根據),brainstorming 過程中討論到「單檔 HTML 沒辦法帶 MP3、base64 嵌入會讓檔案爆到 30MB、用 File API 每次要重選」三個技術方案的取捨後,使用者自己說「先不要」。如果沒經過討論直接開寫,我大概會先做 File API + ducking 邏輯寫個兩小時,結果做完發現整個方向不對。

    砍掉案例 2:獨立話題卡

    原本規劃「話題卡」+「遊戲中陪伴提示」是兩個獨立功能。討論到一半,使用者界定:「這個 APP 是玩樂的時候用,真的要純聊天另外開 APP」。這句話直接把「獨立話題卡」功能從 spec 刪除,只保留遊戲情境下的提示。沒有這個界定,我會把話題卡塞進首頁,未來做下一個 APP 會有功能衝突。

    砍掉案例 3:每日心情打卡

    我在 brainstorming 時列過 5 個功能候選,其中「每日狀態簡記」(3 秒打卡心情/精神/食慾)看起來很有價值。使用者沒選這個,理由是「會把 v2 從『打開就用』變成『每天要記得打卡』,失智照顧者已經很累了」——這是使用者比我更懂他的使用情境的典型例子。AI 單獨設計是想不到這層的。

    這三個砍掉的功能合計估計省了 3-4 小時的 coding + 之後的 code review + git 回改。這才是 Claude Design 最值錢的部分——它讓「沒寫到 code 就砍掉」變成可能。

    實戰案例二:「可預期」這個原則如何救了 45 條提示語

    brainstorming 過程中,使用者往往會不經意說出一句話,變成整個系統的設計支柱。這次是這一句:

    「我希望對於照顧者而言,他是腦子清晰的,他可以有期待的方式知道,我可以看到該說什麼。」

    這句話裡面的「可預期」被提煉成整個功能的設計原則,寫進了 spec。然後這個原則驅動了三個具體決策:

    1. 提示固定模板:15 個遊戲 × 3 個時機(開場/答對/完成)= 45 條提示,全部用「情境 → 可以直接說的話」這個同一個格式,照顧者看一次就學會。
    2. 摘要強制預覽:不是一按就複製,而是開 modal 預覽、確認內容,才複製。照顧者對輸出「可預期」。
    3. 按鈕只在完成活動後才出現:有資料才有按鈕,避免使用者按下去才發現「沒東西可傳」。

    沒有 brainstorming 把這個原則浮出來、沒有 spec 把它寫下來,我會寫 45 條有個性的不同句型(AI 本能會追求多樣性)。結果照顧者每次要重新解讀 UI,反而更累。「可預期」這個字沒有出現在原始需求,是對話中自然生成的,但它比任何功能清單更重要。

    實戰案例三:Spec 表格讓語氣不漂移

    Spec 文件裡有一張表格,把 15 個遊戲 × 3 個時機 × 實際內容全部列出來:

    遊戲 開場 答對時 完成時
    顏色辨識 哇,好多顏色,你以前最愛穿什麼顏色? 對!你好厲害 今天陪你看顏色,我也覺得很漂亮
    認字遊戲 這個字你以前就認得吧 對啦,這個字你小時候就會了 今天還認這麼多字,真棒
    呼吸練習 我們一起慢慢呼吸 (改成中段顯示)吸氣…吐氣…不急 輕輕摸摸他的手,這樣就好

    如果不是在 spec 階段一次寫完這張表,而是「做到顏色遊戲時寫顏色的 3 條 → 做到形狀遊戲時寫形狀的 3 條」這樣推進,語氣一定會漂移。寫到第 10 個遊戲的時候我會忘記前面的語氣,變成有些句子很溫暖、有些很乾。表格逼我一次寫完,才有辦法保持「你年輕時、你很厲害」這類一致的溫度。

    這是表格化內容的威力——它讓「一致性」不是靠意志力維持,而是靠資料結構強制。

    反例:Claude Design 不適合的時候

    這次實戰也讓我踩到一個很明顯的坑:subagent-driven-development 對單檔 HTML 原型是殺雞用牛刀

    我一開始對 13 個 task 全部套用標準流程:每個 task 派 1 個 implementer subagent + 1 個 spec reviewer + 1 個 code reviewer,總共 39 次 subagent dispatch,每次 20-130 秒。前幾個 task 都只是「加一個 const、改一個函式」這種改動,triple review 完全是過殺。

    使用者實測後直接問我:「你寫程式變慢很多你用什麼模型」——這是一個誠實的信號。我當下檢討並切換到 inline 執行模式(我自己在 session 裡直接做),後半段 8 個 task 的速度回到正常的 3-5 倍。

    這個教訓很值:流程的 overhead 必須跟 task 粒度匹配。如果你的 task 只是改 20 行 code、不會影響其他模組,triple review 沒有價值,還會讓每個 task 多花 3-5 分鐘在 subagent 啟動/總結上。

    更重要的反省:Claude Design 是「菜譜」,不是基本功

    讀到這裡,你可能會問:「Claude Design 其實不就是 Spec-Driven Development(SDD)嗎?」 沒錯。brainstorming + spec + plan + implement 這四步是 SDD 老方法,不是 Claude Code 發明的。Claude Design 做的事其實是把 SDD 從「一千個人有一千種做法」方法化成「人人可以順暢工具化」的標準流程

    這是好事,也是很危險的事。

    菜譜出現前、出現後

    想像一下麻婆豆腐這道菜:

    • 菜譜出現前:只有師傅會做。每個師傅的麻婆豆腐都不一樣,因為他們從「為什麼要用豆瓣醬、為什麼花椒要後下」這種基本功思考過。客人要求「少辣多麻、加竹筍」這種變化,師傅能即時調整。
    • 菜譜出現後:人人可以照做,麻婆豆腐變得普及。但只會照菜譜的人,遇到「客人對豆瓣醬過敏,要用別的替代」這種問題就卡住了——因為他從來沒問過「為什麼要用豆瓣醬」。

    Claude Design 就是出現了菜譜。它把 SDD 的步驟變成 Skill、把「設計審批」變成 <HARD-GATE>、把 subagent 審查變成標準流程。你不需要知道為什麼要分離「設計」和「實作」,照著 skill 走就有規範的輸出。

    為什麼 AI 時代這件事特別危險

    菜譜時代的廚師,至少還能從菜譜回推原理——多做幾次就知道花椒晚下是為了香氣不揮發。但 AI 時代:

    1. 你問 AI「怎麼做需求分析」→ AI 給你 Claude Design 流程
    2. 你照流程做,產出看起來很漂亮的 spec 和 plan
    3. 你以為你會做需求分析了
    4. 遇到「這個需求太模糊、brainstorming 走 10 輪還是卡住」這種菜譜沒涵蓋的情況
    5. 你再問 AI → AI 給你另一個菜譜
    6. 你永遠繞著菜譜轉,沒有真的建立「為什麼需求會模糊、要怎麼引出使用者的隱藏前提」這種基本功

    最可怕的結果:你的能力上限永遠等於 AI 提供的菜譜深度。菜譜涵蓋不了的變化,你就做不到。而且因為你沒痛過傳統 SDD 的坑,你連「現在這個情境是菜譜解不了的」都判斷不出來——你不知道自己不知道

    SDD 真正的基本功是什麼

    Claude Design 的 skill 不會教你這些,但這些才是真正讓你能判斷、變通、甚至挑戰流程的基本功:

    菜譜只教你「做什麼」 基本功讓你懂「為什麼」
    brainstorming 要一次問一個問題 人的認知頻寬有限,多問題並排會讓使用者選擇癱瘓而隨便回答
    spec 要寫 45 條提示的表格 分批生成會有語氣漂移,但為什麼會漂移?因為 LLM 每次 context 都重新「感覺」一次
    實作前要設計審批 因為修改 code 的成本遠高於修改文字,越晚發現方向錯越貴
    subagent 要 triple review 多視角審查降低單一 agent 的盲點,但前提是 task 複雜到值得這個 overhead
    每 task 一個 commit Git bisect 的粒度等於 debug 速度,太粗的 commit 追 bug 要多花 10 倍時間

    懂了「為什麼」,你才能在菜譜斷裂的地方自己接住。例如:brainstorming 走不下去,你會知道這是因為使用者自己也沒想清楚,你要換一個方式(給他看 mockup 而不是繼續問字)而不是換另一個菜譜。

    給讀者的反省題

    每次用 Claude Design 之前,自問一句:「如果沒有這個菜譜,我會怎麼做這件事?」

    • 如果你答得出來 → 你用 Claude Design 是省時間
    • 如果你答不出來 → 你該先花時間讀 SDD 的原理,而不是依賴 skill 的自動化

    這不是反對 Claude Design。菜譜是好事,讓一道菜普及化。我想提醒的是:Claude Design 方便到你可能永遠不會問「為什麼」。而一個工程師的上限,取決於他問過多少個「為什麼」

    什麼時候用、什麼時候跳過?判斷決策表

    情境 建議流程 理由
    有多個可能方向、還在猶豫 brainstorming 避免選錯方向重工
    要改 15+ 個相似位置、要寫一致的內容 brainstorming + spec 用表格強制一致性
    多檔複雜後端、有 test framework、多人協作 完整三層 + subagent triple review 能防止衝突跟回歸 bug
    單檔 HTML、改一個函式、加一個按鈕 直接 inline,跳過流程 overhead 大於價值
    修 bug 已經知道怎麼修 直接改,不派流程 問題明確時流程是拖累
    重構一個模組的架構 brainstorming + spec(可能跳過 subagent) 要想清楚新架構但執行可以快

    3 個給讀者的實作建議

    1. 開工前先問自己一句話:「這個 task 的粒度適不適合走流程?」如果是「修一個 bug」「改一個顏色」,直接做;如果是「加一個新功能」「重構一個模組」,走 brainstorming。
    2. brainstorming 時刻意引導 AI 砍東西,不是加東西。AI 本能傾向加功能,你要主動問「這個是不是另一個 APP 的事?」「這個能不能先不要做?」。砍掉的功能是最值錢的產出。
    3. Spec 一定要用表格呈現重複性內容。如果你有 10+ 個相似的東西(15 個遊戲的 3 條提示、20 個 API 端點的 error message、12 個表單欄位的 placeholder),強制用表格一次寫完,不要分批生成。

    中華一番案例:AI 結構上做不到的創新

    講到這裡都還是抽象論述。讓我用一個具體案例把「AI 為什麼結構上做不到某些創新」講清楚——1997 年日本動畫《中華一番》第 43 集「大魔術熊貓豆腐」。

    劇情背景:小當家與黑暗料理界的邵安,在樓麟艦上進行豆腐對決。評委要求不能用現成豆腐,必須從黃豆開始做。比賽中:

    1. 對手下黑手:黑暗料理界的向恩把稻草偷偷放進小當家的大豆裡
    2. 意外發生:稻草上的納豆菌讓大豆發酵,大豆變成了納豆(日本傳統發酵食品)
    3. 認知翻轉:小當家看到黏糊牽絲的納豆,不是當成「比賽被破壞」丟掉,而是把這個意外當成靈感起點
    4. 創新誕生:從納豆的特性衍生出做法與工具,最終做出「大魔術熊貓麻婆豆腐」擊敗邵安

    (資料來源:萌娘百科納豆條目,ACGN 中的納豆相關劇情段落)

    這故事裡有三個 AI 結構上做不到的元素

    劇情元素 AI 為什麼做不到
    對手下黑手破壞材料 AI 的 brainstorming 永遠假設「正常情境」,不會模擬「比賽中有人陷害你」這種社會性干擾
    辨識大豆已變納豆 需要跨文化背景知識在當下湧現。一個四川廚師要有人把日本發酵食品的視角帶進來,AI 知道但不會主動從「邊緣」冒出來
    把失敗當靈感起點 AI 被訓練避免失敗、給成功解。被汙染的食材應該丟掉重做——這是 AI 的強勢模式。把 contamination 翻轉成創新起點是訓練資料裡的反模式

    我把這個對比叫做「紹安路 vs 小當家路」

    • 紹安路:精修技術、重組既有元素、走正統菜譜 → AI 擅長
    • 小當家路:個人記憶 + 意外事件 + 跨文化知識 + 重新定義失敗 → AI 做不到

    紹安在豆腐三重奏對決中輸得更深:他自以為原創的料理,其實 7 年前師父陳邦鈴就做過一樣的。他切斷了有意識的傳承,但無意識的傳承切不斷——他走遍中國、投奔黑暗料理界研發的「自創」菜,結構上還是師承的重組。

    用 Claude Design 久了的人可能遇到比紹安更慘的處境:紹安至少還是在複刻真實的師父,你在複刻 AI 訓練資料——但你不會知道,因為沒人會告訴你「這個東西 AI 在 2023 年就生成過一模一樣的了」。

    7 個對抗紹安化的具體做法(可以從下個 task 開始)

    如果你接受「菜譜化是現實、不會回頭」這個前提,那問題就不是「要不要用 Claude Design」,而是「怎麼用但不被它吃掉」。以下是我經過這次專案後整理的 7 個具體做法:

    1. 先離線想 10 分鐘,再開 AI

    用紙筆或純文字檔,在沒有 AI 的狀態下先寫下你對這題的想法——即使亂七八糟、半句話、只有關鍵字。寫完才來找 AI。這 10 分鐘的差別,是你有沒有在對話開始前建立自己的立場。

    2. 刻意加入 AI 絕對不會建議的約束

    AI 傾向推薦「平均來說最好的解」。你主動加怪條件逼自己走不一樣的路。例:做失智症陪伴工具時,不要說「做陪伴 APP」,說「做一個只能給老花眼、色盲、聽障照護者用的工具」——限制是創新的助產士。

    3. 每週跟一個「四郎」講一次話

    不是讓他們給你解決方案,是把他們的「意外知識」放進你生活。失智照護協會的阿姨、你媽或阿嬤(上一代的照護記憶)、會日文的朋友、幼稚園老師(他們跟認知差異的小孩互動方式跟失智照顧很像)⋯⋯讓他們隨口說的話在你腦裡發酵,像稻草丟進黃豆

    4. 把「bug / 意外 / 失敗」當創作材料,不是要避免的事

    開一個 inspirations-from-failures.md,每次遇到意外事件,先不要問怎麼解,先寫三句話:這個意外讓我看到什麼我原本沒看到的?這個限制如果我接受它,會變成什麼新東西?如果我把這個「bug」當成功能,會是什麼?AI 的訓練資料裡「bug 要修」是強勢模式,你要刻意反抗這個傾向。

    5. 對 AI 使用「反向問法」

    每次 AI 給你答案,下一句問:「這答案的相反是什麼?」「80 歲阿嬤會怎麼想這件事?」「如果這是錯的,錯在哪?」「這答案看起來合理,可是我錯過了什麼?」——這會強迫 AI 跳出訓練資料的中心,去邊緣抓東西。AI 不會主動做這件事,你得逼它。

    6. 保留一塊「AI 絕不介入」的創作領域

    不是「少用 AI」,是完全禁止。具體例子:照顧長輩的手寫日記(絕不給任何 AI 看)、一個嗜好(煮菜、種花、學樂器)、每週一天完全不開 Claude / ChatGPT。這塊領地是你保持「能產生小當家型靈感」的保護區。失去這塊,你永遠只能是紹安。

    7. 跟 AI 約定「小當家模式」信號詞

    當你要創新、不要優化時,直接跟 AI 說:「這次我要小當家模式,不要 Claude Design」。你的 AI 應該立刻做三件事:關閉所有 brainstorming/spec/plan 流程建議、不給業界做法、反過來問你的個人史跟身邊的人。這是你跟 AI 之間的信號詞。沒有它,AI 會把菜譜當成預設。

    優先順序:如果只能選一個開始

    選第 6(AI 禁區)。沒有這個,其他六個遲早會被 Claude 侵蝕回去。禁區是你維持「小當家能力」的物理基礎。

    結論:不是流程多就好,是流程跟 task 匹配才好

    Claude Design 不是一個「你該永遠用」的聖杯,也不是一個「多此一舉」的噱頭。它是一套當你面對真正需要思考的問題時,把你跟 AI 之間的對話規則化的工具。

    我這次失智症陪伴 APP 專案裡,Claude Design 救了我的前半段(brainstorming 砍功能 + spec 寫一致的 45 條提示),拖慢了我的後半段(subagent-driven-development 對單檔 HTML 過殺)。能分清這條線,是下次用它用得更好的關鍵。

    如果你的下一個 task 真的很簡單、你已經知道怎麼做——直接做。但如果你正在「想不清楚這功能該不該做」或「要做 15 個相似的東西怕語氣不一致」,那就值得花 20 分鐘先走 brainstorming。這 20 分鐘會幫你省下 3-4 小時。

    延伸閱讀

  • Ionic 逆向重建 Flutter 完整踩坑紀錄:三套 APP、20+ 個坑、一套方法論

    重點摘要

    • 從 Ionic 1 / AngularJS + WordPress PHP 逆向重建三套 Flutter APP,歷時一週,踩了 20+ 個分類的坑
    • 最毒的方法論錯誤:審查時讀了原始碼,實作時卻只靠缺失清單——導致多輪審查永不收斂
    • PHP Broker API 的 Content-Type 是 text/html、數值欄位全是 String、token 欄位名稱每個子系統不同
    • WordPress Multisite 的 table prefix 陷阱:直接打 plugin 路徑走 main site(wp_),跟 WP Admin 看到的(wp_2_)不同
    • 逆向工程的核心原則:原始碼是唯一 ground truth,不是用戶的記憶,不是截圖,不是 AI 的推測

    這篇文章記錄了一個完整的逆向重建專案:將一套社區管理系統(三套 APP + WordPress 後端)從 Ionic 1 / AngularJS 遷移到 Flutter。不是新開發,是一比一逆向複製——原版有的每一個按鈕、每一個欄位規則、每一個邊角功能,新版都必須完全復現。

    三套 APP 分別是:住戶 APP(社區公告、包裹、費用等)、管理平板(出勤、包裹管理、公設租借、訪客登記等)、門禁保全 APP(簽到簽退、巡邏、QR 掃描)。它們共用同一個 WordPress PHP 後端。

    以下是按主題分類的完整踩坑紀錄和方法論總結。

    一、逆向重建最毒的方法論錯誤是什麼?

    逆向重建最毒的方法論錯誤是「審查讀原始碼、實作不讀」。這聽起來不可能,但在 AI 輔助開發中極其常見:

    1. 審查 Agent:從原版 HTML / JS 逐行讀 → 產出缺失清單 → 每項有行號出處 ✅
    2. 實作 Agent / 新 Session:拿到缺失描述(如「公告無窮捲軸缺失」)→ 直接寫 Flutter → 沒有讀原版邏輯
    3. 結果:修了 A,同頁的 B/C/D 仍缺(因為根本沒讀那頁的完整原始碼)
    4. 下輪審查:再從原版讀 → 再找到 B/C/D → 循環不斷

    我們經歷了 7 輪審查才讓管理平板的缺失清單收斂。前 3 輪每輪都有 10+ 個新發現,根本原因只有一個——方向反了。

    建立的強制規則

    • 拿到缺失 ID 時,必須先讀對應的原始碼(file:line),不得只靠缺失描述動手
    • 修某頁某功能時,如果手上沒有該頁完整 Source Inventory → 必須先做 Source Inventory
    • Review 方向必須是:原版 HTML → 原版 JS → 原版 PHP → 列清單 → 逐項對照新版。禁止從 Flutter 出發猜原版有什麼

    二、Source Inventory 協議:逆向工程的唯一正確開始方式

    Source Inventory 是在動手寫任何程式之前,先把原版的所有功能逐行列出來的過程。每一項都必須標注原始碼來源(檔案 + 行號),沒有行號的項目等於捏造的。

    - [ ] 登出按鈕
          來源:account.html:142 <button ng-click="logout()">
    
    - [ ] 棟別/樓層兩層下拉選單
          來源:visitor-form.html:55-67, controllers.js:9366-9398
    
    - [ ] 黑名單檢查(借用簽名後、API 呼叫前)
          來源:publicequip.js:2040-2052

    清單涵蓋四大類:所有 UI 元素(按鈕、欄位、badge、空狀態提示)、所有互動行為(點擊、滑動、下拉刷新)、所有 API 呼叫及欄位映射所有頁面入口/出口

    最容易漏的永遠是邊角功能:登出藏在 header component、空狀態提示在條件分支、黑名單檢查在簽名驗證之後。主流程之外的東西,AI 不會主動去找。

    三、PHP Broker API 的七大陷阱

    這套系統的 API 層是 WordPress PHP plugin,所有請求都走同一個 Broker endpoint。以下是我們踩過的每一個 API 相關的坑:

    3.1 Content-Type 是 text/html

    PHP Broker 的回應 Content-Type 是 text/html 而非 application/json。Dio(Flutter HTTP 套件)如果設了 ResponseType.json,會解析失敗。必須設 ResponseType.plain 再手動 jsonDecode

    3.2 數值欄位全是 String,除了偶爾不是

    大多數 JSON 數值欄位回傳的是字串("id":"1")。但 $wpdb->get_results() 對 int DB 欄位有時會回傳 PHP native int(JSON 裡沒有引號)。解法:所有 nullable String 欄位一律用 ?.toString(),避免 type 'int' is not a subtype of type 'String?'

    3.3 Token 欄位名稱每個子系統不同

    子系統 Token 放在 例外
    主 Broker(住戶/平板)data.cookie
    Guard Broker(門禁)data.tokenvalidate_authdata.cookie

    搞混了就會被判定為 anonymous user,API 回 "非有效角色,無法使用!",而且沒有任何認證失敗的明確錯誤碼

    3.4 returnCode 不統一

    "OK""0"(package 模組)、"1""ERROR""dup"——全是字串,不要做整數比較。每個模組的成功碼不同,必須逐一確認。

    3.5 Category / Method 命名混亂

    有的是 snake_case(get_ticket_by_member_id),有的是 camelCase(retrivePublicEquipTXN——對,retrive 是拼錯的),有的是完全不同的規則(createTableAccount)。必須從 PHP 程式碼抄出精確字串,不能猜。

    3.6 Response 結構不一致

    • mutual:回 {rows_1:[], rows_2:[]}(自己的 + 社區其他人的)
    • ticket:回 {data: {rows, total, totalPages}}(分頁結構)
    • package_light:returnCode 用 "0" 而非 "OK"
    • getTwCode:空表時回 data: ""(空字串),不是 []

    3.7 磁卡批次 API 是 flat array

    大部分 API 的 data 格式是 {data: {key: value}},但磁卡批次領取是平坦陣列 [{id, card_no, status}]。PHP 端用 is_array($data) 判斷。這意味著 Flutter HTTP client 的 data 參數不能寫死為 Map,必須改成 dynamic

    四、WordPress Multisite 的 Table Prefix 陷阱

    WordPress Multisite table prefix 陷阱是整個專案最令人崩潰的問題之一。直接打 plugin PHP 路徑(如 /wp-content/plugins/.../API_Broker.php)時,WP 識別為 main site (blog_id=1),使用 wp_ 前綴。但在 WP Admin 介面、phpMyAdmin 看到的是 wp_2_(子站表)。

    後果:seed 測試資料時插到 wp_2_ulifeplus_*,但 API 查的是 wp_ulifeplus_*——資料永遠看不到,而且不報錯,就是空陣列。

    另外,改網域必須改 5 個地方wp_options(siteurl + home)、wp_blogs(domain)、wp_site(domain)、wp-config.php(DOMAIN_CURRENT_SITE + WP_HOME + WP_SITEURL)。DOMAIN_CURRENT_SITE必須含 port,否則會無限 302 redirect。

    五、validate_role() 全面封鎖事件

    所有 28 個 PHP endpoint 都在進入主邏輯前呼叫 validate_role()。原版只接受 ulifeplus_api / ulifeplus_admin / administrator / ulifeplus_operator,不含住戶帳號 ulifeplus_subscriber

    原因:原版平板用的是專屬服務帳號(QR code 開通碼流程),不是住戶帳號直接登入。重建版讓住戶直接登入 → 所有 API 一律 ERROR

    修補方案需要雙層:(1) patch PHP 接受 ulifeplus_subscriber;(2) 給測試帳號加 ulifeplus_api role。而且 wp_capabilities 的序列化格式 a:N:{s:LEN:"role_name";b:1;} 的 LEN 必須精確——寫錯一個字元,整個 unserialize 就失效,用戶變成沒有任何 role。

    六、三套 APP 的進化軌跡:從混亂到方法論

    第一套:住戶 APP——摸清後端規則

    住戶 APP 是最先做的,主要踩了後端相關的坑:Content-Type 是 text/html、數值欄位全是 String、member_id vs WP user_id 混淆、validate_role 全面封鎖、WP Multisite table prefix。這些經驗讓我們對 PHP Broker 的行為有了完整的心智模型。

    第二套:管理平板——方法論崩潰與重建

    管理平板是最複雜的(10+ 模組),也是方法論崩潰的戰場。7 輪審查、每輪都有新發現、多個 Agent 交叉審查卻互相誤報(false positive)。最終逼迫我們建立了 Source Inventory 協議、四大卡點規則、和「審查必須從原版出發」的強制流程。

    核心教訓包括:

    • Grid → Card List 轉換會遺失 checkbox column 和 cellTemplate 等「免費」UI 行為
    • 條件式按鈕(enableShowClosed 等)的每個 ng-if 都是業務意圖,不能合併或省略
    • smart_disp.get_hidden_code() 遮名演算法需要完整移植,不能簡化
    • 日期範圍查詢必須含時間(00:00:00 / 23:59:59),否則 BETWEEN 漏掉當天
    • Feature flag 的預設值不一定是 false,必須讀完整條件判斷

    第三套:門禁 APP——方法論成熟

    到第三套門禁 APP 時,Source Inventory 協議已經內化。整個 APP 從原始碼分析到 21/21 測試通過只花了一天。但還是踩了新坑:

    • Guard Broker 的 token 欄位是 data.token(不是主 Broker 的 data.cookie
    • PHP class constant const data = "date" 從不生效(bareword array key 行為)
    • showDialog 的 BuildContext 跨 async 導致確認 dialog 靜默失敗
    • HTTP 部署下相機 API 被瀏覽器封鎖(Secure Context 限制)
    • Flutter Web 的 SPA 狀態在測試間污染(需 full HTTP reload)

    七、Flutter 遷移的技術坑清單

    症狀 修法
    flutter_secure_storage Web 失敗HTTPS 才能用 Web Crypto APIWeb 改用 SharedPreferences
    Platform.isAndroid Web crashdart:io 在 Web 不可用kIsWeb + defaultTargetPlatform
    CORS 重複 headerAccess-Control-Allow-Origin: *, *PHP 已有 CORS,不要加 .htaccess
    Dialog context stale確認後邏輯靜默跳過dialogCtx 不用外層 context
    Release build debugPrint 消失完全無錯誤訊息寫 SharedPreferences breadcrumb
    ConsumerWidget 無 initState需要 async 初始化改用 ConsumerStatefulWidget
    base-href 部署子路徑資源 404--base-href=/app/
    API_BASE_URL dart-defineWeb 連到 localhost--dart-define=API_BASE_URL=http://IP:PORT

    八、AI 輔助逆向工程的認知陷阱

    AI 輔助逆向工程的認知陷阱是這個專案最深層的教訓。AI 在讀原始碼方面能力極強,但在以下場景會系統性犯錯:

    1. 「我以為我知道這頁有什麼」——AI 會基於已讀的程式碼推測未讀的部分,經常猜錯
    2. 改名後誤報缺失——搜尋 scan_addr_code() 找不到,但 Flutter 用了 _scanAddressCode(),同樣邏輯換了名字就被誤報
    3. 函數名稱 ≠ 實際行為——updateUser() 實際上還做 log 寫入、狀態機轉換;getActiveItems() SQL 是 status != 'deleted' 不是 status = 'active'
    4. 「延後功能」不是藉口——AI 傾向把不確定的功能標記為「deferred」,但只要原版存在的就必須實作

    破解方式:建立 Source Inventory 清單,每項附行號。行號是可審計的(可以回去原始碼驗證),AI 的記憶不可審計。

    九、跨專案知識管理:Brain 檔案系統

    為了讓踩過的坑不只活在一個專案裡,我們建立了 Domain Brain 系統:每個技術領域一個 markdown 文件,記錄所有踩過的坑、修法、和來源。

    例如 legacy-code-rebuild.md 記錄了逆向工程的通用方法論;wordpress-broker.md 記錄了 WP Broker API 的所有特殊行為。每次 fix: commit 時,強制要求更新對應的 brain file。

    核心原則:Brain = 上次做的時候踩了什麼坑(經驗)Skill = 正確的做法是什麼(模式)。兩個都要讀。

    十、建議給想做逆向重建的團隊

    1. Source Inventory 先行——不管系統多簡單,先把所有功能列出來(附行號)。簡單的系統往往有最多隱性規則
    2. 後端先跑通——先用 curl 打通每一個 API endpoint,確認 request/response 格式,再寫 Flutter
    3. 每個模組獨立測試——不要等到所有模組做完才整合。我們的 21/21 unit + integration test 在開發過程中抓到了大量問題
    4. 記錄每一個坑——Brain 系統不是可選的,是必要的。第一套 APP 踩的坑如果沒記下來,第三套 APP 會再踩一次
    5. 不要信任 AI 的記憶——AI 會遺忘、會推測、會混淆。只有程式碼行號是可驗證的

    結語

    這個專案讓我深刻體會到:逆向重建的難度不在於「寫新程式」,而在於「完整理解舊系統」。舊系統的每一行 if/else 都是某個真實場景的反映,每一個看似多餘的欄位都有它存在的理由。

    AI 可以加速這個過程,但無法取代「逐行讀原始碼」這個步驟。捷徑是最遠的路——我們前 3 輪審查走了捷徑(從 Flutter 出發找問題),花了 3 倍時間;改用正確方法論(從原版出發列清單)後,第三套 APP 一天就完成了。

    希望這篇記錄能讓正在考慮做逆向重建的團隊少走一些彎路。

    追記:驗收階段又踩的五個大坑(2026-04-13 深夜)

    上面的文章發佈後幾小時,用戶開始實際驗收。結果又炸出一系列問題,每一個都是在開發階段「看了原始碼但沒看完整」造成的。

    坑 10:Dart 的 Map<dynamic, dynamic> 型別推導陷阱

    Flutter 的 API client 在呼叫 api.call(data: {}, token: token) 時,{} 空 Map literal 在 dynamic 參數中被 Dart 推導為 Map<dynamic, dynamic>。原本程式碼檢查 effectiveData is Map<String, dynamic>false → token 永遠不被加到 request 裡。

    影響範圍:27 個 API call。所有傳 data: {} 的頁面全壞(儀表板、帳號開通等),但傳了明確 key 的頁面(如 data: {'address_code': x})正常。這造成「有些頁面好有些壞」的假象,極難排查。

    教訓:原版 JavaScript param.token = value 不做任何型別檢查,直接賦值。重寫到靜態型別語言時,不要加「聰明」的型別守衛。笨方法之所以沒 bug,就是因為它笨。

    坑 11:config.js 常數映射層被完全忽略

    原版 Ionic 有一層 config.js 常數映射:sel → "select"upd → "update"del → "delete"add → "insert"sel2 → "select2"。Flutter 重寫時,有些地方用了短名(config.js 的 key),有些用了長名(PHP 接受的值)。PHP 只認長名。

    影響範圍:19 個 API call。寄放交辦頁面完全打不開(PHP switch/case 不匹配,回 ERROR 但 message 空字串),debug 時完全看不到線索。

    教訓:逆向重建時必須識別原版的每一層抽象。看了 controllers.js(呼叫端)和 factories.js(發送端)不夠——中間的 config.js 映射層不能跳過。每一個字串值都必須追到 PHP handler 的 switch/case 確認一致。

    坑 12:捏造不存在的 API method

    Flutter 程式碼裡出現了 method: 'select_category_detail'(包裹統計)和 category: 'util'(多帳號驗證碼)等原版完全不存在的 API call。追溯原始碼發現:前者在原版是純客戶端計算(groupBy + filter),後者正確的 category 是 'app_member'、method 是 'register_switchsite_validation_code'

    教訓:如果在原始碼裡找不到某個 API endpoint,那它就不存在。不要「合理推測」一個 API 可能存在。

    坑 13:API URL 不應該寫死在 compile time

    Flutter 用 --dart-define=API_BASE_URL=http://192.168.0.48:8010 在 compile time 寫死 API URL。結果 LAN 和 HTTPS 要分別 build,Cloudflare 快取舊 JS 時 URL 就錯。

    原版做法:API_BROKER_URL 在 config.js 是空字串,QR 碼啟動或登入時從 server 回傳 burl(blog_site_url),組合成完整 URL 存入 localStorage。

    修法:Web 版用 Uri.base.origin 自動偵測當前頁面的 origin 作為 API base URL。不管從哪個網域開,API 自動跟著。compile time 的 --dart-define 只作為 fallback。

    坑 14:外部服務走錯路由

    廣告 Banner API 在原版是打一個完全獨立的外部伺服器(vender01.tw),不是走 WP Broker。Flutter 把它包成了 category: 'ad_banner' 送進 WP Broker,當然找不到。

    教訓:原版有多個 factory(brokerFactorycommonServerFactoryomFactoryapi-vender),每個打不同的 server。重寫時必須識別每個 API call 走的是哪個 factory、打的是哪個 server。

    總結:為什麼驗收時才發現這些問題

    以上 5 個坑有一個共通點:「看了原始碼」不等於「看完了原始碼」。每次都是「看了主要的幾個檔案」但漏了中間層(config.js 映射、factory 路由、型別推導規則)。

    逆向重建的正確審查流程應該是:從 PHP handler 的 switch/case 開始,反向追每一個常數值回到 config.js,再追到 controllers.js 的呼叫端。不是從呼叫端出發猜 PHP 接受什麼。方向反了,就永遠追不完。

  • 工程師做完專案就丟上 GitHub?你少做了這些事

    身為一個寫 code 的人,我以前的工作流程大概是這樣:

    1. 有個想法
    2. 熬夜把它做出來
    3. git push origin main
    4. 收工,去睡覺

    然後呢?然後就沒有然後了。

    專案靜靜地躺在 GitHub 上,星星數停在個位數(其中兩個是我自己的帳號和我女朋友被我拜託按的),偶爾有個路過的陌生人開了個 issue 問「這還有在維護嗎?」——沒有,但我不好意思說。

    直到最近我做了一個小專案,花了一些時間研究「做完之後該做什麼」,才發現原來我們工程師漏掉的東西,比寫的 code 還多。


    META Tags 不是裝飾品

    先來個靈魂拷問:你的 index.html<head> 裡面有什麼?

    我猜大概是這樣:

    <head>
      <meta charset="UTF-8">
      <title>My Cool Project</title>
    </head>
    

    恭喜,你的網站在搜尋引擎眼中跟一張白紙差不多。

    Google 爬蟲來到你的頁面,看到一個 title,然後……就沒了。它不知道你這個頁面在幹嘛、給誰用、解決什麼問題。它只好自己猜,而搜尋引擎猜東西的能力,大概跟我猜女朋友今天為什麼不開心一樣爛。

    最低限度,你應該加上這些:

    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>你的專案名稱 — 一句話說明它是什麼</title>
      <meta name="description" content="用 50-160 字描述你的專案做什麼、給誰用">
      <meta name="keywords" content="關鍵字1, 關鍵字2, 關鍵字3">
    
      <!-- Open Graph:社群分享預覽 -->
      <meta property="og:title" content="專案名稱">
      <meta property="og:description" content="專案描述">
      <meta property="og:image" content="https://your-username.github.io/your-repo/preview.png">
      <meta property="og:url" content="https://your-username.github.io/your-repo/">
      <meta property="og:type" content="website">
    
      <!-- Schema.org JSON-LD:結構化資料 -->
      <script type="application/ld+json">
      {
        "@context": "https://schema.org",
        "@type": "WebApplication",
        "name": "你的專案名稱",
        "description": "專案描述",
        "url": "https://your-username.github.io/your-repo/",
        "author": {
          "@type": "Person",
          "name": "Your Name"
        },
        "applicationCategory": "UtilityApplication",
        "operatingSystem": "Web Browser"
      }
      </script>
    </head>
    

    我知道你在想什麼:「這也太多了吧,我只是做個 side project 耶。」

    對,我也這樣想過。但你花了 40 小時寫 code,多花 20 分鐘把 meta tags 補齊,投報率其實很高。


    SEO 和 AEO 的差別

    大家都聽過 SEO(Search Engine Optimization),就是讓 Google 找到你的東西。但 2025 年以後,有另一個東西叫 AEO —— Answer Engine Optimization。

    差別在哪?

    • SEO 是讓使用者搜尋「台灣失智症照護工具」的時候,你的網站出現在搜尋結果裡。
    • AEO 是讓使用者問 ChatGPT 或 Perplexity「有沒有推薦的失智症照護互動工具?」的時候,AI 直接把你的專案資訊抽出來回答。

    關鍵差異:傳統 SEO 靠的是關鍵字密度、反向連結、網站權重這些。AEO 靠的是結構化資料

    上面那段 Schema.org JSON-LD 就是結構化資料。它用一種機器能直接理解的格式,告訴 AI「這個網站是什麼類型、做什麼用、誰做的」。AI 搜尋引擎不需要去「理解」你的網頁內容,它直接讀這段結構化的 JSON 就好。

    這就像是你寫了一份完美的文件,但沒寫 API 文件一樣。人類看得懂,但機器不知道怎麼呼叫你。Schema.org 就是你給搜尋引擎寫的 API 文件。


    GitHub Topics 是免費的曝光

    這個我真的覺得很虧,因為我用了 GitHub 這麼久,從來沒認真設定過。

    你的 repo 頁面右上角有個 About 區塊,裡面可以寫 description 和加 topics。Topics 就像是 hashtag,GitHub 有專門的 topic 搜尋頁面,使用者可以透過 topic 找到相關專案。

    你最多可以加 20 個 topics。免費的曝光,不用白不用。

    用 CLI 設定很快:

    # 設定 repo description
    gh repo edit your-username/your-repo --description "你的專案一句話描述"
    
    # 加上 topics(注意:GitHub Topics 只支援英文小寫)
    gh repo edit your-username/your-repo --add-topic "dementia-care,elderly-care,cognitive-training,taiwan,web-app,html,javascript,open-source,healthcare,accessibility"
    

    重點提醒:GitHub Topics 只支援英文。所以就算你的專案是中文的,topics 也要用英文寫。想想你的目標受眾會用什麼英文關鍵字搜尋,就加什麼。


    GitHub Pages 等於免費網站

    如果你的 repo 裡有 index.html,恭喜你,你離擁有一個免費網站只差兩個步驟:

    1. 去 repo 的 Settings > Pages
    2. Source 選 main branch,資料夾選 / (root)
    3. 按 Save

    完成。你的網站就是 https://your-username.github.io/your-repo/

    每次你 git push,GitHub Actions 會自動幫你部署。不用買主機、不用設定 DNS、不用搞 nginx 設定檔、不用 Docker。零成本。

    更重要的是:你前面寫的那些 meta tags 和 Schema.org 結構化資料,只有在一個可以被公開訪問的網站上才有意義。 GitHub repo 頁面不會被 Google 當成你的「網站」來索引那些 meta tags。開了 GitHub Pages,你的 SEO 和 AEO 才算正式上線。


    Google Search Console — 主動告訴 Google 你存在

    很多人以為把網站放上去,Google 自然就會找到你。

    理論上是的。實際上,一個沒有任何外部連結指向的小網站,Google 爬蟲可能好幾個月都不會路過。你的專案就這樣安安靜靜地存在於網路上,像深山裡的一間便利商店,開著燈但沒有路。

    解法很簡單:去 Google Search Console 主動提交。

    驗證方式最簡單的是 meta tag 驗證——Google 給你一段 meta tag,你貼到 index.html<head> 裡:

    <meta name="google-site-verification" content="你的驗證碼">
    

    然後在 Search Console 的「網址審查」功能裡,貼上你的 GitHub Pages URL,按「要求建立索引」。

    我的經驗是提交後大概 2-3 天就會被 Google 索引。比起被動等待可能要等幾個月,這個 ROI 非常高。整個流程大概 10 分鐘。


    打賞和贊助機制

    「我做的是免費開源專案耶,談錢太俗了吧。」

    我以前也這樣想。但後來我發現:願意付費支持你的人,跟你收不收費是兩回事。有些人就是覺得你做的東西有價值,想請你喝杯咖啡。你不給他管道,他想付都付不了。

    幾個選項,各有優缺點:

    Ko-fi — 國際通用的打賞平台,介面很乾淨。但台灣收款要透過 PayPal 或 Stripe,PayPal 的手續費偏高,Stripe 台灣的個人帳號支援也有限制。適合有國際受眾的專案。

    綠界 ECPay — 台灣最方便的選擇,支援信用卡、ATM 轉帳、超商繳費,對台灣使用者來說付款門檻最低。缺點是設定流程比較繁瑣,可能需要聯繫客服才能搞定。但搞定之後就很順了。

    銀行轉帳 QR Code — 最簡單直接的方式。產生你的銀行帳號 QR code,使用者用手機銀行掃一下就能轉帳。零手續費、零平台抽成。缺點是沒有平台幫你追蹤誰贊助了多少。

    GitHub Sponsors — 在 repo 根目錄放一個 .github/FUNDING.yml,你的 repo 頁面就會自動出現一個 Sponsor 按鈕:

    # .github/FUNDING.yml
    github: your-username
    ko_fi: your-kofi-username
    custom:
      - https://your-payment-link.example.com
    

    這個檔案的設定非常簡單,但效果很好——那個 Sponsor 按鈕就放在 repo 頁面最顯眼的位置,每個路過的人都看得到。

    重點是:你不需要只選一個。 你可以同時放 Ko-fi 給國際用戶、綠界給台灣用戶、銀行轉帳給懶得註冊任何平台的人。多一個管道就多一個機會。


    README 是你的門面

    工程師寫 README 通常是這樣:

    # My Project
    
    ## Installation
    npm install
    
    ## Usage
    npm start
    

    然後就沒了。

    拜託,你的 README 是大多數人對你專案的第一印象(也可能是最後一印象)。它不只是技術文件,它是你的故事。

    一個好的 README 應該包含:

    1. 為什麼做這個 — 你遇到了什麼問題?什麼契機讓你動手做?這個故事比你想像的重要一百倍。「我阿嬤確診失智症,我想做一個讓她可以動動腦的小工具」比「這是一個認知訓練 Web App」有感染力多了。
    2. 這是什麼、給誰用 — 用一般人聽得懂的話說明。
    3. 怎麼用 — 截圖、GIF、或是 live demo 連結。
    4. 技術細節 — 用了什麼技術、架構是什麼(這部分寫給工程師看的)。
    5. 如何支持 — 打賞連結、或是告訴別人怎麼 contribute。

    真實的故事比任何行銷文案都有效。人們不只是在用你的工具,他們是在參與你的故事。


    Social Preview 和 OG Tags

    最後一個,也是最容易被忽略的:分享預覽

    當你把 repo 連結或網站連結貼到 LINE 群組、Facebook、Twitter 的時候,會出現什麼?

    如果你什麼都沒設定,就是一個光禿禿的網址。沒有預覽圖、沒有描述、沒有標題。在訊息流裡面,它跟垃圾連結看起來一模一樣。

    如果你有設定 OG tags(前面 meta tags 那段已經教過了)加上一張好看的預覽圖,分享出去就會有標題、描述、還有圖片。在 LINE 群組裡點擊率差個三五倍很正常。

    GitHub repo 本身也可以設定 Social Preview:去 repo 的 Settings > Social Preview,上傳一張 1280×640 的圖。這樣別人在社群分享你的 repo 連結時,就會顯示這張圖。

    你可以用 Canva、Figma 之類的工具花 5 分鐘做一張。不需要多精美,有總比沒有好太多了。


    結論

    回顧一下,做完 side project 之後你應該做的事:

    1. 把 meta tags 補齊(description、OG tags、Schema.org JSON-LD)
    2. 開 GitHub Pages,讓你的專案有一個公開網址
    3. 去 Google Search Console 提交你的網址
    4. 設定 GitHub Topics 和 About description
    5. 放上打賞/贊助連結
    6. 好好寫你的 README,說你的故事
    7. 設定 Social Preview,讓分享出去有個樣子

    這些事情全部加起來,大概花你一到兩個小時。

    你已經花了幾十個小時甚至幾百個小時寫 code,多花兩個小時讓它被看見,很值得。

    我以前一直覺得「好的東西自然會被發現」。但事實是,網路上好的東西太多了,大部分都沒被發現。被發現的那些,不一定是最好的,但一定是最容易被找到的。

    我們工程師很擅長解決技術問題,但不太擅長「讓別人知道我們解決了什麼問題」。

    這篇文章就是我學到這件事之後,寫給跟我一樣的人的。

    希望你的下一個 side project,不再只是 GitHub 上的一個小點。

  • 為什麼 Claude 不遵守 Superpowers 的鐵律?理論與實務的落差分析

    重點摘要

    • Superpowers skills 有嚴格的鐵律,但實務上 Claude 常常無視它們
    • 根本原因:skills 是文字指令,沒有程式化的強制機制
    • 五個主要原因:skill 未載入、context 被壓縮、訓練行為覆蓋、無狀態計數、Haiku 能力不足
    • 每條規則附上 GitHub 原始碼出處,讓你自己驗證

    上一篇文章整理了 github.com/obra/superpowers 裡所有 skill 的隱藏規則。這篇要回答一個更根本的問題:這些規則白紙黑字寫得清清楚楚,為什麼 Claude 實務上常常不遵守?

    Skill 的規則是真實存在的

    先確認這些規則不是我們誤解或誤記的。以下是幾條最關鍵規則的原始出處:

    鐵律 1:修了三次還沒修好,停下來

    來源:skills/systematic-debugging/SKILL.md 第 195-197 行

    If < 3: Return to Phase 1, re-analyze with new information
    If ≥ 3: STOP and question the architecture (step 5 below)
    DON’T attempt Fix #4 without architectural discussion

    同一個檔案第 227 行:

    “One more fix attempt” (when already tried 2+)
    ALL of these mean: STOP. Return to Phase 1.

    鐵律 2:選最便宜的 model

    來源:skills/subagent-driven-development/SKILL.md 第 89-91 行

    Use the least powerful model that can handle each role to conserve cost and increase speed.
    Mechanical implementation tasks (isolated functions, clear specs, 1-2 files): use a fast, cheap model. Most implementation tasks are mechanical when the plan is well-specified.

    鐵律 3:沒有失敗測試不能寫 code

    來源:skills/test-driven-development/SKILL.md 第 31-34 行

    ## The Iron Law

    NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST

    鐵律 4:1% 機率就必須 invoke skill

    來源:skills/using-superpowers/SKILL.md 第 11-15 行

    If you think there is even a 1% chance a skill might apply to what you are doing, you ABSOLUTELY MUST invoke the skill.

    IF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT.

    This is not negotiable. This is not optional. You cannot rationalize your way out of this.

    鐵律 5:宣稱完成前必須這個訊息內跑過驗證

    來源:skills/verification-before-completion/SKILL.md 第 16-22 行

    ## The Iron Law

    If you haven’t run the verification command in this message, you cannot claim it passes.

    規則是真實的,寫得清楚,甚至用了「Iron Law」、「ABSOLUTELY MUST」、「NOT negotiable」這些最強烈的措辭。

    那為什麼實務上 Claude 修了四次五次還在猜?為什麼還是會選 Haiku?為什麼不跑完驗證就說「完成了」?

    五個根本原因

    原因 1:Skill 是文字,沒有執行引擎

    Skills 的運作方式是:Claude 呼叫 Skill 工具 → 工具把 SKILL.md 的內容貼進 context → Claude 讀完然後「盡力遵守」。

    沒有 interpreter,沒有 runtime,沒有 if-then 邏輯,沒有計數器,沒有警報。Claude 違反規則不會有任何程式層面的後果。

    這就是為什麼 using-superpowers/SKILL.md 第 13 行要用大寫強調「YOU DO NOT HAVE A CHOICE」—— 因為它知道 Claude 有選擇,它在試圖用措辭彌補缺乏強制力這件事。

    原因 2:Skill 沒被載入就不存在

    using-superpowers skill 規定「每次對話開始前先查 skill」,但執行這條規則的還是 Claude 本身。如果 Claude 這次忘了 invoke Skill 工具,systematic-debugging 的三次上限根本不在 context 裡,等於不存在。

    這是一個自我參照的問題:「用 skill 確保 skill 被用」的規則本身也依賴 skill 被正確載入才能生效。

    原因 3:Context 壓縮吃掉規則

    長對話之後,Claude Code 會自動壓縮前面的 context。Skill 內容被載入進 context,但在第五次修 bug 的時候,第一次載入的 systematic-debugging 很可能已經被壓縮到只剩摘要,「三次停下來」這條規則不見了。

    Claude 不是故意無視規則,是規則已經不在它的視野裡了。

    原因 4:RLHF 訓練行為覆蓋 skill 規則

    Claude 的訓練讓它傾向:

    • 持續幫忙(不輕易放棄)
    • 樂觀估計(「這次應該可以」)
    • 不讓使用者失望(說「我不知道怎麼修」感覺像失敗)

    Skill 說「第三次停下來討論架構」,但訓練說「繼續幫用戶解決問題」。訓練是骨子裡的,skill 是貼上去的文字。骨子裡的贏。

    這個矛盾在 skill 作者知道:systematic-debugging/SKILL.md 第 195 行不只說「stop」,還用粗體、全大寫,以及「DON’T attempt Fix #4」的雙重否定,都是試圖用措辭強度來對抗訓練行為。

    原因 5:Haiku 沒有能力執行複雜的工作流程規則

    來源:skills/subagent-driven-development/SKILL.md 第 89-100 行告訴 Claude 選最便宜的 model。

    但兩階段 review(spec compliance → code quality)、四種 status 的不同處理邏輯、三次上限計數、context 打包給 subagent——這些都需要相當的推理能力。Haiku 被選來做「機械性」的工作,卻遇到需要判斷的情況時,它沒有能力忠實執行這些細緻規則,就退回最直覺的行為:繼續做、繼續猜。

    所以 skill 的 model 選擇規則本身,就是讓 skill 的其他規則失效的原因之一。

    一個具體的案例:兩階段 Review 的崩潰

    subagent-driven-development 規定兩階段 review,而且有嚴格順序(SKILL.md 第 247 行):

    Start code quality review before spec compliance is ✅ (wrong order)

    這個規定存在,是因為曾經出問題(skills/writing-skills/SKILL.md 第 154-156 行):

    Testing revealed that when a description summarizes the skill’s workflow, Claude may follow the description instead of reading the full skill content. A description saying “code review between tasks” caused Claude to do ONE review, even though the skill’s flowchart clearly showed TWO reviews (spec compliance then code quality).

    換句話說:

    1. Skill 的 description 寫了工作流程摘要
    2. Claude 讀了 description 就走捷徑,沒有讀完整 SKILL.md
    3. 看到「code review between tasks」→ 只做了一次 review
    4. 整個兩階段機制失效

    修法是把 description 改成只描述「什麼時候用這個 skill」,不描述工作流程。但這同時說明:一個措辭上的疏漏,就足以讓整個 skill 的核心機制失效,而且你不會知道。

    另一個案例:Permission 擋住了整個 Review Loop

    我們最近遇到的真實案例:在 ~/.claude/settings.json 裡,PermissionRequest hook 的 matcher 設定為 Agent|TeamCreate|Team,而 hook 的行為是對 Agent 工具直接回傳 deny

    結果:每次 LEAD 要 dispatch subagent(不管是 implementer、spec reviewer 還是 code quality reviewer),都被系統層面攔截拒絕。

    兩階段 review 的規則還在 context 裡,Claude 也打算遵守,但 Agent 工具每次都失敗。Skill 的工作流程完全無從執行。

    修法:把 Agent 從 hook matcher 移除(改成 TeamCreate|Team),並把 defaultMode 改成 bypassPermissions。這個設定層面的問題修好之後,Agent Team 才能真正按 skill 的設計跑。

    Skills 在什麼條件下才有效

    綜合以上,Skills 的效果受以下條件影響:

    條件 有利 不利
    Session 長度新開的 session,context 乾淨長對話,skills 被壓縮
    ModelSonnet / Opus,有推理能力Haiku,複雜 workflow 跟不上
    Permission 設定Agent 工具不被攔截Permission hook 擋住 subagent dispatch
    Skill 載入LEAD 主動 invoke 正確的 skill沒有 invoke,規則不在 context
    文件完整性AGENTS.md 明確指定每個 agent 的 model讓 Claude 自己判斷 model,選 Haiku

    你能做什麼

    Skill 的規則沒辦法完全靠 Claude 自己執行,但有幾件事可以提升遵守率:

    1. 在 CLAUDE.md 加覆寫規則(降低對 skill 的依賴)

    ## Superpowers Skill Override Rules
    
    ### Model Selection
    NEVER use haiku for implementation tasks. Follow:
    - opus: architecture, code review, cross-file reasoning
    - sonnet: all implementation tasks
    - haiku: file scanning, directory listing ONLY
    
    ### Git Branch
    No branch confirmation needed when already on non-main/master branch.
    
    ### Debugging Limit
    After 3 failed fix attempts, STOP and escalate to user.
    Do not attempt Fix #4 without discussion.

    2. 修好 settings.json(讓 Agent 工具不被攔截)

    {
      "permissions": {
        "allow": ["Agent"],
        "defaultMode": "bypassPermissions"
      },
      "feedbackSurveyRate": 0
    }

    3. 在 AGENTS.md 明確指定每個 agent 的 model

    | Agent | Model | Role |
    |-------|-------|------|
    | implementer | sonnet | Feature implementation |
    | spec-reviewer | sonnet | Spec compliance check |
    | code-reviewer | opus | Code quality review |

    4. 永遠從 dev branch 開工

    git checkout -b dev

    避開所有 skill 的 main/master 保護規則,減少一類不必要的確認詢問。

    一個誠實的評估

    Superpowers skill 系統的設計思路是正確的:把軟體開發的最佳實踐(TDD、系統性除錯、分層 review)轉化為 AI agent 的工作協議。規則本身大多有充分的理由。

    但在現實中,一個純粹依賴文字指令的系統,要對抗 LLM 的訓練行為、context 長度的物理限制、以及工具層的設定問題,注定只能是「盡力遵守」而非「強制執行」。

    理解這個落差,比假設 Claude 完全遵守更有用。知道規則存在、知道為什麼可能失效,讓你能夠在關鍵節點主動介入,而不是事後才發現 Claude 在第五次猜測同一個 bug。


    延伸閱讀:

  • Claude Code Superpowers 隱藏規則:4 個你不知道的坑與避開方法

    重點摘要

    • Superpowers skills 有幾條「隱藏規則」會在你不注意時改變 Claude 的行為
    • 最常見的問題:skill 自動選 Haiku 做本該 Sonnet/Opus 的工作
    • 三個簡單設定可以避開 90% 的干擾:dev branch、AGENTS.md 指定 model、關閉 feedback survey
    • 文末附 CLAUDE.md 覆寫規則範本,直接貼進去就能用

    用 Claude Code 跑 Agent Team 一段時間後,你可能會發現:明明設定都正確,Claude 還是會跑來問奇怪的問題、用錯 model、或在不該停的地方停下來。這篇文章整理了 Superpowers plugin 裡幾條「你不一定知道」的隱藏規則,以及最簡單的避開方法。

    為什麼 Agent Team 會「自己做決定」?

    Claude Code 的 Superpowers plugin 提供了一套 skill 系統,讓 Claude 在執行任務時有明確的工作流程可依循。這些 skill 設計上是給通用場景用的,因此內建了一些「省成本、保安全」的預設行為。

    問題是:這些預設行為有時候和你的需求相衝突,而且你很難從文件上看出來。

    隱藏規則 1:Skill 會自動選最便宜的 Model

    來源: subagent-driven-development skill

    這條規則直接寫在 skill 裡:

    “Use the least powerful model that can handle each role to conserve cost and increase speed. Mechanical implementation tasks: use a fast, cheap model.”

    也就是說,當 Claude 判斷一個 task 是「機械性的」(1-2 個檔案、規格清楚),它就會選 Haiku。這對一般的 CRUD 功能可能沒問題,但對複雜業務邏輯(像 iDempiere plugin、Taiwan 發票系統)來說,Haiku 根本不夠用。

    Skill 的 Model 選擇邏輯

    Task 類型 Skill 的選擇 適合複雜專案?
    Mechanical(1-2 files, clear spec)Haiku(最便宜)❌ 通常不夠用
    Integration(多 file、需判斷)Sonnet(標準)✅ 通常足夠
    Architecture / ReviewOpus(最強)✅ 正確

    避開方法:在 AGENTS.md 明確指定 Model

    最簡單的解法是在每個專案的 AGENTS.md 裡明確寫好每個 agent 的 model。Claude 在 dispatch subagent 時,如果 AGENTS.md 有寫,就應該照抄,不用自己判斷。

    | Agent | Model | Role |
    |-------|-------|------|
    | pack-builder | sonnet | Build 2Pack XML + ZIP |
    | model-fixer | sonnet | Fix Model classes |
    | idempiere-expert | opus | Technical reviewer |

    同樣地,在 IMPLEMENTATION_PLAN.md 每個 phase 標上 model,讓 LEAD 照單全收:

    ## Phase 0.1:建立 PackOut.xml [pack-builder / sonnet]
    ## Phase 0.2:Activator 邏輯 [activator-fixer / sonnet]
    ## Review Gate [idempiere-expert / opus]

    隱藏規則 2:在 main/master 上工作會被詢問確認

    來源: 幾乎所有 implementation skill

    所有 skill 都有這條規則:“Never start implementation on main/master without explicit user consent.” 只要你的 working branch 叫 mainmaster,Claude 每次開始實作前都會停下來問你確認。

    避開方法:永遠從 dev branch 開工

    一條指令解決:

    git checkout -b dev

    在 dev branch 上,這條保護規則不會觸發。這也是好的 git 習慣,順手為之即可。

    隱藏規則 3:Subagent 不繼承你的對話 Context

    來源: 所有使用 subagent 的 skill

    這是設計上的特性,不是 bug:每個 subagent 都是 fresh 啟動,完全不知道你之前跟 LEAD 說過什麼。LEAD 要把所有需要的 context 手動打包給 subagent。

    這代表你告訴 LEAD「不要動 X 檔案」、「記得用 Y 方式」,subagent 不一定會知道,除非 LEAD 把這些資訊包進去。

    避開方法:把規則寫進文件,不要只說給 LEAD 聽

    任何重要的約定,放進 AGENTS.mdCLAUDE.mdIMPLEMENTATION_PLAN.md。這些檔案 subagent 啟動時會讀到,不依賴 LEAD 的記憶。

    隱藏規則 4:Feedback Survey 會擋住畫面

    Claude Code 會隨機彈出「How is Claude doing this session?」的評分畫面。這個畫面不是 blocking prompt,按 Enter 沒有用,要按 0 才能 dismiss。

    更乾脆的做法是直接關閉它。在 ~/.claude/settings.json 加一行:

    {
      "feedbackSurveyRate": 0
    }

    設為 0 後,這個 survey 就永遠不會出現了。

    完整 CLAUDE.md 覆寫規則範本

    把以下內容加進你的 CLAUDE.md,可以覆寫 skill 的預設行為:

    ## Superpowers Skill Override Rules
    
    ### Model Selection (OVERRIDES subagent-driven-development skill)
    NEVER use haiku for implementation tasks. Follow this mapping regardless
    of what the skill says about "mechanical" tasks:
    - opus: architecture decisions, code review, cross-file reasoning
    - sonnet: all implementation tasks (CRUD, API, forms, tests, services)
    - haiku: file scanning, directory listing, config comparison ONLY
    
    When dispatching subagents, ALWAYS check AGENTS.md for the assigned model.
    If AGENTS.md specifies a model, use it. Do not override with cheaper model.
    
    ### Git Branch
    Never ask for branch confirmation if already on a non-main/master branch.
    Treat any branch that is not named "main" or "master" as pre-approved for
    implementation work.

    一次性設定清單

    以下是只需要做一次的設定,之後每個專案都受益:

    設定 位置 效果
    "feedbackSurveyRate": 0~/.claude/settings.json永久關閉 feedback survey
    "defaultMode": "bypassPermissions"~/.claude/settings.json工具不再逐一詢問確認
    Model 覆寫規則~/.claude/CLAUDE.md強制 sonnet 做實作工作

    以下是每個新專案開始時的習慣:

    1. git checkout -b dev(避開 main/master 保護規則)
    2. 建立 AGENTS.md 並寫好每個 agent 的 model
    3. IMPLEMENTATION_PLAN.md 每個 phase 標記 model

    為什麼這些規則存在?

    這些 skill 是為「通用場景」設計的,預設行為是合理的:

    • 省成本: 對大多數用戶來說,Haiku 做簡單任務確實夠用,費用少一半
    • 保安全: 不讓 Claude 在 main branch 亂動是好習慣
    • 隔離 context: Fresh subagent 避免舊 context 污染新任務

    問題不是規則本身,而是當你的專案比「通用場景」複雜時,這些預設值就不夠精準了。透過明確的文件(AGENTS.md、CLAUDE.md)和一次性的 settings.json 設定,你可以讓 Claude 按照你的規格工作,而不是照 skill 的預設值工作。


    延伸閱讀:

  • Agent Team 穩定的關鍵:spawn 之前先建好兩份文件

    重點摘要

    • Agent Team 不穩定的根本原因:agent 靠對話記憶工作,不靠文件
    • 解法:spawn agents 之前,必須先建好 CLAUDE.md 和 AGENTS.md
    • CLAUDE.md 寫專案現況,AGENTS.md 寫團隊規則,缺一不可
    • Agent 之間的工作交接必須透過實體檔案,不能靠口頭傳遞

    同樣是用 Claude Code 跑 Agent Team,有人的 team 順暢完成、互動極少,有人的 team 一直卡住、不斷要人介入。

    差距不在任務複雜度,不在模型,在一件事:有沒有在 spawn agents 之前先建好文件。

    為什麼 Agent Team 會卡住

    要理解這個問題,先理解 agent 的本質。

    當你 spawn 一個 agent,它只知道你在那一刻的 prompt 裡說了什麼。你的對話歷史、你之前說的規則、其他 agent 做了什麼——它全都不知道。

    這代表什麼?

    如果你沒有把規則寫進文件,你(orchestrator)就是整個 team 唯一的記憶體。你要記住所有規則,要在每個 spawn prompt 裡正確地說一遍,要把 agent A 的結果正確地轉述給 agent B。

    這就是卡住的來源:

    • Prompt 寫漏一條規則 → agent 做出不符合期望的結果
    • Agent A 的結果透過我轉述給 Agent B → 轉述過程中遺漏細節
    • 對話太長,舊的 context 被壓縮 → 規則消失
    • 某個 agent 失敗重啟 → 什麼都不記得,要重頭說
    • 多個 agent 平行跑 → 每個人收到的規則說法略有不同

    每一個都是可能的失敗點。越複雜的 team,失敗的機率越高。

    讓 Team 穩定的解法:兩份文件

    穩定的 Agent Team 做一件事:把所有 agent 需要知道的東西,從對話記憶移到磁碟上的文件。

    文件是客觀存在的。所有 agent 讀同一份,規則永遠一致。Agent 失敗重啟,讀一遍文件就恢復。多個 agent 平行跑,各自讀文件,不需要我轉述。

    需要兩份文件,職責不同:

    文件 寫什麼 類比
    CLAUDE.md專案現況:ID、路徑、已完成的項目、已知問題、版本新人入職的專案交接文件
    AGENTS.md團隊規則:誰做什麼、如何交接、鐵律、失敗怎麼處理公司的工作手冊

    CLAUDE.md 要寫什麼

    寫所有「agent 每次都要重新查,但其實不需要查」的東西:

    # 專案名稱
    
    ## 關鍵 ID 和路徑
    - WordPress 分類 ID:失智照顧=76、家屬心聲=78
    - 已發布文章:[Post ID 清單]
    - 輸出目錄:./content/drafts/
    
    ## 技術環境
    - 使用版本:XXX
    - API endpoint:[測試] / [正式]
    
    ## 已知的坑
    - 台灣失智症協會網站用 http:// 不支援 https
    - 這個 API 的日期格式是 YYYYMMDD 不是 ISO 8601
    
    ## 已完成 / 待處理
    - ✅ 已完成:XXX
    - ⚠️ 待處理:YYY

    沒有 CLAUDE.md,agent 每次都要重新查分類 ID、確認文章有沒有發過、試連結通不通。每一步都是潛在的失敗點。

    AGENTS.md 要寫什麼

    AGENTS.md 有四個必要部分:

    1. 鐵律(所有 agent 不可違反)

    ## 鐵律
    - 所有醫療資訊必須附上可驗證的來源 URL
    - 不能修改 iDempiere core 代碼,只能在 plugin 層擴充
    - 沒有測試的代碼不算完成

    2. 每個 agent 的定義

    ### researcher(研究員)
    職責:搜尋資料,每筆資訊必須記錄來源 URL
    工具:WebSearch, WebFetch, Read
    輸出格式:[明確定義]

    3. 交接協議(最關鍵、最常被忽略)

    ## 交接協議
    researcher 完成 → 存到 ./drafts/research-[topic]-[YYYYMMDD].md
    writer 開始前  → 必須讀取上面那個檔案
    writer 完成   → 存到 ./drafts/article-[topic]-[YYYYMMDD].md
    publisher 開始前 → 讀取 article 檔案,驗證 References 後才發布

    4. 失敗處理規則

    ## 失敗處理
    - 找不到可信來源:停止,回報「無法找到符合鐵律的來源」,等待指示
    - 需求不清楚:列出疑問,等確認後再開始,不要自行假設
    - 任何 agent:遇到不確定的事,停下來問,不要猜

    具體案例:iDempiere 台灣統一發票 Plugin

    用一個真實場景說明這套做法。假設要用 Agent Team 開發一個 iDempiere 的台灣統一發票 plugin,team 成員是 PM、RD、架構師。

    CLAUDE.md(專案現況)

    # iDempiere 統一發票 Plugin
    
    ## 技術環境
    - iDempiere 版本:11.0,Java 17
    - Plugin 目錄:/path/to/plugin
    - 財政部電子發票規格書版本:5.0(2025年)
    
    ## 已知 iDempiere 約束
    - Callout 用 @Callout annotation(見 idempiere-callout-generator skill)
    - 不能用 Spring,只能用 OSGi service
    - DB 操作只能透過 PO 或 DB class,不能直接 JDBC
    
    ## 已完成的模組
    - ✅ 發票開立
    - ⚠️ 作廢(待測試)
    - ❌ 查詢(未開始)

    AGENTS.md 的交接協議

    ## 新功能開發流程
    
    pm 寫需求 → 存到 ./specs/req-[feature].md
        ↓
    architect 設計 → 讀 req 檔案 → 存到 ./specs/arch-[feature].md
        ↓
    rd 實作 → 讀 req + arch 檔案 → 代碼 + ./specs/impl-[feature].md
        ↓
    architect review → 讀 impl 摘要 → 存到 ./reviews/review-[feature].md

    每個 agent 知道自己要讀什麼、存到哪裡。PM 和 RD 不需要「對話」,他們透過檔案交接。Architect 不需要等 PM 說完才知道需求,直接讀需求檔案。

    每次 spawn agent 的啟動句

    請先閱讀 CLAUDE.md 和 AGENTS.md,
    確認你的角色、鐵律和交接路徑後再開始工作。

    這一句話讓 agent 在開始工作前自己去讀規則,不需要我每次重複說一遍。

    不穩定 vs 穩定:對照表

    沒有文件(常見做法) 有文件(穩定做法)
    規則從哪來我的 prompt(每次可能不同)AGENTS.md(永遠一致)
    專案狀態我的記憶(可能過時或漏掉)CLAUDE.md(客觀存在)
    Agent 間交接我轉述(容易漏細節)實體檔案(完整保留)
    Agent 失敗重啟什麼都不記得讀文件即恢復
    平行跑多個 agent規則可能不一致讀同一份文件,完全一致
    需要人工介入頻繁只在真正需要決策時

    標準流程:每次建立 Agent Team 前

    1. 建立 CLAUDE.md:寫入專案現況(ID、路徑、已知問題、版本、已完成項目)
    2. 建立 AGENTS.md:寫入鐵律、每個 agent 的定義、交接協議、失敗處理規則
    3. Spawn agent 時第一句:「請先閱讀 CLAUDE.md 和 AGENTS.md,確認規則後再開始」
    4. 交接一律用實體檔案:agent 完成後存到指定路徑,下一個 agent 從那裡讀

    沒有做完這四步就開始 spawn,你就是在用對話記憶撐整個 team。任務越複雜,遲早會卡住。

    常見問題

    Q:簡單的任務也需要這兩份文件嗎?

    一個 agent 做一件事,不需要。兩個以上的 agent 有交接,就需要。判斷標準很簡單:如果你需要「把 A 做完的東西交給 B」,就要用文件定義這個交接。

    Q:CLAUDE.md 和 AGENTS.md 要多詳細?

    CLAUDE.md:詳細到「新加入的 agent 不需要問任何問題就能知道專案現況」。AGENTS.md:詳細到「每個 agent 知道自己的輸出要存到哪個路徑」。最常被忽略的就是交接路徑,這是 team 失敗最常見的原因。

    Q:文件要每次重寫嗎?

    AGENTS.md 的團隊結構通常固定,一次寫好後很少改。CLAUDE.md 的專案狀態會變,每次任務完成後更新「已完成項目」。把更新 CLAUDE.md 當作任務完成的一部分,下次 team 啟動時文件就是最新的。

  • 舊系統整合場景下,會用 vs 不會用 Claude Code 的差距

    重點摘要

    • 舊系統整合最大的陷阱:Claude 看不到舊系統,但舊系統的約束決定了新功能能不能用
    • 不會用的人:讓 Claude 在沒有舊系統上下文的情況下做新功能,結果接不上去
    • 會用的人:先讓 Claude 讀關鍵接口,CLAUDE.md 記錄現有約束,設計文件定義接合點
    • 三個場景示範:醫療 HIS 接 LINE 掛號、舊報表接新數據、舊 ERP 接電商平台

    上一篇文章講的是新功能開發。但現實是,大多數人面對的不是一張白紙,而是一個已經在跑的舊系統。

    舊系統整合比全新開發難十倍,不是因為技術更難,而是因為有一大堆隱性約束 Claude 不知道。格式、命名、邊界、不能動的地方,這些都在舊代碼裡,Claude 看不到就無從遵守。

    這篇用三個場景直接模擬:有舊系統在的情況下,會用和不會用 Claude Code 的差距。

    根本差距:Claude 的上下文只有你給它的部分

    Claude Code 非常聰明,但它只知道你告訴它的東西。在全新專案,你說什麼格式就用什麼格式,問題不大。在整合舊系統時,如果你沒有把舊系統的關鍵結構告訴它,它會做出一個邏輯正確但無法接上的東西。

    這不是 Claude 的問題,是你的輸入不完整。

    舊系統整合的核心挑戰是:讓 Claude 在動手之前,先理解它不能動的邊界在哪裡。

    場景一:醫院 HIS 系統加掛 LINE 預約掛號

    情境

    一家地區醫院用了十年的 HIS 系統(Windows Server + MSSQL),所有掛號邏輯都在 stored procedures 裡。現在要加 LINE Chatbot 讓患者能線上預約,但 HIS 系統不能動,只能從外部透過 API 呼叫它。

    不會用的人怎麼做

    幫我寫一個 LINE Chatbot 預約掛號系統,要能讓患者選科別、選醫師、選時段。

    Claude 做出一個完整的 LINE bot,資料庫設計清楚,對話流程順暢。

    開始對接 HIS 系統時,問題一個接一個:

    • HIS 的患者 ID 是 8 位數字,Claude 設計的是 UUID — 整個 primary key 要換
    • HIS 的診次代碼格式是 YYYYMMDD-科別碼-序號(例如 20260325-INT-001),Claude 自己設計了完全不同的格式
    • HIS 只接受 stored procedure 呼叫,不開放直接讀表,Claude 設計的是直接 SELECT
    • 科別代碼是 HIS 裡的維護資料(內科=INT、外科=SUR),Claude 用了自己的命名

    每一個問題單獨看都能修,但修完之後發現下一個格式又不對。最後花了兩天在做格式轉換,而不是做功能。

    結果:開發 3 天,對接 2 天,還有格式轉換層要長期維護。

    會用的人怎麼做

    第一步:先讓 Claude 讀懂舊系統的接口

    把 HIS 系統對外開放的 SP 簽名整理成文件,餵給 Claude:

    請先閱讀以下 HIS 系統的接口文件,
    告訴我你對這個系統的理解,特別是資料格式和呼叫限制,
    再討論 LINE bot 的架構設計。
    
    --- HIS 接口文件 ---
    sp_GetAvailableSessions
      @DeptCode NCHAR(3)      -- 科別碼,參照 tb_Dept.DeptCode
      @DateFrom NCHAR(8)      -- YYYYMMDD 格式
      @DateTo   NCHAR(8)
      回傳: SessionId NCHAR(16), DoctorName, SessionDate, RemainSlots
    
    sp_CreateBooking
      @PatientId NCHAR(8)     -- 8位數字,不足補0
      @SessionId NCHAR(16)    -- 從 sp_GetAvailableSessions 取得
      @Phone     NVARCHAR(20)
      回傳: BookingNo NCHAR(12), Status (SUCCESS/FULL/DUPLICATE)
    
    sp_CancelBooking
      @BookingNo NCHAR(12)
      @Reason    NVARCHAR(100)
    ---

    第二步:CLAUDE.md 記錄現有系統的約束

    ## 整合約束(HIS 系統,不可更動)
    - PatientId:8 位數字字串,不足補 0(例如 "00012345")
    - SessionId:格式為 YYYYMMDD-DeptCode-NNN(例如 "20260325-INT-001")
    - 所有 HIS 呼叫只能透過 stored procedure,不允許直接查表
    - 科別代碼參照 tb_Dept,常用:INT=內科、SUR=外科、PED=小兒科
    
    ## 新系統原則
    - LINE bot 層只做對話邏輯
    - HIS 接口層做格式轉換(HisAdapter class)
    - 不在 LINE bot 層直接呼叫 HIS

    第三步:設計文件定義接合點,不是重新設計格式

    # 功能:LINE 掛號 → HIS 預約對接
    
    ## 接合點(Integration Points)
    LINE 用戶選擇診次 → HisAdapter.getAvailableSessions(deptCode, dateRange)
      → 呼叫 sp_GetAvailableSessions
      → 回傳格式轉為 LINE flex message 可用的結構
    
    用戶確認掛號 → HisAdapter.createBooking(lineUserId, sessionId, phone)
      → 查詢或建立患者檔(PatientId)
      → 呼叫 sp_CreateBooking
      → 處理 FULL / DUPLICATE 回傳狀態
    
    ## 不碰的東西
    - HIS 資料庫 schema 完全不動
    - 所有 PatientId 維持 8 位補零格式
    - SessionId 格式完全繼承 HIS
    
    ## Done When
    - HisAdapter 有完整的 unit test(mock SP 回傳)
    - LINE bot 不包含任何 HIS 格式邏輯(全在 Adapter)

    結果:1.5 天完成,無格式轉換層,後續維護只在 HisAdapter 這一層。

    場景二:舊版股市報表腳本接新即時數據

    情境

    一個量化分析師用了三年的 Python 腳本,每天手動下載 CSV,跑一堆計算,輸出報表。現在要改成自動化:自動爬取數據、自動計算、推播到 Line Notify。但舊腳本的計算邏輯非常複雜(含自訂指標、過去三年調整過的參數),不能改,只能把數據來源換掉。

    不會用的人怎麼做

    幫我把這個股市分析腳本改成自動化,自動抓數據然後推 LINE 通知。

    Claude 看了舊腳本,做了一個新的自動化版本。看起來很整齊,比舊腳本乾淨很多。

    跑了一週,發現結果跟舊版不一樣:

    • 舊腳本的 RSI 計算用的是 Wilder 平滑法,Claude 預設用了 SMA 版本,數值不同
    • 舊腳本對成交量有一個「過去 20 日剔除最高最低各兩天後的平均」的自訂邏輯,新版沒有
    • 舊腳本在除權息日前後有特別處理,新版沒有
    • 欄位名稱被 Claude 重新命名了(舊版 vol_adj 在新版變成 adjusted_volume),下游所有 Excel 公式全壞

    分析師說:「它幫我重寫了,但重寫出來的東西跟我的不一樣,我現在不知道以哪個為準。」

    結果:新舊結果不一致,花了一週在驗算差異,反而比手動下載多花時間。

    會用的人怎麼做

    關鍵原則:計算邏輯一行都不能動,只換數據來源。

    第一步:讓 Claude 讀懂舊腳本,先提取它的業務邏輯

    請閱讀這個舊腳本,告訴我:
    1. 它依賴哪些輸入欄位(欄位名稱和格式)
    2. 有哪些自訂計算邏輯(非標準指標)
    3. 最後輸出哪些欄位
    
    不要修改任何東西,只告訴我你的理解。

    這一步讓 Claude 自己找出所有隱性依賴,避免後面遺漏。

    第二步:CLAUDE.md 把舊腳本的約束凍結

    ## 舊系統相容性約束(不可更動)
    - 所有輸出欄位名稱必須與 legacy_report.py 完全一致
      (vol_adj、rsi_wilder、price_adj 等,不得重新命名)
    - RSI 計算必須使用 Wilder 平滑法(非 SMA),與舊版等價
    - 成交量平均:去掉最高最低各 2 天後的 16 日均量
    - 除權息調整邏輯:參見 legacy_report.py 第 87-134 行,禁止修改
    
    ## 本次修改範圍
    - 只修改數據來源層(DataFetcher class)
    - 所有計算邏輯保持不變
    - 輸出格式和欄位名稱保持不變

    第三步:設計文件只描述「換什麼」,明確說「不換什麼」

    # 功能:數據來源自動化
    
    ## 要換的
    舊:手動下載 CSV 放在 ./data/ 目錄
    新:DataFetcher 自動從 TWSE API 抓取,存成相同格式的 DataFrame
    
    ## 不換的
    - 所有 calculate_*() 函數:一行都不動
    - 所有欄位名稱
    - 輸出的 Excel 格式和公式
    
    ## 驗證方式
    用同一天的歷史數據,新舊兩版並排執行,
    所有欄位數值差異必須在浮點誤差範圍內(< 0.0001)

    「驗證方式」這一段給了 Claude 一個清楚的完成定義:不是「看起來跑得動」,而是「跟舊版數字一樣」。

    結果:1 天完成,新舊並排驗算通過,分析師信心十足上線。

    場景三:舊訂單系統接新電商平台(Shopee / momo)

    情境

    一家中型品牌商有自己的後台訂單系統(自建,PHP + MySQL,跑了七年),現在要同時開 Shopee 和 momo 的店,訂單要自動回拋到自建系統,庫存要即時同步。自建系統的代碼文件不齊全,但不能大改,只能在外面包一層。

    不會用的人怎麼做

    幫我串接 Shopee 和 momo 的訂單,自動同步到我們自己的系統。

    Claude 寫了一個整合服務,讀 Shopee/momo 的 webhook,轉換格式,打進自建系統的 API。

    測試時發現:

    • 自建系統的商品 SKU 格式是 PRD-XXXXXXXX,但 Shopee 上的 SKU 是當初手動輸入的,有些根本對不上
    • 自建系統的訂單狀態只有 5 種,Shopee 有 12 種,Claude 的對照表做了一半,有幾個狀態沒處理
    • momo 的訂單金額包含平台折扣,自建系統的商品價格是定價,兩邊金額對不上帳
    • 自建系統在創建訂單時會觸發一個庫存扣減的觸發器,Claude 不知道這件事,導致庫存被扣兩次

    最後一個問題最嚴重:庫存被扣兩次,一直到實際出貨才發現。

    結果:開發 4 天,測試又 3 天,上線後還是出現庫存問題。

    會用的人怎麼做

    舊系統不熟,先讓 Claude 幫你挖清楚它的邊界。

    第一步:讓 Claude 讀舊系統,主動找隱性行為

    請閱讀這個訂單系統的代碼,特別注意:
    1. 創建訂單時會觸發哪些副作用(觸發器、事件、其他表的更新)
    2. 庫存扣減在哪裡發生(是 API 層還是資料庫層)
    3. 訂單狀態的完整清單和流轉規則
    
    告訴我所有你發現的隱性行為,不要開始寫任何代碼。

    「隱性行為」這個說法很重要。Claude 在讀舊代碼時會主動找資料庫 trigger、事件監聽器、side effect,這些是最容易被遺漏的整合風險。

    第二步:用 Plan Mode 規劃整合架構,重點在「邊界」

    【背景】
    自建訂單系統(PHP + MySQL),創建訂單時資料庫層會自動扣減庫存(trigger)。
    Shopee 和 momo 各有自己的訂單狀態體系。
    
    【目標】
    Shopee/momo 新訂單自動進到自建系統,庫存只扣一次,狀態對照完整。
    
    【約束條件】
    - 自建系統的 trigger 不能改(沒有完整文件,風險太高)
    - SKU 對照表需要人工確認後再上線(不能用 Claude 猜測)
    - momo 的折扣金額要分開記錄,不能直接入自建系統的商品價
    
    請制定整合架構計劃,
    特別說明如何避免庫存被扣兩次,
    等我確認計劃後再開始實作。

    Plan Mode 裡,Claude 提出了三個方案,推薦的是:新建一個 OrderBridge 服務,只負責格式轉換和狀態對照,在呼叫自建系統 API 之前先把庫存檢查做在 Bridge 層(避免 API 呼叫失敗後 trigger 已執行的問題)。

    第三步:設計文件把 SKU 對照、狀態對照、金額拆分全部定義清楚

    ## SKU 對照策略
    - 對照表存在 sku_mapping 資料表,人工審核後才生效
    - 找不到對照的 SKU:訂單進 pending_review 佇列,不自動處理
    - 禁止猜測或模糊匹配
    
    ## 訂單狀態對照(Shopee → 自建)
    UNPAID        → 不同步(等付款)
    READY_TO_SHIP → processing
    SHIPPED       → shipped
    COMPLETED     → completed
    CANCELLED     → cancelled
    其他狀態      → 記錄 log,不同步,發警報
    
    ## momo 金額處理
    momo_original_price → 自建系統 unit_price
    momo_discount       → 另存 discount_record 資料表
    momo_final_price    → 自建系統 actual_amount
    (三個欄位分開記錄,不做合併計算)

    結果:2 天完成 OrderBridge,庫存零重複扣減,SKU 對照人工審核後上線,穩定運行。

    舊系統整合的核心技巧整理

    技巧 怎麼做 目的
    先讓 Claude 讀現有接口提供 API 簽名、schema、關鍵函數,要求 Claude 說出理解後再動手讓 Claude 在正確的上下文下設計,不做無效假設
    要求 Claude 找隱性行為明確說「找出所有 trigger、side effect、副作用,不要開始寫代碼」在整合前把地雷挖出來,不是做完才踩到
    CLAUDE.md 凍結不能動的邊界在 CLAUDE.md 明確寫「不得修改 X 格式 / Y 欄位名稱 / Z 計算邏輯」Claude 不會因為「更整齊」而擅自重新命名或重構
    設計文件定義接合點,不定義格式設計文件描述「新舊系統在哪裡接觸」,格式繼承舊系統,不重新設計避免做一個格式轉換層長期維護
    驗證方式要對比舊系統Done When 裡明確說「與舊系統同樣輸入,輸出結果必須一致」讓 Claude 自己驗算新舊等價性,不是跑起來就算完成

    一個可以直接用的提示模板

    每次要在舊系統上加新功能,用這個模板啟動:

    【現有系統】
    [描述現有系統的技術棧和關鍵接口,附上接口文件或關鍵代碼片段]
    
    【要加的功能】
    [一句話描述]
    
    【不能動的邊界】
    - [現有系統的格式、欄位名稱、計算邏輯等不能更動的項目]
    - [如果有 DB trigger 或其他隱性行為,也列在這裡]
    
    【請先做這兩件事,再開始設計】
    1. 告訴我你對現有接口的理解(特別是你覺得可能影響整合的部分)
    2. 指出你看到的整合風險(格式衝突、重複操作、狀態對照缺口)
    
    確認理解正確後,我們再討論設計。

    這個模板做了三件事:把舊系統的上下文給 Claude、凍結不能動的邊界、要求 Claude 在動手前先說出它的理解和風險判斷。

    常見問題

    Q:舊系統的代碼很亂,文件也沒有,怎麼辦?

    先讓 Claude 讀代碼,問它「這個系統對外暴露了哪些接口?資料庫有哪些關鍵的 table 和 trigger?」讓 Claude 幫你反向整理出一份接口文件,確認沒有遺漏後再進行整合設計。不要跳過這一步,這是整合成功的前提。

    Q:整合的範圍不確定,不知道要動到哪裡?

    先用 Plan Mode,給 Claude 目標和約束,讓它畫出影響範圍。Plan Mode 的價值在複雜整合場景特別高,因為它會列出所有相關的文件和狀態流,讓你確認範圍是否正確,再決定怎麼切入。

    Q:新功能做完,但舊系統有些邏輯說不清楚,怕 Claude 做錯?

    這種情況用「新舊並排驗算」:先在測試環境讓舊版和新版用同樣輸入各跑一次,比較輸出。在設計文件裡明確寫出這個驗證條件,Claude 就會把「新舊等價」列為完成定義的一部分。

    從不會用到會用:舊系統整合的具體升級路徑

    舊系統整合的升級路徑跟全新開發不太一樣:問題不是「我沒說邊界條件」,而是「Claude 根本不知道舊系統長什麼樣」。所以升級的重點是:在動手前把舊系統的關鍵資訊餵給 Claude

    第一步:今天就能做到(一個句子)

    在你的提示前面加上這段:

    我有一個現有系統,新功能必須跟它相容。
    
    現有系統的關鍵格式:
    [把你知道的接口格式、欄位名稱、資料格式貼在這裡]
    
    新功能不能更動上面這些格式。先告訴我你的理解,再開始設計。

    就算你只知道一部分格式,先寫一部分。有比沒有好。

    醫療 HIS 整合:Level 0 → Level 1

    不會用(Level 0) 初步會用(Level 1)
    幫我串接 HIS 系統做 LINE 掛號(見下方)
    我有一個舊的 HIS 系統(不能修改),需要在外面接一個 LINE 掛號 bot。
    
    HIS 現有接口(Stored Procedure):
    sp_GetAvailableSessions(@DeptCode NCHAR(3), @DateFrom NCHAR(8), @DateTo NCHAR(8))
    sp_CreateBooking(@PatientId NCHAR(8), @SessionId NCHAR(16), @Phone NVARCHAR(20))
      回傳 Status: SUCCESS / FULL / DUPLICATE
    
    格式約束(不能改):
    - PatientId 是 8 位數字字串,不足補 0
    - 所有呼叫只能透過 stored procedure,不能直接查表
    
    請先告訴我:
    1. 你對這個 HIS 接口的理解
    2. 你覺得 LINE bot 和 HIS 之間需要什麼樣的轉換層
    
    確認後再討論架構設計。

    舊報表腳本接新數據:Level 0 → Level 1

    我有一個舊的 Python 分析腳本,計算邏輯不能動,只要換掉數據來源(從手動 CSV 改成自動抓取)。
    
    舊腳本的輸入依賴(這些欄位名稱不能改):
    - date (YYYY-MM-DD)
    - open, high, low, close, volume
    - vol_adj(自訂欄位:去掉最高最低各2天的16日均量)
    
    計算邏輯不能動的原因:
    - RSI 用的是 Wilder 平滑法(非標準 SMA),三年來的報告都是這個版本
    - 改了數值會跟歷史記錄不一致
    
    請先告訴我:
    1. 你理解哪些東西不能動
    2. 你打算怎麼讓新舊版本在同樣輸入下輸出一致的結果
    
    確認後再開始實作數據來源層。

    舊 ERP 接電商平台:Level 0 → Level 1

    我有一個舊的訂單系統(PHP + MySQL),要串接 Shopee 的訂單進來。
    舊系統不能大改,只能在外面包一層。
    
    已知的舊系統行為:
    - 創建訂單時,資料庫層有 trigger 會自動扣庫存
    - 訂單狀態:pending / processing / shipped / completed / cancelled(只有這五種)
    
    Shopee 訂單狀態有 12 種,需要做對照。
    
    我擔心的問題:
    - 庫存被扣兩次(trigger + 外面的 API 都扣)
    - 狀態對照不完整,有些 Shopee 狀態沒有對應的舊系統狀態
    
    請先幫我分析這兩個風險,告訴我你的處理方案,再開始設計架構。

    注意最後一段:把你擔心的問題說出來。這讓 Claude 優先處理你知道有風險的地方,而不是從它認為重要的地方開始。

    第二步:下週可以做到(CLAUDE.md 記錄舊系統約束)

    舊系統整合的 CLAUDE.md 要特別加一個「整合約束」區塊:

    # 整合約束(現有系統,不可更動)
    
    ## [系統名稱] 的格式規範
    - [欄位名稱] 的格式:[說明]
    - [接口規範]:[說明]
    - 禁止直接操作資料庫,只能透過 [API / SP / 特定方法]
    
    ## 已知的隱性行為
    - [觸發器 / 事件 / side effect 描述]
    - 注意:[操作 X] 會同時觸發 [Y],不要重複執行
    
    ## 新功能的邊界
    - 只修改 [Adapter / Bridge / 特定模組],不動舊系統
    - 欄位名稱繼承舊系統,不重新命名

    每次發現一個新的隱性行為(觸發器、計算邏輯、格式特例),就加進這個區塊。它會越來越完整,讓你以後的整合工作越來越省力。

    第三步:一個月後的進化

    進化 A:在開始任何整合前,先讓 Claude 找隱性行為

    請閱讀 [現有系統代碼/文件],找出所有:
    1. 資料庫 trigger 和它的作用
    2. 創建/更新/刪除記錄時的 side effect
    3. 對外暴露的接口(API / SP / 事件)和它們的格式
    
    告訴我你找到的所有隱性行為,不要開始設計,先讓我確認。

    這個步驟在整合開始前把地雷挖出來,比做完後踩到省 10 倍時間。

    進化 B:複雜整合用 Plan Mode,重點讓 Claude 畫出影響範圍

    【現有系統】[描述]
    【目標】[一句話]
    【不能動的邊界】[列清楚]
    
    請制定整合計劃,特別標出:
    - 會影響到的現有功能
    - 每個整合點的風險
    - 我需要在上線前人工驗證的項目
    
    等我確認計劃後再開始實作。

    進化 C:設計文件加「新舊等價性驗證」

    舊系統整合的完成定義,永遠要加這一條:

    ## 驗證方式
    用同一份歷史輸入,新舊兩版並排執行,
    [關鍵輸出欄位] 的結果差異必須在 [可接受範圍] 內。
    新版上線前,提供新舊對比報告。
    階段 做什麼 關鍵句
    Level 0直接說要串接什麼
    Level 1(今天)把舊系統格式和約束說清楚「這些格式不能改,告訴我你的理解再開始」
    Level 2(下週)CLAUDE.md 記錄舊系統約束和隱性行為每次整合後補一條「已知隱性行為」
    Level 3(一個月後)先讓 Claude 挖地雷,再 Plan Mode 確認影響範圍「找出所有隱性行為,不要開始設計」
  • 會用 vs 不會用 Claude Code:醫療、股市、電商三場景對比

    重點摘要

    • 差距不在「會不會用 AI」,在「有沒有給 AI 做事的結構」
    • 不會用的人:一句話丟需求 → 結果跑偏 → 多輪修正 → 累積沮喪
    • 會用的人:CLAUDE.md + 設計文件 + 分段驗證 → 第一次就對
    • 三個真實場景(醫療 / 股市 / 電商)示範具體差距

    「Claude Code 對我沒用,我試過,它做出來的東西都不對。」

    這句話我聽過很多次。幾乎每次深入問,問題都不在 Claude,在提問的方式。

    這篇文章用三個真實的軟體開發場景,直接模擬「不會用的人」和「會用的人」各自怎麼做,讓你看清楚差距在哪裡。

    核心差距:有沒有給 AI 做事的結構

    不會用 Claude Code 的人,把它當成「很聰明的搜尋引擎」,問一句,期待完美答案。

    會用的人,把它當成「需要完整簡報才能開工的新進工程師」:你給的資訊越清楚,他做出來的東西越準確。

    差距的本質是:你的輸入有沒有結構

    場景一:醫療預約系統(門診掛號)

    痛點

    診所要做線上掛號,需要處理:醫師排班、假日停診、同時段人數上限、患者重複掛號防止。每個規則都有例外,例外裡還有例外。

    不會用的人怎麼做

    直接開口:

    幫我寫一個門診預約系統的 API,要能掛號、取消、查詢。

    Claude 給了一個乾淨的 REST API,CRUD 完整,code 看起來不錯。

    開始整合後發現問題一個接一個:

    • 沒處理同時段上限(診所每診次只收 20 人,API 沒有 capacity 邏輯)
    • 沒有重複掛號檢查(同一個患者可以掛同一診次兩次)
    • 沒有假日判斷(系統不知道什麼是醫院休診日)
    • 時區沒處理(台灣 UTC+8,stored as UTC,前端顯示全錯)

    開始補需求:「喔對,要加上每診次人數上限」→ Claude 修改。「還有重複掛號要擋掉」→ Claude 再改。「假日要停診」→ 再改。每次修改都可能動到之前改好的邏輯,三輪之後代碼開始難以追蹤。

    結果:8 小時,仍有未發現的 bug,信心不足。

    會用的人怎麼做

    第一步:CLAUDE.md 裡早就寫好領域規則

    ## 醫療領域規則
    - 所有時間以 UTC+8 儲存,API 回應包含 timezone 欄位
    - 患者 ID 採用身分證字號格式,需驗證格式(字母+9位數字)
    - 診次 (session) 為最小預約單位,每診次有 capacity 上限
    - 相同患者在同一診次只能有一筆有效預約
    
    ## 錯誤處理標準
    - 業務邏輯錯誤:HTTP 422 + { code, message, field }
    - 驗證錯誤:HTTP 400 + 同上格式

    第二步:先寫設計文件(20 分鐘)

    # 功能:門診掛號 API
    
    ## 輸入
    { patientId: string, sessionId: string }
    
    ## 驗證順序(按此順序,遇錯即停)
    1. patientId 格式是否合法
    2. sessionId 是否存在且為未來時間
    3. 該診次是否已達 capacity
    4. 該患者是否已有此診次的有效預約
    
    ## 邊界條件
    - capacity 滿:422,code: SESSION_FULL
    - 重複掛號:422,code: DUPLICATE_BOOKING
    - 患者格式錯:400,code: INVALID_PATIENT_ID
    - 診次已過去:422,code: SESSION_EXPIRED
    
    ## Done When
    - 所有邊界條件有單元測試
    - integration test 驗證完整掛號流程
    - 0 TypeScript errors

    第三步:分段給任務

    請先閱讀 CLAUDE.md 和這份設計文件。
    閱讀完告訴我你的理解,特別是驗證順序的邏輯,再開始實作。
    先只實作 validateBooking() 函數和對應單元測試,不要動 API 層。

    確認驗證邏輯正確後,再說「現在依照這個驗證函數實作 POST /bookings endpoint」。

    結果:2.5 小時,第一次就通過所有測試,零修改。

    場景二:股市回測系統

    痛點

    想驗證一個交易策略:當 5 日均線上穿 20 日均線時買進,死亡交叉時賣出。聽起來簡單,但台股有漲跌停、只能在交易日交易、最小交易單位是 1000 股、手續費和證交稅要扣掉,每個細節都會影響回測結果。

    不會用的人怎麼做

    幫我寫一個台股回測程式,策略是 5 日均線上穿 20 日均線買進,死叉賣出。

    Claude 給了一個 Python 回測,用 pandas 計算均線,邏輯清楚。跑了一下,報酬率看起來很漂亮。

    仔細看才發現:

    • 買賣都用收盤價,但實際上收盤價買不到(要用隔日開盤)
    • 沒有漲跌停限制,假設任何價格都能成交
    • 沒扣手續費(0.1425%)和證交稅(0.3%)
    • 沒有最小交易單位,0.1 張也買
    • 跑到非交易日(週末)的資料也在交易

    這些問題加起來,讓回測結果虛報了約 30–40%。一個看起來賺錢的策略,修正後可能是虧損的。

    結果:6 小時修修改改,最後不確定結果是否可信。

    會用的人怎麼做

    設計文件把所有台股規則先寫清楚:

    # 功能:台股均線策略回測引擎
    
    ## 市場規則(必須完整實作)
    - 交易日:排除週末 + 台灣國定假日(用 holidays-tw 套件)
    - 成交價:訊號發生在收盤,執行在「隔一個交易日開盤價」
    - 漲跌停:每日最大漲跌幅 ±10%,超過範圍無法成交,標記 LIMIT_HIT
    - 最小交易單位:1000 股,不足整張無法下單
    - 手續費:買賣各 0.1425%(可設定),最低 20 元
    - 證交稅:賣出 0.3%(ETF 為 0.1%)
    
    ## 回測輸出格式
    {
      total_return_pct: float,    # 扣除所有費用後
      trades: [{ date, action, price, shares, cost, tax, net_pnl }],
      unfilled: [{ date, reason }],   # LIMIT_HIT 等無法成交紀錄
      sharpe_ratio: float,
      max_drawdown_pct: float
    }
    
    ## 邊界條件
    - 漲停無法賣出(LIMIT_HIT_SELL)
    - 跌停無法買入(LIMIT_HIT_BUY)
    - 資金不足一張:跳過,記錄 INSUFFICIENT_FUNDS
    - 最後持倉:回測結束日強制以收盤價平倉

    提示方式:

    請先閱讀這份設計文件,告訴我:
    1. 成交時間點的邏輯(訊號日 vs 執行日)你的理解
    2. 漲跌停時的處理流程
    
    確認理解正確後,先只實作 TaiwanMarketRules 類別和測試,
    包含漲跌停判斷、交易日判斷、手續費計算三個方法。
    不要實作策略邏輯或回測引擎。

    結果:3 小時,回測結果可信,且有完整的無法成交紀錄供分析。

    場景三:電商金流串接(綠界 ECPay)

    痛點

    要串接台灣最常用的金流服務商,支援信用卡一次付清 + ATM 虛擬帳號。牽涉到加密簽章驗證、非同步回調(ReturnURL / OrderResultURL)、以及各種付款失敗情境。

    不會用的人怎麼做

    幫我串接綠界金流,支援信用卡和 ATM 付款。

    Claude 寫了一個串接,看起來完整。測試環境跑起來。上線後三天,開始收到客訴:

    • 付款成功但訂單沒更新(沒有正確處理綠界的非同步通知)
    • ATM 超時未付款,訂單卡在「待付款」沒有自動取消
    • CheckMacValue 驗簽偶發失敗(特殊字元的 URL encode 方式不對)
    • 退款流程完全沒實作(以為付款和退款是同一組 API)

    每個問題單獨看都能修,但修一個又會影響另一個。金流 bug 是最難測試的,因為要模擬真實付款行為。

    結果:上線後 bug,緊急修補兩天,損失用戶信任。

    會用的人怎麼做

    先用 Plan Mode 讓 Claude 梳理所有狀態流:

    【背景】
    我要串接綠界 ECPay,使用 Node.js + PostgreSQL,
    CLAUDE.md 中規定所有金流操作要記 audit log。
    
    【目標】
    支援信用卡一次付清和 ATM 虛擬帳號,訂單狀態要與付款狀態完全同步。
    
    【約束條件】
    - 不能有「已付款但訂單未更新」的狀態
    - ATM 超過 3 天未付款自動取消訂單並釋放庫存
    - CheckMacValue 驗簽失敗必須記錄並告警
    
    請制定實作計劃,列出所有需要處理的狀態流轉,
    等我確認計劃後再開始實作。

    Claude 在計劃中列出了 14 個狀態節點,包含「非同步通知重複到達」、「驗簽失敗的處理」這些不明顯的情境。確認計劃後再開始做。

    設計文件特別標明的邊界條件:

    ## 邊界條件(金流特有)
    - ReturnURL(非同步)和 OrderResultURL(同步)可能「都」被呼叫
      → 用 idempotency key 確保同一筆交易只更新一次訂單
    - CheckMacValue 驗簽:URL encode 順序必須按綠界規範(非標準 encodeURIComponent)
      → 測試案例需包含含特殊字元的 MerchantTradeNo
    - ATM 逾期:用 pg-cron 排程,不要依賴前端觸發
    - 退款:獨立 API,與付款 API 完全分離,需要人工審核 flag

    結果:4 小時,上線零 bug,audit log 完整。

    差距總結

    面向 不會用的人 會用的人
    提示方式「幫我做 X」「背景 + 目標 + 約束條件 + 邊界條件」
    領域規則每次用到才補說寫進 CLAUDE.md,一次設定永久生效
    邊界條件做完後才發現沒處理設計文件裡最前面就列清楚
    複雜任務一次丟,結果跑偏再修Plan Mode 確認方向,分段執行
    驗證方式全部做完再整體測試每段完成後先確認,錯誤早期發現
    對話輪數8–15 輪2–4 輪
    結果品質能跑,但邊界不完整完整,測試覆蓋所有邊界

    為什麼大多數人卡在「不會用」

    不是因為懶,是因為直覺錯了。

    我們習慣搜尋引擎:問一句,得到答案。Claude Code 不是搜尋引擎,它是一個需要簡報才能開工的工程師。你給的資訊越完整,它做出來的東西越準確。

    轉換這個直覺需要時間,但一旦轉過來,你就不會想回頭了。

    從下一個任務開始,試著在開口前先回答三個問題:

    1. 這個功能的輸入和輸出各是什麼格式?
    2. 哪些邊界條件會讓它失敗?
    3. 我怎麼確認它做對了?

    把這三個問題的答案寫下來,你的 Claude Code 使用效果會立刻不一樣。

    常見問題

    Q:每次都要先寫設計文件,不會很花時間嗎?

    一份最小版設計文件 20 分鐘。省下的多輪修改至少 2–4 小時。這筆帳很好算。

    小功能(一個函數、修一個 bug)不需要設計文件,直接做。設計文件是為了「有多個邊界條件、或跨越兩層以上架構」的任務。

    Q:CLAUDE.md 不是每個專案都要重寫一遍嗎?

    寫一次,維護成本低。每次發現 Claude 做了一個你不喜歡的決定,把那條規則加進 CLAUDE.md,下次就不會再發生。它是越用越省力的資產。

    Q:我的需求很複雜,文件要寫到多詳細?

    詳細到「可以讓另一個工程師依照這份文件實作,不需要問你問題」。如果你寫完文件還是覺得有地方模糊,那就是還有沒想清楚的需求,先想清楚再開始比較省事。

    從不會用到會用:各情境的具體升級路徑

    看完上面三個場景,你可能知道差距在哪,但還不知道今天要改什麼。這一節給你一條明確的路,從第一步到進階,每步都有可以直接複製的東西。

    第一步:今天就能做到(不需要任何準備)

    在你現在的任何提示最後加上這一句:

    先告訴我你的理解和假設,再開始實作。

    就這一句。它會讓 Claude 在動手前先說出它的假設,你可以在它寫出一堆錯誤代碼前糾正它。成本 0,效果立竿見影。

    三個情境的具體升級示範:

    醫療場景:Level 0 → Level 1

    不會用(Level 0) 初步會用(Level 1)
    幫我寫門診預約系統(見下方)
    幫我寫門診掛號的 API。
    
    輸入:{ patientId: string, sessionId: string, phone: string }
    輸出:{ bookingNo: string, status: "SUCCESS" | "FULL" | "DUPLICATE" }
    
    必須處理:
    - 同一診次超過容量上限 → 回傳 FULL
    - 同一患者重複掛同一診次 → 回傳 DUPLICATE
    - 所有時間以 UTC+8 處理
    
    先告訴我你的理解,特別是這三種情況你打算怎麼處理,再開始實作。

    改變了什麼:加了輸入輸出格式、三個邊界條件、確認步驟。這 5 分鐘的準備,省掉事後發現「沒處理重複掛號」的 2 小時修改。

    股市場景:Level 0 → Level 1

    幫我寫台股均線回測。策略:5日均線上穿20日均線買進,死叉賣出。
    
    台股特有規則(全部都要實作):
    - 訊號發生在收盤,執行在隔交易日開盤價(不是同日收盤)
    - 漲跌停 ±10%,超過無法成交,記錄 LIMIT_HIT
    - 手續費:買賣各 0.1425%,最低 20 元
    - 證交稅:賣出 0.3%
    - 最小交易單位 1000 股,不足不下單
    
    先告訴我這些規則你的理解,特別是成交時間點的邏輯,再開始寫。

    電商金流場景:Level 0 → Level 1

    幫我串接綠界 ECPay,支援信用卡一次付清。
    
    必須處理的情況:
    - ReturnURL(非同步)和 OrderResultURL(同步)可能都會被呼叫,
      同一筆交易只能更新訂單一次(要有 idempotency 機制)
    - CheckMacValue 驗簽失敗:記 log,不更新訂單,回傳 0|Error
    - 付款成功後訂單狀態必須立刻更新
    
    先告訴我你打算怎麼處理「非同步和同步通知都到達」這個情況,再開始實作。

    第二步:下週可以做到(CLAUDE.md)

    把你的領域規則寫成一個檔案,放在專案根目錄,命名 CLAUDE.md。之後每次對話都不用再重複說這些規則。

    先從最小版開始,15 分鐘寫完:

    # 專案規則
    
    ## Tech Stack
    [填你用的技術]
    
    ## 這個領域的特殊規則
    [把你每次都要補充說明的規則寫在這裡]
    例:
    - 台股交易日排除週末 + 台灣國定假日
    - 醫療系統所有時間 UTC+8
    - 金流驗簽失敗一律記 log 不更新訂單
    
    ## 代碼標準
    [你每次都要糾正的習慣寫在這裡]
    例:
    - 禁止 any 類型
    - 每個函數必須有對應測試
    - API 錯誤格式統一:{ code, message, field }
    
    ## 邊界條件規則
    [這個專案特有的邊界處理方式]

    寫好之後,下次開口前說「請先讀 CLAUDE.md」或什麼都不用說(Claude Code 會自動載入)。

    第三步:一個月後的進化(設計文件 + Plan Mode)

    當你習慣 Level 1 之後,下一步是在動手前多寫一份設計文件。這份文件不是給人看的,是給 Claude 看的,20 分鐘寫完,節省的是事後 4–6 小時的修改。

    設計文件的最小格式:

    # 功能:[名稱]
    
    ## 輸入 / 輸出
    輸入:[JSON 範例]
    輸出:[JSON 範例]
    
    ## 邊界條件(必須處理)
    - [條件 A] → [預期行為]
    - [條件 B] → [預期行為]
    
    ## 完成定義
    - [ ] 所有邊界條件有對應單元測試
    - [ ] TypeScript 0 errors

    有了設計文件之後,任務的啟動提示變成:

    請先閱讀 CLAUDE.md 和 [設計文件名]。
    閱讀完告訴我你的理解,特別是邊界條件部分。
    確認後先只實作 [最小單元],不要動其他層。

    當任務更複雜(跨 5 個以上文件、不可逆的架構改動),改用 Plan Mode 啟動:

    請先制定實作計劃,列出方案選項和取捨,等我確認後再開始執行。
    階段 做什麼 時間投資 節省的來回
    Level 0直接說需求00
    Level 1(今天)加輸入/輸出/邊界 + 確認步驟5 分鐘/次2–4 輪
    Level 2(下週)CLAUDE.md 寫入領域規則15 分鐘(一次性)每次省 1–2 輪
    Level 3(一個月後)設計文件 + Plan Mode20 分鐘/功能第一次就對
  • Claude Code 實戰:5 個核心技巧讓 AI 一次到位

    重點摘要

    • CLAUDE.md 是一次性投資,讓每次對話自動遵守規則,減少 50–70% 重複提示
    • 設計文件寫在執行前,讓 Claude 一次完成實作,避免多輪修改
    • Plan Mode + Agent Teams 適合複雜任務,正確啟動方式決定準確率
    • Hooks 自動化格式、測試、安全掃描,讓你專注在真正需要判斷的事

    你是否有過這樣的經驗:跟 Claude Code 說了一大段需求,它做出來的結果差了一點點,於是你開始修正、補充說明、再確認,來回四五輪才終於完成?

    這篇文章整理的,就是如何系統性地消滅這些來回。不靠運氣,靠結構。

    1. CLAUDE.md:把規則寫進專案,不用每次重說

    CLAUDE.md 是 Claude Code 自動載入的專案規則檔,放在 ~/your-project/CLAUDE.md。它是永久生效的,只要存在,每次對話都會自動套用。

    效果:寫一次,永久有效,減少 50–70% 重複提示。

    CLAUDE.md 應該寫什麼

    分四層,由外到內:

    層次 內容 範例
    基本資訊Tech stack、架構決策Next.js 14 App Router + PostgreSQL
    代碼標準命名規則、檔案結構TypeScript strict mode,禁止 any
    業務邏輯領域規則、合規要求台灣統一編號驗證邏輯
    技術決策測試策略、代碼審查規則每個函數必須有對應單元測試

    可直接複製的最小版 CLAUDE.md

    # 專案規則
    
    ## Tech Stack
    - Runtime: Node.js 20, TypeScript strict
    - Frontend: Next.js 14 App Router
    - Database: PostgreSQL + Prisma ORM
    - Testing: Vitest + Testing Library
    
    ## 代碼標準
    - 禁止使用 `any` 類型
    - 所有 API 回應都必須有錯誤處理
    - 命名:camelCase 變數/函數,PascalCase 元件
    - 每個新函數必須有對應測試
    
    ## 禁止事項
    - 不要在 .env 以外的地方寫入 secrets
    - 不要 commit node_modules
    - 不要繞過 TypeScript 類型檢查
    
    ## 測試策略
    - 單元測試:純函數、工具類
    - 整合測試:API routes、資料庫操作
    - E2E:核心用戶流程

    常見錯誤:規則太模糊(「要寫好的代碼」)。寫 CLAUDE.md 要具體到可驗證,例如「API 回應必須包含 { success, data, error } 結構」。

    2. 設計文件:讓 Claude 第一次就做對

    沒有設計文件,Claude 會根據最可能的假設去實作。你的需求愈複雜,這些假設偏離你想法的機率就愈高。

    設計文件 ≠ CLAUDE.md:CLAUDE.md 是永久規則,設計文件是「這個功能」的一次性說明。

    最小版設計文件(20 分鐘內完成)

    # 功能:[名稱]
    
    ## 要做什麼
    [一段話描述,包含用戶場景]
    
    ## 輸入 / 輸出格式
    輸入:{ invoiceNumber: string, amount: number }
    輸出:{ success: boolean, invoiceId: string }
    
    ## 邊界條件
    - 金額為 0 時:回傳錯誤,不建立發票
    - 統編格式錯誤時:拋出 ValidationError
    - 重複發票號碼:回傳已存在的 invoiceId
    
    ## 完成定義(Done When)
    - [ ] 所有邊界條件有對應測試
    - [ ] API 回應符合 CLAUDE.md 定義的格式
    - [ ] TypeScript 0 errors

    這 20 分鐘可以省下 4–6 小時的修改。數學很簡單。

    複雜場景:從用戶故事快速產出設計文件

    當你腦中只有模糊需求,可以用這個提示讓 Claude 幫你產出設計文件初稿:

    我需要實作:[用戶故事]
    
    請幫我寫一份設計文件,包含:
    1. 功能描述(一段話)
    2. 輸入/輸出格式(JSON 範例)
    3. 邊界條件清單
    4. 完成定義
    
    不要實作,只寫文件。

    確認文件正確後,再說「依照這份設計文件實作」。這是「計劃→確認→執行」的標準流程,比直接說需求減少至少 2 輪來回。

    3. Plan Mode:大型任務的正確啟動方式

    Plan Mode 是 Claude Code 的三段式決策機制:探索 → 規劃 → 用戶確認。只有用戶批准後才開始執行,避免走錯方向浪費的大量時間。

    何時使用 Plan Mode

    場景 使用 Plan Mode? 原因
    修一個 bug不需要範圍小,直接做
    新增一個 API endpoint不需要單一改動
    重構模組(跨 5+ 個文件)需要需要確認拆分策略
    架構遷移(框架升級)需要不可逆,要先對齊
    全新功能模組(3 天以上工作量)需要複雜度高,先確認再做

    Plan Mode 的正確提示格式

    啟動 Plan Mode 後,給 Claude 的提示要包含三個部分:

    【背景】
    這個專案是 [系統描述],目前 [現況]。
    
    【目標】
    我需要 [具體目標],完成後要能 [驗收標準]。
    
    【約束條件】
    - 不能破壞現有的 [X] 功能
    - 必須相容 [Y] 版本
    - 不要修改 [Z] 目錄的任何檔案
    
    請先制定實作計劃,列出方案選項和取捨,等我確認後再開始執行。

    「等我確認後再開始執行」這句話非常關鍵。沒有這句話,Claude 可能在呈現計劃的同時就開始執行了。

    4. Agent Teams:平行作業的正確姿勢

    Agent Teams 讓多個 Claude 實例同時處理獨立任務。正確使用可以把 3 天的工作壓縮到 1 天,錯誤使用會讓機器記憶體爆掉。

    模型選擇速查

    模型 記憶體 適合任務 口訣
    Opus~1GB/agent架構決策、複雜業務邏輯、Code Review需要「想」
    Sonnet~600MB/agentCRUD 實作、API 對接、表單頁面需要「做」
    Haiku~400MB/agent檔案掃描、配置對比、簡單查詢需要「找」

    建立 Agent Team 前必做的三件事

    1. 評估記憶體:執行 free -h,可用記憶體必須大於預計用量的 1.5 倍(安全邊界)
    2. 拆分獨立任務:每個 agent 的任務不能有隱性依賴,確認前後順序再分配
    3. 準備共用 CLAUDE.md:所有 agent 共享同一套規則,避免各自用不同標準

    任務拆分原則

    適合平行的任務:API endpoint A、API endpoint B、前端表單 C(互不依賴)

    不適合平行的任務:「建資料庫 schema」→「實作 API」→「寫測試」(有嚴格先後順序)

    # 建立 Agent Team 的標準提示
    我需要建立一個 Agent Team 完成以下任務:
    
    【總目標】[一句話]
    
    【任務清單】(已確認互相獨立)
    1. [任務 A] → 負責人:Sonnet agent
    2. [任務 B] → 負責人:Sonnet agent
    3. [任務 C](需要架構決策)→ 負責人:Opus agent
    
    【共用規則】
    - 所有代碼遵守 CLAUDE.md
    - 任務完成後回報:完成的文件列表 + 測試通過狀態
    
    【資源限制】
    可用記憶體:[X]GB,請確認 agent 數量不超過安全上限。

    5. Hooks:讓機器自動做重複的事

    Hooks 是在特定事件(編輯後、提交前、排程)自動執行的腳本。設定一次,永久省力。

    三個最值得設定的 Hook

    Hook 1:編輯後自動格式化(after-edit)

    {
      "hooks": {
        "after-edit": {
          "command": "prettier --write $FILE && eslint --fix $FILE",
          "on_failure": "warn",
          "timeout": 30000
        }
      }
    }

    Hook 2:提交前強制測試通過(before-commit)

    {
      "hooks": {
        "before-commit": {
          "command": "npm run test -- --passWithNoTests && npm run lint",
          "on_failure": "block",
          "timeout": 120000
        }
      }
    }

    "on_failure": "block" 代表測試未通過時 commit 會被阻止,不是只警告。

    Hook 3:每週安全掃描(scheduled)

    {
      "hooks": {
        "scheduled": {
          "cron": "0 10 * * 6",
          "command": "npm audit fix && npm outdated",
          "on_failure": "warn"
        }
      }
    }

    這三個 Hook 每週省下約 60 分鐘,一年就是 52 小時。

    6. 降低來回、提高準確的通用技巧

    多文件上下文提示法

    要讓 Claude 了解跨文件的關係,不要一次只給一個文件,要同時提供:

    請先閱讀這三個文件後再開始:
    - src/types/invoice.ts(資料模型)
    - src/api/invoices.ts(現有 API)
    - docs/designs/invoice-search.md(本次設計文件)
    
    閱讀完成後告訴我你的理解,再開始實作。

    「閱讀完成後告訴我你的理解」這個確認步驟,能在執行前抓到 Claude 對現有代碼的誤解。

    邊界條件先行法

    把邊界條件和錯誤情況列在需求的最前面,而不是最後面。Claude 讀到越早的內容,優先度越高:

    # 不好的順序
    實作用戶登入功能,支援 email/password,記得處理密碼錯誤的情況
    
    # 好的順序
    實作用戶登入功能
    
    【錯誤情況(必須處理)】
    - 帳號不存在 → 401,訊息「帳號或密碼錯誤」(不透露哪個錯)
    - 密碼錯誤 → 401,同上訊息
    - 連續失敗 5 次 → 鎖定帳號 15 分鐘
    
    【正常流程】
    支援 email/password,成功回傳 JWT token

    分段確認法(適合複雜場景)

    不要一次把整個複雜需求丟給 Claude,分段完成並確認:

    1. 「先實作資料模型,不要碰 API 層,完成後給我看」
    2. (確認模型正確)「現在依照這個模型實作 API」
    3. (確認 API 正確)「現在寫整合測試」

    每一段都比整體更容易驗證,錯誤也更容易在早期被發現。

    明確說「不要做什麼」

    Claude 很善意,會主動補充它認為合理的東西。如果不想要這些補充:

    # 加上明確的範圍限制
    只修改 src/utils/tax.ts 這個文件,不要動 tests/ 目錄,
    不要重構現有函數,只新增 calculateVAT() 函數。

    整合使用:複雜功能的標準流程

    把上面所有技巧整合成一套可重複使用的流程:

    1. 確認 CLAUDE.md 存在且最新(一次性,專案生命週期)
    2. 寫設計文件(每個新功能,20–30 分鐘)
    3. 用「計劃→確認→執行」啟動任務(複雜任務用 Plan Mode)
    4. 分段驗證(模型 → API → 測試,每段確認一次)
    5. Hooks 自動把關(格式、測試、安全)

    這套流程把原本 10–15 輪的來回壓縮到 2–3 輪。

    常見問題

    Q:CLAUDE.md 要多詳細才夠?

    夠到「可以驗證」就夠了。「代碼要好維護」是沒用的規則,「函數超過 50 行必須拆分」是有用的規則。從最重要的 5 條開始,持續更新。

    Q:設計文件需求中途改了怎麼辦?

    先更新設計文件,再告訴 Claude「設計文件已更新,請依最新版本繼續,以下是改變的部分:[…]」。不要只口頭說需求變了,有文件才有依據。

    Q:Agent Teams 記憶體爆掉怎麼辦?

    立即執行 free -h 確認狀況,用 ps aux --sort=-%mem | head -20 找出佔用最多的 agent,優先結束 Opus 實例。恢復後先用 git status 確認哪些工作已完成,從斷點繼續而不是重頭來過。

    Q:Claude 輸出的代碼跟我的風格差很多?

    這幾乎都是 CLAUDE.md 不夠具體的問題。找一個你認為寫得好的現有文件,告訴 Claude「比照這個文件的風格」,然後把那個風格總結後加進 CLAUDE.md。

  • git flow說明

    git flow

    網路版本

    我方版本

    gitGraph
           commit id: "main"
           branch develop
           commit id: "init"
           branch feature1
           commit id: "feature1"
           checkout develop
           branch feature2
           commit id: "feature2"
           checkout feature2
           branch mergeFeature
           merge  feature1
           commit id: "merge12ToDev"
           commit tag:"dev-0.0.1"
           branch ga
           commit id: "toPro"
           commit tag:"ga-0.0.1"
           checkout main
           merge  ga
           commit id: "mergeAllFeature"
           checkout develop
           merge  main
           commit id: "202301XX"
           checkout develop
           branch feature3
           commit id: "feature3"
           checkout develop
           branch feature4
           commit id: "feature4"
           checkout mergeFeature
           merge  feature3
           merge  feature4
           commit id: "merge34ToDev"
    
    

    主要的幾個分支

    main(有時候是master)

    基本上每一次上板後都要merge回這一個分支,此分支為主要基底,方向只有ga可以改回來他,平常不可改動他,任何情境下都不可以

    (閱讀全文…)