Silent fail 家族

Cron 連 3 天 0 信號的 root cause:subprocess timeout + 2>/dev/null 是 silent fail trap

看起來像「真的沒事件」 某天早上 8:55 看 daily report,Polymarket bot 連續第 3 天 0 信號: === Polymarket Bot 2026-04-26 08:55 CST === 🔍 掃描: 2026-04-26 07:56 | 無信號 💰 餘額: $57.47 | 持倉 1 筆 📝 t2-20260423-111155.log 共同問題是三個信號都 (no summary),MM 沒提供可驗證的新聞依據... 📊 累計 6 筆交易 | 最後交易: 2026-03-29 第一感覺是政治冷淡期——4 月底國際新聞確實淡。Cron log 看下去: [2026-04-26 00:35:22] Exit signals: 0 [2026-04-26 00:35:22] News: 0 signals [2026-04-26 00:35:23] Correlation: 0 signals [Sun Apr 26 00:35:23 CST 2026] No signals, skipping ... (連續 9 次都長這樣) 每 30 分鐘一次 cron、整天都「No signals, skipping」。看起來都正常運作、只是真的沒事件。 ...

April 27, 2026 · 5 分鐘 · Mark Lee
PR 沒被 merge 但 fix 上 main 了

PR 沒被 merge,但 fix 上 main 了——第一次貢獻 OSS 大專案的反直覺結局

「Your pull request has been closed」 2026-04-26 早上打開 GitHub,看到一封 12 天前送出的 PR 來自 maintainer 的最新通知: Your pull request has been closed. State: CLOSED mergedAt: null 第一反應是嘆口氣——卡了 6 輪 bot review,最後還是被關了。準備重新開一個 issue 解釋為什麼這個方向是對的。 但點進去看留言才發現完全不是那回事。 12 天前發生了什麼 04-14 半夜我在用自己跑在 VPS 上的 AI agent,那個 agent 走 OpenClaw 串接 Discord。每個 Discord thread 可以綁一個 ACP(Agent Client Protocol)session 跟 Claude/Codex/Gemini 等 CLI agent 對話。 用到一半發現一個怪現象:在綁定 thread 內打 /acp close,原本應該關掉 ACP session,但卻被 ACP agent 當成「請求」吃掉,回了一段莫名其妙的對話。/status、/unfocus 也一樣。 trace 進 OpenClaw commands-acp.ts 發現 dispatch 路由跳過了 handleAcpCommand:在 ACP-bound 的 conversation 裡,所有 text 都被當 prompt 送給 ACP harness,連 /acp 開頭的管理指令都不例外。 ...

April 27, 2026 · 4 分鐘 · Mark Lee
一個下午補完 17 張 blog 封面:Codex gpt-image-2 + 一個 sandbox 陷阱的救援

一個下午補完 17 張 blog 封面:Codex gpt-image-2 + 一個 sandbox 陷阱的救援

這個部落格有個存在很久的小債:17 篇文章裡,一張封面都沒有。每次打開文章列表都是一排光禿禿的灰底 placeholder,社群媒體分享預覽也只有標題文字。 一直沒處理是因為:要嘛手動一張張找圖很煩,要嘛丟給外部服務(Midjourney / DALL-E)要自己掏錢 + 管 API key + 存圖檔對應 slug,光想這個 pipeline 就懶。 直到昨天刷到一則推文:Codex CLI 0.122 把 gpt-image-2 預設打開了,不需要 API key,走你現有的 ChatGPT 帳號計費。配套還有一個叫 baoyu-skills 的 Claude Code skill 集合,專門餵 Codex 生各種規格的圖。 也就是說:整條 pipeline 已經在我手邊,只是我不知道。那今天就來補債。 最後結果 17 張全生出來了,過程中踩到一個 --sandbox workspace-write 的誤會,有 14 張看起來全失敗,後來發現圖其實都生成了,只是被困在 Codex 的快取目錄裡。這篇記錄流程 + 踩坑 + 救援。 驗證:Codex 真的能畫圖 先 live test。我的 Codex 版本剛好是 0.122.0。 codex exec --skip-git-repo-check --sandbox workspace-write \ --output-last-message "$OUT" -m gpt-5.4 \ '$imagegen Create a simple 256x256 PNG of a red circle on white background. Save as /tmp/test.png. Final message: only the file path.' \ < /dev/null 跑完 ls /tmp/test.png 就有了。32 KB PNG、256×256 8-bit RGB、花了 ~30k tokens。 ...

