<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>White&apos;s Tech Notes</title><description>Backend engineering notes on Go, Java, Lua, DevOps and AI-assisted development. 後端工程師的技術筆記：踩過的坑、根因與解法。</description><link>https://ggwhite.github.io/ggwhite/</link><language>zh-TW</language><item><title>Google News RSS 連結要解碼，不是轉址</title><link>https://ggwhite.github.io/ggwhite/posts/google-news-rss-links-need-decoding/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/google-news-rss-links-need-decoding/</guid><description>stock-analyzer 從 2026-06 起再也沒抓到任何新聞內文。failed=0，看起來像「這些來源本來就該跳過」，五個月沒人發現。計數器全部落在「跳過」那一格，要當成失敗看。</description><pubDate>Mon, 02 Nov 2026 16:00:00 GMT</pubDate></item><item><title>Browser agent: upload a local file when file_upload fails and CSP blocks localhost</title><link>https://ggwhite.github.io/ggwhite/posts/browser-agent-upload-local-file-past-csp/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/browser-agent-upload-local-file-past-csp/</guid><description>先 curl -sI 看目標站的 content-security-policy 和 cross-origin-opener-policy，就知道 fetch 會不會被擋、popup relay 能不能用。</description><pubDate>Thu, 29 Oct 2026 16:00:00 GMT</pubDate></item><item><title>配額有限的批次：便宜必要的工作要排在昂貴輪詢前面</title><link>https://ggwhite.github.io/ggwhite/posts/quota-batches-run-cheap-work-before-polling/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/quota-batches-run-cheap-work-before-polling/</guid><description>stock-analyzer 的 fetch-financials 每小時排程都印「完成 84/294 檔，請於下個整點重跑」，看起來正常。有配額的批次工作，便宜且必要的資料要排在昂貴且多半空手的輪詢前面；混在同一個逐項迴圈裡，昂貴的那一半會把清單尾端餓死。</description><pubDate>Wed, 28 Oct 2026 16:00:00 GMT</pubDate></item><item><title>Claude Code mod：用「最近畫過才 tick」省重畫，會讓 pane 永久凍結</title><link>https://ggwhite.github.io/ggwhite/posts/claude-code-mod-seen-gated-tick-freezes-pane/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/claude-code-mod-seen-gated-tick-freezes-pane/</guid><description>jarvis mod 的 pane 在有 subagent 跑時每 150ms 重畫一次，長 session 裡 terminal 很吃 CPU。用「上次畫的時間」當閘門，閘門本身又只能靠重畫打開，就是一個沒有外力就重啟不了的死結。</description><pubDate>Thu, 22 Oct 2026 16:00:00 GMT</pubDate></item><item><title>zsh 變數後接冒號會被當成 modifier</title><link>https://ggwhite.github.io/ggwhite/posts/zsh-colon-after-variable-is-a-modifier/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/zsh-colon-after-variable-is-a-modifier/</guid><description>21 條分支全部回 0，看起來像「沒有命中」，其實每條都有 2～3 個。「全部回 0」比「部分回 0」更可疑：先拿一條手動驗證，對照組不一致就是工具鏈的問題。</description><pubDate>Thu, 22 Oct 2026 16:00:00 GMT</pubDate></item><item><title>Claude Desktop 畫 Claude Code mod 的坑</title><link>https://ggwhite.github.io/ggwhite/posts/claude-code-mod-pitfalls-in-claude-desktop/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/claude-code-mod-pitfalls-in-claude-desktop/</guid><description>mod 的 TSX 裡 JSX factory 叫 h：任何含 JSX 的作用域都不能有叫 h 的參數或變數，否則執行期丟 h is not a function（型別檢查抓不到）。</description><pubDate>Wed, 14 Oct 2026 16:00:00 GMT</pubDate></item><item><title>Edge AppleScript 新增書籤會讓 Edge 當掉</title><link>https://ggwhite.github.io/ggwhite/posts/edge-applescript-add-bookmark-crashes/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/edge-applescript-add-bookmark-crashes/</guid><description>想用 osascript 把 Microsoft Edge 某個視窗的分頁批次存成書籤再關掉。抓背景視窗截圖不必切到前景：用 CGWindowListCopyWindowInfo 取得 window number。</description><pubDate>Tue, 13 Oct 2026 16:00:00 GMT</pubDate></item><item><title>Claude Code worktree 隔離的 subagent 跑 git 被擋</title><link>https://ggwhite.github.io/ggwhite/posts/claude-code-worktree-subagent-git-blocked/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/claude-code-worktree-subagent-git-blocked/</guid><description>用 isolation: worktree 派 subagent（Claude Code 2.1.296）。這個保護擋的是「看不懂的指令」，不是 git 本身。</description><pubDate>Mon, 12 Oct 2026 16:00:00 GMT</pubDate></item><item><title>Claude Code mod 在 herdr 裡畫圖片</title><link>https://ggwhite.github.io/ggwhite/posts/claude-code-mod-images-in-herdr/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/claude-code-mod-images-in-herdr/</guid><description>寫了一個 Claude Code mod。外層終端機是 cmux（libghostty，支援 kitty graphics），中間隔一層 herdr。驗證有沒有真的畫：herdr pane read 的文字快照裡，圖片位置是一段空白列＝有畫；只有一行 [alt]＝圖片被關。</description><pubDate>Sun, 11 Oct 2026 16:00:00 GMT</pubDate></item><item><title>Roblox Studio MCP 驗證時的三個坑</title><link>https://ggwhite.github.io/ggwhite/posts/roblox-studio-mcp-verification-pitfalls/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/roblox-studio-mcp-verification-pitfalls/</guid><description>MCP 的 execute_luau 不是在遊戲腳本的同一個環境裡跑：模組快取、鏡頭都不共用。驗證結果怪怪的時候，先懷疑工具環境，再懷疑程式。</description><pubDate>Sat, 03 Oct 2026 16:00:00 GMT</pubDate></item><item><title>Roblox Translator FormatByKey 數字會顯示成 5.00</title><link>https://ggwhite.github.io/ggwhite/posts/roblox-translator-formatbykey-adds-decimals/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/roblox-translator-formatbykey-adds-decimals/</guid><description>用 Roblox 內建多國語系時，結果顯示成 &quot;5.00 coins&quot;。參數值只做替換，不會重新解析。</description><pubDate>Sat, 03 Oct 2026 16:00:00 GMT</pubDate></item><item><title>CentOS 搬到 Ubuntu 後 cron 腳本被 dash 靜默打壞</title><link>https://ggwhite.github.io/ggwhite/posts/centos-to-ubuntu-dash-breaks-cron-scripts/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/centos-to-ubuntu-dash-breaks-cron-scripts/</guid><description>Mongo 過期資料清理的兩支腳本，從 CentOS 裸機搬到 Ubuntu 26.04 docker 機。「手動測過」不等於「cron 會跑」：兩者的 shell 不同。</description><pubDate>Thu, 01 Oct 2026 16:00:00 GMT</pubDate></item><item><title>npx skills 相對路徑 symlink 在 symlink 目錄下失效</title><link>https://ggwhite.github.io/ggwhite/posts/npx-skills-relative-symlink-breaks-under-symlink/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/npx-skills-relative-symlink-breaks-under-symlink/</guid><description>跑 npx skills check 後，Claude Code 讀不到 hyperframes 系列、media-use、herdr、share-html 等 skill。相對路徑 symlink 的解析基準是 symlink 檔案「實際所在」的目錄，不是你走進來的那條路徑。</description><pubDate>Tue, 29 Sep 2026 16:00:00 GMT</pubDate></item><item><title>SQLite FTS5 MATCH 的使用者輸入要先包成 phrase</title><link>https://ggwhite.github.io/ggwhite/posts/sqlite-fts5-match-quote-user-input/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/sqlite-fts5-match-quote-user-input/</guid><description>memory-mcp 的搜尋把使用者輸入直接帶進 WHERE memories_fts MATCH ?。參數綁定不等於跳脫。</description><pubDate>Tue, 29 Sep 2026 16:00:00 GMT</pubDate></item><item><title>Agent 的 bash 跑在 macOS Background session，讀不到 Keychain</title><link>https://ggwhite.github.io/ggwhite/posts/agent-background-session-cannot-read-keychain/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/agent-background-session-cannot-read-keychain/</guid><description>訊息指向「解密失敗」，很容易往 cookie 過期、瀏覽器版本、加密格式改版這些方向查——全部都是死路。一個吞掉錯誤、改用 fallback 繼續跑的函式，會把失敗點搬到離現場很遠的地方。</description><pubDate>Wed, 16 Sep 2026 16:00:00 GMT</pubDate></item><item><title>instaloader 的 get_posts() 看不到 Reels 分頁</title><link>https://ggwhite.github.io/ggwhite/posts/instaloader-get-posts-misses-reels/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/instaloader-get-posts-misses-reels/</guid><description>一支同步工具包著 instaloader，把公開 IG 帳號的貼文增量抓到本機。某支 Reel 在瀏覽器上看得到，同步工具卻怎麼跑都抓不到，而且每次都回報「成功、0 個新檔」——是正確地成功，不是報錯。「成功但結果是空的」比報錯難查，因為它不會叫。</description><pubDate>Wed, 16 Sep 2026 16:00:00 GMT</pubDate></item><item><title>同一語意寫成兩份實作、只有一份有測試，會靜默分岔</title><link>https://ggwhite.github.io/ggwhite/posts/duplicate-logic-with-one-test-diverges/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/duplicate-logic-with-one-test-diverges/</guid><description>台股選股工具的月營收資料永遠落後一期。8 月營收 9/10 公布，9/12 查 DB 還是只有 7 月——而且不只一檔，全 watchlist 298 檔都沒進來，monthly_revenue 最後寫入停在 9/1。同一個語意在程式裡出現第二份實作，就一定會分岔。</description><pubDate>Fri, 11 Sep 2026 16:00:00 GMT</pubDate></item><item><title>flock 的 fd 會被子進程繼承，讓 cron 監控靜默死亡</title><link>https://ggwhite.github.io/ggwhite/posts/flock-fd-inheritance-kills-cron-monitor/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/flock-fd-inheritance-kills-cron-monitor/</guid><description>一支用 flock 防重疊的 cron 監控腳本，某台機器連續多輪回報「零命中」。人工用同一套判準手動驗證，卻發現目標明明還在——五個服務全部中標。「監控靜默死亡」比「沒裝監控」危險。</description><pubDate>Fri, 11 Sep 2026 16:00:00 GMT</pubDate></item><item><title>macOS bsdtar 會吃掉 ._* 條目，tar -tf | grep 驗不出 AppleDouble 殘檔</title><link>https://ggwhite.github.io/ggwhite/posts/macos-bsdtar-swallows-appledouble-entries/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/macos-bsdtar-swallows-appledouble-entries/</guid><description>._xxx 是 macOS 的 AppleDouble：把檔案的 extended attributes（xattr）與 resource fork存成一個同目錄的伴隨檔。用同一個工具家族去驗它自己的輸出，驗不到它自己會隱藏的東西。</description><pubDate>Thu, 10 Sep 2026 16:00:00 GMT</pubDate></item><item><title>Redis ZREMRANGEBYRANK 不收縮 dict，判斷要不要瘦身一律看 ZCARD 不看 MEMORY USAGE</title><link>https://ggwhite.github.io/ggwhite/posts/redis-zremrangebyrank-keeps-dict-size-use-zcard/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/redis-zremrangebyrank-keeps-dict-size-use-zcard/</guid><description>一支千萬級的 sorted set 用 ZREMRANGEBYRANK 分批刪到只剩 1000 筆之後，MEMORY USAGE 仍然回報 288 MB——合理值應該是 1000 × ~190 B ≈ 0.2 MB，差了三個數量級。「容器縮小了」和「容器佔用的記憶體縮小了」是兩件事。</description><pubDate>Tue, 08 Sep 2026 16:00:00 GMT</pubDate></item><item><title>mc rm --recursive 是前綴比對，不是目錄比對</title><link>https://ggwhite.github.io/ggwhite/posts/mc-rm-recursive-is-prefix-match-not-directory/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/mc-rm-recursive-is-prefix-match-not-directory/</guid><description>用 mc 清理 MinIO 上累積的舊版本目錄，每個平台保留最新 5 個。刪除清單事前驗證過：與保留清單交集為 0，聯集正好等於原始總數。清單正確不等於執行正確。</description><pubDate>Mon, 07 Sep 2026 16:00:00 GMT</pubDate></item><item><title>Claude Code plugin 跨機同步：設定會同步，binary 不會</title><link>https://ggwhite.github.io/ggwhite/posts/claude-code-plugin-cross-machine-sync-trap/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/claude-code-plugin-cross-machine-sync-trap/</guid><description>which headroom 找不到，但完全不記得裝過這個東西。Claude Code plugin 的「啟用意圖」會跨機同步，「執行環境」不會。</description><pubDate>Fri, 04 Sep 2026 16:00:00 GMT</pubDate></item><item><title>Prompt 會長大，寫死的 timeout 遲早被跨過</title><link>https://ggwhite.github.io/ggwhite/posts/prompts-grow-past-hardcoded-timeouts/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/prompts-grow-past-hardcoded-timeouts/</guid><description>台股選股專案的每月 AI 分析排程（stock value-analyze），從 2026-08-11 起連續 16 天每天失敗。「沒改程式碼所以不是我弄壞的」是錯的直覺。</description><pubDate>Wed, 26 Aug 2026 16:00:00 GMT</pubDate></item><item><title>macOS shell 存取 iCloud Drive 回 EINTR</title><link>https://ggwhite.github.io/ggwhite/posts/macos-icloud-drive-shell-eintr/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/macos-icloud-drive-shell-eintr/</guid><description>看起來很像 iCloud Drive 同步卡死。EINTR 在 iCloud Drive 上不是「暫時性中斷、重試就好」，是權限被擋的偽裝。</description><pubDate>Mon, 24 Aug 2026 16:00:00 GMT</pubDate></item><item><title>detached Popen 讓 PPID=1，看起來像 launchd 拉的</title><link>https://ggwhite.github.io/ggwhite/posts/detached-popen-makes-ppid-1-look-like-launchd/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/detached-popen-makes-ppid-1-look-like-launchd/</guid><description>兩個 session 講好共用一台租來的 GPU：A 先跑 6 張、不關機，B 接著跑 16 張、跑完關機。B 只送了 16 個任務，遠端佇列卻有 30 個。PPID=1 不代表 launchd。</description><pubDate>Sun, 16 Aug 2026 16:00:00 GMT</pubDate></item><item><title>codex exec 在 iCloud Drive 路徑下讀寫檔會卡死</title><link>https://ggwhite.github.io/ggwhite/posts/codex-exec-hangs-on-icloud-drive-paths/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/codex-exec-hangs-on-icloud-drive-paths/</guid><description>把專案資料夾搬到 macOS iCloud Drive之後，codex exec 內建的 image_gen 工具在該路徑下工作時會卡死：process 存活、CPU 幾乎不動（10分鐘只增加零點幾秒），長時間不產出任何檔案，最後以 exit code 1 結束但沒有任何錯誤訊息。</description><pubDate>Fri, 14 Aug 2026 16:00:00 GMT</pubDate></item><item><title>codex exec 的 -i 參數會吞掉後面的 prompt，且失敗時 exit code 仍是 0</title><link>https://ggwhite.github.io/ggwhite/posts/codex-exec-image-flag-swallows-prompt/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/codex-exec-image-flag-swallows-prompt/</guid><description>跑完 exit code 是 0，看起來成功，但實際上一張圖都沒有重新生成（目標檔案的內容、mtime 完全沒變）。exit code 0 不代表產出了預期結果。</description><pubDate>Thu, 13 Aug 2026 16:00:00 GMT</pubDate></item><item><title>ffmpeg -shortest 會把輸出截到「較短」那條軌，不是「對齊」</title><link>https://ggwhite.github.io/ggwhite/posts/ffmpeg-shortest-truncates-to-shorter-stream/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/ffmpeg-shortest-truncates-to-shorter-stream/</guid><description>hyperframes 影片 render 完後用 ffmpeg 做 grading + 換音軌，成品時長比原始 render 短了好幾秒，結尾卡片（ending-screen 淡入的「CASE CLOSED」畫面）整段消失，觀眾完全看不到。拿掉 -shortest。</description><pubDate>Mon, 10 Aug 2026 16:00:00 GMT</pubDate></item><item><title>要 LLM 比對兩件事，得先讓它分別寫下來</title><link>https://ggwhite.github.io/ggwhite/posts/make-llm-write-each-side-before-comparing/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/make-llm-write-each-side-before-comparing/</guid><description>給一個 AI 角色做的即時照片產線，加了一道「送出前打開圖看一眼，跟情境對不對得上」的驗收。拿一張已知拍錯的照片去測——角色設定上她在辦公室上班，圖畫成了她家臥室——驗收回 ok: true。「A 跟 B 對不對得上」是一個讓模型可以合法閃避的問題。</description><pubDate>Thu, 06 Aug 2026 16:00:00 GMT</pubDate></item><item><title>ffmpeg -loop 1 的預設輸入幀率是 25，zoompan 的 fps 救不回來</title><link>https://ggwhite.github.io/ggwhite/posts/ffmpeg-loop-1-defaults-to-25fps/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/ffmpeg-loop-1-defaults-to-25fps/</guid><description>用 ffmpeg 把一組靜照剪成 30fps 的直式短影片，每一顆鏡頭指定停留秒數（hold），十二顆接起來應該是 30.0 秒。這又是同一個形狀：失敗的樣子跟成功的樣子一模一樣。</description><pubDate>Mon, 03 Aug 2026 16:00:00 GMT</pubDate></item><item><title>claude -p 子行程限制 Read 權限，只有 --settings 的 deny 有效</title><link>https://ggwhite.github.io/ggwhite/posts/claude-p-read-limits-only-deny-works/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/claude-p-read-limits-only-deny-works/</guid><description>一個聊天機器人 shell 出去呼叫 claude -p 回話，原本只在「這一輪有新圖」時才給 Read 工具。改版後她要能回頭打開對話歷史裡任何一張舊照片，於是 Read 從「偶爾開」變成「常開」。單元測試驗不到這件事。</description><pubDate>Sun, 02 Aug 2026 16:00:00 GMT</pubDate></item><item><title>加了保護但保護不存在的三種形狀</title><link>https://ggwhite.github.io/ggwhite/posts/three-shapes-of-safeguards-that-never-worked/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/three-shapes-of-safeguards-that-never-worked/</guid><description>一套會自動回覆 Threads 公開留言的產線，上線前補四道防護。四道都寫完、測試全綠、覆蓋率看起來很好，實際去打真的 API 才發現其中一道從來沒有生效過，另一道的測試把常數改成 999 照樣綠。「靜默失敗」的判準是：壞掉的樣子跟正常的樣子長得一模一樣。</description><pubDate>Sun, 02 Aug 2026 16:00:00 GMT</pubDate></item><item><title>Prompt 漏抓時先查「是不是被某條排除規則主動擋掉」，不要先調取捨強度</title><link>https://ggwhite.github.io/ggwhite/posts/prompt-misses-check-exclusion-rules-first/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/prompt-misses-check-exclusion-rules-first/</guid><description>yuna 專案有一段抽取用的 prompt：讀一天的聊天記錄，把角色自己講過、而設定裡沒有的事實抽出來。漏抓有兩種完全不同的成因：模型「沒想到要收」，跟模型「有一條規則叫它不要收」。</description><pubDate>Wed, 29 Jul 2026 16:00:00 GMT</pubDate></item><item><title>Python sqlite3 的 with conn: 拿不到原子性——當 repo 函式自己 commit</title><link>https://ggwhite.github.io/ggwhite/posts/sqlite3-inner-commit-breaks-with-conn-atomicity/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/sqlite3-inner-commit-breaks-with-conn-atomicity/</guid><description>Review 指出這不是原子操作：中途失敗（database is locked、process 被砍）會留下「事實寫進去了、但沒標記」，下一輪重跑就重複寫入同一批。with conn: 只在「區塊內沒有任何 commit」時才有原子性。</description><pubDate>Wed, 29 Jul 2026 16:00:00 GMT</pubDate></item><item><title>LLM 工具回傳要把關鍵參數念回去</title><link>https://ggwhite.github.io/ggwhite/posts/llm-tool-results-should-echo-key-params/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/llm-tool-results-should-echo-key-params/</guid><description>一個角色扮演 bot 有 add_plan_event 工具，讓它把「跟人約好的事」寫進行程表。嘴上七點半，寫進 start_time 的卻是 18:30。工具回傳不要只回「已完成 #id」。</description><pubDate>Tue, 28 Jul 2026 16:00:00 GMT</pubDate></item><item><title>subprocess 讀 JSON 不能假設 stdout 只有 JSON</title><link>https://ggwhite.github.io/ggwhite/posts/subprocess-stdout-may-not-be-pure-json/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/subprocess-stdout-may-not-be-pure-json/</guid><description>一個常駐 bot 要驗收「這張圖裡有沒有人臉」，但影像套件（insightface / onnxruntime）只裝在另一個專案的 venv 裡。「工具壞了」跟「我讀錯了」在 log 上長得一模一樣，而排除順序應該是後者優先。</description><pubDate>Tue, 28 Jul 2026 16:00:00 GMT</pubDate></item><item><title>bash 全形標點緊接變數會被吃進變數名，set -u 下讓整個函式靜默不執行</title><link>https://ggwhite.github.io/ggwhite/posts/bash-fullwidth-punctuation-eats-variable-name/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/bash-fullwidth-punctuation-eats-variable-name/</guid><description>腳本沒有任何錯誤輸出、exit code 也不是 0 以外的值（因為 stderr 被 2&gt;&amp;1 | grep 過濾掉了），log 檔停在函式呼叫前的最後一行，看起來就像「函式沒被呼叫」。set -u + 管線過濾 stderr = 靜默失敗。</description><pubDate>Mon, 27 Jul 2026 16:00:00 GMT</pubDate></item><item><title>hyperframes render 多 worker 會在 worker 邊界掉幀</title><link>https://ggwhite.github.io/ggwhite/posts/hyperframes-workers-drop-frames-at-boundaries/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/hyperframes-workers-drop-frames-at-boundaries/</guid><description>用 npx hyperframes render（預設 4 workers）渲染一支 109 秒的直式影片，成品在 27.3s 與 81.8s 各出現約 0.3 秒的黑閃——背景圖整片消失，但疊在上面的 HUD、對話框、角色立繪都還在。沒有 worker 邊界就沒有這個問題。</description><pubDate>Mon, 27 Jul 2026 16:00:00 GMT</pubDate></item><item><title>SQLite FTS5 trigram 搜不到兩個字的中文詞</title><link>https://ggwhite.github.io/ggwhite/posts/sqlite-fts5-trigram-cannot-match-two-character-chinese-words/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/sqlite-fts5-trigram-cannot-match-two-character-chinese-words/</guid><description>一個中文聊天機器人用 FTS5 全文檢索翻歷史對話。不報錯、不拋例外，就是回空清單——跟「這件事從來沒被提過」長得一模一樣。測試資料剛好避開邊界，比沒有測試更危險。</description><pubDate>Mon, 27 Jul 2026 16:00:00 GMT</pubDate></item><item><title>Plash 桌布長時間播放多支影片卡死變黑，只能整個 Quit 重開救回</title><link>https://ggwhite.github.io/ggwhite/posts/plash-wallpaper-video-freeze-needs-restart/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/plash-wallpaper-video-freeze-needs-restart/</guid><description>用 Plash 把本機 HTML（含多支 muted loop 影片的拍立得桌布動畫）當 macOS 動態桌布用，跑一段時間後（數小時到一兩天）影片會停止播放、凍結。Plash 是用 WKWebView 把本機網頁渲染成桌面背景。</description><pubDate>Fri, 24 Jul 2026 16:00:00 GMT</pubDate></item><item><title>Codex JSONL Tool Checkpoints</title><link>https://ggwhite.github.io/ggwhite/posts/codex-jsonl-tool-checkpoints/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/codex-jsonl-tool-checkpoints/</guid><description>A long-running codex exec --json coding task could change files for many tool calls before the orchestration round ended.</description><pubDate>Tue, 14 Jul 2026 16:00:00 GMT</pubDate></item><item><title>edge-tts 連續呼叫偶爾回傳空音檔（NoAudioReceived），要加重試機制</title><link>https://ggwhite.github.io/ggwhite/posts/edge-tts-noaudioreceived-retry/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/edge-tts-noaudioreceived-retry/</guid><description>用 edge-tts 套件在同一支腳本裡連續生成多段 TTS（例如逐句念旁白、要合併成一支完整音檔）時，導致整個批次中斷。單獨把出錯的那段文字抽出來測試（同樣的 voice/rate/pitch），完全正常生成，證明不是文字內容或參數的問題。</description><pubDate>Mon, 13 Jul 2026 16:00:00 GMT</pubDate></item><item><title>後台顯示亂碼：先查是不是「歷史髒資料換了新展示層才曝光」而非現行系統新 bug</title><link>https://ggwhite.github.io/ggwhite/posts/diagnose-mojibake-historical-vs-current-bug/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/diagnose-mojibake-historical-vs-current-bug/</guid><description>GM/BI 後台某個查詢頁面的文字欄位（例如「備注」）顯示亂碼，混雜 HTML entity 與亂碼字元（例如 &amp;auml;&amp;ordm; 或直接顯示 ä»¥å¡° 這類字元）。亂碼只出現在特定時間窗口，是「歷史髒資料」的強訊號，不是「現行系統新 bug」。</description><pubDate>Fri, 10 Jul 2026 16:00:00 GMT</pubDate></item><item><title>Cobra StringSliceVar 會把 flag 值用逗號切割</title><link>https://ggwhite.github.io/ggwhite/posts/cobra-stringslicevar-comma-splitting/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/cobra-stringslicevar-comma-splitting/</guid><description>設計「用符號切割的 CLI 值格式」時，先問：分隔符會不會出現在使用者的正常內容裡？冒號（時間、coordinate、URL）和逗號（URL、英文）幾乎必然出現，不是邊角案例。</description><pubDate>Tue, 07 Jul 2026 16:00:00 GMT</pubDate></item><item><title>Go Module 巢狀 sub-module 的 module path 必須對齊目錄結構</title><link>https://ggwhite.github.io/ggwhite/posts/go-module-nested-submodule-path-must-match-directory/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/go-module-nested-submodule-path-must-match-directory/</guid><description>主 module go-masker/v3 正常，只有 sub-module 抓不到。Go modules 的 major version suffix（/v3）是主 module 專屬的語法糖，sub-module 不享有這個待遇。</description><pubDate>Tue, 23 Jun 2026 16:00:00 GMT</pubDate></item><item><title>Go Module sub-module 發布時必須移除 replace 指令</title><link>https://ggwhite.github.io/ggwhite/posts/go-module-replace-directive-in-released-tags/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/go-module-replace-directive-in-released-tags/</guid><description>Go Module sub-module 發布時必須移除 replace 指令：replace 是開發工具，不是發布工具——它不該出現在任何 release tag 裡。</description><pubDate>Tue, 23 Jun 2026 16:00:00 GMT</pubDate></item><item><title>Docker Compose volume mount 空目錄陷阱</title><link>https://ggwhite.github.io/ggwhite/posts/docker-compose-mount-empty-dir-trap/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/docker-compose-mount-empty-dir-trap/</guid><description>old-game-server 容器化後，GM 加減幣回 &quot;invalid token&quot;。Docker compose 對不存在的 bind mount source 會自動建空目錄（root owned） — 不報錯、不警告，容器正常啟動但 mount 是空的。</description><pubDate>Wed, 17 Jun 2026 16:00:00 GMT</pubDate></item><item><title>Spring 容器化後 static block 載入寫死 IP 的 MongoDB 連線</title><link>https://ggwhite.github.io/ggwhite/posts/spring-static-block-mongodb-leak/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/spring-static-block-mongodb-leak/</guid><description>其他非容器化環境和正式環境看起來沒事。classpath:spring_mongodb.xml（無 path prefix） 優先找 JAR root-level 的檔案，不是 WAR config/spring_mongodb.xml — 同名不同路徑。</description><pubDate>Wed, 17 Jun 2026 16:00:00 GMT</pubDate></item><item><title>首次 Release 踩坑：goreleaser + Tauri + GitHub Actions</title><link>https://ggwhite.github.io/ggwhite/posts/first-release-gotchas-goreleaser-tauri/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/first-release-gotchas-goreleaser-tauri/</guid><description>用 goreleaser + Tauri 做第一次 v0.1.0 release，CI 連續 fail 了好幾輪，每輪修一個坑。跨平台打包的坑幾乎都是「本機能跑 CI 不行」——本機有全域 config、有 cache、有裝好的 native 工具。</description><pubDate>Sun, 14 Jun 2026 16:00:00 GMT</pubDate></item><item><title>docker compose 跨 VM 部署 cluster RPC 必須用 network_mode: host</title><link>https://ggwhite.github.io/ggwhite/posts/docker-compose-network-mode-host-cross-vm/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/docker-compose-network-mode-host-cross-vm/</guid><description>把舊有 cluster framework（skynet / akka / erlang OTP / Elixir cluster）從裸機部署改成 docker compose multi-VM 部署時，跨 host 的 cluster RPC 完全不通。</description><pubDate>Sun, 03 May 2026 16:00:00 GMT</pubDate></item><item><title>Docker mutable tag 在多 host 環境會拉到不同 SHA</title><link>https://ggwhite.github.io/ggwhite/posts/docker-mutable-tag-multi-host/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/docker-mutable-tag-multi-host/</guid><description>同一個 docker tag、同一個 image registry repo，在多台 host 上跑 docker pull 拉到的 image SHA 不同——某些 host 拿到 broken 版本。</description><pubDate>Sun, 03 May 2026 16:00:00 GMT</pubDate></item><item><title>MongoDB 慢查詢引發簽到 Race Condition</title><link>https://ggwhite.github.io/ggwhite/posts/mongodb-slow-query-race-condition-signin/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/mongodb-slow-query-race-condition-signin/</guid><description>某平台 MongoDB 主機發生 CPU 告警，慢查詢 log 顯示 coinlog、fishlog collection 查詢時間過長（數十秒甚至數分鐘）。慢查詢不只是效能問題，在有狀態操作的流程中，過長的等待時間會放大 Race Condition 的觸發機率。</description><pubDate>Fri, 17 Apr 2026 16:00:00 GMT</pubDate></item><item><title>遊戲伺服器遭駭：Redis 資料篡改攻擊與防禦嘗試</title><link>https://ggwhite.github.io/ggwhite/posts/redis-tampering-attack-and-defense-attempts/</link><guid isPermaLink="true">https://ggwhite.github.io/ggwhite/posts/redis-tampering-attack-and-defense-attempts/</guid><description>遊戲伺服器（Lua/Skynet）的 Redis 資料被攻擊者篡改，將遊戲狀態改為免費中獎狀態，導致異常獲利。最終整個資料庫被清空。加密保護的前提是 key 不能外洩。</description><pubDate>Fri, 17 Apr 2026 16:00:00 GMT</pubDate></item></channel></rss>