靜態檢查 × CI × AI 摘要 2026

2026 OpenClaw 前端實戰:
遠端 Mac 網關合併 ESLint JSON 與 Stylelint,產出單一門禁摘要並回傳 PR 可讀評論

2026.04.27 要把靜態檢查納入 CI 與 AI 摘要的前端團隊 約 7 分鐘閱讀

人群:希望把靜態檢查納入CI,並讓下游AI 發布摘要只吃一份結構化訊號的前端團隊。關鍵詞:OpenClawESLint JSONStylelint遠端 MacPR 摘要。做法是在 Git 託管旁放一座網關(常與租用的 Apple Silicon 遠端 Mac 同網段):匯入兩份機讀報告、套用政策、輸出單一 Markdown 區塊供審閱者在 PR 內直接閱讀。延伸可搭配ESLint/Stylelint JSON 與修復分支草稿,以及權杖範圍化的 E2E 摘要自動化

00 HowTo:可複現清單

每一台工作者(含租用的遠端 Mac)都跑同一套步驟,本機才能與 CI、網關對齊,避免路徑或格式被「猜」錯。

  1. 依賴安裝使用與 CI 相同的 Node 22+ 主版本;必要時在 package.jsonengines 鎖定。
  2. 產出 ESLint JSONeslint . -f json -o .openclaw/reports/eslint.jsonStylelintstylelint "**/*.{css,scss}" --formatter json -o .openclaw/reports/stylelint.json
  3. CI 將兩檔與 GIT_SHAPR_NUMBER、選填 BASE_REF 一併送交 OpenClaw 網關。
  4. 網關執行合併腳本(見下文片段),寫入 pr_lint_gate_summary.md、依閾值決定離開碼,並呼叫 Git 供應商 API 更新 PR 評論。
  5. 下游 LLM 或內部機器人只讀合併後的摘要路徑,提示詞較小且欄位穩定。

若流水線還含瀏覽器任務,建議將 lint JSON 放在較輕量的階段;階段排序可對照遠端 Mac 上 Playwright 分片報告的建議順序。

01 本地/CI 輸出格式統一

本機與 CI 若各用預設終端格式,網關無法可靠解析。路徑正規化:ESLint 每檔的 filePath、Stylelint 的 source 常為絕對路徑,網關應扣掉儲存庫根,改以相對路徑當分組鍵,PR 摘要才不會因克隆目錄不同而跳動。

鎖定 formatter:CI 務必顯式指定 -f json--formatter json,並用 -o 寫檔,讓 stdout 留給其他工具。Apple Silicon 上僅在會影響外掛原生二進位時對齊架構變數;JSON 形狀仍應一致。

片段——package.json 腳本(Node 22+):

{
  "engines": { "node": ">=22" },
  "scripts": {
    "lint:eslint:json": "mkdir -p .openclaw/reports && eslint . -f json -o .openclaw/reports/eslint.json",
    "lint:stylelint:json": "mkdir -p .openclaw/reports && stylelint \"**/*.{css,scss}\" --formatter json -o .openclaw/reports/stylelint.json",
    "lint:json:all": "npm run lint:eslint:json && npm run lint:stylelint:json"
  }
}

02 網關側聚合與閾值

網關不重跑 linter,而是把 ESLint JSON(每檔 messagesseverity)與 Stylelint 陣列(warnings、是否 errored)合併成 lint_gate/v1:總錯誤/警告、熱門規則、最差檔案與工具歸屬。此物件同時驅動人讀 Markdown 與 Slack、LLM。

閾值:ESLint severity 2 與 Stylelint 在失敗 run 上的錯誤視為硬擋;另以倉庫內 YAML 維護警告預算(例如正式分支 max_stylelint_warnings: 12),功能分支可僅警示。網關比對計數後設定 HTTP 狀態或 CI 離開碼。

片段——合併骨架(Node 22 ESM,跑在 OpenClaw 網關):

// tools/merge-lint-gate.mjs — 報告就位後於網關執行
import { readFile, writeFile } from "node:fs/promises";

const root = process.env.REPO_ROOT ?? "";
const strip = (p) => (p && p.startsWith(root) ? p.slice(root.length + 1) : p);

const eslint = JSON.parse(await readFile(".openclaw/reports/eslint.json", "utf8"));
const style = JSON.parse(await readFile(".openclaw/reports/stylelint.json", "utf8"));