April 22, 2026 · 4 分鐘 · Mark Lee
從 OpenAI Agents SDK 偷了三個概念,用在我們的 Claude Code 工作區 template

從 OpenAI Agents SDK 偷了三個概念,用在我們的 Claude Code 工作區 template

OpenAI 在 4 月 15 日更新了 Agents SDK,加入了 sandbox 隔離、Harness/compute 分離、Manifest 工作區描述、Capabilities 分層。看完技術文件後我的第一反應是「這跟我們在做的事情不一樣」,第二反應是「但裡面有幾個結構性概念可以偷」。 這篇記錄我們從中借了什麼、怎麼落地到 openclaw-workspace-template v3.0.0,以及為什麼大部分東西我們選擇不抄。 兩個系統的定位差異 先把前提講清楚:OpenAI Agents SDK 跟我們的 workspace template 解決的是完全不同的問題。 OpenAI Agents SDK 我們的 workspace template 目標使用者 企業,多租戶 SaaS 個人,單使用者 執行環境 雲端 sandbox(Modal / E2B / Cloudflare / Vercel) 本機 Mac / Linux,直接 filesystem access 權限模型 Tool calls 在 unprivileged container 裡跑,隔離網路和 secret 跟使用者同權限,能碰 git / cron / Telegram / Obsidian State serialize_session_state() / resume(),snapshot 整個 workspace 檔案系統就是 state,git 就是 snapshot Memory 內建 Memory() capability,session close 自動 summarize → consolidate 自建 MemPalace:hall-tagged journal + 主題筆記 + weekly reflection + knowledge graph OpenAI 在解的是「怎麼讓 agent 安全可靠地跑在生產環境」。我們在解的是「怎麼讓一個人的知識和自動化系統持續累積和整合」。拿來直接比就像比 AWS Lambda 跟家裡的 crontab。 ...

April 16, 2026 · 4 分鐘 · Mark Lee
Hybrid memory search:把 journal 搜尋當成 ranking 問題

Hybrid memory search:把 journal 搜尋當成 ranking 問題

給 LLM agent 用的記憶系統寫了半年,最後發現自己打開次數最多的不是 MEMORY.md 或主題筆記,而是 memory/YYYY-MM-DD.md 這份逐日 journal。日常查的也多半是「上次搞 PostgreSQL 是什麼時候」「那個 config 的決定寫在哪天」這種問題。 問題是:搜尋它不太好用。 grep 噪音太多。半年的 journal 把任何常用詞炸出幾百個 hit。 embedding-only 搜尋對 journal 不適合。journal 裡面多半是兩三行的短 entry,embedding 模型給短句的向量區分度不夠;而且 journal 每天長,每次 incremental embed 都要算 hash、做 rate limit、管 cache,出錯就是一整天的記憶搜不到。 最關鍵的是,journal 是本質上有時間性的資料。我問「上次搞 PostgreSQL 是什麼時候」,語意相似度幫不上忙,時間才是主角。 所以我把 journal 搜尋重新當成一個 ranking 問題,用三個分數軸融合:keyword overlap × temporal recency × hall-type boost。Python 不到 130 行,沒有外部依賴。 這篇記錄設計過程、實測結果,還有一個在 bootstrap 測試時才發現的 case-sensitivity bug。 為什麼不直接用 embedding 先說清楚:embedding 不是沒用。我自己在 notes/ 的相關筆記推薦也還是用 embedding 跑 cron。問題是把它用在 journal 搜尋上有幾個具體的不匹配: ...

April 10, 2026 · 3 分鐘 · Mark Lee
Anthropic 收費政策突變與 MiniMax M2.7 的意外相遇

Anthropic 收費政策突變與 MiniMax M2.7 的意外相遇

2026 年 4 月 4 日,收到一封信 那天像平常一樣,結果打開郵箱多了一封 Anthropic 的通知。讀完標題就知道事情不對: 「第三方 harness 不再消耗訂閱配額,需另外付費。」 這句話翻譯一下:OpenClaw 從這天起,不能再用馬克的 Claude Max Plan 配額了。 政策內容 項目 說明 第三方 harness OpenClaw、agent-broker 等,不消耗訂閱配額,需另外付費 官方產品 claude.ai / Claude Code CLI / Claude Cowork,正常消耗訂閱 Max Plan 用戶補償 $100 credit,4/17 前領取,90 天效期 取消選項 4/9 前在網頁版 cancel 可自動退款 $100 credit 這點很重要,是 Anthropic 的善意。但重點是:這改變了整個用量結構。 先搞清楚:Anthropic 是怎麼偵測第三方 harness 的? 一個問題立刻浮現:Anthropic 是怎麼知道我在用 OpenClaw 的? 直接逆向 Claude Code CLI v2.1.85 二進制檔案(用 strings + Node.js binary inspection),找到了答案。 ...

