寫作
儀器壞了,你所有的結論都是假的
事情的起點很小:我想讓 MacBook 蓋上蓋子之後不要停。
我常常在跑一些要花時間的任務——語音轉檔、批次處理、AI agent 在背景做事。跑到一半要出門,蓋子一闔,全部斷掉。我要的就一件事:蓋上還能繼續跑,螢幕黑掉沒關係,我甚至希望它黑掉,省點電。
聽起來十分鐘能解決。結果花了一個下午,而且過程裡我跟 AI 都很篤定地錯了好幾次。
值得寫下來的不是最後那個工具,是錯的方式。
第一個錯:以為 caffeinate 就夠了
我的腳本本來都包著 caffeinate -i。這是 Unix 世界的標準做法,意思是「我在做事,別睡」。我用了很久,一直以為它涵蓋了所有情況。
不是。caffeinate 擋的是閒置休眠——你太久沒動鍵盤滑鼠,系統自己睡著。但蓋蓋子是完全另一條路徑,叫 clamshell sleep,caffeinate 完全管不到。
證據就寫在系統裡,我從來沒去看過:
"Last Sleep Reason" = "Clamshell Sleep"
真正的開關在核心層,叫 SleepDisabled。這件事不難查,我只是從來沒懷疑過自己的前提。
第二個錯:測試通過了,但什麼都沒證明
翻開關之後要驗證。我們寫了一支測試:每五秒記一筆時間戳,蓋上兩分鐘再打開,如果時間戳中間沒有斷層,就代表機器沒停。
報告很漂亮:92 拍心跳、零斷層、系統零睡眠紀錄、三個綠勾。
然後回頭一查——那兩分鐘裡我根本沒把蓋子蓋上。
我在讀訊息、在做別的事,等我想起來要蓋的時候,測試視窗早就跑完了。那份漂亮的報告,只證明了「機器不會閒置休眠」——而那件事 caffeinate 本來就做得到。
這是我學到最實用的一課:一個只會通過的測試,等於沒有測試。
修法是讓測試自己檢查前提。改版之後它會直接讀取蓋子的實體狀態,沒偵測到闔上就印:
INVALID — 沒偵測到蓋子闔上,這次測試無效
不是「失敗」,是「無效」。這兩件事必須分開。失敗代表你學到東西,無效代表你什麼都沒學到卻以為學到了——後者危險得多。
第三個錯,也是最狠的:儀器是壞的
蓋子的問題解決之後,冒出新問題:蓋上了,螢幕還亮著。看不到卻在耗電,這很蠢。
我們去量背光電流。系統的 ioreg 裡有個欄位叫 BrightnessMicroAmps,聽起來就是背光 LED 的實際電流,完美的指標。
量出來 3737 µA。蓋上,再量,還是 3737。蓋上五分鐘,59 筆取樣,每一筆都是 3737。
結論很明確:背光全程亮著在燒電。
我們據此推翻了兩個假設、換了兩種修法、又量了兩輪。
一直到後來,我們寫了一個可以直接控制亮度的小工具,順手把亮度從 0 掃到 1 驗證它有沒有效——
亮度 0.0 → 3737 µA
亮度 1.0 → 3737 µA
亮度 0.3 → 3737 µA
那個數字在任何情況下都不會變。它不是測量值,是一個快取的常數。
我拿一把壞掉的尺量了三輪,寫了一堆很有說服力的分析,全部作廢。
第四個錯:我自己設錯了三年
過程中還挖出一個我自己的問題。
我的 macOS 設定裡,「螢幕永不自動關閉」。為什麼?因為我以為螢幕關掉,機器就停止工作了。所以我把它關掉,這樣任務才不會斷。
這個前提是錯的,而且錯得很基本。螢幕休眠、螢幕保護程式、鎖屏——這三件事都不影響任何運算。CPU 照跑、網路照連、任務照做。會讓工作停止的只有系統休眠,那是完全不同的東西。
我基於一個錯誤的理解,設了一個沒必要的設定,然後那個設定又剛好讓後面的問題更難查。
所以,方法是什麼
整理成幾條,我自己之後會照著做:
一、先驗證你的儀器,再相信它的讀數。 最便宜的方法:把輸入從最小掃到最大,看那個數字動不動。不動的話,它就不是在測量。這件事花三十秒,可以省掉一整個下午。
二、分清楚「回傳成功」和「真的發生」。 關螢幕的指令回傳 0,代表「指令被接受了」,不代表「螢幕關了」。這兩件事之間,需要一個獨立的觀測。
三、讓工具自己判斷前提成不成立。 不要依賴人記得做對的事。我不會每次都記得蓋蓋子,所以測試必須自己去確認蓋子闔上了沒。把「人要記得」的部分,盡量搬進機器裡。
四、AI 講得很篤定,不代表它對。 這輪我遇到好幾次很流暢、很有邏輯、聽起來完全站得住腳的解釋——「powerd 抓著 assertion 不放」——後來被實測推翻。AI 補洞的能力很強,強到你不去驗證就看不出來。
五、我講得很篤定,也不代表我對。 這條更重要。我的錯誤前提在對話裡待了很久沒被挑戰,因為我說得很確定。AI 傾向接受你給的前提,除非你主動要求它去驗證。
六、把被推翻的假設也記下來,不只記結論。 我最後把這些寫進工具的 README 和我自己的筆記,不是寫「答案是 X」,而是寫「我曾經以為是 A,實測不是,因為 B」。半年後再碰這塊,這種記錄比結論有用得多。
東西做出來了
最後那個工具叫 lidawake,開源,Apache-2.0。蓋上筆電時它會:存下亮度 → 鎖屏 → 把背光壓到 0;打開時一秒內還原,Touch ID 進去,任務全程沒斷。接電就撐住,沒接電則電量掉到 20% 自動放手。
但老實說,工具本身沒什麼了不起,兩百多行 shell 加四十行 C。
真正值錢的是那個下午學到的東西:在你相信任何數字之前,先確認那個數字會動。