const rows = [];
for (const f of Array.isArray(eslint) ? eslint : []) {
  for (const m of f.messages ?? []) {
    rows.push({ tool: "eslint", file: strip(f.filePath), rule: m.ruleId ?? "syntax", sev: m.severity });
  }
}
for (const f of Array.isArray(style) ? style : []) {
  for (const w of f.warnings ?? []) {
    rows.push({ tool: "stylelint", file: strip(f.source), rule: w.rule ?? "unknown", sev: w.severity });
  }
}

const gate = {
  version: 1,
  errors: rows.filter((r) => r.sev === 2 || r.sev === "error").length,
  warnings: rows.filter((r) => r.sev === 1 || r.sev === "warning").length,
  topRules: [] /* 依 rule 分組取前 N */
};
await writeFile(".openclaw/reports/lint_gate.json", JSON.stringify(gate, null, 2));

補齊 topRules 的 reducer 後,將 schema 版本寫死,讓 OpenClaw 提示詞可引用 lint_gate/v1 而不怕欄位突變。

03 失敗重試與截斷策略

傳輸與供應商限制(429、5xx、TLS 瞬斷)應指數退避加抖動重試,同一台遠端 Mac 對外 IP 若併發多個 PR 更需如此。Lint 邏輯失敗不應盲目重跑;僅在偵測到不完整 JSON(例如離開碼非零但陣列為空、疑似程序崩潰)時再執行一次。

截斷:每條規則最多列出少數檔案(例如五個),整篇 Markdown PR 摘要總行數設上限(例如 120 行),末行註明「已截斷:另有 N 筆——見 CI 產物 eslint.json/stylelint.json」。檔名層級的指引安全;避免在評論內塞長 base64。

片段——有界重試 shell 包裝:

#!/usr/bin/env bash
set -euo pipefail
attempt=0 max=4
until node tools/post-pr-lint-summary.mjs; do
  code=$?
  attempt=$((attempt + 1))
  if [[ "$code" -eq 77 ]] && [[ "$attempt" -lt "$max" ]]; then
    sleep $((2 ** attempt + RANDOM % 3))
    continue
  fi
  exit "$code"
done

post-pr-lint-summary.mjs 內保留離開碼 77 代表「可重試的供應商錯誤」,與 lint 未過分開,排錯才不混淆。

04 與 Git provider 評論 API 思路(不寫需登入的私有 URL)

常見做法為 REST「對 PR 發議題留言」或錨在 diff 上的 review comment;只要網關持有範圍限縮的權杖(精細 PAT、GitHub App installation token、GitLab job token 等)即可。重點是冪等:在 Markdown 頂端放隱藏 HTML 註解作為標記(例如 <!-- openclaw-lint-gate:雜湊 -->),每次先搜尋機器人既有留言,有則 PATCH 更新,避免重排隊洗版。

不要寫進公開 PR 的內容:需組織登入才打得開的私有預覽網址——審閱者可能無權限,搜尋引擎也可能帶出標題外洩。改寫「見 CI 工作流執行 #12345 產物」或只連到公開文件;細節以評論內截斷片段或受權限保護的 artifact 為主。

示意 POST:例如 POST /repos/{owner}/{repo}/issues/{pr}/comments,body 為 { "body": "<markdown 摘要>" },標頭 Authorization: Bearer …。GitLab、Bitbucket 對應各自資源即可,OpenClaw 網關僅需薄適配層。

小結

ESLint JSONStylelint 共用同一路徑契約,並在 OpenClaw 網關單點合併,PR 摘要就能用一則敘事交代總量、熱門規則與有界檔案清單,兼顧人讀與下游 CI+AI;節點放在 Apple Silicon 遠端 Mac 上亦易與 Safari/WebKit 冒煙並列維運。

站內導覽:首頁幫助中心技術見解(部落格索引)

Apple Silicon CI 主機

在專用遠端 Mac 上跑同一套 OpenClaw lint 門禁

若你希望 Node 22+ 工作者與 Safari/WebKit 冒煙同網段、低抖動,可租用 Apple Silicon 遠端 Mac 承載網關與 CI。開啟購買頁比對方案並免登入結帳,適合正在標準化 OpenClawESLint JSONStylelint 單一流水線的團隊。

單一 lint 門禁摘要 PR 評論自動化 Apple Silicon
租用 M4 — 免登入