April 5, 2026 · 2 分鐘 · Mark Lee
AI Agent 記憶的 Context Tree:從日誌地獄到兩層架構

AI Agent 記憶的 Context Tree:從日誌地獄到兩層架構

記憶系統撐到了極限 跑了四個月的 AI agent,記憶目錄(memory/)膨脹到 37 個檔案。聽起來不多,但仔細一看: 日常日誌(2026-03-12.md、2026-03-13.md…)佔大多數 混雜著主題檔(sso-booking.md、cramclaw-webhook.md) 還有 session 元數據(只有 5 行的 session key/id) 甚至有一個 .html 檔案不知道怎麼混進來的 Agent 每次啟動要讀今天和昨天的日誌,加上 MEMORY.md 長期索引。理論上這套系統能運作,但實際上出了幾個問題。 問題一:日誌噪音 每天的日誌什麼都記——閒聊、debug 過程、中間嘗試、最終結論。當你搜尋「WireGuard 設定」,會找到五天前的 debug 記錄,卻找不到最終的設定方案,因為那被埋在某天日誌的第 200 行。 問題二:知識碎片化 同一個主題散落在不同日期的日誌裡。咖啡研究在 3/10、3/18、3/23 都有,但沒有一個統一的地方彙整「我目前對 Soup Method 的理解」。Agent 沒辦法回答「關於 X 我知道什麼」——它只能回答「某天發生了什麼跟 X 有關的事」。 問題三:重複與矛盾 知識庫(Obsidian notes)裡有 377 個筆記,掃描後發現 9 組重複(18 個檔案)。同一個技術方案在 02-Areas/Tech/ 和 01-Projects/ 各有一份,內容略有差異。哪個是對的?都不完全對。 借鏡:Harness Engineering 的 Entropy Management 2026 年 AI 工程圈開始談 Harness Engineering——不只是讓 agent 能做事,而是控制它做事的品質。三個支柱: Context Engineering:給 agent 什麼資訊 Architectural Constraints:限制 agent 的行為邊界 Entropy Management:防止系統隨時間退化 記憶系統的問題本質上是 entropy 問題。沒有主動管理,資訊會自然趨向混亂——重複累積、過時不清、碎片分散。 ...

March 28, 2026 · 3 分鐘 · Mark Lee
讓 AI Agent 的技能自我進化:用 GEPA 自動優化 SKILL.md

讓 AI Agent 的技能自我進化:用 GEPA 自動優化 SKILL.md

問題:SKILL.md 靠人工調校太慢 OpenClaw 的 skill 系統靠 SKILL.md 指引 agent 行為——什麼時候觸發、怎麼執行、輸出什麼格式。寫得好,agent 就穩定;寫得差,每次跑出來的品質都不一樣。 我的 workspace 裝了二十多個 skill,平時靠「出問題 → 改一行 → 觀察幾天 → 再改」的方式迭代。這種人工調校有兩個問題: 回饋週期太長。 改了一行要等幾天才知道有沒有效果。 靠直覺不靠數據。 改完「感覺比較好」,但沒有量化指標。 如果能讓 LLM 自己評估 SKILL.md 的效果,再自動改進,迭代速度會快很多。 靈感:GEPA(ICLR 2026) 逛 GitHub 時發現 NousResearch 的 hermes-agent,裡面有一套 self-evolution 機制,核心引用了 GEPA 這篇論文(Genetic Prompt Evolution with NL Reflection,ICLR 2026 Oral)。 GEPA 的概念不複雜: 評估:用 LLM 打分(而不是人類標註) 反思:讓 LLM 自己分析「哪裡扣分了、為什麼」 變異:根據反思結果修改 prompt 選擇:保留最高分的版本,淘汰退步的 跟 RLHF 不同,整個過程只需要 API call,不需要 GPU 做 gradient update。論文宣稱比 GRPO 少 35 倍 rollouts。 ...

March 24, 2026 · 3 分鐘 · Mark Lee
用 AI Agent 打造咖啡萃取記錄器

