目標:把唯一的人工關卡自動化掉

Bobo Labs 的內容流程原本是三段排程: 18:00 掃 journal 落差 → 22:00 草擬文章到 _pending/ → 翌日人工核可才 push。 最後那一步「人工核可」是刻意保留的安全閥,但它讓「全自主」只差一口氣。

今天的目標是把人工核可換成 5 道 QA gate: 紅線硬擋(grep 敏感詞)、HTML 結構驗證、無佔位字串、不覆蓋既有文章、LLM 自評。 全過才 push;任一不過留在 _pending/,等人工處理。 每次 push 上限 2 篇,避免洗版。

發現 bug:git status 冒出 memory/

建好 autopublish skill 後,先在 _pending/ 空的狀態跑一次端到端空跑—— 這是最安全的驗證方式:沒有草稿意味著即使流程全對也不會發布任何東西, 但仍然會走完所有路徑,包括 ops log 的寫入。

跑完之後執行 git status,看到這個:

?? memory/

memory/ 目錄不應該出現在站台 repo 裡。Ops log 是內部稽核檔, 裡頭有每次 AI 自動操作的紀錄,包括草稿標題、決策理由、commit hash—— 這些放上 GitHub Pages 就是公開資訊。

根因:headless claude 的 cwd 是 wrapper 的 cd 目標

Skill 裡的 ops log 路徑用的是相對路徑 memory/ops/bobo_ops_log.jsonl。 在互動模式的 Claude Code 裡,這條路徑解析到 ~/.claude/projects/.../memory/ops/...,完全正確。

但 launchd 呼叫的 wrapper script 會先 cd 到站台根目錄再啟動 headless claude -p。Headless 模式下, claude 的工作目錄就是 wrapper 的 cd 目標——也就是站台根。 相對路徑 memory/ops/... 就解析成了 bobo-labs-site/memory/ops/...,寫進了站台 repo。

這個 bug 沒有任何警告。寫入成功、沒有 exception——只是寫到了完全錯誤的地方。 靠空跑 + 立刻看 git status 才抓到。

修法:絕對路徑 + .gitignore 雙保險

修法有兩層,缺一不可:

治本:把 skill 裡所有「站台根以外」的路徑全部改成絕對路徑。 任何要寫到 ~/.claude/... 的地方不能用相對路徑,因為 headless 模式下 ~/.claude/ 和站台根不是同一個起點。

兜底:在站台 repo 的 .gitignore 加上 memory/。 即使未來有哪個路徑又寫錯,git 不會追蹤這個目錄,也不會 commit 進去、不會 push 到 GitHub Pages。

兩層同時到位。只靠 .gitignore 不夠,因為 ops log 可能永遠寫不到對的地方; 只靠絕對路徑也不夠,因為下次寫新 skill 可能又犯同樣的錯。

ops log 的可靠性:不該是唯一依據

修好之後重新驗證,也順手翻了歷史 ops log——發現過去幾次 launchd 自動跑的 draft-pending 記錄裡有缺漏。ops log 的 append 在 headless 模式不夠穩定: 有時成功、有時沉默失敗,不報錯。

這讓 ops log 的定位變得清晰:它是 best-effort 的稽核輔助,不是保證。 真正的回滾依據是 git 歷史和 commit message—— 只要 commit message 寫清楚「via /bobo-autopublish」, git log --grep autopublish 就能重建完整的自動操作時間線, 不依賴 ops log 是否有記到。

待驗證的環節

空跑驗證了「安全退出 + 路徑正確 + git clean」, 但完整的 publish 路徑(有真實草稿 → QA gate 通過 → push → 部署驗證)今天沒跑過。 明早 06:00 排程觸發時,如果今晚 22:00 draft-pending 產出合格草稿, 就是第一次真實 end-to-end 驗證。

四條教訓

Headless claude 的 cwd = wrapper 的 cd 目標:不是 ~/.claude/,也不是 home。任何 skill 裡要寫到站台根以外的地方,路徑必須絕對,這是首要檢查項。

絕對路徑 + .gitignore 雙保險:絕對路徑治本(寫到正確的地方),.gitignore 兜底(萬一再出錯,git 不追蹤)。任一單獨都不夠穩。

空跑是最安全的端到端驗證:讓流程在沒有真實輸入的狀態跑完,驗 noop 安全退出 + 揪路徑 bug,零誤發風險。有比空跑更便宜的驗證方式嗎?

ops log 是輔助,git 歷史才是保證:headless LLM 的寫入不可靠。把回滾依據放在 commit message 上,git log --grep 能重建自動操作時間線,不依賴 ops log。

來源:個人開發日誌 2026-05-29 · Bobo Labs 自主發布 v2.0 · 5 QA gate · 空跑驗證通過