安安~我是ChiYu~
昨天把五個 Tool 全部排好位置後,我很聽話地進入 feature freeze:不加第六個 Tool,也不再
偷偷塞一個「這個應該很實用吧」的新功能。
接著畫面上出現兩種讓工程師心情很好的綠燈。第一種是 Inspector 裡的 PASS,代表 Agent 真的
選了 Tool、帶入參數並拿到結果;第二種是 unit test、API test 與 Playwright 全部通過。
它們都叫 PASS,卻不能直接合成一句「本系統已通過完整 Agent 驗證」。
程式測試通過,證明網站在受控條件下照契約運作;Agent trace 通過,才是在回答模型有沒有
發現正確 Tool、選對參數,並把前一步結果接到下一步。兩邊都重要,但不能互相代打。
今天先把這兩種綠燈拆開來看。
昨天的 Journey 整合停在程式里程碑 v3-day-21;今天開始驗證正式發布基線,因此改用v3-p0-release.1。它指向完整 commit:
8e89e6519406388a0de8c456a890d6fcc8cc5544
請在乾淨工作目錄切換並安裝相依套件:
git switch --detach v3-p0-release.1
npm ci
main 會繼續往前走,文章裡的測試結果不該跟著偷偷換版本。今天所有 unit、API、security、
browser 與 build 結果,都以這個 release 為準;Inspector 的 Agent trace 則繼續保留為另一類
證據。

圖 1:Unit、API、security、browser、production replay 與 Agent Eval 各自回答不同問題。E2 全綠,不能直接跳級成 E4。
這一步先不問 Agent,改問比較樸實的問題:schema、API、server guard、Human UI 與 production
build 還站得住嗎?
如果連 API 都壞了,Agent 當然也會失敗。這時再去調 Tool description,效果大概跟網路線
沒插,卻一直改 Wi-Fi 名稱差不多。
在專案根目錄執行:
Get-Location
Test-Path .\package.json
npm run verify
Test-Path 應回傳 True。如果原本工作目錄放了自己的修改,不要為了切換版本把它蓋掉,
另開乾淨 clone 會比較安全。
npm run verify 依序檢查七道關卡這個指令有固定順序:
lint
→ typecheck
→ deterministic tests
→ API tests
→ security tests
→ browser tests
→ production build
前一層失敗就停止。型別已經壞掉時,繼續啟動 browser suite 通常只會多收集幾頁紅字,
不會讓真相變得更清楚。
verify.ts
會把每個 command、arguments、開始時間、結束時間與 exit code 寫入evidence/latest/verification.json。即使中途失敗,也看得出是哪一層先倒下。
成功報告還保留這些欄位:
{
"evidenceLevel": "E2",
"source_type": "test_output",
"webmcp_capability": "not_tested",
"agent_invocation": "not_tested",
"test_harness": "browser_automation"
}
最重要的不是 passed,而是兩個 not_tested。它們提醒我:這份報告驗證網站與測試 harness,
沒有觀察真正的 WebMCP discovery,也沒有看到模型實際呼叫 Tool。
固定 release 的結果如下:
| 驗證層 | 結果 |
|---|---|
npm test |
143 passed |
npm run test:api |
16 passed |
vitest run tests/security |
6 passed |
npm run test:e2e |
37 passed |
npm run build |
client、server build passed |
API 與 security tests 已包含在 npm test 裡,後面再跑一次,是為了替各層留下獨立結果,
不代表突然長出另一批測試案例。同一張考卷影印兩次,紙變多了,題目沒有。
Browser output 裡也會出現前幾天刻意保留的 locator timeout。那不是 suite 偷偷失敗,而是
案例本來就在驗證「找不到元素時應該超時」,所以捕捉到預期錯誤後仍然通過。看到紅色字樣
以前,先看 assertion 在期待什麼,能少冤枉不少正常工作的程式。
如果輸出是 Timed out waiting 60000ms from config.webServer 或 EADDRINUSE,再看這一段;
沒有遇到就直接往下,不必主動替自己製造支線任務。
Get-Location
Get-NetTCPConnection -State Listen |
Where-Object { $_.LocalPort -in 3000, 5173 }
不要看到 port 被占用就順手終止陌生 process。那可能是另一個正在工作的專案,而它沒有義務
為今天的文章犧牲。
需要平行執行時,可以替這次 Playwright 測試換一組連接埠:
$env:PLAYWRIGHT_API_PORT = "3261"
$env:PLAYWRIGHT_WEB_PORT = "5261"
npm run verify
環境等待逾時、locator timeout 與產品 assertion failure 是三種不同問題。名字裡都有 timeout,
不代表它們住在同一戶。
Playwright 可以檢查 DOM、request 次數、focus、UI 是否更新,也能在受控測試裡觸發 syntheticagentInvoked event。這些測試可以回答:
但測試裡沒有真正的生成式模型,所以回答不了:
Chrome 官方的 WebMCP Evals 也把兩層分開:
deterministic tests 驗證 Tool logic、dependencies、UI side effects 與回傳值;涉及模型選擇、
參數與後續行動時,才需要能容納機率性結果的 evals。
Playwright 不是比較低階的 Agent 測試,它負責另一份工作。先用它排除產品與契約錯誤,後面
Inspector 失敗時,才有理由往 Tool selection、arguments 或 grounding 繼續查。
這次 release 的 commit 是 8e89e651...,對應的
GitHub Actions run 30549409859
結論為 Success。
不過,我檢查 tag 裡的
verification.json
時,發現其中記錄的是較早 commit:
ae03a9230a67747b32f96ac009c3f78cafd85400
檔案雖然存在,卻不能替 8e89e651... 背書。因此這一輪 release 的通過結果以同 commit 的
Actions run 為準,舊 report 只保留為歷史紀錄。
這個落差有點尷尬,卻剛好示範為什麼證據要帶 commit。沒有版本座標的「全部通過」,保存
期限通常比終端機視窗還短。
今天沒有新增網站功能。完成的是可重播的 deterministic gate:inventory、deadline、
confirmation intent、browser journey 與 build 都在固定 release 上通過,因此結果停在 E2。
Inspector trace 不能替它代考;這份測試報告也不能替 Agent invocation 升級。兩種綠燈分開,
後面除錯時才知道問題究竟在產品程式,還是模型與 Tool 的交界。
明天要把一段惡意指令塞進活動摘要,再請 Agent 整理資料。那時真正要看的,不是頁面能不能
正常顯示,而是 Agent 會把這串字當成活動內容,還是很熱心地照著它改規則。測試地基今天
已經打好,接下來終於可以放心把怪東西搬進屋裡。