0:00——一次建置完成了。智慧代理說它做完了,但這只是一個關於「程式碼已寫好」的說法,而不是「程式碼確實能運作」的說法。每一個使用過 AI 建構器的人,都至少感受過這兩種說法之間的落差一次:預覽畫面打開,點下第三個按鈕,什麼事都沒發生。我曾親眼看過,在那一刻整個示範現場瞬間安靜下來。所以,在任何人看到建置結果之前,它會先經歷大約六分鐘、一連串彼此互相質疑的檢查鏈。以下就是這個過程實際的樣子,我們追蹤了一次出了狀況、後來又被修好的建置。
0:02——程式碼審查開始。不是撰寫該程式碼的那個智慧代理重新檢查自己的作業——而是另一個智慧代理,用不同的提示詞,和這次建置能否通過沒有任何利害關係。這種區隔比聽起來還要重要。一個在下午 2:14 認定「沒有錯誤處理的 fetch 呼叫」沒問題的智慧代理,如果你在 2:15 請它檢查自己的作品,它仍然會這麼認為。而一個被告知「找出哪裡壞了,並指出檔案位置」的全新審查者,表現得就像你真正需要坐鎮這個崗位、脾氣暴躁的資深工程師。在過去一次建置中,它抓出了一個購物車總金額從未更新的問題——`updateTotal` 在 `Cart.jsx` 中被定義了,但從未接上數量變更的處理器,所以這個函式存在,卻完全沒有被執行過。這正是程式碼審查該抓的那一類問題:編譯器對此毫不在意的問題。
0:04——安全稽核。這一層刻意設計得比聽起來狹窄——這不是滲透測試,而是針對一小撮真正會出現在 AI 生成程式碼中的錯誤模式做地毯式搜尋。字串拼接的 SQL 語句。僅在客戶端做驗證,卻被當成完整驗證來信任。還有那個經典款:寫死的 API 金鑰,因為撰寫該功能的智慧代理面前沒有現成的環境變數慣例,於是就用了行得通的做法。這種情況我們見得夠多,幾乎已經算不上意外了。
0:07 — 連結與 SEO。這部分不起眼,但能抓出那些沒人注意到、直到客戶發現才知道的問題:例如導覽連結指向 /pricing 而該頁面實際產生的位置是 /price,或是網站地圖裡有一個條目指向一個回傳 404 的頁面,還有 meta description 仍然停留在範本佔位文字。這些都不會讓建構失敗。但都會悄悄拖垮我們大多數使用者建立網站的初衷——被找到、被點擊。
0:09——無障礙檢測。這是自動化的 axe-core 掃描,不是完整的人工稽核,值得誠實說明這個取捨換來了什麼。axe-core 能抓出對比度、缺少替代文字、未加標籤的表單欄位、跳脫正常順序的 Tab 鍵導覽陷阱——這是機械層面的問題,大約佔完整 WCAG 審查會標記出的問題的 30-40%。它抓不出「技術上合規,但實際使用起來讓螢幕報讀器使用者一頭霧水」的體驗問題。我們選擇只做自動化檢測,是因為它幾秒鐘就能跑完,而且透過這個流程上線的大多是行銷網站和小型工具,不是那種局部稽核就會對使用者構成真正風險的應用程式。
0:11——一致性檢核。這一層問的不是「這個做得好不好」,而是「這個是否符合當初承諾的內容」。計畫說要四個頁面,建置卻只交出三個——一致性檢核就是負責發現這種落差的層級。計畫承諾一個能運作的聯絡表單,實際交付的卻是一個沒有送出動作的表單——同一層級,同一種抓法。這是最直接對使用者負責的檢查層級,因為它是拿使用者陳述的意圖來衡量,而不是某種抽象的品質標準。
0:13——瀏覽器內實測,而這正是我們這次建置真正出問題的地方。這一層是最難蒙混過關的,因為它不是讀程式碼,而是實際操控一個真實瀏覽器——點擊、輸入、等待、檢查 DOM 是否照應有的方式改變。這次的建置是一款放置型遊戲,而遊戲在這一層會多接受一輪額外檢查,因為一款遊戲可以在畫面上呈現得像素級完美,卻依然完全無法遊玩——分數顯示可能看起來毫無瑕疵,卻和計分邏輯完全脫節。驗證器實際玩了這款遊戲。分數更新正常,但音效完全沒有聲音。
三輪之後,升級處理
這項發現並不是以錯誤回報的形式交給我們——它直接進入了修正流程,而檢查鏈也隨之再次驗證,在這次建置中最多進行了三輪。第一輪:修正動到了原本就沒問題的混音器初始化程式碼,所以音效依然沒有聲音。第二輪:另一個修正處理了一個看起來相關的載入狀態邊界情況,結果——這種情況比你想像的更常發生——引入了一個新的小問題,原本的問題卻依然沒解決。第三輪:依然沒有聲音,到了這個地步,你通常會面對兩種情況之一:一個真正棘手的問題,或是一場虛驚,而這次是前者。
於是平台自行啟動了升級處理。它排定了一次後續修正執行,範圍完全鎖定在這個仍未解決的發現上,並且是在該建置的複本上進行,而不是原本的建置——這代表就算這次升級執行失敗,也不會賠上我們手上那個已經能運作的版本。這次執行找出了真正的原因:一個在先前除錯階段設下、卻從未還原的靜音旗標,藏在一個和前兩次修正完全不同的檔案裡。清除旗標,重新驗證,通過。在這個建置真正能運作之前,沒有任何人看過它。
| 訂單 | 層級 | 抓出的問題 |
|---|---|---|
| 1 | 程式碼審查 | 邏輯錯誤、失效的事件處理器、狀態相關的錯誤 |
| 2 | 安全稽核 | 注入攻擊面、外洩的機密資訊、不安全的程式模式 |
| 3 | 連結與 SEO | 失效連結、缺少的中繼資料、sitemap/robots.txt 的正確性 |
| 4 | 無障礙 | 自動化 axe-core 檢測:對比度、標籤、鍵盤導覽 |
| 5 | 符合性 | 這次建置的內容是否符合計畫中的承諾 |
| 6 | 瀏覽器內實測 | 實際執行這次建置——點擊、輸入,觀察它的回應 |
下次我會跳過的事
在那次放置型遊戲出現問題的幾個月前,我們曾嘗試過一套較寬鬆的版本——允許驗證者以任何方式提出任何顧慮。結果產生了諸如「考慮把這段抽成一個輔助函式」和「這個變數名稱可以更清楚一點」之類的發現,聽起來很用心,卻什麼都沒修好。修正流程整輪整輪地被耗在潤飾文句上,而不是修正真正壞掉的地方。我們把規則收緊為:要嘛指名一個檔案、描述一個失敗情況,要嘛什麼都別說。驗證者輸出的內容量因此減少了大約一半,而剩下的幾乎都是可以直接採取行動的。如果讓我從頭重來,我會直接跳過那個寬鬆版本,一開始就採用這條「證據規則」——我們不需要靠付出昂貴代價才學到這個教訓,但我們確實是這樣走過來的。
這條規則是有實際代價的,我不打算掩飾:一個模糊但可能屬實的顧慮,像是「這個 API 設計六個月後會出問題」,現在會直接被捨棄,因為驗證者無法把它釘在一個具體的失敗上。我們接受了這個取捨。一條同時要做架構審查的檢查鏈,速度不足以在每一次建置上都執行,而速度正是把這件事自動化、而不是交給人來做的重點所在。
如果有人問起,我也建議不要增加第四輪。我們已經根據實際建構結果調校過輪次數量,第三輪之後的邊際效益會急遽下降——第一輪能解決大多數可修復的問題,第二輪主要是清理第一輪引入的問題,到了第三輪,剩下的問題若不是真的很棘手,就是原本根本沒壞。第四輪多半只會讓你多等一段時間,卻得到相同的結果。
這一切都不是免費的,也不是萬無一失的。六個層級加上不論需要幾輪的修正迴圈,都會為每次建構增加實際的時間——差別可能是不到一分鐘完成,或是需要好幾分鐘才能完成。我們認為,對於任何即將呈現給你自己客戶的東西來說,這是值得的取捨——但「快速」和「經過驗證」是互相拉扯的方向,而我們選擇了驗證。驗證器本身也是 LLM,偶爾會誤判某個其實沒問題的地方,或漏掉某個真正有問題的地方。證據規則和多輪迴圈是針對這種情況的防範措施,而不是保證。
你最後得到的是一份紀錄:哪些層級執行過、發現了什麼、修復了什麼,以及還有哪些留待你自行判斷。這份紀錄比程式碼本身更接近真正的產品——這就是「因為看起來完成了就相信這次建構」和「因為有東西先嘗試過刻意破壞它卻失敗了才相信」之間的差別。