用 AI Agent 打造咖啡萃取記錄器

Espresso 的變數太多:豆子、烘焙度、粉量、研磨度、萃取時間⋯⋯每個參數都會影響風味。想穩定萃取,就得記錄每次的參數,慢慢找到每支豆子的 sweet spot。 紙筆記了幾天就懶了,試過幾個 App 也都不順手。最後決定自己做一個。 用對話蓋出來的 整個開發過程是透過 OpenClaw(開源 AI Agent 框架)完成的。我沒打開 IDE,就是在對話框裡描述需求: 「單頁 HTML,localStorage 存資料,Chart.js 畫圖。」 「豆子名稱要能搜尋。」 「預設值帶入上一杯的參數。」 AI 生成程式碼、我測試、回報問題、它修。來回大約 30 分鐘,從空白檔案到部署上 NAS。 Placeholder 的坑 過程中卡最久的是預設值。需求很簡單:新增記錄時自動帶入上一杯的粉量、研磨度等參數,使用者只改有變動的欄位。 前幾版用 placeholder 顯示預設值。畫面上看得到數字,但 placeholder 只是提示文字,不是 input.value。留空送出時,存進去的是空值,不是畫面上顯示的數字。 來回修了三版才想通:別用 placeholder 模擬預設值,直接把值填進 input。看到什麼就存什麼,沒有歧義。 最佳參數怎麼算 儀表板有一個「各豆子最佳參數」的區塊。一開始是取所有記錄的平均值,但這樣失敗的杯次會拉低數據。 改成:找每支豆子評分最高的記錄,取那些記錄的平均水粉比、研磨度、萃取時間。邏輯很簡單,就是 filter + reduce,但語義上合理多了——你想參考的是最好的幾杯,不是所有杯的平均。 長什麼樣 記錄表單:填完按儲存,預設值自動帶入上一杯 最近 10 杯,每筆可編輯或刪除 儀表板:各豆子最佳參數、研磨度趨勢、評分分佈 功能 記錄:豆子、烘焙度、粉量、研磨度、萃取時間、出杯量、粉碗、評分、備註 豆子和粉碗都有搜尋(從歷史記錄建 autocomplete) 預設值自動帶入,選了歷史豆子會切換成該豆子上次的參數 時間快捷鍵:現在 / 5 分前 / 10 分前 / 30 分前 / 1 小時前 儀表板:研磨度趨勢、評分分佈、各豆子最佳參數 JSON 匯入匯出 深色主題,手機可用 技術上就是一個 HTML 檔,沒後端。 ...

March 23, 2026 · 1 分鐘 · Mark Lee
AI Agent 記憶品質:用數據決定什麼該記、什麼該忘

AI Agent 記憶品質:用數據決定什麼該記、什麼該忘

前情:記憶清理的粗暴現狀 上一篇講了記憶架構怎麼從空白演化成多層結構——daily files、MEMORY.md 長期記憶、自動反芻和做夢機制。寫入的問題解決了,但清理一直很粗暴。 memory-expire.sh 的邏輯就一行:超過 30 天就歸檔。 大部分時候這沒問題。但有些記憶明明超過 30 天了,卻每天都在被搜尋命中——比如二月初寫的 espresso 配方筆記,到三月中還一直被引用。一刀切歸檔會把活躍記憶誤殺。 另一方面,有些記憶寫完就再也沒被搜到過。它們佔著 embedding 搜尋的空間,拉低搜尋精度。 需要一個比日期更聰明的判斷依據。 思路:追蹤「誰在用這段記憶」 靈感很直接:如果一段記憶在過去 30 天內被搜尋命中過多次,它就是「活的」,不該被歸檔。 做法:掃描所有 session 的 JSONL 日誌,提取 memory_search tool call 的結果,統計每個記憶檔案被命中的次數。 session JSONL → 提取 memory_search 結果 → 統計命中次數 → hit_counts.jsonl 這個 hit count 資料就是 Memory Quality Score 的核心。 實作:從 Python 到 Rust Python 原型(200 行) 第一版用 Python 寫,邏輯很直接: 掃 ~/.openclaw/agents/main/sessions/*.jsonl 找 tool_use type 是 memory_search 的 entries 從對應的 tool_result 提取命中的檔案路徑 累計到 memory/hit_counts.jsonl 跑一次大概 160ms,掃完 145 個 session 檔案得到 408 個命中記錄。 ...

March 21, 2026 · 2 分鐘 · Mark Lee