昨天 Demo 的那次失敗,是人讀著錯誤訊息把 manifest 修好的。今天要換個做法,變成由 AI Agent 讀訊息、改設定檔。
這是這個系列第一次真的讓 AI 進場,所以今天先不急著動手,把「交給 AI 之前要先想清楚的事」講完,明天再實際跑一次。
人工寫 manifest,一章大概十幾到三十行 YAML。昨天 Demo 的範例只有四章,感覺還可以,但真實產品的手冊上看二、三十章,第一次從零開始寫就是整整一天的事。
更麻煩的是改版。UI 調整之後,要回頭確認每一章的 testid 還在不在、操作順序還通不通。這件事本身並不難,只是很瑣碎,而「瑣碎但不難」正是這個系列第一天說的、最容易讓文件過期的那種工作。
讓 AI 參與寫設定檔,信任程度可以分三級:
第一種太浪費 AI Agent 的能力了,整個流程還是很依靠人類,這個我就直接放棄了。
理想上是要可以做到第三種程度,但是它有一個前提是,需要一個完善的驗收機制,來判斷怎麼樣才算成功 (i.e. 怎樣才算是一個高品質的使用手冊)。
因此,在使用手冊產線建立初期,會比較傾向先用第二種程度進行過渡,等後續驗收機制完善了,再轉往第三種程度,盡可能地放給 AI Agent 全權處理。
讀上下文(TESTID.md / UI-MAP / schema / 已審過的章節)
→ probe 探勘當下畫面
→ 寫一章 manifest
→ validate(不開瀏覽器,擋格式)
→ run --chapter(開瀏覽器,擋 selector 與狀態)
→ 失敗就讀錯誤訊息修,再跑一次
→ 通過之後產出 diff 給人 review
這個迴圈的重點,是讓 agent 有辦法自己知道對不對。如果它只能「看一眼畫面、憑印象寫 selector」,寫出來的東西本質上是猜測。能實際去跑、能讀到為它設計過的錯誤訊息、能據此修正,整件事才從一次性的猜測變成有回饋的迭代。
這也是為什麼 Day 15 要提到「錯誤訊息要把下一個指令也寫出來」。
不知道大家有沒有注意到,前面提到的工作迴圈中,除了執行腳本外,前面還多了兩個工作:probe 與 validate。
validate:驗證設定檔格式這個相對直覺,就是要驗證設定檔格式是否正確,以及裡面提到的各種操作是否都是有定義過的。
probe:探勘當下畫面probe 是專門為 agent 設計的探勘指令,目的是為了要印出當下畫面上所有可見且具 data-testid 的元件,連同文字內容與 boundingBox:
$ npm run probe -- --mode web --after click:camera-add
畫面:monitor(camera-dialog 開啟中) 1600×900
可見且具 testid:23 個(整份 DOM 共 131 個)
camera-dialog 「新增攝影機」 x=560 y=180 w=480 h=420
camera-dialog-name (空白輸入框) x=584 y=268 w=432 h=36
camera-dialog-zone 「大廳」(下拉) x=584 y=330 w=432 h=36
camera-dialog-source 「rtsp://…」(placeholder) x=584 y=392 w=432 h=36
camera-dialog-enabled 「啟用推論」(開關) x=584 y=454 w=52 h=28
camera-dialog-cancel 「取消」 x=812 y=540 w=88 h=36
camera-dialog-confirm 「新增」(disabled) x=908 y=540 w=88 h=36
有三個設計值得提一下:
只印可見的,不印整份 DOM
直接把 HTML 丟給 agent 是最省事的做法,但一份 1600×900 的畫面 HTML 動輒上萬行,agent 要自己從裡面挑出有用的東西,既慢又容易挑錯。結構化的清單則是「這個畫面此刻真的有什麼」,資訊密度高得多。
帶 --after,因為條件渲染的元件在首頁探勘不到
範例 App 的對話框、設定子項、授權區塊全都是 v-if,沒開啟就真的不在 DOM 裡。所以 probe 必須支援「先做幾個操作再探勘」,不然 agent 永遠只看得到首頁那一層。
帶文字內容
camera-dialog-confirm 這個名字只說明它是確認鍵,畫面上寫的是「新增」還是「儲存」,必須要靠文字才能告訴 AI agent,避免影響後面寫正文時的按鈕名稱。
順帶一提,
probe的輸出跟 Day 15 失敗訊息裡那份候選清單是同一套東西,只是一個是主動查詢,一個是失敗時自動附上。
範例專案 auto-manual-gen 裡,給 agent 的東西集中在兩個地方:agent/ 與靶專案自己的 TESTID.md。(明天才會更新內容XD)
apps/demo-stream-app/TESTID.md
命名規範與現有標記清單,Day 08 就寫好的那份。它同時是給人看的規範與給 agent 的上下文,這是它最划算的地方。
agent/UI-MAP.md
頁面與導覽結構。讓 agent 知道「系統設定在 nav-tab_settings 底下」「授權區塊要 role=admin 才存在」,它才有辦法規劃操作順序。
agent/QUIRKS.md
這個 App 的特性。例如「3×3 以上 grid-cell-fps_{n} 會被精簡掉」「./api/cameras 一定會失敗,會退回內建假資料」。這類知識人要遇到兩三次才會記住,寫下來之後 agent 第一次就能避開。
manifest/schema.json
設定檔的 JSON Schema。給了它,agent 產出的東西從一開始就大致合法,而不是產完再被擋下來重寫。
再加上 agent/examples/ 底下已經審核通過的兩章當 few-shot 範例。這件事比任何形容詞都有效:與其在 prompt 裡寫「請寫得精簡一點、註解清楚一點」,不如直接給它兩份可以直接參考的 YAML。
一開始難免會忍不住直接把整個 codebase 塞進 context,期待 agent 自己挑出有用的。實際上效果通常不如一份兩百行、人工整理過的摘要。雜訊會稀釋掉真正關鍵的資訊,而且每一次迭代都要重付一次 token。
今天講的都還是設計:AI 的邊界劃在哪、要交出去到什麼程度、agent 需要哪些上下文與指令。這些東西之所以成立,靠的是 Day 14、15 已經準備好的三樣:可被 diff 的設定檔、會留下線索的錯誤訊息、可以只跑一章的 runner。
明天把這套東西實際跑一次:讓 agent 幫範例專案加一章,看它怎麼探勘、怎麼被擋下來、又怎麼自己修好。