檢查回傳 0,有兩種可能:真的沒問題,或者檢查器根本沒在比對。沒拋錯不代表成功講的是工具沒報錯不等於成功,怎麼寫一個真的會擋下來的閘門寫的是判準本身;這篇是同一組判準在這一週又撞出來的新案例——連拿來確認「有沒有成功」的那個檢查器,本身都可能是壞的。這週一連撞上好幾次,長得全都跟「檢查通過」一模一樣。
檢查器自己壞掉
09-17 一晚踩了四次:Firestore 選項是 {id, text} 物件,String(o) 比對變成 [object Object],全庫掃出假的「0 筆污染」;對照表鍵對錯欄位,get(k, 預設值) 全部回預設,55 題被標成同一期別,卻顯示「每筆都有月份」;macOS pgrep 沒有 -c,配 || true 後 stdout 一片空白,被我讀成「全線收工」讀了兩次,寫手其實都還在跑;答案閘門只比盲解一致性、不查尾端樣板改沒改正解,38 筆污染的答案直接上線。
09-14,batch_tag.js 印出錯誤數後仍 exit 0,後製與驅動都當它成功,5 題沒標籤、沒人被通知——只印訊息不改離開碼,等於沒有閘門。同一天 pgrep -f "gmatclub-run.py run" 連自己的命令列都抓進去,等待迴圈永遠等不到程序消失,變殭屍,同一個 session 踩了兩次,第二次還誤報「後製仍在跑」,其實十分鐘前就結束了。我把「15/15 uid 對得上、每題有答案有詳解」當成交件完整的證據,結果 \text{} 被解碼成 TAB 控制字元——驗收要用管線既有判準,不能自己另發明較寬鬆的外形檢查。
09-15,ai-initial-grading.js 的離開碼修法,反驗連三次回 0 都不算數:複本放 scratchpad 解不到 require,MSR 當下沒有未評分題目可失敗,注入點又放在早退之後。09-18 守衛反驗更荒謬:假寫手寫成 sh -c 'sleep 6' run-rc-queue.sh write,sh 對單一指令直接 exec,argv 變成 sleep,pgrep -f 一個字都看不到——症狀跟「守衛沒生效」一模一樣。同一天想證明「拿掉隔離會漏檔」,第一次把迴圈改成 while false; read -r f,複合條件只看最後一個指令的離開碼,迴圈照跑,測試全綠。
09-16,Windows 上 subprocess.run(..., text=True) 用當地編碼(cp1252)解碼,子行程吐中文時例外拋在 reader thread,主執行緒拿到 stdout=None 但 returncode=0,看起來像成功;pytest 只在 warnings summary 留一行 PytestUnhandledThreadExceptionWarning,測試不會紅。
各層局部都對,組合起來還是壞
同一週使用者真的撞上四個 bug。付費牆在 production 沒接上——錯誤庫六筆 403 查出是互動式引導漏接,一位七個月付費客戶取消當天回來試功能,拿到假的「請檢查你的網路連線」。KaTeX 裡 \$10,000:\$ 在文字位置惰性不開數學式,但數學式一旦開啟,下一個 $ 就收尾,反斜線擋不住,真正結尾變成下一個開頭,全文之後位移一格;KaTeX 對數學模式裡的中文和 ① 不丟例外,只印 No character metrics,讀者只看到斜體怪句子。300 筆快取全量實測:錯誤數 125 降到 6,中文被當數學式 59 降到 0。學生端用逗號位置切開判分,不讀 dropdowns[].correct_answer,下拉選項千分位逗號讓後面每格錯位,選對被判錯;14,436 題掃出 3 題真誤判、1 題潛在風險。主站恢復回合若一題都取不回(會員到期或權限被收回),舊碼照跑,空題目清單過濾已存作答等於全部篩掉;一位學生六次 403 後回來開 12 題回合,歸零,8 題作答消失。
回 0 之前,先拿已知會命中的樣本證明檢查器真的有在比對。反驗失敗時,第一懷疑是反驗自己沒接上,不是被驗的程式碼。破壞案例沒失敗時,第一懷疑是破壞本身沒成立,不是程式碼很穩。