iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0
Software Development

收到自己的紅色炸彈!婚期就是 Deadline:前端一人用 AI 規格流水線,30 天出貨婚禮 SaaS系列 第 20

Day 20 規則會被忘記,所以我讓機器守門!從 Git Hooks 到 108 行視覺 Lint 的兩道自動化防線

  • 分享至 

  • xImage
  •  

兩道閘門:Playwright 雙區紅燈分流與 pre-push 自動化把關實務
Day 20 規則會被忘記,所以我讓機器守門!從 Git Hooks 到 108 行視覺 Lint 的兩道自動化防線

📍 流水線位置|入口 → flow → 型別 → mock → 測試 → UI → 【vibe】 → 上線(守門)

流水線位置|入口 → flow → 型別 → mock → 測試 → UI → 【vibe】 → 上線(守門)

搞定了前端不用等後端(D10–13)、測試成為主規格(D14–17),以及 UI 自由的邊界(D18–19),第二個十天算告一段落。

合約立了、測試綠了,業務紅線也畫得明明白白。但說實話,只要規則還是在靠人的記憶力去守,遲早有失守的一天。當所有人都在趕進度,或是改 UI 改到恍神時,根本不會有人打開規範文件一條條對照。

要讓 Day 19 的紅線真正被守住,最靠譜的方法就是把規範寫成自動化腳本:不靠自律,讓機器幫我們硬核守門。


第一道閘門:commit 與 push 前的自動化驗證

專案中配置了 playwright.gate.config.ts,這份設定檔直接整合了兩組測試:凍結的主規格測試(業務合約),以及 Vibe 階段自動生成的行為測試。

在完成 vibe 重構、準備 commit 之前,根據工作流政策(CLAUDE.md)要求必先執行 gate 檢查,測試全數通過(綠燈)才進行提交;到了 git push 階段,pre-push hook 則會以同一套 gate 設定進行強制把關,只要亮紅燈,就直接擋下 Push,絕不讓未經驗證的變更進入遠端儲存庫。

這道 gate 檢查正是 Day 04 清單中 Vibe 治理那排 vibe-check 的守備範圍:當 vibe 改版做完,在對話裡呼叫這支指令,就是要求在 commit 之前先把這份 gate 設定跑過一輪。

而在更上游的 AI 工具層,還掛載了即時攔截機制。專案透過 Claude hook 掛載了兩支守衛腳本:

  • frozen-paths-guard
    在 AI 動手修改檔案的當下,直接擋下凍結區既有檔案的變更

  • server-security-guard
    在編輯 server 端程式碼時,自動注入安全規範摘要,並偵測常見的越權存取寫法。

凍結與安全這兩條紅線,根本不必等到測試階段,在 AI 編輯發生的瞬間,就已經被機器死死守住。

雙層自動化守門員管線圖

配置自動化閘門的目的,就是要用系統化的檢核取代不穩定的人工抽查,畢竟只要是人,總會有狀態差的時候。

那麼,大家口中常說的「我以為我只改了樣式」,實際上到底長什麼樣子?

下圖是我重現 Day 22 那次撞名事故的真實 gate 輸出(這不是當天現場截圖,而是事後為了還原現場、重新跑出來的同一種報錯):

gate 紅燈:改了一個 aria-label,凍結區的合約測試當場中斷(重現示範,細節見 Day 22)


紅燈分流機制:合約與紀錄的權責劃分

gate 亮紅燈時,第一件事是看失敗案例落在哪個目錄,這兩個區域的修復策略與權責完全不同:

Red Light 分流處置 SOP 圖

  • 🔴 主規格測試區域(test/e2e/specs/):
    此區域代表「業務邏輯合約」。出現紅燈代表此次變更已觸犯紅線原則,包括實體識別失效、狀態語意遺漏或核心操作路徑中斷。修正方向必須集中於前端介面與邏輯的回滾或修復,嚴禁修改此區域的測試檔。該區域採完全凍結策略。

  • 🟡 vibe 測試區域(test/e2e/vibe/):
    此區域的測試用於記錄既有介面的 UI 行為。當新變更與舊測試發生衝突時,需由開發者評估屬於迴歸錯誤或屬於預期內的 UI 規格更迭。若是後者,則允許依據最新介面行為更新測試腳本。

這兩區採用完全不同的處理原則,原因在於一區屬於不可違背的業務合約,另一區則屬於允許隨版本演進的行為紀錄。


第二道閘門:視覺層級與 Token 規範的靜態檢查

