2026 OpenClaw 前端實戰:
遠端 Mac 解析生命週期與 Cache Storage 鍵變更並生成 PR 摘要回傳
合併審查需要控制者切換與快取鍵差分的機讀證據。本文給遠端 Mac 可複現路徑:sw_cache_delta.json、NDJSON、指數退避、OpenClaw 產 pr_sw_cache_summary.md 冪等回傳。內鏈 發布驗收、建置摘要、Deploy Hook。
01 痛點與目標
痛點一:截圖難重現時間序。痛點二:鍵集合變化口述易漏。痛點三:主控台全文貼 PR 易洩路徑。目標以薄契約凍結註冊與快取差分,必要時計 opaque 數,交 OpenClaw 寫短摘要並冪等回傳;網關與 Git 權杖分離。
在遠端 Mac Runner 上,請先匯出可追蹤脈絡:GIT_SHA、PR_NUMBER、BASE_URL(預覽或正式網址需與合併目標一致)、OPENCLAW_RUN_ID。審查者關心的是「控制者是否切換」「快取前綴是否跨環境洩漏」「是否逼近配額」,因此產物應可與 main 上的基線 JSON 做機讀對照,而不是僅貼一段主控台輸出。
02 生命週期與快取訊號對照
鎖定同一預覽網址與瀏覽器小版本,暖站後兩次導覽間插入短等待,讓狀態落地;若需立即接管另分支驗 skipWaiting 與 clients.claim。
第一次導覽後,registration.installing 可能仍為 waiting;第二次導覽或短暫延遲後再讀,較能對齊「已啟用」與 controllerchange。WebKit 與 Chromium 在更新節奏上不同,建議同一管線各跑一輪,並在 NDJSON 標註 browserProfile,避免把單引擎行為誤推為規格結論。
| 訊號 | 擷取與審閱 |
|---|---|
| 生命週期 | 記錄安裝啟用時間戳、是否 skipWaiting、控制者腳本雜湊;對照靜態版號與雙引擎節奏。 |
| 快取鍵 | caches.keys 排序後做 added/removed,附條目數與 opaque 計數,檢前綴是否跨環境洩漏。 |
03 sw_cache_delta.json 欄位解析
固定 schemaVersion;時間用整數毫秒;鍵名排序後再 diff。
| 欄位 | 含義 |
|---|---|
schemaVersion git_sha pr_number |
契約版本、提交、PR 編號;供閘道與冪等鍵對齊。 |
lifecycle |
陣列:階段名(如 activated)、整數毫秒時間戳、可選 scriptUrl 雜湊前綴。 |
cacheKeysAdded cacheKeysRemoved |
相對上一快照的鍵集合差分;鍵名必先排序再 diff,避免集合順序噪聲。 |
opaqueEntryCount quotaEstimateMb |
不透明條目計數;若 navigator.storage.estimate 可用則寫估計 MB,否則 null。 |
quotaErrorFlag |
布林:採樣流程是否捕獲 QuotaExceededError,供 PR 摘要一句話帶過。 |
① 兩次採樣同網域同路徑。② 摘要短、細節連工件。③ 對 main 基線同鎖 CDN 與靜態版號。
04 腳本與探針占位(可複現步驟)
scripts/sw-probe-placeholder.mjs:playwright.webkit.launch()(或專案約定的chromium)開預覽;檔內以// TODO標註BASE_URL、Cookie、自訂標頭(例如預覽密碼)。public/__sw_probe__.html(或僅供 CI 的隱藏路由):window.addEventListener('load')後讀caches.keys(),經postMessage回 Runner;勿在網址列暴露敏感 token。- 雙次導覽間
sleep,落盤sw_cache_snapshot_a.json、sw_cache_snapshot_b.json,差分得sw_cache_delta.json;以jq -e .schemaVersion做最小驗證。 - 對
main檢出的基線做集合差,輸出sw_cache_gate.json(level:pass/warn/fail);OpenClaw 讀取 delta+gate 產pr_sw_cache_summary.md。 - Webhook 或
gh pr comment冪等回傳,正文只放結論與.openclaw/reports/…連結。
報告目錄與他篇 OpenClaw 管線共用 .openclaw/reports/<sha>/ 前綴,便於與 建置度量摘要、trace 工件並列。
Shell 占位(複製後替換變數即可跑):
export BASE_URL="https://your-preview.example" GIT_SHA="$(git rev-parse HEAD)" PR_NUMBER="123" OPENCLAW_RUN_ID="$(uuidgen)"
mkdir -p ".openclaw/reports/${GIT_SHA}"
node scripts/sw-probe-placeholder.mjs --url "$BASE_URL" --out ".openclaw/reports/${GIT_SHA}/"
jq -e '.schemaVersion' ".openclaw/reports/${GIT_SHA}/sw_cache_delta.json"
- 預覽 HTTPS 與發布路徑一致。
- 雙引擎各跑一輪。
05 NDJSON 日誌欄位說明
每行一筆 JSON 至 stdout 或 sw_probe.ndjson,小駝峰、淺層嵌套。
| 欄位 | 用途 |
|---|---|
ts runId event retryCount |
ISO 時間或 epoch ms;與 OpenClaw 其他任務共用 runId;事件名如 warmup_done、snapshot_written;當前退避輪次。 |
browserProfile swState cacheKeyCount |
例如 [email protected];控制者 registration.active?.state;快取鍵數量。 |
gateLevel errorClass |
閘道結果;錯誤分類如 quota、network、contract(4xx 契約錯誤),便於儀表板聚合。 |
backoffMs backoffTotalMs lastHttpStatus |
單次等待毫秒;累計退避;Webhook 或 Git API 最後 HTTP 狀態。 |
finalStatus idempotencyKey |
整輪 ok/degraded/failed;建議 ${GIT_SHA}:${PR_NUMBER}:sw-cache,與標頭一致以便去重。 |
單行範例(寫入 sw_probe.ndjson 或 stdout 皆可):
{"ts":1713200000123,"runId":"oc_7f3a","event":"callback_attempt","retryCount":2,"browserProfile":"webkit","swState":"activated","cacheKeyCount":6,"gateLevel":"warn","lastHttpStatus":429,"backoffMs":800,"finalStatus":null,"idempotencyKey":"abc123def:42:sw-cache"}
06 失敗重試與冪等回傳
指數退避:二百毫秒起加倍,上限例如八秒,至多五次;每輪可加少量隨機抖動,降低與其他 Runner 同相衝撞。NDJSON 必寫 retryCount、backoffMs、backoffTotalMs。
回傳路徑二選一或並用:① 閘道 Webhook(Body 含 git_sha、pr_number、gate.level、Markdown 或工件 URL),以 HMAC-SHA256 驗簽;② gh pr comment,內文底部保留 HTML 註解 <!-- openclaw-sw-cache:$SHA --> 供去重。HTTP 429 與 5xx 才重試;401/403/404 視為契約或權限問題,應停止並改設定,避免洗無效流量。
請求標頭建議:Authorization: Bearer …、Idempotency-Key: ${GIT_SHA}:${PR_NUMBER}:sw-cache。網關僅做模板渲染與速率限制,具寫入 PR 權限的細粒度 token 放在 Runner 祕鑰庫,與 OpenClaw 控制面分離。
07 結構化資料與內鏈規劃
頁首 application/ld+json 使用 @graph:BlogPosting(標題、摘要、主圖、日期與 mainEntityOfPage)、BreadcrumbList(首頁→技術見解→本文 URL)、HowTo(步驟文字與正文「腳本占位/重試」一致)、FAQPage(與下方 FAQ 段落同題,便於複合搜尋結果)。若站內另有組織層級 Organization,可於全站模板合併,不必在單篇重複贅述。
內鏈規劃:導語放「決策鏈」相關文——Service Worker 發布驗收與 Safari 差異、建置耗時 PR 摘要、Deploy Hook 冒煙管線;實作段落可補 部署前冒煙 作為前置閘。錨文字用主題名而非「點此」,CTA 區保留 技術見解列表、免登入購買 轉化路徑。
08 FAQ
為何出現 QuotaExceededError?同一 origin 下,Cache Storage、IndexedDB、localStorage 等共用儲存預算;若離線包或第三方 no-cors 快取膨脹,常在 activate 或大量 cache.put 時爆掉。探針應回傳 quotaEstimateMb、快取鍵總數與 opaqueEntryCount;閘道可設「鍵數突增」與「opaque 占比」雙條件,先 warn 讓維運刪除過期前綴或改 RELEASE_ID 前綴策略,必要時才 fail 擋合併。
Opaque response 對審計有什麼影響?跨來源以 fetch(url, { mode: 'no-cors' }) 取得的回應寫入 Cache 時,多為 opaque,瀏覽器不提供可靠內容長度;若把「估計體積」與同源 JS/CSS 放在同一欄位加總,會誤判 bundle 是否異常。正確作法是在 sw_cache_delta.json 與 PR 摘要中分開統計 opaque 條目數,並在文字中明確標示「體積未知」,僅對同源可讀條目做 KB/MB 閾值。
五次重試後仍失敗?將 finalStatus 設為 failed 或(部分成功時)degraded,NDJSON 寫入 lastHttpStatus 與 backoffTotalMs;PR 只貼一句結論與工件路徑。若 lastHttpStatus 常為 429,檢查是否與 Deploy Hook、Lighthouse 任務同一出口 IP;可將 SW 探針排到離峰或為閘道加配額。
暖站雙採樣 → 差分 sw_cache_delta.json → 閘道 sw_cache_gate.json → OpenClaw 產 pr_sw_cache_summary.md → 指數退避後冪等回傳;NDJSON 全程可稽核。需要 Apple Silicon 真機節點請至 購買公開頁免登入選型。