重點摘要
- Markdown vs HTML 是假議題 — 真正問題是「LLM 給人類決策時的介面設計」
- AI 加工成 🟢🟡🔴 標籤的「成本/風險」評分,使用者不信。要 raw evidence (檔案、行數、schema 影響),讓使用者自己判斷
- 解法:一個 Flask + systemd + Cloudflare tunnel 的 decision-server,每個決策生 HTML 頁,使用者在瀏覽器/手機看真實證據後點選項
- 規則寫進全域
~/.claude/CLAUDE.md,所有 Claude session (含 Telegram bot) 自動遵循 - 實戰跑通:4 個 agent 並行審查 dementia-care home-handbook 找出 45 個 findings → 5 個獨立決策 page → 答完 5 tier 自動改動 → commit 3d1f101 → 自動部署 GitHub Pages
起點:一個假議題
今天早上我問 Claude:「最近有一個聲音說過去我們使用 markdown 沒有實用性,要用 HTML。你幫我比較一下。」
Claude 給了一份標準比較 — Markdown 的 token 效率、git diff 友善;HTML 的語意豐富、表達力強。然後得出結論:「在你的場景 markdown 全面勝出」。
但我打斷他。真正卡我的不是文檔格式,是另一個問題:每次 Claude 問我做決策時丟一面牆的 markdown 字,我不知道背後意義、不知道範圍、不知道要考慮什麼,認知負擔很重。如果能像 HTML 那樣用顏色區塊跟拖拉條一眼判斷,我做決策的速度會快很多。
這篇文章記錄今天從這個誤會開始,到我跟 Claude 一起建出一個跨 session 通用的決策伺服器,中間踩到的設計坑 + 抽出的協作方法論。
第一次嘗試:加 🟢🟡🔴 對照表
Claude 第一個提案是用 Claude Code 內建的 AskUserQuestion 工具,加上 emoji 視覺對照表。範例:
速度 成本 風險
A 拆分 🟢 🔴 🟢
B 單檔 🟡 🟢 🟡
C 折衷 🟡 🟡 🟢
推薦 → C (綜合最佳)
看起來不錯。我選了這個格式。Claude 還幫我寫進 feedback memory,以後預設都用這種對照表。
30 分鐘後,我反悔了:「你說的成本不一定是真的成本,你說的風險也不一定是真的風險。你的比較我也不太能夠相信。」
核心問題:Raw Evidence vs 加工標籤
🟢🟡🔴 是 Claude 對「成本/風險」的主觀評分。它幫我把證據壓縮成一個顏色,但這個壓縮過程是有損的,而且我看不到原始材料,沒辦法 second-guess。
真正能幫我決策的不是「Claude 認為這個選項風險 🔴」,而是「這個選項會動 db/migrations/0042.sql 第 38 行的 CHECK constraint,影響 50,000 rows」。前者是評分,後者是事實。前者我半信半疑,後者我自己判斷。
這個 framing 反過來界定了 LLM 在人類決策流程裡的角色:
- 不該做的:替使用者打分數、給推薦星等、用顏色暗示優劣
- 該做的:把零散證據整理成可掃描的結構,擴展使用者的判斷面,不替代它
解法:decision-server
我提了一個架構:在我的迷你 PC 上開一個 port,Claude 要我做決策時生成 HTML 丟到那個 port,我用瀏覽器/手機看。Claude 接過去做了完整實作:
- Server:
~/decision-server/server.py(Flask, 87 行) - Service:
systemctl --user enable decision-server(linger 開,跨重開機) - Port:
8765 - Public URL:
https://askme.tomting.com(Cloudflare Tunnel) - Endpoints:
GET /d/{slug}看頁面,POST /d/{slug}收答案
每個決策 3 個檔案共用一個 slug:
| 檔案 | 寫入者 | 內容 |
|---|---|---|
pages/{slug}.html |
AI | 人類看的決策頁面 |
meta/{slug}.json |
AI | question + options 的結構化規格 |
answers/{slug}.json |
Server | 人類點完寫入,自我描述 (含 choice_label 全文) |
關鍵設計:answer.json 自我描述。不只存 choice: "B",連 choice_label 全文也存。三個並行 session 都點 B,後續讀檔不會混淆,因為每個 B 都帶著自己的語義。
Selenium 跑了一輪整合測試:3 個假 session 各生一個決策 (slug 開頭分別 a3f7- / 9e2c- / b51d-),選不同字母,驗證:
- 3 個 session 各自寫到自己的 answer.json,零交叉污染
- index 頁正確分組顯示
- 每個 answer 自描述完整
頁面設計的演進
第一版 page 只有「標題 + change_cards + options」。Tom 開了一張 demo 看完反應:「感覺資訊很少,情境根本無法懂問題是什麼,我要怎麼決策?」
對。決策者通常從別的事情切過來,不會有問題提出者的 context。設計 onboarding 區塊變成必填:
- 📖 背景 (background):這個功能是什麼?涉及哪些表/服務?為什麼會跑出這個 decision?
- ⚡ 核心問題 (problem):具體哪裡卡?矛盾在哪?
- 🩸 不解的後果 (impact):拖著會怎樣?(技術債/錯誤/blocking 什麼)
- 🔍 證據卡 (change_cards):真實 file:line + 真實 +/- 行數 + 1-3 個 bullet
- 🎯 選項 (options):每個帶 consequence (成本 / 副作用 / 適合什麼情境)
三層 framing 補完,Tom 就算前 5 分鐘在洗碗,開連結 30 秒內也能判斷。
讓所有 session 都用這個 protocol
我們建好了 server,但有個問題:Tom 同時開好幾個 Claude session — 寫 iDempiere 的一個、跑 Home123 的一個、Telegram 上的 ccbot 一個。每個 session 都要知道用 decision-server,不能靠每次重提。
解法:寫進全域 ~/.claude/CLAUDE.md (Claude Code 對所有 session 都會載入的全域指引)。新增段落「🌐 Decision-Server Protocol — MANDATORY for asking Tom decisions」,包含:
- 觸發情境表:10 種要用 decision-server 的真實場景 (方案選擇 / 範圍決定 / 優先順序 / 動作授權 / 設計選擇 / Code review 後 / Schema 變更 / 批次決策 / 工具升級 / 不可逆操作)
- 不觸發情境表:6 種對話講就好的例外 (確認理解 / 缺資訊 / 真瑣碎 yes/no / 用戶明說 / 教學模式 / Server 掛了)
- 必填欄位表:14 個欄位的必選規格
- 完整範例:一個 canonical JSON 直接抄
- 禁止寫法表:9 條紅線 (例如禁止
"risk": "🔴"主觀標籤) - 常見錯誤:5 個 future-session 易犯的
驗證方式:跨 session 自動採用。寫完規則沒多久,ccbot (跑在 Telegram 上的獨立 Claude session) 在不知情狀況下,自動讀到全域 CLAUDE.md,自動用 protocol 生了 6 個決策 page (session_id 6089),Tom 在 Telegram 看到「卡你決策 6 條」改成 6 個 askme.tomting.com 連結,在手機上 5 分鐘答完。
真實案例:home-handbook 審查
整個 stack 跑通後,我用它做了第一個真實任務:全面審查 ~/Desktop/dementia-care/home-handbook/ (失智照護 handbook,4 個 HTML 檔案 4719 行)。
步驟 1 · 並行 agent 掃描
派 4 個 general-purpose agent 並行掃 4 個檔案 (index / caregiver / long-term / emergency),每個 agent 應用同一份 10 項檢查清單,清單來自 brain/llm-handbook-writing-pitfalls.md 的 9 個失敗模式 + design-principles 的 CDN/emoji 規則:
- 細節腦補 (沒驗證就寫具體名詞/數字)
- 失能 vs 失智 frame 混淆
- boredom vs restlessness frame
- 加法 vs 減法 (測試記憶 framing)
- 醫療因果 claim 無文獻 (「會/導致/加速 + 醫學名詞」紅線)
- SOP magic number 沒推導
- 戲劇化描述 (「像 X 一樣」「彷彿」)
- 工程師腦過度設計 (可觀測性、冗餘、invariant 思維)
- PII 洩漏 (姓名、稱呼、地址)
- CDN / 外部依賴 / 新 emoji (Unicode 14+)
並行加總 4 個 agent 跑完 ~2 分鐘,回報 45 個具體 findings,每個帶 file:line + 引用原文 + 建議改法。
步驟 2 · 用 decision-server 生 5 個獨立決策 page
45 個 findings 不是 45 個決策。Claude 把它們合併成 5 個策略性決策(因為一頁一決策原則:類似議題歸為同一決策,選項是「處理策略」):
| # | 議題 | 我選的 |
|---|---|---|
| 1 | PII 清理範圍 | B:保留 meta author,內文一律第三人稱 + 砍 HTML 註解 |
| 2 | 外部連結處理 | B:保留連結 + 加 rel=”nofollow” |
| 3 | 醫療因果 claim | D:混合 — 有臨床共識的補引用 (Beers Criteria / NICE),其他弱化或砍 |
| 4 | scope overreach (E6/E7/E8 跨 CDR 2 經驗) | D:保留現狀,disclaimer 移到三章開頭加明顯 |
| 5 | magic number 無推導 | D:混合 — 自家 SOP 補推導,醫療閾值補 disclaimer |
步驟 3 · 執行 + 部署
我用瀏覽器答完 5 個 page,Claude 讀 answers/*.json 自我描述的 choice_label,執行對應改動。整理出 5 個 tier 的具體 edit (PII / 外部連結 nofollow / 醫療 claim 引用 / scope disclaimer / magic number 推導),全部用 Edit 工具批次處理。
最後輸出:
- commit
3d1f101on dev branch,4 files changed, +46/-34 lines - merge dev → main (commit
d3ccc98) - push origin/main
- GitHub Pages 5 秒部署完成
- 線上版:
https://tm731531.github.io/dementia-care/home-handbook/
抽出來的方法論
原則 1 · Raw evidence > 加工標籤
LLM 替使用者壓縮資訊是有損操作。決策接口要顯示可驗證的事實(檔案路徑、行數、schema 影響、binary 屬性),不是顯示 AI 對事實的評分(🔴 高風險、複雜度中等)。標籤把使用者鎖在 AI 的判斷裡,事實讓使用者用自己的判斷。
原則 2 · 決策頁要做 onboarding 設計
使用者打開決策頁時通常是「從別的事情切過來」,沒有問題提出者的 context。背景 / 問題 / 不解後果三段缺一不可。光列證據卡片他看不懂為什麼這個問題重要。
原則 3 · 選項要帶後果
選項 label 不夠。每個 option 帶 consequence 三件事:成本 (要做多少工)、副作用 (選了會被什麼牽動)、適合什麼情境。沒這三件事使用者只能猜選了會發生什麼。
原則 4 · 一頁一決策
N 個決策要用 N 個獨立 page,不要塞在同一頁。理由:answer.json 自我描述,每個答案要能單獨理解。多決策塞同頁 = 回到 Tom 鄙視的「文字牆」。
原則 5 · 全域配置 > 個別提醒
跨 session 要一致,要寫進全域 system prompt (Claude Code 的 ~/.claude/CLAUDE.md),不能靠每個 session 個別記住。寫進全域 = 自動覆蓋所有未來 session 包含 sub-agent 跟跨平台 bridge (ccbot)。
原則 6 · 流程要可驗證
關鍵 invariant 要寫測試。test_multi_session.py 用 Selenium 驗證 3 個並行 session 不互相污染。每次改 server 或 generator 都跑一次。PII 清理用 grep 自動驗:grep -c "老媽" 應該為 0。
整套 Stack 重現指南
如果你想複製這套協作模式,這是最小的 reproducible setup:
- Server:Flask app,3 個 endpoint (GET / + GET /d/<slug> + POST /d/<slug>)
- Generator:Python helper 接 stdin JSON spec 生 page + meta
- Wait:Python helper 阻塞 polling 直到 answer.json 出現
- Templates:Jinja2 – decision.html (含 session bar / 三層 context block / change cards / options buttons)
- Service:systemd user service + linger 開 (持久跨重開機)
- Public access:Cloudflare Tunnel (免費,1 條 command)
- Global config:Claude Code 的
~/.claude/CLAUDE.md加 MANDATORY 區塊
所有 Python 依賴只用 Flask + Selenium (測試用) + Jinja2,記憶體佔用 ~20MB,啟動時間 1 秒。整個 server.py 87 行,generator.py 75 行,template 88 行 (含 CSS)。建構成本 1 個下午,跑通就終身使用。
結語:不要替我打標籤
這篇文章的起點是 markdown vs HTML,但真正的問題從來不是文檔格式。是「LLM 在人類決策流程裡扮演什麼角色」。
當 LLM 把所有事情壓縮成 🟢🟡🔴 或星等推薦,它就把使用者鎖在自己的判斷裡。當 LLM 把零散證據整理成可掃描的結構頁面,它擴展使用者的判斷面。前者是 LLM 取代人,後者是 LLM 服務人。
建一個決策伺服器只是工具實作。背後的設計決定才是真正的協作哲學:給事實不給評分,給結構不給結論,給選項不給推薦。
發佈留言