建置不再頂嘴的那個星期六
那些拍不成截圖的修正,才是決定你的執行期能不能出貨的修正。RakuAI 花了一週把軟肋清光,好讓接下來八個月的打造再也不用跟建置爭辯。
有一類工作是不會產出截圖的。它產出的是一個在過去會把它弄紅的機器上轉綠的建置。它產出的是一個不再逾時的 CI 執行。它產出的是一個不再出現的堆疊追蹤,因為造成它的空指標現在在邊界就被攔下了。在這個星期六結束的這一週,就是那種週。
十八個 DLL 在 Linux 上轉綠
執行期以十八個原生 DLL 的形式出貨。直到兩週前,這些 DLL 在 Windows 上建置乾淨、在 macOS 上建置乾淨,在 Linux 上卻卡在符號可見性錯誤。修正在 4 月 11 日的 PR #1463 落地。
故事是不光鮮的那種。GCC 預設讓共享函式庫裡的每個符號都可見。MSVC 預設讓每個符號都隱藏,除非明確匯出。執行期的程式碼是以 MSVC 的預設值為前提寫的,需要跨越 DLL 邊界的符號標了 __declspec(dllexport)。在 Linux 上這些宣告是空操作,意味著每個符號都可見,意味著連結器搞不清楚正確的 DLL 內部繫結,意味著十八個 DLL 裡有幾個建不起來。
修法是在 GCC 建置加上編譯器旗標 -fvisibility=hidden,並在需要匯出的符號上加明確的可見性屬性。diff 很小。影響範圍很大。Linux 建置現在是一等公民目標。出貨執行期變更的代理,現在可以讓 CI 矩陣自動在 Linux 上測試它。伺服器部署、容器映像、雲端建置農場,這一切現在都搆得到了。
這是那種感覺像報稅折抵的修正。它不會把產品往前推。但它也不再擋路了。這就夠了。
每個 LLM 呼叫端的提示長度防護
另一個值得記下的四月 commit 是提示長度防護的大掃除。執行期現在在好幾個地方呼叫 Claude:NPC 行為大腦、對話模型、世界事件敘事器、程序化內容播種器。這些呼叫端每一個都靠串接脈絡、指令和當前狀態來組建提示。只要脈絡長得夠大,每一個都可能產出超過模型輸入視窗的提示。
天真的失敗模式是 LLM 呼叫回傳錯誤。危險的失敗模式是 LLM 呼叫回傳被截斷的回應,呼叫端沒偵測到截斷,引擎就照著一個殘缺的答案行動。NPC 講到一半停住。對話樹分岔到空無一物。世界事件帶著錯誤的參數觸發。
PR #1465 為每個 LLM 呼叫端加上防護:呼叫前先估算 token 數,超過預算就拒絕送出,並發出呼叫端能夠回應的結構化錯誤。PR #1466 稽核了整個程式碼庫,驗證每個呼叫點都裝好了防護。PR #1467 補上文件,讓下一個呼叫端知道這條紀律。
這件事之所以重要,是因為執行期裡的 AI 呼叫不是偶爾發生的。高峰時每個影格會發生很多次。一個讓提示每次呼叫多長幾個 token 的組建臭蟲,在一百個影格內是隱形的,到一千個影格就是災難。防護把失敗變成大聲且有邊界的,而不是無聲且無上限的。
API 命名空間穩定化
第三個 commit 是三者中最安靜的,卻可能是影響最深遠的。執行期對外暴露一個 REST API,供外部工具、儀表板和 SDK 溝通。過去六個月這個 API 一直住在 /api/v2/ 底下,因為它接替了一個僅供內部使用的早期 /api/v1/。
/api/v2/ 是個錯誤的名字。它暗示 v1 曾是公開的、被取代了,但事實不是。它也暗示 v3 正在路上,但事實也不是。PR #1464 走遍程式碼庫裡的每個引用和文件裡的每個引用,把命名空間從 /api/v2/ 改名為 /api/raku/。這個名字現在穩定了。之後沒有版本號要談判。命名空間內的向後相容就是契約。
這是那種必須恰好發生一次、而且必須在任何外部開發者針對這個命名空間寫程式之前發生的改名。我們及時趕上了。下一次團隊以外的人寫腳本打這個 API 時,他們會看到 /api/raku/,而且六個月後不必重做他們的工作。
把空指標安全當成一次大掃除
執行期上最近的 commit,是兩天前 4 月 30 日的 58c3a806:「fix(build): resolve all build errors, warnings, and null-pointer safety」。標題裡的「null-pointer safety」一詞承擔了很多。它底下的變更是掃過整個程式碼庫,找出每一個指標可能為空、卻在沒有檢查的情況下被解參考的地方。
觸發這次大掃除的模式,是其中一個範例應用程式的當機回報。一個貼圖載入器收到了空的資產清單指標,解參考了它,然後當掉。修法是在進入點加一個檢查。稽核則是那個問題:程式碼庫裡還有多少地方有同樣的模式。
答案是好幾十處。不是每一處都可被利用。其中很多是從來沒被走到的程式路徑,因為呼叫端的程式碼恰好從來沒傳過空值。那不是防禦。防禦是邊界上的檢查。
大掃除加上了這些檢查。它沒有改變快樂路徑上的行為。它為失敗路徑加了一個回傳值(RAKU_ERR_INVALID_PARAM)和一行日誌。執行期在那些過去是無聲當機的情況下,現在變得更吵了。吵比無聲好。AR 執行期裡的無聲當機是最糟糕的一種臭蟲。
為什麼這種週正是該有的那種週
當你以週末節奏、帶著一支代理艦隊經營一個引擎專案時,誘惑是不停地出新功能。每個星期六早上佇列重新填滿。每個星期六晚上 diff 比上週更大。這種節奏獎勵向前的動能。
這種節奏也容忍技術債。過去八個月合併的每個 PR,都對建置環境、API 介面、LLM 輸入視窗或空指標安全契約做了一個小小的假設。這些假設沒有一個單獨看是錯的。加在一起,它們是一張終究會裂開的軟肋清單。
停下前進的腳步、花一週修補軟肋,不是浪費時間。它是那個之後接下來八個月的前進可以不用再跟建置、API、LLM 輸入或空指標爭辯的一週。爭辯才是浪費時間的東西。爭辯正是這次清理終結的東西。
接下來是什麼
代理們這個週末回到佇列上了。下一輪 issue 就是我這個星期六早上正在建立的。它們不再是清理 issue 了。它們是功能 issue。建置不會跟它們頂嘴。
這就是一個乾淨的建置買給你的東西。不是截圖。是出貨的許可。
一個在無聊的事上贏得信任的執行期
每個目標上都是綠的、穩定的 API、大聲的失敗而不是無聲的當機。RakuAI 是用正式環境要求的紀律打造的空間執行期。看看為什麼合作夥伴選擇在它上面打造。