第一道閘門守住了「功能有沒有壞」,但 UI 重構時最常偷溜進來的,往往是另一類隱形風險:視覺層級失衡與 Design Token 濫用。

專案中的 issue #19 就曾記錄過這種「視覺大亂鬥」的經典案例:

現況:
一個畫面常疊四層大字互搶焦點
(sidebar 選中項 → PageHeader 主標 → 區塊標題 → 空狀態大字)。

當時的空狀態(empty state)套用了超大字體與圖示,結果「目前無賓客資料」這幾個字,居然比頁面的主標題還要搶眼!對 E2E 測試來說,只要文字有成功印在 DOM 上就是綠燈 pass,它完全管不到視覺比重是不是已經失控。

為了防範這種視覺漂移,我寫了一支腳本(scripts/visual-hierarchy-check.mjs),裡面訂了 9 條硬性規則,並掛載於 npm run eslint 流程後自動觸發。
ㄧㄠ
它是怎麼管的?

  • 鎖死字級上限:
    強行禁止寫 text-5xl 以上的 class,違規就直接噴 後台介面最大 text-3xl,當場把大字互搶的問題連根拔起。

  • 抓亂寫的任意值:
    禁止寫死 text-[64px]bg-[#1a2b3c]。要用顏色或字級,必須去 @theme 設定檔裡定義好 Design Token 才能用。

  • 抓 AI 模板味:
    直接把 bg-clip-text(漸層文字)列入黑名單,警告直接寫 AI 模板味,禁用

這套機制並非限制視覺的多樣性,而是阻止開發者繞過設計系統、硬編碼(Hard-code)一次性數值。若需要特定字級或顏色,開發者必須於主題設定檔中定義具名 token(Design Token)後調用。警告訊息也已標明修復指引:改用內建字級,或先在 @theme 定義具名 token。透過 Token 化管理,就能徹底消除手寫 Class 造成的視覺漂移。

說白一點:「鎖死字級上限」與「禁止漸層字」這兩條,其實已經超出了「攔截任意值」的範疇,本質上是我替後台介面立下的品味約定,也是 Day 19 自由清單中「顏色、字體自由」的兩條明列例外。

例外可以存在,但必須寫成規則、交給機器執行,而不是藏在某個人的審美裡。

不過,靜態檢查也有它的極限。像是「單一頁面只能有一個主焦點」這種需要整體語意上下文的規範,機器就無法精準判斷,終究還是得仰賴開發者在重構時的自律與拿捏。


回顧 Day 02:人工確認點,到底該放在哪?

在 Day 02 導入 OpenSpec 時我就發現過於頻繁的人工確認點會打斷開發節奏。將當時的體悟落實在目前的門禁架構中:人的確認該放在哪裡,比要不要確認更關鍵。

在當前的開發流程中,人工確認主要收斂於兩個時間點:

  1. 前期: 規格與紅線定義階段
  2. 後期: gate 檢查亮紅燈時

嚴格說還有第三個零散的介入點:前一節坦白過的視覺語意規範,機器判不了,只能靠工程師在重構當下守住。但整體而言,在這兩個主要時間點之間,開發者與 AI 助手可以全速執行程式碼變更,完全不需要在中途設定無謂的人工打斷點。

變更出錯有自動化閘門攔截並兜底,但開發者的專注狀態一旦被打斷,重新建立 Context 的成本極高。

只有被納入自動化檢查管線的規範,才能確保 100% 被執行。

未透過工具強制的規則,說穿了都只是軟性約定。守不守得住取決於開發者的即時狀態,忙起來或狀態不好時,錯誤仍在所難免。這也是為什麼能轉化為腳本的規則,就不應消耗開發者的大腦記憶體。

閘門機制能有效確保既有功能不被破壞,但改版過程中常會衍生出全新互動與狀態。
下一篇將介紹 vibe 測試腳本如何透過自動化流程自動生成。

🎒 最小一步|將目前專案中最常遺漏的一條 UI 或代碼規範,寫成腳本並加入 pre-commit 檢查中。
📎 本篇證據|


上一篇
Day 19 畫面讓你隨便改,但動到這 3 樣算你毀約!Vibe UI 治理的三條業務紅線與自由重構地圖
下一篇
Day 21 新增互動功能:讓 AI 自動生成對應測試
系列文
收到自己的紅色炸彈!婚期就是 Deadline:前端一人用 AI 規格流水線,30 天出貨婚禮 SaaS21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言