diff --git a/docs/zh-TW/ci.md b/docs/zh-TW/ci.md index 9896c6a1d..4ef6b28f9 100644 --- a/docs/zh-TW/ci.md +++ b/docs/zh-TW/ci.md @@ -1,75 +1,75 @@ --- read_when: - 你需要了解 CI 作業為何執行或未執行 - - 您正在偵錯一項失敗的 GitHub Actions 檢查 - - 你正在協調發布驗證的執行或重新執行 -summary: CI 作業圖、範圍閘門、發布總括項與本機命令對應項 + - 你正在偵錯一個失敗的 GitHub Actions 檢查 + - 您正在協調發布驗證的執行或重新執行 +summary: CI 作業圖、範圍閘門、發行總括項與本機命令對應項 title: CI 管線 x-i18n: - generated_at: "2026-04-30T09:35:01Z" + generated_at: "2026-04-30T18:38:35Z" model: gpt-5.5 provider: openai - source_hash: a9c18f0801864ca1030aac9ea81117b011bd7936388984a1809ce3ae6e906e62 + source_hash: a24afc27606ac7f4e9ead89acdd319bffa23336610f8a6cd8b576ea1a5b233dd source_path: ci.md workflow: 16 --- -OpenClaw CI 會在每次推送到 `main` 以及每個 pull request 上執行。`preflight` 作業會分類差異,並在只有不相關區域變更時關閉昂貴的執行路徑。手動 `workflow_dispatch` 執行會刻意略過智慧範圍界定,並展開完整圖形,以供發行候選版本和廣泛驗證使用。Android 路徑透過 `include_android` 維持選用。僅限發行的 Plugin 覆蓋範圍位於獨立的 [`Plugin 預發行`](#plugin-prerelease) 工作流程中,且只會從 [`完整發行驗證`](#full-release-validation) 或明確的手動派發執行。 +OpenClaw CI 會在每次推送到 `main` 以及每個 pull request 上執行。`preflight` 工作會分類 diff,並在只有不相關區域變更時關閉昂貴的執行路徑。手動 `workflow_dispatch` 執行會刻意略過智慧範圍界定,並為候選版本與廣泛驗證展開完整圖。Android 執行路徑透過 `include_android` 維持選擇加入。僅限發行的 Plugin 涵蓋範圍位於獨立的 [`Plugin Prerelease`](#plugin-prerelease) workflow,且只會從 [`Full Release Validation`](#full-release-validation) 或明確的手動 dispatch 執行。 -## 管線概觀 +## 管線概覽 -| 作業 | 用途 | 執行時機 | +| 工作 | 目的 | 執行時機 | | -------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------- | -| `preflight` | 偵測僅文件變更、已變更範圍、已變更擴充功能,並建置 CI manifest | 一律在非草稿推送和 PR 上執行 | -| `security-scm-fast` | 透過 `zizmor` 偵測私密金鑰並稽核工作流程 | 一律在非草稿推送和 PR 上執行 | -| `security-dependency-audit` | 針對 npm advisories 進行不需相依性的正式環境 lockfile 稽核 | 一律在非草稿推送和 PR 上執行 | -| `security-fast` | 快速安全性作業的必要彙總 | 一律在非草稿推送和 PR 上執行 | -| `check-dependencies` | 僅針對正式環境 Knip 相依性的檢查,加上未使用檔案 allowlist 防護 | Node 相關變更 | -| `build-artifacts` | 建置 `dist/`、Control UI、已建置 artifact 檢查,以及可重複使用的下游 artifact | Node 相關變更 | -| `checks-fast-core` | 快速 Linux 正確性路徑,例如 bundled/plugin-contract/protocol 檢查 | Node 相關變更 | -| `checks-fast-contracts-channels` | 分片的 channel contract 檢查,並提供穩定的彙總檢查結果 | Node 相關變更 | -| `checks-node-core-test` | Core Node 測試分片,不含 channel、bundled、contract 和 extension 路徑 | Node 相關變更 | -| `check` | 分片的主要本機 gate 對等項:正式環境型別、lint、防護、測試型別與嚴格 smoke | Node 相關變更 | -| `check-additional` | 架構、邊界、extension-surface 防護、package-boundary 與 gateway-watch 分片 | Node 相關變更 | -| `build-smoke` | 已建置 CLI 的 smoke 測試與啟動記憶體 smoke | Node 相關變更 | -| `checks` | 已建置 artifact channel 測試的驗證器 | Node 相關變更 | -| `checks-node-compat-node22` | Node 22 相容性建置與 smoke 路徑 | 發行用手動 CI 派發 | -| `check-docs` | 文件格式化、lint 與斷裂連結檢查 | 文件已變更 | -| `skills-python` | Python 支援 skills 的 Ruff + pytest | Python skill 相關變更 | -| `checks-windows` | Windows 專用 process/path 測試,加上共用 runtime import specifier 回歸 | Windows 相關變更 | -| `macos-node` | 使用共用已建置 artifact 的 macOS TypeScript 測試路徑 | macOS 相關變更 | -| `macos-swift` | macOS app 的 Swift lint、建置與測試 | macOS 相關變更 | -| `android` | 兩種 flavor 的 Android 單元測試,加上一個 debug APK 建置 | Android 相關變更 | -| `test-performance-agent` | 受信任活動後的每日 Codex 慢速測試最佳化 | Main CI 成功或手動派發 | +| `preflight` | 偵測僅文件變更、變更範圍、變更的 Plugin,並建立 CI manifest | 一律在非草稿 push 與 PR 上執行 | +| `security-scm-fast` | 透過 `zizmor` 進行私鑰偵測與 workflow 稽核 | 一律在非草稿 push 與 PR 上執行 | +| `security-dependency-audit` | 針對 npm advisories 進行不需安裝相依套件的 production lockfile 稽核 | 一律在非草稿 push 與 PR 上執行 | +| `security-fast` | 快速安全性工作的必要彙總 | 一律在非草稿 push 與 PR 上執行 | +| `check-dependencies` | Production Knip 僅相依套件檢查,加上未使用檔案 allowlist 防護 | Node 相關變更 | +| `build-artifacts` | 建置 `dist/`、Control UI、建置成品檢查,以及可重用的下游 artifacts | Node 相關變更 | +| `checks-fast-core` | 快速 Linux 正確性執行路徑,例如 bundled/plugin-contract/protocol 檢查 | Node 相關變更 | +| `checks-fast-contracts-channels` | 分片的 channel contract 檢查,並具備穩定的彙總檢查結果 | Node 相關變更 | +| `checks-node-core-test` | Core Node 測試分片,排除 channel、bundled、contract 與 Plugin 執行路徑 | Node 相關變更 | +| `check` | 分片的主要本機 gate 等價檢查:prod types、lint、guards、test types 與 strict smoke | Node 相關變更 | +| `check-additional` | 架構、邊界、Plugin 介面防護、package-boundary 與 gateway-watch 分片 | Node 相關變更 | +| `build-smoke` | Built-CLI smoke tests 與 startup-memory smoke | Node 相關變更 | +| `checks` | 建置成品 channel tests 的驗證器 | Node 相關變更 | +| `checks-node-compat-node22` | Node 22 相容性建置與 smoke 執行路徑 | 發行用手動 CI dispatch | +| `check-docs` | 文件格式、lint 與 broken-link 檢查 | 文件已變更 | +| `skills-python` | Python-backed skills 的 Ruff + pytest | Python-skill 相關變更 | +| `checks-windows` | Windows 特定的 process/path 測試,加上共用 runtime import specifier 回歸檢查 | Windows 相關變更 | +| `macos-node` | 使用共用建置成品的 macOS TypeScript 測試執行路徑 | macOS 相關變更 | +| `macos-swift` | macOS app 的 Swift lint、build 與 tests | macOS 相關變更 | +| `android` | 兩種 flavor 的 Android unit tests,加上一個 debug APK build | Android 相關變更 | +| `test-performance-agent` | 受信任活動後的每日 Codex slow-test 最佳化 | Main CI 成功或手動 dispatch | ## Fail-fast 順序 -1. `preflight` 會決定哪些路徑實際存在。`docs-scope` 和 `changed-scope` 邏輯是此作業內的步驟,不是獨立作業。 -2. `security-scm-fast`、`security-dependency-audit`、`security-fast`、`check`、`check-additional`、`check-docs` 和 `skills-python` 會快速失敗,不需等待較重的 artifact 與平台矩陣作業。 -3. `build-artifacts` 會與快速 Linux 路徑重疊,讓下游消費者能在共用建置完成後立即開始。 -4. 較重的平台與 runtime 路徑之後會展開:`checks-fast-core`、`checks-fast-contracts-channels`、`checks-node-core-test`、`checks`、`checks-windows`、`macos-node`、`macos-swift` 和 `android`。 +1. `preflight` 決定哪些執行路徑實際存在。`docs-scope` 與 `changed-scope` 邏輯是此工作內的步驟,不是獨立工作。 +2. `security-scm-fast`、`security-dependency-audit`、`security-fast`、`check`、`check-additional`、`check-docs` 與 `skills-python` 會快速失敗,不等待較重的 artifact 與平台矩陣工作。 +3. `build-artifacts` 會與快速 Linux 執行路徑重疊,因此下游消費者可以在共用 build 準備好後立即開始。 +4. 較重的平台與 runtime 執行路徑接著展開:`checks-fast-core`、`checks-fast-contracts-channels`、`checks-node-core-test`、`checks`、`checks-windows`、`macos-node`、`macos-swift` 與 `android`。 -當同一個 PR 或 `main` ref 上有較新的推送進來時,GitHub 可能會將被取代的作業標記為 `cancelled`。除非同一 ref 的最新執行也失敗,否則請將其視為 CI 雜訊。彙總分片檢查使用 `!cancelled() && always()`,因此它們仍會回報正常的分片失敗,但不會在整個工作流程已被取代後繼續排隊。自動 CI concurrency key 已版本化(`CI-v7-*`),因此 GitHub 端舊佇列群組中的僵屍項目無法無限期阻擋較新的 main 執行。手動完整套件執行使用 `CI-manual-v1-*`,且不會取消進行中的執行。 +當較新的 push 落在同一個 PR 或 `main` ref 上時,GitHub 可能會將被取代的工作標記為 `cancelled`。除非同一 ref 的最新執行也失敗,否則將其視為 CI 雜訊。彙總分片檢查使用 `!cancelled() && always()`,因此仍會回報一般分片失敗,但不會在整個 workflow 已被取代後繼續排隊。自動 CI concurrency key 已版本化(`CI-v7-*`),因此 GitHub 端舊佇列群組中的 zombie 不會無限期封鎖較新的 main 執行。手動 full-suite 執行使用 `CI-manual-v1-*`,且不會取消進行中的執行。 ## 範圍與路由 -範圍邏輯位於 `scripts/ci-changed-scope.mjs`,並由 `src/scripts/ci-changed-scope.test.ts` 中的單元測試涵蓋。手動派發會略過 changed-scope 偵測,並讓 preflight manifest 表現得像每個有範圍的區域都已變更。 +範圍邏輯位於 `scripts/ci-changed-scope.mjs`,並由 `src/scripts/ci-changed-scope.test.ts` 中的 unit tests 涵蓋。手動 dispatch 會略過 changed-scope detection,並讓 preflight manifest 表現得像每個 scoped area 都已變更。 -- **CI 工作流程編輯** 會驗證 Node CI 圖形加上工作流程 linting,但本身不會強制執行 Windows、Android 或 macOS 原生建置;這些平台路徑仍只限於平台原始碼變更。 -- **僅 CI 路由編輯、選定的便宜 core-test fixture 編輯,以及狹窄的 Plugin contract helper/test-routing 編輯** 會使用快速的 Node-only manifest 路徑:`preflight`、security,以及單一 `checks-fast-core` 工作。當變更僅限於快速工作直接涵蓋的路由或 helper 表面時,該路徑會略過 build artifacts、Node 22 相容性、channel contracts、完整 core 分片、bundled-plugin 分片,以及額外的 guard 矩陣。 -- **Windows Node 檢查** 會限定於 Windows 專用 process/path wrapper、npm/pnpm/UI runner helper、package manager config,以及執行該路徑的 CI 工作流程表面;不相關的原始碼、Plugin、install-smoke 和僅測試變更會留在 Linux Node 路徑上。 +- **CI workflow 編輯**會驗證 Node CI 圖與 workflow linting,但本身不會強制 Windows、Android 或 macOS native builds;那些平台執行路徑仍限定於平台原始碼變更。 +- **CI routing-only 編輯、選定的低成本 core-test fixture 編輯,以及狹窄的 plugin contract helper/test-routing 編輯**會使用快速 Node-only manifest 路徑:`preflight`、security 與單一 `checks-fast-core` task。當變更僅限於 fast task 直接執行的 routing 或 helper surfaces 時,該路徑會略過 build artifacts、Node 22 compatibility、channel contracts、full core shards、bundled-plugin shards 與 additional guard matrices。 +- **Windows Node checks**限定於 Windows 特定的 process/path wrappers、npm/pnpm/UI runner helpers、package manager config,以及執行該執行路徑的 CI workflow surfaces;不相關的 source、Plugin、install-smoke 與 test-only 變更會留在 Linux Node 執行路徑。 -最慢的 Node 測試家族會被拆分或平衡,讓每個作業維持小型而不過度保留 runner:channel contracts 以三個加權分片執行,小型 core unit 路徑會配對,auto-reply 以四個平衡 worker 執行(reply 子樹拆成 agent-runner、dispatch 與 commands/state-routing 分片),而 agentic gateway/plugin config 會分散到既有的 source-only agentic Node 作業中,不需等待已建置 artifact。廣泛的瀏覽器、QA、媒體與雜項 Plugin 測試會使用各自專用的 Vitest config,而不是共用的 Plugin catch-all。Include-pattern 分片會使用 CI 分片名稱記錄計時項目,因此 `.artifacts/vitest-shard-timings.json` 可以區分整個 config 與已過濾分片。`check-additional` 會將 package-boundary compile/canary 工作放在一起,並將 runtime topology architecture 與 gateway watch 覆蓋範圍分開;boundary guard 分片會在單一作業內並行執行其小型獨立防護。Gateway watch、channel 測試與 core support-boundary 分片會在 `dist/` 和 `dist-runtime/` 已建置後,於 `build-artifacts` 內並行執行。 +最慢的 Node test families 會被拆分或平衡,讓每個工作維持小型且不過度保留 runners:channel contracts 以三個加權分片執行,小型 core unit 執行路徑會配對,auto-reply 以四個平衡 workers 執行(reply subtree 拆成 agent-runner、dispatch 與 commands/state-routing 分片),而 agentic gateway/plugin configs 會分散在既有的 source-only agentic Node jobs 中,而不是等待 built artifacts。廣泛的 browser、QA、media 與 miscellaneous plugin tests 使用各自專用的 Vitest configs,而不是共用 plugin catch-all。Include-pattern shards 會使用 CI shard name 記錄 timing entries,因此 `.artifacts/vitest-shard-timings.json` 可以區分完整 config 與 filtered shard。`check-additional` 會將 package-boundary compile/canary 工作放在一起,並將 runtime topology architecture 與 gateway watch coverage 分開;boundary guard shard 會在單一工作內並行執行其小型獨立 guards。Gateway watch、channel tests 與 core support-boundary shard 會在 `dist/` 與 `dist-runtime/` 已建置後,於 `build-artifacts` 內並行執行。 -Android CI 會同時執行 `testPlayDebugUnitTest` 和 `testThirdPartyDebugUnitTest`,接著建置 Play debug APK。third-party flavor 沒有獨立 source set 或 manifest;其單元測試路徑仍會使用 SMS/call-log BuildConfig 旗標編譯該 flavor,同時避免在每次 Android 相關推送上重複執行 debug APK packaging 作業。 +Android CI 會執行 `testPlayDebugUnitTest` 與 `testThirdPartyDebugUnitTest`,然後建置 Play debug APK。third-party flavor 沒有獨立的 source set 或 manifest;其 unit-test 執行路徑仍會使用 SMS/call-log BuildConfig flags 編譯該 flavor,同時避免在每個 Android 相關 push 上重複 debug APK packaging job。 -`check-dependencies` 分片會執行 `pnpm deadcode:dependencies`(一個針對正式環境的 Knip dependency-only pass,固定使用最新 Knip 版本,且針對 `dlx` 安裝停用 pnpm 的最低發行年齡限制)以及 `pnpm deadcode:unused-files`,後者會將 Knip 的正式環境未使用檔案發現與 `scripts/deadcode-unused-files.allowlist.mjs` 比較。當 PR 新增未經審查的未使用檔案,或留下過時的 allowlist 項目時,未使用檔案防護會失敗,同時保留 Knip 無法靜態解析的刻意動態 Plugin、generated、build、live-test 與 package bridge 表面。 +`check-dependencies` shard 會執行 `pnpm deadcode:dependencies`(production Knip 僅相依套件檢查,釘選到最新 Knip 版本,且為 `dlx` 安裝停用 pnpm 的 minimum release age)與 `pnpm deadcode:unused-files`,後者會將 Knip 的 production unused-file findings 與 `scripts/deadcode-unused-files.allowlist.mjs` 比對。當 PR 新增未經審查的 unused file,或留下過期的 allowlist entry 時,unused-file guard 會失敗,同時保留 Knip 無法靜態解析的 intentional dynamic plugin、generated、build、live-test 與 package bridge surfaces。 -## 手動派發 +## 手動 Dispatch -手動 CI 派發會執行與一般 CI 相同的作業圖形,但會強制開啟每個非 Android 範圍路徑:Linux Node 分片、bundled-plugin 分片、channel contracts、Node 22 相容性、`check`、`check-additional`、build smoke、文件檢查、Python skills、Windows、macOS 與 Control UI i18n。獨立的手動 CI 派發只有在 `include_android=true` 時才會執行 Android;完整發行 umbrella 會透過傳遞 `include_android=true` 啟用 Android。Plugin 預發行靜態檢查、僅限發行的 `agentic-plugins` 分片、完整 extension 批次掃描,以及 Plugin 預發行 Docker 路徑皆排除於 CI 之外。Docker 預發行套件只會在 `Full Release Validation` 以啟用 release-validation gate 的方式派發獨立 `Plugin Prerelease` 工作流程時執行。 +手動 CI dispatch 會執行與一般 CI 相同的 job graph,但強制開啟每個非 Android scoped lane:Linux Node shards、bundled-plugin shards、channel contracts、Node 22 compatibility、`check`、`check-additional`、build smoke、docs checks、Python skills、Windows、macOS 與 Control UI i18n。獨立手動 CI dispatch 只有在 `include_android=true` 時才會執行 Android;完整發行 umbrella 會透過傳入 `include_android=true` 啟用 Android。Plugin prerelease static checks、僅限發行的 `agentic-plugins` shard、完整 Plugin batch sweep,以及 plugin prerelease Docker lanes 都排除於 CI 之外。Docker prerelease suite 只會在 `Full Release Validation` 以啟用 release-validation gate 的方式 dispatch 獨立的 `Plugin Prerelease` workflow 時執行。 -手動執行會使用唯一的 concurrency group,因此發行候選版本的完整套件不會被同一 ref 上的另一個推送或 PR 執行取消。選用的 `target_ref` 輸入可讓受信任的呼叫端針對 branch、tag 或完整 commit SHA 執行該圖形,同時使用所選派發 ref 的工作流程檔案。 +手動執行使用唯一的 concurrency group,因此 release-candidate full suite 不會被同一 ref 上的另一個 push 或 PR run 取消。選用的 `target_ref` input 讓受信任的 caller 可以針對 branch、tag 或完整 commit SHA 執行該圖,同時使用所選 dispatch ref 的 workflow file。 ```bash gh workflow run ci.yml --ref release/YYYY.M.D @@ -81,15 +81,15 @@ gh workflow run full-release-validation.yml --ref main -f ref= | 執行器 | 作業 | | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `ubuntu-24.04` | `preflight`、快速安全性作業與彙總(`security-scm-fast`、`security-dependency-audit`、`security-fast`)、快速協定/合約/內建檢查、分片的頻道合約檢查、除 lint 外的 `check` 分片、`check-additional` 分片與彙總、Node 測試彙總驗證器、文件檢查、Python skills、workflow-sanity、labeler、auto-response;install-smoke preflight 也使用 GitHub 託管的 Ubuntu,讓 Blacksmith 矩陣可以更早排入佇列 | -| `blacksmith-4vcpu-ubuntu-2404` | `CodeQL Critical Quality`、較低負載的 extension 分片、`checks-fast-core`、`checks-node-compat-node22`、`check-prod-types` 和 `check-test-types` | -| `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`、build-smoke、Linux Node 測試分片、內建 Plugin 測試分片、`android` | -| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`(對 CPU 夠敏感,8 vCPU 的成本高於節省的時間);install-smoke Docker 建置(32-vCPU 佇列時間的成本高於節省的時間) | +| `ubuntu-24.04` | `preflight`、快速安全性作業與彙總(`security-scm-fast`、`security-dependency-audit`、`security-fast`)、快速協定/合約/ bundled 檢查、分片的頻道合約檢查、除 lint 以外的 `check` 分片、`check-additional` 分片與彙總、Node 測試彙總驗證器、文件檢查、Python Skills、workflow-sanity、labeler、auto-response;install-smoke preflight 也使用 GitHub 託管的 Ubuntu,讓 Blacksmith 矩陣能更早排入佇列 | +| `blacksmith-4vcpu-ubuntu-2404` | `CodeQL Critical Quality`、較低權重的 Plugin 分片、`checks-fast-core`、`checks-node-compat-node22`、`check-prod-types` 和 `check-test-types` | +| `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`、build-smoke、Linux Node 測試分片、bundled Plugin 測試分片、`android` | +| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`(對 CPU 夠敏感,8 vCPU 的成本高過省下的時間);install-smoke Docker 建置(32 vCPU 的佇列時間成本高過省下的時間) | | `blacksmith-16vcpu-windows-2025` | `checks-windows` | | `blacksmith-6vcpu-macos-latest` | `openclaw/openclaw` 上的 `macos-node`;fork 會退回 `macos-latest` | | `blacksmith-12vcpu-macos-latest` | `openclaw/openclaw` 上的 `macos-swift`;fork 會退回 `macos-latest` | -## 本機對應項目 +## 本機等效命令 ```bash pnpm changed:lanes # inspect the local changed-lane classifier for origin/main...HEAD @@ -117,23 +117,23 @@ pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifac ## 完整發行驗證 -`Full Release Validation` 是「在發行前執行所有項目」的手動總括工作流程。它接受分支、標籤或完整 commit SHA,使用該目標派送手動 `CI` 工作流程、派送 `Plugin Prerelease` 以進行僅限發行的 Plugin/套件/靜態/Docker 證明,並派送 `OpenClaw Release Checks` 以進行安裝 smoke、套件驗收、Docker 發行路徑套件、即時/E2E、OpenWebUI、QA Lab parity、Matrix 和 Telegram 通道。提供已發布套件規格時,它也可以執行發布後的 `NPM Telegram Beta E2E` 工作流程。 +`Full Release Validation` 是「發行前執行所有內容」的手動總括工作流程。它接受分支、標籤或完整 commit SHA,使用該目標派送手動 `CI` 工作流程,為僅發行用的 Plugin/套件/靜態/Docker 證明派送 `Plugin Prerelease`,並為安裝煙霧測試、套件接受度、Docker 發行路徑套件、live/E2E、OpenWebUI、QA Lab parity、Matrix 和 Telegram 通道派送 `OpenClaw Release Checks`。提供已發布套件規格時,它也可以執行發布後的 `NPM Telegram Beta E2E` 工作流程。 -`release_profile` 控制傳入發行檢查的即時/供應商廣度: +`release_profile` 控制傳入發行檢查的 live/供應商涵蓋範圍: - `minimum` 保留最快的 OpenAI/核心發行關鍵通道。 -- `stable` 加入穩定的供應商/後端集合。 -- `full` 執行廣泛的建議供應商/媒體矩陣。 +- `stable` 加入穩定供應商/後端集合。 +- `full` 執行廣泛的諮詢供應商/媒體矩陣。 -總括工作流程會記錄已派送的子執行 ID,而最終的 `Verify full validation` 作業會重新檢查目前子執行結論,並為每個子執行附加最慢作業表。如果子工作流程重新執行後變為綠燈,只需重新執行父驗證器作業,即可重新整理總括結果與時間摘要。 +總括流程會記錄已派送的子執行 ID,而最終的 `Verify full validation` 作業會重新檢查目前子執行結論,並為每個子執行附加最慢作業表。如果子工作流程重新執行後轉為綠燈,只需重新執行父驗證器作業,即可重新整理總括結果與時間摘要。 -為了復原,`Full Release Validation` 和 `OpenClaw Release Checks` 都接受 `rerun_group`。對發行候選版本使用 `all`,只對一般完整 CI 子項使用 `ci`,對每個發行子項使用 `release-checks`,或在總括工作流程上使用較窄的群組:`install-smoke`、`cross-os`、`live-e2e`、`package`、`qa`、`qa-parity`、`qa-live` 或 `npm-telegram`。這會讓失敗的發行盒在焦點修復後,重新執行範圍維持受限。 +若要復原,`Full Release Validation` 和 `OpenClaw Release Checks` 都接受 `rerun_group`。發行候選版本使用 `all`,僅一般完整 CI 子項使用 `ci`,每個發行子項使用 `release-checks`,或在總括流程上使用較窄的群組:`install-smoke`、`cross-os`、`live-e2e`、`package`、`qa`、`qa-parity`、`qa-live` 或 `npm-telegram`。這會讓失敗的發行盒在針對性修復後,重新執行範圍保持有界。 -`OpenClaw Release Checks` 使用受信任的工作流程 ref,將所選 ref 解析一次成 `release-package-under-test` tarball,然後將該 artifact 傳給即時/E2E 發行路徑 Docker 工作流程與套件驗收分片。這會讓套件位元組在各個發行盒之間保持一致,並避免在多個子作業中重新打包同一個候選版本。 +`OpenClaw Release Checks` 使用受信任的工作流程 ref,將所選 ref 解析一次為 `release-package-under-test` tarball,然後將該成品傳給 live/E2E 發行路徑 Docker 工作流程和套件接受度分片。這能讓套件位元組在各發行盒之間保持一致,並避免在多個子作業中重新打包同一個候選版本。 -## 即時與 E2E 分片 +## Live 和 E2E 分片 -發行即時/E2E 子項保留廣泛的原生 `pnpm test:live` 覆蓋範圍,但它會透過 `scripts/test-live-shard.mjs` 以具名分片執行,而不是單一序列作業: +發行 live/E2E 子項保留廣泛的原生 `pnpm test:live` 涵蓋範圍,但它會透過 `scripts/test-live-shard.mjs` 以具名分片執行,而不是單一序列作業: - `native-live-src-agents` - `native-live-src-gateway-core` @@ -145,57 +145,57 @@ pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifac - `native-live-extensions-openai` - `native-live-extensions-o-z-other` - `native-live-extensions-xai` -- 分割的媒體音訊/影片分片,以及依供應商篩選的音樂分片 +- 拆分的媒體音訊/視訊分片,以及依供應商篩選的音樂分片 -這會維持相同的檔案覆蓋範圍,同時讓緩慢的即時供應商失敗更容易重新執行與診斷。彙總的 `native-live-extensions-o-z`、`native-live-extensions-media` 和 `native-live-extensions-media-music` 分片名稱仍可用於手動一次性重新執行。 +這會保留相同的檔案涵蓋範圍,同時讓緩慢的 live 供應商失敗更容易重新執行與診斷。彙總的 `native-live-extensions-o-z`、`native-live-extensions-media` 和 `native-live-extensions-media-music` 分片名稱仍可用於手動一次性重新執行。 -原生即時媒體分片在 `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04` 中執行,該映像由 `Live Media Runner Image` 工作流程建置。該映像預先安裝 `ffmpeg` 和 `ffprobe`;媒體作業只會在設定前驗證二進位檔。請將 Docker 支援的即時套件保留在一般 Blacksmith 執行器上,因為容器作業不適合啟動巢狀 Docker 測試。 +原生 live 媒體分片在 `Live Media Runner Image` 工作流程建置的 `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04` 中執行。該映像已預先安裝 `ffmpeg` 和 `ffprobe`;媒體作業只會在設定前驗證二進位檔。請將 Docker 支援的 live 套件放在一般 Blacksmith 執行器上,container 作業不是啟動巢狀 Docker 測試的合適位置。 -Docker 支援的即時模型/後端分片會針對每個選取的 commit 使用個別共享的 `ghcr.io/openclaw/openclaw-live-test:` 映像。即時發行工作流程會建置並推送該映像一次,然後 Docker 即時模型、Gateway、CLI 後端、ACP bind 和 Codex harness 分片會使用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 執行。如果這些分片各自重新建置完整來源 Docker 目標,表示發行執行設定錯誤,並會在重複映像建置上浪費實際時間。 +Docker 支援的 live 模型/後端分片會對每個所選 commit 使用個別共用的 `ghcr.io/openclaw/openclaw-live-test:` 映像。live 發行工作流程會建置並推送該映像一次,接著 Docker live 模型、Gateway、CLI 後端、ACP bind 和 Codex harness 分片會以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 執行。如果這些分片各自重新建置完整原始碼 Docker 目標,表示發行執行設定錯誤,會在重複映像建置上浪費牆鐘時間。 -## 套件驗收 +## 套件接受度 -當問題是「這個可安裝的 OpenClaw 套件是否能像產品一樣運作?」時,請使用 `Package Acceptance`。它與一般 CI 不同:一般 CI 會驗證來源樹,而套件驗收會透過使用者在安裝或更新後執行的相同 Docker E2E harness,驗證單一 tarball。 +當問題是「這個可安裝的 OpenClaw 套件是否能作為產品運作?」時,請使用 `Package Acceptance`。它不同於一般 CI:一般 CI 驗證原始碼樹,而套件接受度會透過使用者在安裝或更新後實際執行的同一套 Docker E2E harness 來驗證單一 tarball。 ### 作業 -1. `resolve_package` 會 checkout `workflow_ref`、解析一個套件候選版本、寫入 `.artifacts/docker-e2e-package/openclaw-current.tgz`、寫入 `.artifacts/docker-e2e-package/package-candidate.json`、將兩者作為 `package-under-test` artifact 上傳,並在 GitHub 步驟摘要中列印來源、工作流程 ref、套件 ref、版本、SHA-256 和設定檔。 -2. `docker_acceptance` 會以 `ref=workflow_ref` 和 `package_artifact_name=package-under-test` 呼叫 `openclaw-live-and-e2e-checks-reusable.yml`。可重用工作流程會下載該 artifact、驗證 tarball 清單、在需要時準備 package-digest Docker 映像,並針對該套件執行所選的 Docker 通道,而不是打包工作流程 checkout。當設定檔選取多個目標 `docker_lanes` 時,可重用工作流程會準備套件與共享映像一次,然後將這些通道展開為平行的目標 Docker 作業,且各自使用唯一 artifact。 -3. `package_telegram` 可選擇性呼叫 `NPM Telegram Beta E2E`。當 `telegram_mode` 不是 `none` 時會執行;若 Package Acceptance 已解析套件,則安裝相同的 `package-under-test` artifact;獨立 Telegram 派送仍可安裝已發布的 npm 規格。 -4. 如果套件解析、Docker 驗收或可選的 Telegram 通道失敗,`summary` 會讓工作流程失敗。 +1. `resolve_package` 會 checkout `workflow_ref`、解析一個套件候選、寫入 `.artifacts/docker-e2e-package/openclaw-current.tgz`、寫入 `.artifacts/docker-e2e-package/package-candidate.json`、將兩者作為 `package-under-test` 成品上傳,並在 GitHub 步驟摘要中列印來源、工作流程 ref、套件 ref、版本、SHA-256 和 profile。 +2. `docker_acceptance` 會以 `ref=workflow_ref` 和 `package_artifact_name=package-under-test` 呼叫 `openclaw-live-and-e2e-checks-reusable.yml`。可重用工作流程會下載該成品、驗證 tarball 清單、在需要時準備 package-digest Docker 映像,並針對該套件而不是打包工作流程 checkout 執行所選 Docker 通道。當 profile 選取多個目標 `docker_lanes` 時,可重用工作流程會準備套件與共用映像一次,然後將這些通道展開為具有唯一成品的平行目標 Docker 作業。 +3. `package_telegram` 會選擇性呼叫 `NPM Telegram Beta E2E`。當 `telegram_mode` 不是 `none` 時它會執行,並在 Package Acceptance 已解析套件時安裝相同的 `package-under-test` 成品;獨立 Telegram 派送仍可安裝已發布的 npm 規格。 +4. 如果套件解析、Docker 接受度或選用的 Telegram 通道失敗,`summary` 會使工作流程失敗。 ### 候選來源 -- `source=npm` 只接受 `openclaw@beta`、`openclaw@latest`,或精確的 OpenClaw 發行版本,例如 `openclaw@2026.4.27-beta.2`。這用於已發布 beta/穩定版的接受測試。 -- `source=ref` 會封裝受信任的 `package_ref` 分支、標籤或完整 commit SHA。解析器會擷取 OpenClaw 分支/標籤,驗證所選 commit 可從儲存庫分支歷史或發行標籤抵達,在分離的 worktree 中安裝相依項目,並使用 `scripts/package-openclaw-for-docker.mjs` 封裝。 +- `source=npm` 只接受 `openclaw@beta`、`openclaw@latest`,或精確的 OpenClaw 發行版本,例如 `openclaw@2026.4.27-beta.2`。請將此用於已發布 beta/穩定版的驗收。 +- `source=ref` 會封裝受信任的 `package_ref` 分支、標籤或完整 commit SHA。解析器會擷取 OpenClaw 分支/標籤、驗證所選 commit 可從儲存庫分支歷史或發行標籤到達、在分離的 worktree 中安裝相依套件,並使用 `scripts/package-openclaw-for-docker.mjs` 封裝。 - `source=url` 會下載 HTTPS `.tgz`;必須提供 `package_sha256`。 -- `source=artifact` 會從 `artifact_run_id` 與 `artifact_name` 下載一個 `.tgz`;`package_sha256` 為選用,但外部分享的 artifact 應提供此值。 +- `source=artifact` 會從 `artifact_run_id` 和 `artifact_name` 下載一個 `.tgz`;`package_sha256` 是選用,但外部共享的 artifact 應提供。 -請將 `workflow_ref` 與 `package_ref` 分開。`workflow_ref` 是執行測試的受信任 workflow/harness 程式碼。`package_ref` 是在 `source=ref` 時會被封裝的來源 commit。這讓目前的測試 harness 可以驗證較舊的受信任來源 commit,而不必執行舊的 workflow 邏輯。 +請將 `workflow_ref` 和 `package_ref` 分開。`workflow_ref` 是執行測試的受信任 workflow/harness 程式碼。`package_ref` 是在 `source=ref` 時會被封裝的來源 commit。這讓目前的測試 harness 可以驗證較舊的受信任來源 commit,而不必執行舊的 workflow 邏輯。 ### 套件組合設定檔 -- `smoke` — `npm-onboard-channel-agent`、`gateway-network`、`config-reload` -- `package` — `npm-onboard-channel-agent`、`doctor-switch`、`update-channel-switch`、`bundled-channel-deps-compat`、`plugins-offline`、`plugin-update` -- `product` — `package` 加上 `mcp-channels`、`cron-mcp-cleanup`、`openai-web-search-minimal`、`openwebui` +- `smoke` — `npm-onboard-channel-agent`, `gateway-network`, `config-reload` +- `package` — `npm-onboard-channel-agent`, `doctor-switch`, `update-channel-switch`, `upgrade-survivor`, `bundled-channel-deps-compat`, `plugins-offline`, `plugin-update` +- `product` — `package` 加上 `mcp-channels`, `cron-mcp-cleanup`, `openai-web-search-minimal`, `openwebui` - `full` — 含 OpenWebUI 的完整 Docker 發行路徑區塊 - `custom` — 精確的 `docker_lanes`;當 `suite_profile=custom` 時必填 -`package` 設定檔使用離線 Plugin 覆蓋範圍,因此已發布套件驗證不會受即時 ClawHub 可用性阻擋。選用的 Telegram lane 會在 `NPM Telegram Beta E2E` 中重用 `package-under-test` artifact,並保留已發布 npm 規格路徑供獨立派送使用。 +`package` 設定檔使用離線 Plugin 覆蓋範圍,因此已發布套件驗證不會受限於即時 ClawHub 可用性。選用的 Telegram lane 會在 `NPM Telegram Beta E2E` 中重用 `package-under-test` artifact,並保留已發布 npm 規格路徑供獨立 dispatch 使用。 -發行檢查會以 `source=ref`、`package_ref=`、`workflow_ref=`、`suite_profile=custom`、`docker_lanes='bundled-channel-deps-compat plugins-offline'` 與 `telegram_mode=mock-openai` 呼叫 Package Acceptance。發行路徑 Docker 區塊涵蓋重疊的 package/update/plugin lane;Package Acceptance 則針對相同解析出的套件 tarball,保留 artifact 原生的 bundled-channel 相容性、離線 Plugin 與 Telegram 證明。跨 OS 發行檢查仍涵蓋 OS 特定的 onboarding、installer 與平台行為;package/update 產品驗證應從 Package Acceptance 開始。Windows 封裝與 installer fresh lane 也會驗證已安裝套件可以從原始絕對 Windows 路徑匯入 browser-control override。OpenAI 跨 OS agent-turn smoke 在已設定時預設使用 `OPENCLAW_CROSS_OS_OPENAI_MODEL`,否則使用 `openai/gpt-5.4-mini`,因此安裝與 Gateway 證明可保持快速且確定性。 +發行檢查會以 `source=ref`、`package_ref=`、`workflow_ref=`、`suite_profile=custom`、`docker_lanes='bundled-channel-deps-compat plugins-offline'` 和 `telegram_mode=mock-openai` 呼叫 Package Acceptance。發行路徑 Docker 區塊涵蓋重疊的 package/update/Plugin lane;Package Acceptance 會針對同一個已解析套件 tarball 保留 artifact-native 的內建 channel 相容性、離線 Plugin 和 Telegram 證明。跨 OS 發行檢查仍涵蓋 OS 專屬的 onboarding、安裝程式和平台行為;package/update 產品驗證應從 Package Acceptance 開始。Windows 封裝與安裝程式全新 lane 也會驗證已安裝套件可從原始絕對 Windows 路徑匯入 browser-control override。OpenAI 跨 OS agent-turn smoke 會在已設定時預設使用 `OPENCLAW_CROSS_OS_OPENAI_MODEL`,否則使用 `openai/gpt-5.4-mini`,因此安裝與 Gateway 證明會保持快速且具決定性。 ### 舊版相容性期間 -Package Acceptance 對已發布套件設有有限的舊版相容性期間。到 `2026.4.25` 為止的套件,包括 `2026.4.25-beta.*`,可以使用相容性路徑: +Package Acceptance 對已發布套件有有限的舊版相容性期間。到 `2026.4.25` 為止的套件,包括 `2026.4.25-beta.*`,可以使用相容性路徑: - `dist/postinstall-inventory.json` 中已知的私有 QA 項目可以指向 tarball 省略的檔案; -- 當套件未公開該 flag 時,`doctor-switch` 可以略過 `gateway install --wrapper` 持久化子案例; -- `update-channel-switch` 可以從 tarball 衍生的假 git fixture 中修剪缺少的 `pnpm.patchedDependencies`,並可記錄缺少持久化的 `update.channel`; -- Plugin smoke 可以讀取舊版 install-record 位置,或接受缺少 marketplace install-record 持久化; -- `plugin-update` 可以允許設定中繼資料遷移,同時仍要求 install record 與 no-reinstall 行為保持不變。 +- 當套件未公開該旗標時,`doctor-switch` 可以略過 `gateway install --wrapper` 持久化子案例; +- `update-channel-switch` 可以從 tarball 衍生的假 git fixture 中剪除缺失的 `pnpm.patchedDependencies`,並可記錄缺失的持久化 `update.channel`; +- Plugin smoke 可以讀取舊版安裝記錄位置,或接受缺失的 marketplace 安裝記錄持久化; +- `plugin-update` 可以允許 config metadata 遷移,但仍要求安裝記錄和無重新安裝行為保持不變。 -已發布的 `2026.4.26` 套件也可以針對已出貨的本機建置中繼資料戳記檔提出警告。後續套件必須符合現代合約;相同條件會失敗,而不是警告或略過。 +已發布的 `2026.4.26` 套件也可以對已出貨的本機 build metadata stamp 檔案發出警告。後續套件必須滿足現代合約;相同條件會失敗,而不是警告或略過。 ### 範例 @@ -238,152 +238,152 @@ gh workflow run package-acceptance.yml \ -f docker_lanes='install-e2e plugin-update' ``` -偵錯失敗的 package acceptance 執行時,請從 `resolve_package` 摘要開始,確認套件來源、版本與 SHA-256。接著檢查 `docker_acceptance` 子執行與其 Docker artifact:`.artifacts/docker-tests/**/summary.json`、`failures.json`、lane 記錄、階段耗時與重新執行命令。請優先重新執行失敗的套件設定檔或精確 Docker lane,而不是重新執行完整發行驗證。 +偵錯失敗的 package acceptance 執行時,請從 `resolve_package` 摘要開始,確認套件來源、版本和 SHA-256。接著檢查 `docker_acceptance` 子執行及其 Docker artifacts:`.artifacts/docker-tests/**/summary.json`、`failures.json`、lane 記錄、階段計時,以及重新執行命令。請優先重新執行失敗的 package 設定檔或精確的 Docker lanes,而不是重新執行完整發行驗證。 ## 安裝 smoke -獨立的 `Install Smoke` workflow 會透過自己的 `preflight` job 重用相同的範圍腳本。它將 smoke 覆蓋範圍拆分為 `run_fast_install_smoke` 與 `run_full_install_smoke`。 +獨立的 `Install Smoke` workflow 會透過自己的 `preflight` job 重用相同的範圍腳本。它會將 smoke 覆蓋範圍拆分為 `run_fast_install_smoke` 和 `run_full_install_smoke`。 -- **快速路徑** 會在 pull request 觸及 Docker/package 表面、bundled Plugin package/manifest 變更,或 Docker smoke job 會演練的核心 Plugin/channel/gateway/Plugin SDK 表面時執行。僅來源的 bundled Plugin 變更、僅測試編輯與僅文件編輯不會保留 Docker worker。快速路徑會建置一次根 Dockerfile 映像、檢查 CLI、執行 agents delete shared-workspace CLI smoke、執行 container gateway-network e2e、驗證 bundled extension build arg,並在 240 秒彙總命令逾時內執行有界限的 bundled-plugin Docker 設定檔(每個情境的 Docker 執行會分別設上限)。 -- **完整路徑** 保留 QR package install 與 installer Docker/update 覆蓋範圍,用於夜間排程執行、手動派送、workflow-call 發行檢查,以及真正觸及 installer/package/Docker 表面的 pull request。在完整模式中,install-smoke 會準備或重用一個 target-SHA GHCR 根 Dockerfile smoke 映像,然後將 QR package install、根 Dockerfile/gateway smoke、installer/update smoke,以及快速 bundled-plugin Docker E2E 作為獨立 job 執行,因此 installer 工作不必等在根映像 smoke 後面。 +- **快速路徑**會針對觸及 Docker/package 表面、內建 Plugin 套件/manifest 變更,或 Docker smoke jobs 會執行的核心 Plugin/channel/Gateway/Plugin SDK 表面的 pull request 執行。僅來源的內建 Plugin 變更、僅測試編輯和僅文件編輯不會保留 Docker worker。快速路徑會建置 root Dockerfile image 一次、檢查 CLI、執行 agents delete shared-workspace CLI smoke、執行容器 gateway-network e2e、驗證內建 extension build arg,並在 240 秒彙總命令逾時內執行受限的內建 Plugin Docker 設定檔(每個情境的 Docker 執行另有上限)。 +- **完整路徑**會保留 QR 套件安裝與安裝程式 Docker/update 覆蓋範圍,用於夜間排程執行、手動 dispatch、workflow-call 發行檢查,以及真正觸及安裝程式/package/Docker 表面的 pull request。在完整模式中,install-smoke 會準備或重用一個目標 SHA 的 GHCR root Dockerfile smoke image,然後將 QR 套件安裝、root Dockerfile/Gateway smoke、安裝程式/update smoke,以及快速內建 Plugin Docker E2E 作為獨立 job 執行,讓安裝程式工作不必等待 root image smoke。 -`main` 推送(包含 merge commit)不會強制使用完整路徑;當變更範圍邏輯在 push 上要求完整覆蓋時,workflow 會保留快速 Docker smoke,並將完整 install smoke 留給夜間或發行驗證。 +`main` push(包括 merge commit)不會強制完整路徑;當變更範圍邏輯會在 push 上要求完整覆蓋範圍時,workflow 會保留快速 Docker smoke,並將完整 install smoke 留給夜間或發行驗證。 -較慢的 Bun 全域安裝 image-provider smoke 由 `run_bun_global_install_smoke` 另行控管。它會在夜間排程與發行檢查 workflow 中執行,手動 `Install Smoke` 派送也可以選擇加入,但 pull request 與 `main` 推送不會執行。QR 與 installer Docker 測試保留各自聚焦於安裝的 Dockerfile。 +慢速的 Bun 全域安裝 image-provider smoke 由 `run_bun_global_install_smoke` 另行控管。它會在夜間排程和發行檢查 workflow 中執行,手動 `Install Smoke` dispatch 可以選擇加入,但 pull request 和 `main` push 不會。QR 和安裝程式 Docker 測試保留各自專注於安裝的 Dockerfile。 ## 本機 Docker E2E -`pnpm test:docker:all` 會預先建置一個共用 live-test 映像,將 OpenClaw 封裝一次為 npm tarball,並建置兩個共用 `scripts/e2e/Dockerfile` 映像: +`pnpm test:docker:all` 會預先建置一個共享 live-test image、將 OpenClaw 封裝一次為 npm tarball,並建置兩個共享 `scripts/e2e/Dockerfile` images: -- 用於 installer/update/plugin-dependency lane 的裸 Node/Git runner; -- 將相同 tarball 安裝到 `/app` 的功能性映像,用於一般功能 lane。 +- 用於安裝程式/update/Plugin 相依性 lane 的裸 Node/Git runner; +- 將相同 tarball 安裝到 `/app` 的功能 image,用於一般功能 lane。 -Docker lane 定義位於 `scripts/lib/docker-e2e-scenarios.mjs`,規劃器邏輯位於 `scripts/lib/docker-e2e-plan.mjs`,runner 只會執行選定的計畫。排程器會使用 `OPENCLAW_DOCKER_E2E_BARE_IMAGE` 與 `OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE` 為每個 lane 選擇映像,然後以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 執行 lane。 +Docker lane 定義位於 `scripts/lib/docker-e2e-scenarios.mjs`,planner 邏輯位於 `scripts/lib/docker-e2e-plan.mjs`,runner 只會執行選取的 plan。排程器會使用 `OPENCLAW_DOCKER_E2E_BARE_IMAGE` 和 `OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE` 為每個 lane 選擇 image,然後以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 執行 lanes。 -### 可調整項目 +### 可調參數 -| 變數 | 預設值 | 目的 | +| 變數 | 預設值 | 用途 | | -------------------------------------- | ------- | --------------------------------------------------------------------------------------------- | -| `OPENCLAW_DOCKER_ALL_PARALLELISM` | 10 | 一般 lane 的主 pool slot 數量。 | -| `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM` | 10 | 對 provider 敏感的 tail-pool slot 數量。 | -| `OPENCLAW_DOCKER_ALL_LIVE_LIMIT` | 9 | 同時執行的 live lane 上限,避免 provider 節流。 | -| `OPENCLAW_DOCKER_ALL_NPM_LIMIT` | 10 | 同時執行的 npm install lane 上限。 | -| `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT` | 7 | 同時執行的多服務 lane 上限。 | -| `OPENCLAW_DOCKER_ALL_START_STAGGER_MS` | 2000 | lane 啟動之間的錯開時間,用於避免 Docker daemon 建立風暴;設為 `0` 表示不錯開。 | -| `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS` | 7200000 | 每個 lane 的備援逾時(120 分鐘);選定的 live/tail lane 使用更嚴格的上限。 | -| `OPENCLAW_DOCKER_ALL_DRY_RUN` | unset | `1` 會列印排程器計畫而不執行 lane。 | -| `OPENCLAW_DOCKER_ALL_LANES` | unset | 以逗號分隔的精確 lane 清單;略過清理 smoke,讓 agent 可以重現單一失敗 lane。 | +| `OPENCLAW_DOCKER_ALL_PARALLELISM` | 10 | 一般 lane 的 main-pool slot 數量。 | +| `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM` | 10 | provider-sensitive tail-pool slot 數量。 | +| `OPENCLAW_DOCKER_ALL_LIVE_LIMIT` | 9 | 並行 live lane 上限,避免 provider 進行節流。 | +| `OPENCLAW_DOCKER_ALL_NPM_LIMIT` | 10 | 並行 npm install lane 上限。 | +| `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT` | 7 | 並行 multi-service lane 上限。 | +| `OPENCLAW_DOCKER_ALL_START_STAGGER_MS` | 2000 | lane 啟動之間的 stagger,用來避免 Docker daemon create 風暴;設為 `0` 表示不 stagger。 | +| `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS` | 7200000 | 每個 lane 的 fallback 逾時(120 分鐘);選取的 live/tail lane 會使用更嚴格的上限。 | +| `OPENCLAW_DOCKER_ALL_DRY_RUN` | unset | `1` 會列印排程器 plan 而不執行 lanes。 | +| `OPENCLAW_DOCKER_ALL_LANES` | unset | 逗號分隔的精確 lane 清單;會略過 cleanup smoke,讓 agents 可以重現一個失敗的 lane。 | -比有效上限更重的 lane 仍可從空 pool 啟動,然後單獨執行直到釋放容量。本機彙總流程會預檢 Docker、移除過時的 OpenClaw E2E 容器、輸出作用中 lane 狀態、保存 lane 耗時供 longest-first 排序使用,且預設在第一次失敗後停止排程新的 pooled lane。 +比有效上限更重的 lane 仍可從空 pool 啟動,然後單獨執行直到釋放容量。本機彙總會 preflight Docker、移除過期的 OpenClaw E2E 容器、發出 active-lane 狀態、保存 lane 計時以便 longest-first 排序,並預設在第一次失敗後停止排程新的 pooled lane。 -### 可重用 live/E2E workflow +### 可重用的 live/E2E workflow -可重用 live/E2E workflow 會詢問 `scripts/test-docker-all.mjs --plan-json` 需要哪些套件、映像種類、live 映像、lane 與憑證覆蓋範圍。`scripts/docker-e2e.mjs` 接著會將該計畫轉換為 GitHub 輸出與摘要。它會透過 `scripts/package-openclaw-for-docker.mjs` 封裝 OpenClaw、下載目前執行的套件 artifact,或從 `package_artifact_run_id` 下載套件 artifact;驗證 tarball 清單;在計畫需要已安裝套件的 lane 時,透過 Blacksmith 的 Docker layer cache 建置並推送以套件 digest 標記的裸/功能性 GHCR Docker E2E 映像;並重用提供的 `docker_e2e_bare_image`/`docker_e2e_functional_image` 輸入或既有套件 digest 映像,而非重新建置。Docker 映像 pull 會以有界限的每次嘗試 180 秒逾時重試,因此卡住的 registry/cache stream 會快速重試,而不是耗盡大部分 CI 關鍵路徑。 +可重用的 live/E2E workflow 會詢問 `scripts/test-docker-all.mjs --plan-json` 需要哪個 package、image kind、live image、lane 和 credential 覆蓋範圍。`scripts/docker-e2e.mjs` 接著會將該 plan 轉換為 GitHub outputs 和摘要。它會透過 `scripts/package-openclaw-for-docker.mjs` 封裝 OpenClaw、下載目前執行的 package artifact,或從 `package_artifact_run_id` 下載 package artifact;驗證 tarball inventory;當 plan 需要已安裝 package 的 lane 時,透過 Blacksmith 的 Docker layer cache 建置並推送以 package digest 標記的 bare/functional GHCR Docker E2E images;並重用提供的 `docker_e2e_bare_image`/`docker_e2e_functional_image` inputs 或現有的 package-digest images,而不是重新建置。Docker image pull 會以每次嘗試 180 秒的受限逾時重新嘗試,讓卡住的 registry/cache stream 能快速重試,而不是消耗大部分 CI 關鍵路徑。 ### 發行路徑區塊 -發行 Docker 覆蓋範圍會以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 執行較小的分塊 job,因此每個區塊只會 pull 它需要的映像種類,並透過相同加權排程器執行多個 lane: +發行 Docker 覆蓋範圍會以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 執行較小的分塊 jobs,因此每個區塊只會 pull 它需要的 image kind,並透過相同的加權排程器執行多個 lanes: - `OPENCLAW_DOCKER_ALL_PROFILE=release-path` - `OPENCLAW_DOCKER_ALL_CHUNK=core | package-update-openai | package-update-anthropic | package-update-core | plugins-runtime-plugins | plugins-runtime-services | plugins-runtime-install-a..h | bundled-channels` -目前發行版 Docker 區塊是 `core`、`package-update-openai`、`package-update-anthropic`、`package-update-core`、`plugins-runtime-plugins`、`plugins-runtime-services`、`plugins-runtime-install-a` 到 `plugins-runtime-install-h`、`bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-discord`、`bundled-channels-update-b`,以及 `bundled-channels-contracts`。彙總的 `bundled-channels` 區塊仍可用於手動一次性重新執行,而 `plugins-runtime-core`、`plugins-runtime` 和 `plugins-integrations` 仍是彙總 Plugin/runtime 別名。`install-e2e` 通道別名仍是兩個供應商安裝器通道的彙總手動重新執行別名。`bundled-channels` 區塊會執行拆分後的 `bundled-channel-*` 和 `bundled-channel-update-*` 通道,而不是序列式全合一的 `bundled-channel-deps` 通道。 +目前發行版本的 Docker 分塊為 `core`、`package-update-openai`、`package-update-anthropic`、`package-update-core`、`plugins-runtime-plugins`、`plugins-runtime-services`、`plugins-runtime-install-a` 到 `plugins-runtime-install-h`、`bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-discord`、`bundled-channels-update-b`,以及 `bundled-channels-contracts`。彙總的 `bundled-channels` 分塊仍可用於手動一次性重新執行,而 `plugins-runtime-core`、`plugins-runtime` 和 `plugins-integrations` 仍保留為彙總的 Plugin/runtime 別名。`install-e2e` 通道別名仍是兩個供應商安裝程式通道的彙總手動重新執行別名。`bundled-channels` 分塊會執行拆分的 `bundled-channel-*` 和 `bundled-channel-update-*` 通道,而不是序列式全包的 `bundled-channel-deps` 通道。 -當完整發行路徑涵蓋範圍要求時,OpenWebUI 會併入 `plugins-runtime-services`,且只有在僅限 OpenWebUI 的分派中才保留獨立的 `openwebui` 區塊。Bundled-channel 更新通道會對暫時性 npm 網路失敗重試一次。 +當完整發行路徑涵蓋範圍要求時,OpenWebUI 會併入 `plugins-runtime-services`,並且只在僅限 OpenWebUI 的派送中保留獨立的 `openwebui` 分塊。內建通道更新通道會針對暫時性 npm 網路失敗重試一次。 -每個區塊都會上傳 `.artifacts/docker-tests/`,其中包含通道記錄、計時、`summary.json`、`failures.json`、階段計時、排程器計畫 JSON、慢速通道表格,以及每個通道的重新執行命令。工作流程 `docker_lanes` 輸入會針對已準備好的映像執行選取的通道,而不是區塊作業,這會將失敗通道的偵錯限制在單一目標 Docker 作業中,並為該次執行準備、下載或重用套件成品;如果選取的通道是即時 Docker 通道,目標作業會為該次重新執行在本機建置即時測試映像。產生的每通道 GitHub 重新執行命令會在這些值存在時包含 `package_artifact_run_id`、`package_artifact_name` 和已準備映像輸入,因此失敗通道可以重用失敗執行中的確切套件與映像。 +每個分塊都會上傳 `.artifacts/docker-tests/`,其中包含通道記錄、計時、`summary.json`、`failures.json`、階段計時、排程器計畫 JSON、慢速通道表格,以及每個通道的重新執行命令。工作流程的 `docker_lanes` 輸入會針對已準備的映像執行所選通道,而不是分塊作業,這會將失敗通道的偵錯限制在一個目標 Docker 作業內,並為該次執行準備、下載或重用套件成品;如果所選通道是即時 Docker 通道,目標作業會在本機建置即時測試映像以供該次重新執行使用。產生的每個通道 GitHub 重新執行命令會在這些值存在時包含 `package_artifact_run_id`、`package_artifact_name` 和已準備映像輸入,因此失敗的通道可以重用失敗執行中的確切套件與映像。 ```bash pnpm test:docker:rerun # download Docker artifacts and print combined/per-lane targeted rerun commands pnpm test:docker:timings # slow-lane and phase critical-path summaries ``` -排程的即時/E2E 工作流程會每日執行完整發行路徑 Docker 套件。 +排程的即時/E2E 工作流程會每日執行完整的發行路徑 Docker 套件。 ## Plugin 預發行 -`Plugin Prerelease` 是成本較高的產品/套件涵蓋範圍,因此它是由 `Full Release Validation` 或明確操作員分派的獨立工作流程。一般 pull request、`main` 推送,以及獨立的手動 CI 分派都不會啟用該套件。它會在八個 extension worker 之間平衡 bundled Plugin 測試;這些 extension shard 作業一次最多執行兩個 Plugin 設定群組,每個群組使用一個 Vitest worker,並使用較大的 Node heap,因此匯入量大的 Plugin 批次不會建立額外的 CI 作業。 +`Plugin Prerelease` 是成本較高的產品/套件涵蓋範圍,因此它是由 `Full Release Validation` 或明確的操作員派送的獨立工作流程。一般 pull request、`main` 推送,以及獨立的手動 CI 派送會保持該套件關閉。它會在八個擴充工作器之間平衡內建 Plugin 測試;這些擴充分片作業每次最多執行兩個 Plugin 設定群組,每個群組使用一個 Vitest 工作器和較大的 Node heap,讓匯入量大的 Plugin 批次不會建立額外的 CI 作業。 ## QA Lab -QA Lab 在主要智慧範圍工作流程之外有專用 CI 通道。 +QA Lab 在主要的智慧範圍工作流程之外有專用的 CI 通道。 -- `Parity gate` 工作流程會在符合的 PR 變更和手動分派時執行;它會建置私有 QA runtime,並比較 mock GPT-5.5 與 Opus 4.6 agentic packs。 -- `QA-Lab - All Lanes` 工作流程會每晚在 `main` 上和手動分派時執行;它會將 mock parity gate、即時 Matrix 通道,以及即時 Telegram 和 Discord 通道展開為平行作業。即時作業使用 `qa-live-shared` 環境,而 Telegram/Discord 使用 Convex leases。 +- `Parity gate` 工作流程會在相符的 PR 變更和手動派送時執行;它會建置私有 QA runtime,並比較模擬 GPT-5.5 和 Opus 4.6 agentic 套件。 +- `QA-Lab - All Lanes` 工作流程會在 `main` 上每晚執行,並在手動派送時執行;它會將模擬同位閘門、即時 Matrix 通道,以及即時 Telegram 和 Discord 通道扇出為平行作業。即時作業使用 `qa-live-shared` 環境,而 Telegram/Discord 使用 Convex 租約。 -發行檢查會使用確定性的 mock 供應商和 mock 限定模型(`mock-openai/gpt-5.5` 和 `mock-openai/gpt-5.5-alt`)執行 Matrix 與 Telegram 即時傳輸通道,因此通道合約會與即時模型延遲和一般供應商 Plugin 啟動隔離。即時傳輸 Gateway 會停用記憶體搜尋,因為 QA parity 會另外涵蓋記憶體行為;供應商連線能力則由獨立的即時模型、原生供應商和 Docker 供應商套件涵蓋。 +發行檢查會使用確定性的模擬供應商和符合模擬資格的模型(`mock-openai/gpt-5.5` 和 `mock-openai/gpt-5.5-alt`)執行 Matrix 和 Telegram 即時傳輸通道,因此通道合約會與即時模型延遲和一般供應商 Plugin 啟動隔離。即時傳輸 Gateway 會停用記憶搜尋,因為 QA 同位會另外涵蓋記憶行為;供應商連線能力由獨立的即時模型、原生供應商和 Docker 供應商套件涵蓋。 -Matrix 對排程和發行 gate 使用 `--profile fast`,只有在簽出的 CLI 支援時才加入 `--fail-fast`。CLI 預設值與手動工作流程輸入仍為 `all`;手動 `matrix_profile=all` 分派一律會將完整 Matrix 涵蓋範圍分片為 `transport`、`media`、`e2ee-smoke`、`e2ee-deep` 和 `e2ee-cli` 作業。 +Matrix 會在排程和發行閘門使用 `--profile fast`,並且只在簽出的 CLI 支援時加入 `--fail-fast`。CLI 預設值和手動工作流程輸入仍為 `all`;手動 `matrix_profile=all` 派送一律會將完整 Matrix 涵蓋範圍分片為 `transport`、`media`、`e2ee-smoke`、`e2ee-deep` 和 `e2ee-cli` 作業。 -`OpenClaw Release Checks` 也會在發行核准前執行發行關鍵的 QA Lab 通道;其 QA parity gate 會將候選與基準 packs 作為平行通道作業執行,然後將兩個成品下載到小型報告作業中,進行最終 parity 比較。 +`OpenClaw Release Checks` 也會在發行核准前執行發行關鍵的 QA Lab 通道;它的 QA 同位閘門會將候選與基準套件作為平行通道作業執行,接著將兩個成品下載到一個小型報告作業中進行最終同位比較。 -除非變更實際觸及 QA runtime、model-pack parity,或 parity 工作流程擁有的表面,否則不要把 PR landing path 放在 `Parity gate` 後方。對於一般通道、設定、文件或單元測試修正,請將它視為選用訊號,並遵循範圍化的 CI/檢查證據。 +除非變更實際觸及 QA runtime、模型套件同位,或同位工作流程擁有的表面,否則不要將 PR 合併路徑置於 `Parity gate` 之後。對於一般通道、設定、文件或單元測試修正,請將其視為選用訊號,並遵循範圍化 CI/檢查證據。 ## CodeQL -`CodeQL` 工作流程有意作為窄範圍的第一道安全掃描器,而不是完整儲存庫掃描。每日、手動和非草稿 pull request guard 執行會掃描 Actions 工作流程程式碼,加上最高風險的 JavaScript/TypeScript 表面,並使用高信心安全查詢篩選到高/重大 `security-severity`。 +`CodeQL` 工作流程刻意作為狹窄的第一輪安全掃描器,而不是完整儲存庫掃描。每日、手動和非草稿 pull request 守門執行會掃描 Actions 工作流程程式碼,以及最高風險的 JavaScript/TypeScript 表面,並使用高信心安全查詢,篩選為高/嚴重 `security-severity`。 -pull request guard 保持輕量:它只會針對 `.github/actions`、`.github/codeql`、`.github/workflows`、`packages` 或 `src` 底下的變更啟動,並執行與排程工作流程相同的高信心安全矩陣。Android 和 macOS CodeQL 不屬於 PR 預設值。 +pull request 守門保持輕量:它只會在 `.github/actions`、`.github/codeql`、`.github/workflows`、`packages` 或 `src` 底下的變更啟動,並執行與排程工作流程相同的高信心安全矩陣。Android 和 macOS CodeQL 不包含在 PR 預設值中。 -### 安全性類別 +### 安全類別 | 類別 | 表面 | | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| `/codeql-security-high/core-auth-secrets` | 驗證、密鑰、沙箱、Cron 和 Gateway 基準 | -| `/codeql-security-high/channel-runtime-boundary` | 核心通道實作合約,加上通道 Plugin runtime、Gateway、Plugin SDK、密鑰、稽核接觸點 | -| `/codeql-security-high/network-ssrf-boundary` | 核心 SSRF、IP 解析、網路 guard、web-fetch,以及 Plugin SDK SSRF 政策表面 | -| `/codeql-security-high/mcp-process-tool-boundary` | MCP 伺服器、程序執行 helper、對外傳遞,以及 agent tool-execution gates | -| `/codeql-security-high/plugin-trust-boundary` | Plugin 安裝、loader、manifest、registry、runtime-dependency staging、source-loading,以及 Plugin SDK 套件合約信任表面 | +| `/codeql-security-high/core-auth-secrets` | Auth、秘密、sandbox、cron 和 Gateway 基準 | +| `/codeql-security-high/channel-runtime-boundary` | 核心通道實作合約,以及通道 Plugin runtime、Gateway、Plugin SDK、秘密、稽核接觸點 | +| `/codeql-security-high/network-ssrf-boundary` | 核心 SSRF、IP 解析、網路防護、web-fetch,以及 Plugin SDK SSRF policy 表面 | +| `/codeql-security-high/mcp-process-tool-boundary` | MCP 伺服器、程序執行協助工具、輸出交付,以及 agent 工具執行閘門 | +| `/codeql-security-high/plugin-trust-boundary` | Plugin 安裝、載入器、manifest、registry、runtime-dependency staging、source-loading,以及 Plugin SDK 套件合約信任表面 | -### 平台特定安全性分片 +### 平台特定安全分片 -- `CodeQL Android Critical Security` — 排程的 Android 安全性分片。為 CodeQL 在 workflow sanity 接受的最小 Blacksmith Linux runner 上手動建置 Android app。上傳到 `/codeql-critical-security/android`。 -- `CodeQL macOS Critical Security` — 每週/手動 macOS 安全性分片。為 CodeQL 在 Blacksmith macOS 上手動建置 macOS app,從上傳的 SARIF 中篩除相依性建置結果,並上傳到 `/codeql-critical-security/macos`。因為即使乾淨時 macOS 建置也主導 runtime,所以保留在每日預設值之外。 +- `CodeQL Android Critical Security` — 排程的 Android 安全分片。為 CodeQL 在工作流程健全性接受的最小 Blacksmith Linux runner 上手動建置 Android 應用程式。上傳到 `/codeql-critical-security/android` 底下。 +- `CodeQL macOS Critical Security` — 每週/手動 macOS 安全分片。在 Blacksmith macOS 上為 CodeQL 手動建置 macOS 應用程式,從上傳的 SARIF 中篩除依賴項建置結果,並上傳到 `/codeql-critical-security/macos` 底下。因為即使乾淨時 macOS 建置也主導 runtime,所以保留在每日預設值之外。 -### Critical Quality 類別 +### 關鍵品質類別 -`CodeQL Critical Quality` 是對應的非安全性分片。它只會在較小的 Blacksmith Linux runner 上,對窄範圍高價值表面執行錯誤嚴重度、非安全性 JavaScript/TypeScript 品質查詢。它的 pull request guard 有意比排程設定檔更小:非草稿 PR 只會針對 agent 命令/模型/工具執行與回覆分派程式碼、設定 schema/migration/IO 程式碼、驗證/密鑰/沙箱/安全性程式碼、核心通道與 bundled 通道 Plugin runtime、Gateway 協定/server-method、記憶體 runtime/SDK glue、MCP/process/outbound delivery、供應商 runtime/model catalog、session diagnostics/delivery queues、Plugin loader、Plugin SDK/package-contract,或 Plugin SDK reply runtime 變更,執行相符的 `agent-runtime-boundary`、`config-boundary`、`core-auth-secrets`、`channel-runtime-boundary`、`gateway-runtime-boundary`、`memory-runtime-boundary`、`mcp-process-runtime-boundary`、`provider-runtime-boundary`、`session-diagnostics-boundary`、`plugin-boundary`、`plugin-sdk-package-contract` 和 `plugin-sdk-reply-runtime` 分片。CodeQL 設定與品質工作流程變更會執行全部十二個 PR 品質分片。 +`CodeQL Critical Quality` 是對應的非安全分片。它只在較小的 Blacksmith Linux runner 上,針對狹窄的高價值表面執行錯誤嚴重性、非安全的 JavaScript/TypeScript 品質查詢。其 pull request 守門刻意小於排程設定檔:非草稿 PR 只會針對 agent 命令/模型/工具執行與回覆派送程式碼、設定 schema/migration/IO 程式碼、auth/secrets/sandbox/security 程式碼、核心通道和內建通道 Plugin runtime、Gateway protocol/server-method、memory runtime/SDK glue、MCP/process/outbound delivery、provider runtime/model catalog、session diagnostics/delivery queues、Plugin loader、Plugin SDK/package-contract,或 Plugin SDK reply runtime 變更,執行相符的 `agent-runtime-boundary`、`config-boundary`、`core-auth-secrets`、`channel-runtime-boundary`、`gateway-runtime-boundary`、`memory-runtime-boundary`、`mcp-process-runtime-boundary`、`provider-runtime-boundary`、`session-diagnostics-boundary`、`plugin-boundary`、`plugin-sdk-package-contract` 和 `plugin-sdk-reply-runtime` 分片。CodeQL 設定和品質工作流程變更會執行全部十二個 PR 品質分片。 -手動分派接受: +手動派送接受: ``` profile=all|agent-runtime-boundary|config-boundary|core-auth-secrets|channel-runtime-boundary|gateway-runtime-boundary|memory-runtime-boundary|mcp-process-runtime-boundary|plugin-boundary|plugin-sdk-package-contract|plugin-sdk-reply-runtime|provider-runtime-boundary|session-diagnostics-boundary ``` -窄範圍設定檔是用於隔離執行單一品質分片的教學/迭代 hook。 +狹窄設定檔是用於單獨執行一個品質分片的教學/迭代掛鉤。 -| 類別 | 涵蓋範圍 | -| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `/codeql-critical-quality/core-auth-secrets` | Auth、secrets、sandbox、Cron,以及 Gateway 安全邊界程式碼 | -| `/codeql-critical-quality/config-boundary` | 設定結構描述、遷移、正規化,以及 IO 合約 | -| `/codeql-critical-quality/gateway-runtime-boundary` | Gateway 協定結構描述與伺服器方法合約 | -| `/codeql-critical-quality/channel-runtime-boundary` | 核心 channel 與內建 channel Plugin 實作合約 | -| `/codeql-critical-quality/agent-runtime-boundary` | 命令執行、模型/提供者分派、自動回覆分派與佇列,以及 ACP 控制平面執行階段合約 | -| `/codeql-critical-quality/mcp-process-runtime-boundary` | MCP 伺服器與工具橋接、程序監督輔助工具,以及對外傳遞合約 | -| `/codeql-critical-quality/memory-runtime-boundary` | 記憶體主機 SDK、記憶體執行階段 facade、記憶體 Plugin SDK 別名、記憶體執行階段啟用銜接,以及記憶體 doctor 命令 | -| `/codeql-critical-quality/session-diagnostics-boundary` | 回覆佇列內部、工作階段傳遞佇列、對外工作階段繫結/傳遞輔助工具、診斷事件/日誌組合表面,以及工作階段 doctor CLI 合約 | -| `/codeql-critical-quality/plugin-sdk-reply-runtime` | Plugin SDK 傳入回覆分派、回覆酬載/分塊/執行階段輔助工具、channel 回覆選項、傳遞佇列,以及工作階段/thread 繫結輔助工具 | -| `/codeql-critical-quality/provider-runtime-boundary` | 模型目錄正規化、提供者驗證與探索、提供者執行階段註冊、提供者預設值/目錄,以及 web/search/fetch/embedding 登錄表 | -| `/codeql-critical-quality/ui-control-plane` | 控制 UI 啟動、本機持久化、Gateway 控制流程,以及任務控制平面執行階段合約 | -| `/codeql-critical-quality/web-media-runtime-boundary` | 核心 web fetch/search、媒體 IO、媒體理解、影像生成,以及媒體生成執行階段合約 | -| `/codeql-critical-quality/plugin-boundary` | 載入器、登錄表、公用表面,以及 Plugin SDK 進入點合約 | -| `/codeql-critical-quality/plugin-sdk-package-contract` | 已發布套件端 Plugin SDK 原始碼與 Plugin 套件合約輔助工具 | +| 類別 | 介面 | +| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `/codeql-critical-quality/core-auth-secrets` | Auth、祕密、沙箱、Cron 與 Gateway 安全邊界程式碼 | +| `/codeql-critical-quality/config-boundary` | 設定結構描述、遷移、正規化與 IO 合約 | +| `/codeql-critical-quality/gateway-runtime-boundary` | Gateway 協定結構描述與伺服器方法合約 | +| `/codeql-critical-quality/channel-runtime-boundary` | 核心通道與隨附通道 Plugin 實作合約 | +| `/codeql-critical-quality/agent-runtime-boundary` | 命令執行、模型/提供者分派、自動回覆分派與佇列,以及 ACP 控制平面執行階段合約 | +| `/codeql-critical-quality/mcp-process-runtime-boundary` | MCP 伺服器與工具橋接、程序監督輔助工具,以及對外傳遞合約 | +| `/codeql-critical-quality/memory-runtime-boundary` | 記憶體主機 SDK、記憶體執行階段外觀、記憶體 Plugin SDK 別名、記憶體執行階段啟用黏合層,以及記憶體 doctor 命令 | +| `/codeql-critical-quality/session-diagnostics-boundary` | 回覆佇列內部、工作階段傳遞佇列、對外工作階段繫結/傳遞輔助工具、診斷事件/記錄組合包介面,以及工作階段 doctor CLI 合約 | +| `/codeql-critical-quality/plugin-sdk-reply-runtime` | Plugin SDK 傳入回覆分派、回覆承載/分塊/執行階段輔助工具、通道回覆選項、傳遞佇列,以及工作階段/執行緒繫結輔助工具 | +| `/codeql-critical-quality/provider-runtime-boundary` | 模型型錄正規化、提供者驗證與探索、提供者執行階段註冊、提供者預設值/型錄,以及網頁/搜尋/擷取/嵌入註冊表 | +| `/codeql-critical-quality/ui-control-plane` | 控制 UI 啟動程序、本機持久化、Gateway 控制流程,以及任務控制平面執行階段合約 | +| `/codeql-critical-quality/web-media-runtime-boundary` | 核心網頁擷取/搜尋、媒體 IO、媒體理解、影像生成,以及媒體生成執行階段合約 | +| `/codeql-critical-quality/plugin-boundary` | 載入器、註冊表、公開介面,以及 Plugin SDK 進入點合約 | +| `/codeql-critical-quality/plugin-sdk-package-contract` | 已發布套件端 Plugin SDK 原始碼與 Plugin 套件合約輔助工具 | -品質與安全維持分離,讓品質發現可以排程、量測、停用或擴充,而不會掩蓋安全訊號。Swift、Python,以及內建 Plugin 的 CodeQL 擴充,應只在狹窄設定檔具備穩定執行階段與訊號之後,再作為有範圍或分片的後續工作加回。 +品質會與安全性分開,因此品質發現可以排程、衡量、停用或擴充,而不會掩蓋安全性訊號。Swift、Python 與隨附 Plugin 的 CodeQL 擴充,應只在窄範圍設定檔具備穩定執行階段與訊號之後,作為具範圍或分片的後續工作加回。 ## 維護工作流程 ### 文件 Agent -`Docs Agent` 工作流程是一條事件驅動的 Codex 維護路徑,用於讓現有文件與最近落地的變更保持一致。它沒有純排程:`main` 上成功的非 bot push CI 執行可以觸發它,也可以透過手動分派直接執行。當 `main` 已經前進,或過去一小時內已有另一個未略過的 Docs Agent 執行被建立時,workflow-run 呼叫會略過。執行時,它會檢視從上一個未略過的 Docs Agent 來源 SHA 到目前 `main` 的提交範圍,因此每小時一次的執行可以涵蓋自上次文件檢查以來累積的所有 main 變更。 +`Docs Agent` 工作流程是一條事件驅動的 Codex 維護通道,用於讓現有文件與最近落地的變更保持一致。它沒有純排程:在 `main` 上成功的非機器人推送 CI 執行可以觸發它,手動派送也可以直接執行它。當 `main` 已前進,或上一小時內已建立另一個未略過的 Docs Agent 執行時,工作流程執行叫用會略過。執行時,它會審查從前一個未略過的 Docs Agent 來源 SHA 到目前 `main` 的提交範圍,因此一次每小時執行可以涵蓋自上次文件巡檢以來累積的所有 main 變更。 ### 測試效能 Agent -`Test Performance Agent` 工作流程是一條事件驅動的 Codex 維護路徑,用於處理慢速測試。它沒有純排程:`main` 上成功的非 bot push CI 執行可以觸發它,但如果另一個 workflow-run 呼叫在該 UTC 日已經執行或正在執行,它會略過。手動分派會繞過每日活動閘門。這條路徑會建立完整套件分組 Vitest 效能報告,讓 Codex 只進行小型且保留覆蓋率的測試效能修正,而不是大範圍重構,接著重新執行完整套件報告,並拒絕會降低通過基準測試數量的變更。如果基準有失敗測試,Codex 只能修正明顯的失敗,且 agent 後的完整套件報告必須通過後才會提交任何內容。當 bot push 落地前 `main` 又前進時,這條路徑會 rebase 已驗證的 patch、重新執行 `pnpm check:changed`,並重試 push;有衝突的過期 patch 會被略過。它使用 GitHub 託管的 Ubuntu,因此 Codex action 可以維持與 docs agent 相同的 drop-sudo 安全姿態。 +`Test Performance Agent` 工作流程是一條事件驅動的 Codex 維護通道,用於處理緩慢測試。它沒有純排程:在 `main` 上成功的非機器人推送 CI 執行可以觸發它,但如果另一個工作流程執行叫用在該 UTC 日已經執行或正在執行,它就會略過。手動派送會略過該每日活動閘門。此通道會建立完整套件分組 Vitest 效能報告,讓 Codex 只進行小型且保留覆蓋率的測試效能修正,而不是大範圍重構,接著重新執行完整套件報告,並拒絕會降低通過基準測試數量的變更。如果基準有失敗測試,Codex 只能修正明顯的失敗,而且 Agent 後的完整套件報告必須通過,才會提交任何內容。當 `main` 在機器人推送落地前前進時,此通道會將已驗證的修補重新基底化、重新執行 `pnpm check:changed`,並重試推送;有衝突的過期修補會被略過。它使用 GitHub 託管的 Ubuntu,因此 Codex 動作可以維持與文件 Agent 相同的 drop-sudo 安全姿態。 ### 合併後的重複 PR -`Duplicate PRs After Merge` 工作流程是供維護者在落地後清理重複項目的手動工作流程。它預設為 dry-run,且只會在 `apply=true` 時關閉明確列出的 PR。修改 GitHub 之前,它會驗證已落地的 PR 已合併,且每個重複項目都有共用的引用 issue,或有重疊的變更 hunk。 +`Duplicate PRs After Merge` 工作流程是用於落地後重複項清理的手動維護者工作流程。它預設為 dry-run,且只有在 `apply=true` 時才會關閉明確列出的 PR。在變更 GitHub 之前,它會驗證已落地的 PR 已合併,並且每個重複項都有共用的參照 issue,或有重疊的變更 hunk。 ```bash gh workflow run duplicate-after-merge.yml \ @@ -394,27 +394,27 @@ gh workflow run duplicate-after-merge.yml \ ## 本機檢查閘門與變更路由 -本機 changed-lane 邏輯位於 `scripts/changed-lanes.mjs`,並由 `scripts/check-changed.mjs` 執行。該本機檢查閘門對架構邊界的要求比廣泛 CI 平台範圍更嚴格: +本機變更通道邏輯位於 `scripts/changed-lanes.mjs`,並由 `scripts/check-changed.mjs` 執行。該本機檢查閘門對架構邊界比廣泛 CI 平台範圍更嚴格: -- 核心 production 變更會執行核心 prod 與核心 test 型別檢查,加上核心 lint/guards; -- 僅核心測試的變更只會執行核心 test 型別檢查,加上核心 lint; -- extension production 變更會執行 extension prod 與 extension test 型別檢查,加上 extension lint; -- 僅 extension 測試的變更會執行 extension test 型別檢查,加上 extension lint; -- 公用 Plugin SDK 或 Plugin 合約變更會擴展到 extension 型別檢查,因為 extensions 依賴這些核心合約(Vitest extension 掃描仍然是明確的測試工作); -- 僅 release metadata 的版本 bump 會執行目標式版本/設定/root-dependency 檢查; -- 未知的 root/config 變更會 fail safe 到所有檢查路徑。 +- 核心生產變更會執行核心生產與核心測試型別檢查,加上核心 lint/guard; +- 僅核心測試變更只會執行核心測試型別檢查,加上核心 lint; +- 擴充功能生產變更會執行擴充功能生產與擴充功能測試型別檢查,加上擴充功能 lint; +- 僅擴充功能測試變更會執行擴充功能測試型別檢查,加上擴充功能 lint; +- 公開 Plugin SDK 或 Plugin 合約變更會擴大到擴充功能型別檢查,因為擴充功能依賴這些核心合約(Vitest 擴充功能掃描仍是明確的測試工作); +- 僅發布中繼資料的版本升級會執行目標式版本/設定/根相依性檢查; +- 未知根目錄/設定變更會以安全失敗方式進入所有檢查通道。 -本機 changed-test 路由位於 `scripts/test-projects.test-support.mjs`,刻意比 `check:changed` 更便宜:直接測試編輯會執行自身,原始碼編輯會優先使用明確映射,接著是同層測試與 import graph 相依項。共享 group-room 傳遞設定是明確映射之一:對 group visible-reply 設定、source reply delivery mode,或 message-tool system prompt 的變更,會透過核心回覆測試加上 Discord 與 Slack 傳遞回歸測試進行路由,因此共享預設值變更會在第一次 PR push 前失敗。只有當變更的範圍廣到便宜映射集合不再是可信代理時,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 +本機變更測試路由位於 `scripts/test-projects.test-support.mjs`,且刻意比 `check:changed` 更便宜:直接測試編輯會執行自身,原始碼編輯優先使用明確對應,接著是同層測試與匯入圖相依項。共用群組房間傳遞設定是其中一個明確對應:群組可見回覆設定、來源回覆傳遞模式,或訊息工具系統提示的變更,會透過核心回覆測試加上 Discord 與 Slack 傳遞回歸測試路由,因此共用預設值變更會在第一次 PR 推送前失敗。只有在變更的範圍涵蓋整個測試框架,使得便宜的對應集合不是可信代理時,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 ## Testbox 驗證 -從 repo root 執行 Testbox,並優先為廣泛證明使用新的已暖機 box。在把慢速閘門花在重複使用、過期,或剛回報非預期大量同步的 box 之前,先在 box 內執行 `pnpm testbox:sanity`。 +從 repo 根目錄執行 Testbox,並優先使用全新預熱的 box 進行廣泛證明。在把緩慢閘門花在已重用、過期,或剛回報異常大量同步的 box 之前,先在 box 內執行 `pnpm testbox:sanity`。 -當必要 root 檔案如 `pnpm-lock.yaml` 消失,或 `git status --short` 顯示至少 200 個已追蹤刪除時,sanity check 會快速失敗。這通常代表遠端同步狀態不是 PR 的可信副本;請停止該 box 並暖機新的 box,而不是偵錯產品測試失敗。對於刻意的大量刪除 PR,為該 sanity 執行設定 `OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1`。 +當必要根目錄檔案(例如 `pnpm-lock.yaml`)消失,或 `git status --short` 顯示至少 200 個已追蹤刪除時,健全性檢查會快速失敗。這通常代表遠端同步狀態不是 PR 的可信副本;請停止該 box 並預熱新的,而不是偵錯產品測試失敗。對於刻意的大量刪除 PR,請為該健全性執行設定 `OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1`。 -`pnpm testbox:run` 也會終止停留在同步階段超過五分鐘且沒有同步後輸出的本機 Blacksmith CLI 呼叫。設定 `OPENCLAW_TESTBOX_SYNC_TIMEOUT_MS=0` 可停用該保護,或針對異常大的本機 diff 使用較大的毫秒值。 +`pnpm testbox:run` 也會終止本機 Blacksmith CLI 叫用,如果它停留在同步階段超過五分鐘且沒有同步後輸出。設定 `OPENCLAW_TESTBOX_SYNC_TIMEOUT_MS=0` 可停用該 guard,或針對異常大的本機 diff 使用更大的毫秒值。 ## 相關 - [安裝概覽](/zh-TW/install) -- [開發 channel](/zh-TW/install/development-channels) +- [開發通道](/zh-TW/install/development-channels) diff --git a/docs/zh-TW/concepts/agent-loop.md b/docs/zh-TW/concepts/agent-loop.md index 47832267a..72e50c9dd 100644 --- a/docs/zh-TW/concepts/agent-loop.md +++ b/docs/zh-TW/concepts/agent-loop.md @@ -1,48 +1,48 @@ --- read_when: - - 您需要 agent 迴圈或生命週期事件的精確逐步解說 - - 你正在變更工作階段佇列、逐字稿寫入或工作階段寫入鎖定行為 + - 你需要代理迴圈或生命週期事件的精確逐步說明 + - 你正在變更工作階段佇列處理、對話紀錄寫入,或工作階段寫入鎖定行為 summary: 代理程式迴圈生命週期、串流與等待語意 -title: 代理程式迴圈 +title: 代理迴圈 x-i18n: - generated_at: "2026-04-30T02:57:55Z" + generated_at: "2026-04-30T18:38:37Z" model: gpt-5.5 provider: openai - source_hash: 902d543bd71dd517a810d825cbe92e244fe89230f47eeada72477c657a2bec32 + source_hash: 5466893253e1f82482284ff82db56f4c3fca018bf12e4114fad76d37cad954df source_path: concepts/agent-loop.md workflow: 16 --- -代理式迴圈是代理的完整「真實」執行流程:接收 → 組裝脈絡 → 模型推論 → -工具執行 → 串流回覆 → 持久化。它是將訊息轉換成動作與最終回覆的權威路徑, +代理式迴圈是代理的完整「真實」執行流程:接收 → 組裝內容脈絡 → 模型推論 → +工具執行 → 串流回覆 → 持久化。這是將訊息轉換為動作與最終回覆的權威路徑, 同時保持工作階段狀態一致。 -在 OpenClaw 中,迴圈是每個工作階段一次單一、序列化的執行,會在模型思考、 -呼叫工具並串流輸出時發出生命週期與串流事件。本文件說明這個真實迴圈如何 -端到端串接。 +在 OpenClaw 中,迴圈是每個工作階段一次單一、序列化的執行,會在模型思考、呼叫工具 +並串流輸出時發出生命週期與串流事件。本文件說明這個真實迴圈如何從端到端串接。 ## 進入點 -- Gateway RPC:`agent` 與 `agent.wait`。 +- Gateway RPC:`agent` 和 `agent.wait`。 - CLI:`agent` 指令。 -## 運作方式(高階) +## 運作方式(高層次) 1. `agent` RPC 會驗證參數、解析工作階段(sessionKey/sessionId)、持久化工作階段中繼資料,並立即回傳 `{ runId, acceptedAt }`。 -2. `agentCommand` 執行代理: +2. `agentCommand` 會執行代理: - 解析模型 + thinking/verbose/trace 預設值 - 載入 Skills 快照 - 呼叫 `runEmbeddedPiAgent`(pi-agent-core 執行階段) - - 如果內嵌迴圈未發出生命週期結束/錯誤,則發出 **lifecycle end/error** + - 如果嵌入式迴圈沒有發出生命週期結束/錯誤,則發出 **lifecycle end/error** 3. `runEmbeddedPiAgent`: - - 透過每工作階段 + 全域佇列序列化執行 - - 解析模型 + 驗證設定檔並建立 pi 工作階段 - - 訂閱 pi 事件並串流 assistant/tool 增量 - - 強制執行逾時 -> 若超過則中止執行 - - 回傳 payload + 用量中繼資料 -4. `subscribeEmbeddedPiSession` 將 pi-agent-core 事件橋接到 OpenClaw `agent` 串流: + - 透過每個工作階段 + 全域佇列序列化執行 + - 解析模型 + 驗證設定檔,並建立 Pi 工作階段 + - 訂閱 Pi 事件,並串流 assistant/tool 增量 + - 強制執行逾時 -> 若超過時間則中止執行 + - 針對 Codex app-server 回合,在終端事件前,如果已接受的回合停止產生 app-server 進度,則中止該回合 + - 回傳 payload + 使用量中繼資料 +4. `subscribeEmbeddedPiSession` 會將 pi-agent-core 事件橋接到 OpenClaw `agent` 串流: - 工具事件 => `stream: "tool"` - - 助理增量 => `stream: "assistant"` + - assistant 增量 => `stream: "assistant"` - 生命週期事件 => `stream: "lifecycle"`(`phase: "start" | "end" | "error"`) 5. `agent.wait` 使用 `waitForAgentRun`: - 等待 `runId` 的 **lifecycle end/error** @@ -50,79 +50,82 @@ x-i18n: ## 佇列 + 並行 -- 執行會依工作階段金鑰(工作階段通道)序列化,並可選擇經由全域通道。 +- 執行會依工作階段鍵(工作階段通道)序列化,並可選擇透過全域通道序列化。 - 這可防止工具/工作階段競態,並保持工作階段歷史一致。 -- 訊息通道可以選擇佇列模式(collect/steer/followup),以輸入這套通道系統。 +- 訊息通道可以選擇佇列模式(collect/steer/followup),並將其送入此通道系統。 請參閱[指令佇列](/zh-TW/concepts/queue)。 -- 轉錄寫入也會受到工作階段檔案上的工作階段寫入鎖保護。該鎖具有程序感知能力且以檔案為基礎, - 因此能捕捉到繞過程序內佇列或來自其他程序的寫入者。 -- 工作階段寫入鎖預設不可重入。如果某個輔助程式刻意在保留單一邏輯寫入者的同時, - 巢狀取得相同鎖,則必須以 `allowReentrant: true` 明確選擇加入。 +- Transcript 寫入也受到工作階段檔案上的工作階段寫入鎖保護。該鎖具備 + 程序感知能力且以檔案為基礎,因此能捕捉繞過程序內佇列或來自 + 其他程序的寫入者。 +- 工作階段寫入鎖預設不可重入。如果輔助工具刻意巢狀取得 + 同一把鎖,同時保留一個邏輯寫入者,則必須使用 + `allowReentrant: true` 明確選擇加入。 ## 工作階段 + 工作區準備 -- 工作區會被解析並建立;沙盒化執行可能會重新導向到沙盒工作區根目錄。 -- Skills 會被載入(或從快照重用),並注入到環境與提示中。 -- Bootstrap/脈絡檔案會被解析,並注入到系統提示報告中。 -- 會取得工作階段寫入鎖;`SessionManager` 會在串流前開啟並準備好。任何 - 後續轉錄重寫、Compaction 或截斷路徑,都必須在開啟或變更轉錄檔前取得相同鎖。 +- 會解析並建立工作區;沙盒化執行可能會重新導向到沙盒工作區根目錄。 +- 會載入 Skills(或重用快照),並注入 env 與提示詞。 +- 會解析 bootstrap/context 檔案,並注入系統提示詞報告。 +- 會取得工作階段寫入鎖;`SessionManager` 會在串流前開啟並準備完成。任何 + 後續的 transcript 重寫、Compaction 或截斷路徑,都必須在開啟或 + 修改 transcript 檔案前取得同一把鎖。 -## 提示組裝 + 系統提示 +## 提示詞組裝 + 系統提示詞 -- 系統提示會由 OpenClaw 的基礎提示、Skills 提示、bootstrap 脈絡與每次執行覆寫建立。 -- 會強制套用模型特定限制與 Compaction 保留 token。 -- 請參閱[系統提示](/zh-TW/concepts/system-prompt),了解模型會看到什麼。 +- 系統提示詞由 OpenClaw 的基礎提示詞、Skills 提示詞、bootstrap 內容脈絡,以及每次執行的覆寫組成。 +- 會強制執行模型特定限制與 Compaction 保留 token。 +- 請參閱[系統提示詞](/zh-TW/concepts/system-prompt),了解模型會看到的內容。 -## 掛鉤點(可攔截的位置) +## Hook 點(你可以攔截的位置) -OpenClaw 有兩套掛鉤系統: +OpenClaw 有兩套 Hook 系統: -- **內部掛鉤**(Gateway 掛鉤):用於指令與生命週期事件的事件驅動腳本。 -- **Plugin 掛鉤**:代理/工具生命週期與 Gateway 管線內的擴充點。 +- **內部 Hook**(Gateway Hook):針對指令與生命週期事件的事件驅動腳本。 +- **Plugin Hook**:代理/工具生命週期與 gateway 管線中的擴充點。 -### 內部掛鉤(Gateway 掛鉤) +### 內部 Hook(Gateway Hook) -- **`agent:bootstrap`**:在系統提示完成前,建立 bootstrap 檔案時執行。 - 使用這個掛鉤新增/移除 bootstrap 脈絡檔案。 -- **指令掛鉤**:`/new`、`/reset`、`/stop`,以及其他指令事件(請參閱 Hooks 文件)。 +- **`agent:bootstrap`**:在系統提示詞完成前,建置 bootstrap 檔案時執行。 + 使用此 Hook 來新增/移除 bootstrap 內容脈絡檔案。 +- **指令 Hook**:`/new`、`/reset`、`/stop`,以及其他指令事件(請參閱 Hook 文件)。 -請參閱[掛鉤](/zh-TW/automation/hooks)取得設定與範例。 +請參閱 [Hook](/zh-TW/automation/hooks) 了解設定與範例。 -### Plugin 掛鉤(代理 + Gateway 生命週期) +### Plugin Hook(代理 + gateway 生命週期) -這些掛鉤會在代理迴圈或 Gateway 管線內執行: +這些 Hook 會在代理迴圈或 gateway 管線內執行: -- **`before_model_resolve`**:在工作階段前執行(沒有 `messages`),以便在模型解析前以決定性方式覆寫供應商/模型。 -- **`before_prompt_build`**:在工作階段載入後執行(含 `messages`),以便在提交提示前注入 `prependContext`、`systemPrompt`、`prependSystemContext` 或 `appendSystemContext`。將 `prependContext` 用於每回合動態文字,將系統脈絡欄位用於應位於系統提示空間中的穩定指引。 -- **`before_agent_start`**:舊版相容掛鉤,可能在任一階段執行;建議使用上方明確的掛鉤。 -- **`before_agent_reply`**:在行內動作之後、LLM 呼叫之前執行,讓 Plugin 可接管該回合並回傳合成回覆,或完全靜默該回合。 +- **`before_model_resolve`**:在工作階段前執行(沒有 `messages`),用於在模型解析前確定性地覆寫供應商/模型。 +- **`before_prompt_build`**:在工作階段載入後執行(含 `messages`),用於在提交提示詞前注入 `prependContext`、`systemPrompt`、`prependSystemContext` 或 `appendSystemContext`。將 `prependContext` 用於每回合動態文字,並將 system-context 欄位用於應位於系統提示詞空間中的穩定指引。 +- **`before_agent_start`**:舊版相容性 Hook,可能在任一階段執行;建議使用上方明確的 Hook。 +- **`before_agent_reply`**:在 inline 動作之後、LLM 呼叫之前執行,讓 Plugin 接管該回合並回傳合成回覆,或完全靜音該回合。 - **`agent_end`**:在完成後檢查最終訊息清單與執行中繼資料。 -- **`before_compaction` / `after_compaction`**:觀察或註記 Compaction 週期。 +- **`before_compaction` / `after_compaction`**:觀察或標註 Compaction 週期。 - **`before_tool_call` / `after_tool_call`**:攔截工具參數/結果。 -- **`before_install`**:檢查內建掃描發現項目,並可選擇封鎖 Skill 或 Plugin 安裝。 -- **`tool_result_persist`**:在工具結果寫入 OpenClaw 擁有的工作階段轉錄前,同步轉換工具結果。 -- **`message_received` / `message_sending` / `message_sent`**:傳入 + 傳出訊息掛鉤。 +- **`before_install`**:檢查內建掃描發現項目,並可選擇封鎖 skill 或 Plugin 安裝。 +- **`tool_result_persist`**:在工具結果寫入 OpenClaw 所有的工作階段 transcript 前,同步轉換工具結果。 +- **`message_received` / `message_sending` / `message_sent`**:輸入 + 輸出訊息 Hook。 - **`session_start` / `session_end`**:工作階段生命週期邊界。 -- **`gateway_start` / `gateway_stop`**:Gateway 生命週期事件。 +- **`gateway_start` / `gateway_stop`**:gateway 生命週期事件。 -傳出/工具防護的掛鉤決策規則: +輸出/工具防護的 Hook 決策規則: -- `before_tool_call`:`{ block: true }` 是終止性決策,會停止較低優先順序的處理常式。 -- `before_tool_call`:`{ block: false }` 是無操作,且不會清除先前的封鎖。 -- `before_install`:`{ block: true }` 是終止性決策,會停止較低優先順序的處理常式。 -- `before_install`:`{ block: false }` 是無操作,且不會清除先前的封鎖。 -- `message_sending`:`{ cancel: true }` 是終止性決策,會停止較低優先順序的處理常式。 -- `message_sending`:`{ cancel: false }` 是無操作,且不會清除先前的取消。 +- `before_tool_call`:`{ block: true }` 是終端決策,會停止較低優先權的處理器。 +- `before_tool_call`:`{ block: false }` 是無操作,不會清除先前的封鎖。 +- `before_install`:`{ block: true }` 是終端決策,會停止較低優先權的處理器。 +- `before_install`:`{ block: false }` 是無操作,不會清除先前的封鎖。 +- `message_sending`:`{ cancel: true }` 是終端決策,會停止較低優先權的處理器。 +- `message_sending`:`{ cancel: false }` 是無操作,不會清除先前的取消。 -請參閱 [Plugin 掛鉤](/zh-TW/plugins/hooks)取得掛鉤 API 與註冊詳細資訊。 +請參閱 [Plugin Hook](/zh-TW/plugins/hooks),了解 Hook API 與註冊細節。 -測試框架可能會以不同方式調整這些掛鉤。Codex app-server 測試框架會將 -OpenClaw Plugin 掛鉤作為文件化鏡像介面的相容性合約,而 Codex 原生掛鉤仍是 -另一套較低階的 Codex 機制。 +Harness 可能會以不同方式調整這些 Hook。Codex app-server harness 會保留 +OpenClaw Plugin Hook,作為已記載映射介面的相容性合約, +而 Codex 原生 Hook 仍是獨立的較低層級 Codex 機制。 ## 串流 + 部分回覆 -- 助理增量會從 pi-agent-core 串流,並作為 `assistant` 事件發出。 +- Assistant 增量會從 pi-agent-core 串流,並作為 `assistant` 事件發出。 - 區塊串流可在 `text_end` 或 `message_end` 發出部分回覆。 - 推理串流可作為獨立串流或區塊回覆發出。 - 請參閱[串流](/zh-TW/concepts/streaming),了解分塊與區塊回覆行為。 @@ -130,26 +133,26 @@ OpenClaw Plugin 掛鉤作為文件化鏡像介面的相容性合約,而 Codex ## 工具執行 + 訊息工具 - 工具 start/update/end 事件會在 `tool` 串流上發出。 -- 工具結果會在記錄/發出前,依大小與圖片 payload 進行清理。 -- 會追蹤訊息工具傳送,以抑制重複的助理確認。 +- 工具結果會在記錄/發出前,針對大小與圖片 payload 進行清理。 +- 訊息工具傳送會被追蹤,以抑制重複的 assistant 確認。 ## 回覆塑形 + 抑制 -- 最終 payload 由以下內容組裝: - - 助理文字(以及可選的推理) - - 行內工具摘要(當 verbose + 允許時) - - 模型出錯時的助理錯誤文字 -- 精確靜默 token `NO_REPLY` / `no_reply` 會從傳出 - payload 中過濾。 +- 最終 payload 會由以下內容組裝: + - assistant 文字(以及可選的推理) + - inline 工具摘要(當 verbose + 允許時) + - 模型發生錯誤時的 assistant 錯誤文字 +- 精確的靜默 token `NO_REPLY` / `no_reply` 會從輸出 + payload 中濾除。 - 訊息工具重複項會從最終 payload 清單中移除。 -- 如果沒有剩餘可渲染的 payload 且工具出錯,則會發出備援工具錯誤回覆 +- 如果沒有剩餘可算繪的 payload,且工具發生錯誤,則會發出備援工具錯誤回覆 (除非訊息工具已經傳送使用者可見的回覆)。 ## Compaction + 重試 -- 自動 Compaction 會發出 `compaction` 串流事件,且可觸發重試。 +- 自動 Compaction 會發出 `compaction` 串流事件,並可觸發重試。 - 重試時,記憶體內緩衝區與工具摘要會重設,以避免重複輸出。 -- 請參閱 [Compaction](/zh-TW/concepts/compaction) 了解 Compaction 管線。 +- 請參閱 [Compaction](/zh-TW/concepts/compaction),了解 Compaction 管線。 ## 事件串流(目前) @@ -159,29 +162,29 @@ OpenClaw Plugin 掛鉤作為文件化鏡像介面的相容性合約,而 Codex ## 聊天通道處理 -- 助理增量會緩衝成聊天 `delta` 訊息。 +- Assistant 增量會緩衝成聊天 `delta` 訊息。 - 聊天 `final` 會在 **lifecycle end/error** 時發出。 ## 逾時 -- `agent.wait` 預設:30 秒(僅等待)。`timeoutMs` 參數可覆寫。 -- 代理執行階段:`agents.defaults.timeoutSeconds` 預設為 172800 秒(48 小時);由 `runEmbeddedPiAgent` 中止計時器強制執行。 -- Cron 執行階段:隔離的代理回合 `timeoutSeconds` 由 cron 擁有。排程器在執行開始時啟動該計時器,在設定的期限中止底層執行,接著執行有界清理,再記錄逾時,避免過時的子工作階段讓通道卡住。 -- 卡住工作階段復原:啟用診斷後,`diagnostics.stuckSessionWarnMs` 會偵測長時間 `processing` 的工作階段。作用中的內嵌執行、作用中的回覆操作,以及作用中的工作階段通道任務,預設只會警告;如果診斷顯示該工作階段沒有作用中的工作,監視器會釋放受影響的工作階段通道,讓已排入佇列的啟動工作可以清空。 -- 模型閒置逾時:當閒置視窗內沒有回應區塊抵達時,OpenClaw 會中止模型請求。`models.providers..timeoutSeconds` 會為較慢的本機/自架供應商延長這個閒置監視器;否則 OpenClaw 會在已設定時使用 `agents.defaults.timeoutSeconds`,預設上限為 120 秒。沒有明確模型或代理逾時的 Cron 觸發執行會停用閒置監視器,並依賴 cron 外層逾時。 -- 供應商 HTTP 請求逾時:`models.providers..timeoutSeconds` 會套用到該供應商的模型 HTTP 擷取,包括連線、標頭、本文、SDK 請求逾時、總體受防護 fetch 中止處理,以及模型串流閒置監視器。對於 Ollama 這類較慢的本機/自架供應商,請先使用此設定,再提高整個代理執行階段逾時。 +- `agent.wait` 預設值:30 秒(僅等待)。`timeoutMs` 參數可覆寫。 +- 代理執行階段:`agents.defaults.timeoutSeconds` 預設值為 172800 秒(48 小時);由 `runEmbeddedPiAgent` 中止計時器強制執行。 +- Cron 執行階段:隔離的代理回合 `timeoutSeconds` 由 cron 擁有。排程器會在執行開始時計時,在設定的期限中止底層執行,接著在記錄逾時前執行有界清理,避免過期的子工作階段讓通道卡住。 +- 卡住工作階段復原:啟用診斷時,`diagnostics.stuckSessionWarnMs` 會偵測長時間處於 `processing` 的工作階段。作用中的嵌入式執行、作用中的回覆操作,以及作用中的工作階段通道任務預設仍僅發出警告;如果診斷顯示該工作階段沒有作用中的工作,watchdog 會釋放受影響的工作階段通道,讓佇列中的啟動工作可以清空。 +- 模型閒置逾時:當閒置視窗前沒有回應區塊抵達時,OpenClaw 會中止模型請求。`models.providers..timeoutSeconds` 會為緩慢的本機/自架供應商延長此閒置 watchdog;否則 OpenClaw 會在已設定時使用 `agents.defaults.timeoutSeconds`,預設上限為 120 秒。沒有明確模型或代理逾時的 Cron 觸發執行會停用閒置 watchdog,並依賴 cron 外層逾時。 +- 供應商 HTTP 請求逾時:`models.providers..timeoutSeconds` 會套用至該供應商的模型 HTTP fetch,包括連線、標頭、本文、SDK 請求逾時、完整 guarded-fetch 中止處理,以及模型串流閒置 watchdog。對於 Ollama 等緩慢的本機/自架供應商,請先使用此設定,再提高整個代理執行階段逾時。 ## 可能提早結束的位置 - 代理逾時(中止) - AbortSignal(取消) -- Gateway 中斷連線或 RPC 逾時 +- Gateway 斷線或 RPC 逾時 - `agent.wait` 逾時(僅等待,不會停止代理) ## 相關 - [工具](/zh-TW/tools) — 可用的代理工具 -- [掛鉤](/zh-TW/automation/hooks) — 由代理生命週期事件觸發的事件驅動腳本 -- [Compaction](/zh-TW/concepts/compaction) — 長對話如何被摘要 -- [Exec 核准](/zh-TW/tools/exec-approvals) — shell 指令的核准閘門 +- [Hook](/zh-TW/automation/hooks) — 由代理生命週期事件觸發的事件驅動腳本 +- [Compaction](/zh-TW/concepts/compaction) — 長對話如何摘要 +- [Exec Approvals](/zh-TW/tools/exec-approvals) — shell 指令的核准閘門 - [Thinking](/zh-TW/tools/thinking) — thinking/reasoning 層級設定 diff --git a/docs/zh-TW/concepts/queue.md b/docs/zh-TW/concepts/queue.md index 881e4771a..057c8cf57 100644 --- a/docs/zh-TW/concepts/queue.md +++ b/docs/zh-TW/concepts/queue.md @@ -1,36 +1,36 @@ --- read_when: - - 變更自動回覆的執行或並行處理 + - 變更自動回覆執行或並行性 - 說明 /queue 模式或訊息導向行為 -summary: 自動回覆佇列模式、預設值與各工作階段覆寫設定 +summary: 自動回覆佇列模式、預設值與逐工作階段覆寫 title: 命令佇列 x-i18n: - generated_at: "2026-04-30T03:02:05Z" + generated_at: "2026-04-30T18:38:36Z" model: gpt-5.5 provider: openai - source_hash: 2ac0c0ded9558b080714fa4b8be0d552f985911bf19b427020f9654ae4955b2d + source_hash: fbf1bb1ffd4ce06fa138f63e31651b8821226d9c95dd6b93d68326a5fb91fdd0 source_path: concepts/queue.md workflow: 16 --- -我們會透過一個小型的程序內佇列,序列化入站自動回覆執行(所有頻道),以避免多個代理執行互相碰撞,同時仍允許跨工作階段的安全平行處理。 +我們透過極小型的處理序內佇列序列化傳入的自動回覆執行作業(所有通道),以防止多個代理程式執行作業互相衝突,同時仍允許跨工作階段的安全平行處理。 ## 原因 -- 自動回覆執行可能成本高昂(LLM 呼叫),且當多個入站訊息接近同時抵達時可能會互相碰撞。 -- 序列化可避免競爭共享資源(工作階段檔案、記錄、CLI stdin),並降低觸發上游速率限制的機率。 +- 自動回覆執行作業可能成本很高(LLM 呼叫),而且當多則傳入訊息在短時間內抵達時可能會互相衝突。 +- 序列化可避免競爭共用資源(工作階段檔案、記錄、CLI stdin),並降低觸發上游速率限制的機率。 ## 運作方式 -- 具執行線感知能力的 FIFO 佇列,會以可設定的並行上限排空每個執行線(未設定執行線預設為 1;main 預設為 4,subagent 為 8)。 -- `runEmbeddedPiAgent` 會依 **工作階段鍵**(執行線 `session:`)排入佇列,以保證每個工作階段同時只有一個作用中的執行。 -- 接著每個工作階段執行會再排入 **全域執行線**(預設為 `main`),因此整體平行度會受 `agents.defaults.maxConcurrent` 限制。 -- 啟用詳細記錄時,排隊的執行若在啟動前等待超過約 2 秒,會輸出簡短通知。 -- 輸入指示器仍會在排入佇列時立即觸發(若該頻道支援),因此在等待輪到我們執行時,使用者體驗不會改變。 +- 具備通道感知能力的 FIFO 佇列會以可設定的並行上限清空每個通道(未設定通道預設為 1;main 預設為 4,subagent 為 8)。 +- `runEmbeddedPiAgent` 會依 **工作階段鍵**(通道 `session:`)入列,以保證每個工作階段一次只有一個作用中的執行作業。 +- 接著,每個工作階段執行作業會被排入 **全域通道**(預設為 `main`),因此整體平行度會由 `agents.defaults.maxConcurrent` 設定上限。 +- 啟用詳細記錄時,如果已入列的執行作業在開始前等待超過約 2 秒,會發出簡短通知。 +- 輸入中指示器仍會在入列時立即觸發(若通道支援),因此在等待輪到我們處理時,使用者體驗不會改變。 ## 預設值 -未設定時,所有入站頻道介面都會使用: +未設定時,所有傳入通道介面都使用: - `mode: "steer"` - `debounceMs: 500` @@ -38,29 +38,28 @@ x-i18n: - `drop: "summarize"` `steer` 是預設值,因為它能讓作用中的模型回合保持回應性,而不會 -啟動第二個工作階段執行。它會排空在下一個模型邊界前抵達的所有 steering 訊息。 -如果目前執行無法接受 steering, -OpenClaw 會退回到一個 followup 佇列項目。 +啟動第二個工作階段執行作業。它會清空所有在下一個模型邊界之前抵達的引導訊息。 +如果目前的執行作業無法接受引導,OpenClaw 會退回到後續佇列項目。 ## 佇列模式 -入站訊息可以 steering 目前執行、等待後續回合,或兩者並行: +傳入訊息可以引導目前的執行作業、等待後續回合,或兩者都做: -- `steer`:將 steering 訊息排入作用中的執行階段。Pi 會在**目前助理回合完成工具呼叫執行後**、下一次 LLM 呼叫前,傳遞所有待處理的 steering 訊息;Codex app-server 會接收一個批次的 `turn/steer`。如果執行未處於作用中串流狀態,或 steering 不可用,OpenClaw 會退回到一個 followup 佇列項目。 -- `queue`(舊版):舊的一次一則 steering。Pi 會在每個模型邊界傳遞一則已排隊的 steering 訊息;Codex app-server 會接收個別的 `turn/steer` 請求。除非你需要先前的序列化行為,否則請優先使用 `steer`。 -- `followup`:在目前執行結束後,將每則訊息排入稍後的代理回合。 -- `collect`:在靜默視窗後,將已排隊訊息合併成**單一**後續回合。如果訊息指向不同頻道/執行緒,會個別排空以保留路由。 -- `steer-backlog`(又稱 `steer+backlog`):立即 steering,**並且**保留同一則訊息供後續回合使用。 -- `interrupt`(舊版):中止該工作階段的作用中執行,然後執行最新訊息。 +- `steer`:將引導訊息排入作用中執行階段。Pi 會在**目前助理回合完成其工具呼叫的執行之後**、下一次 LLM 呼叫之前,遞送所有待處理的引導訊息;Codex app-server 會收到一個批次化的 `turn/steer`。如果執行作業沒有正在主動串流,或無法使用引導,OpenClaw 會退回到後續佇列項目。 +- `queue`(舊版):舊的一次一則引導。Pi 會在每個模型邊界遞送一則已入列的引導訊息;Codex app-server 會收到個別的 `turn/steer` 要求。除非你需要先前的序列化行為,否則建議使用 `steer`。 +- `followup`:將每則訊息排入佇列,在目前執行作業結束後供稍後的代理程式回合使用。 +- `collect`:在靜默視窗之後,將已入列的訊息合併成**單一**後續回合。如果訊息指向不同通道/執行緒,會個別清空以保留路由。 +- `steer-backlog`(又稱 `steer+backlog`):立即引導,**並且**保留同一則訊息供後續回合使用。 +- `interrupt`(舊版):中止該工作階段的作用中執行作業,然後執行最新訊息。 -Steer-backlog 表示你可能會在被 steered 的執行後收到後續回應,因此 -串流介面看起來可能像重複回應。如果你想要 -每則入站訊息只產生一個回應,請優先使用 `collect`/`steer`。 +Steer-backlog 代表你可能會在已引導的執行作業之後取得後續回應,因此 +串流介面看起來可能像重複。若你希望每則傳入訊息只產生一個回應, +請優先使用 `collect`/`steer`。 -如需執行階段特定的時序與相依性行為,請參閱 -[Steering 佇列](/zh-TW/concepts/queue-steering)。 +如需執行階段特定的時序與依賴行為,請參閱 +[引導佇列](/zh-TW/concepts/queue-steering)。 -透過 `messages.queue` 進行全域或每個頻道設定: +透過 `messages.queue` 進行全域或每個通道設定: ```json5 { @@ -78,53 +77,53 @@ Steer-backlog 表示你可能會在被 steered 的執行後收到後續回應, ## 佇列選項 -選項會套用到 `followup`、`collect` 和 `steer-backlog`(以及 steering 退回到 followup 時的 `steer` 或舊版 `queue`): +選項適用於 `followup`、`collect` 和 `steer-backlog`(以及當引導退回到後續時的 `steer` 或舊版 `queue`): -- `debounceMs`:排空已排隊 followups 前的靜默視窗。單純數字代表毫秒;`/queue` 選項接受單位 `ms`、`s`、`m`、`h` 和 `d`。 -- `cap`:每個工作階段可排隊的訊息上限。低於 `1` 的值會被忽略。 -- `drop: "summarize"`:預設值。視需要丟棄最舊的佇列項目,保留精簡摘要,並將其注入為合成的 followup 提示。 -- `drop: "old"`:視需要丟棄最舊的佇列項目,不保留摘要。 -- `drop: "new"`:當佇列已滿時拒絕最新訊息。 +- `debounceMs`:清空已入列後續項目前的靜默視窗。純數字代表毫秒;`/queue` 選項接受單位 `ms`、`s`、`m`、`h` 和 `d`。 +- `cap`:每個工作階段最多可入列的訊息數。低於 `1` 的值會被忽略。 +- `drop: "summarize"`:預設值。視需要丟棄最舊的已入列項目,保留精簡摘要,並將其注入為合成的後續提示。 +- `drop: "old"`:視需要丟棄最舊的已入列項目,不保留摘要。 +- `drop: "new"`:佇列已滿時拒絕最新訊息。 預設值:`debounceMs: 500`、`cap: 20`、`drop: summarize`。 ## 優先順序 -針對模式選擇,OpenClaw 會依序解析: +在模式選擇上,OpenClaw 會依序解析: -1. 內嵌或已儲存的每工作階段 `/queue` 覆寫。 +1. 行內或已儲存的每工作階段 `/queue` 覆寫。 2. `messages.queue.byChannel.`。 3. `messages.queue.mode`。 4. 預設 `steer`。 -針對選項,內嵌或已儲存的 `/queue` 選項優先於設定。接著會套用 -頻道特定 debounce(`messages.queue.debounceMsByChannel`)、Plugin +對於選項,行內或已儲存的 `/queue` 選項優先於設定。接著會套用 +通道特定的 debounce(`messages.queue.debounceMsByChannel`)、Plugin debounce 預設值、全域 `messages.queue` 選項,以及內建預設值。 -`cap` 和 `drop` 是全域/工作階段選項,不是每頻道設定 -鍵。 +`cap` 和 `drop` 是全域/工作階段選項,不是每通道設定鍵。 ## 每工作階段覆寫 -- 以獨立命令傳送 `/queue `,即可儲存目前工作階段的模式。 -- 選項可以合併使用:`/queue collect debounce:0.5s cap:25 drop:summarize` +- 將 `/queue ` 作為獨立命令傳送,以儲存目前工作階段的模式。 +- 選項可以合併:`/queue collect debounce:0.5s cap:25 drop:summarize` - `/queue default` 或 `/queue reset` 會清除工作階段覆寫。 ## 範圍與保證 -- 適用於所有使用 Gateway 回覆管線的入站頻道上的自動回覆代理執行(WhatsApp web、Telegram、Slack、Discord、Signal、iMessage、webchat 等)。 -- 預設執行線(`main`)在程序範圍內供入站 + main heartbeats 使用;設定 `agents.defaults.maxConcurrent` 可允許多個工作階段平行執行。 -- 可能存在其他執行線(例如 `cron`、`cron-nested`、`nested`、`subagent`),因此背景工作可以平行執行,而不會阻塞入站回覆。隔離的 cron 代理回合會持有一個 `cron` 槽位,而其內部代理執行會使用 `cron-nested`;兩者都使用 `cron.maxConcurrentRuns`。共享的非 cron `nested` 流程會保留自己的執行線行為。這些分離執行會被追蹤為[背景任務](/zh-TW/automation/tasks)。 -- 每工作階段執行線保證同一時間只有一個代理執行會觸碰指定工作階段。 -- 沒有外部相依性或背景工作執行緒;純 TypeScript + promises。 +- 適用於所有使用 Gateway 回覆管線的傳入通道上的自動回覆代理程式執行作業(WhatsApp web、Telegram、Slack、Discord、Signal、iMessage、webchat 等)。 +- 預設通道(`main`)在處理序範圍內供傳入訊息 + 主要 Heartbeat 共用;設定 `agents.defaults.maxConcurrent` 可允許多個工作階段平行執行。 +- 可能存在其他通道(例如 `cron`、`cron-nested`、`nested`、`subagent`),因此背景工作可以平行執行,而不會阻塞傳入回覆。隔離的 Cron 代理程式回合會在其內部代理程式執行使用 `cron-nested` 時持有一個 `cron` 槽位;兩者都使用 `cron.maxConcurrentRuns`。共用的非 Cron `nested` 流程會保留自身的通道行為。這些分離的執行作業會被追蹤為[背景工作](/zh-TW/automation/tasks)。 +- 每工作階段通道保證一次只有一個代理程式執行作業會觸及指定工作階段。 +- 沒有外部依賴或背景工作執行緒;純 TypeScript + promises。 ## 疑難排解 -- 如果命令看似卡住,請啟用詳細記錄,並尋找「queued for …ms」這類行,以確認佇列正在排空。 +- 如果命令看似卡住,請啟用詳細記錄,並尋找「queued for …ms」行以確認佇列正在清空。 - 如果你需要佇列深度,請啟用詳細記錄並觀察佇列時序行。 -- 啟用診斷時,工作階段若在超過 `diagnostics.stuckSessionWarnMs` 後仍停留在 `processing`,會記錄卡住工作階段警告。作用中的嵌入式執行、作用中的回覆操作,以及作用中的執行線任務,預設仍只會警告;若啟動時的陳舊簿記沒有作用中的工作階段工作,則可釋放受影響的工作階段執行線,讓已排隊工作繼續排空。 +- 接受一個回合後停止發出進度的 Codex app-server 執行作業,會由 Codex 配接器中斷,因此作用中的工作階段通道可以釋放,而不是等待外層執行作業逾時。 +- 啟用診斷時,在超過 `diagnostics.stuckSessionWarnMs` 後仍維持在 `processing` 的工作階段會記錄卡住工作階段警告。作用中的嵌入式執行作業、作用中的回覆操作,以及作用中的通道工作預設仍只會警告;沒有作用中工作階段工作的過時啟動帳務記錄,可以釋放受影響的工作階段通道,使已入列工作得以清空。 ## 相關 - [工作階段管理](/zh-TW/concepts/session) -- [Steering 佇列](/zh-TW/concepts/queue-steering) +- [引導佇列](/zh-TW/concepts/queue-steering) - [重試政策](/zh-TW/concepts/retry) diff --git a/docs/zh-TW/help/testing.md b/docs/zh-TW/help/testing.md index 790ebc70d..bd2d07126 100644 --- a/docs/zh-TW/help/testing.md +++ b/docs/zh-TW/help/testing.md @@ -1,194 +1,151 @@ --- read_when: - 在本機或 CI 中執行測試 - - 為模型/提供者錯誤新增迴歸測試 - - 偵錯 Gateway + 代理程式行為 -summary: 測試工具包:單元/e2e/live 測試套件、Docker 執行器,以及每項測試涵蓋的內容 + - 為模型/提供者錯誤新增回歸測試 + - 偵錯 Gateway + 代理行為 +summary: 測試工具套件:unit/e2e/live 套件、Docker 執行器,以及每項測試涵蓋的內容 title: 測試 x-i18n: - generated_at: "2026-04-30T03:12:40Z" + generated_at: "2026-04-30T18:38:40Z" model: gpt-5.5 provider: openai - source_hash: c7b506350f11431195cb55c84cb10e99efb5f43b934079528b982627024d1ffc + source_hash: 470a96c6b47c2708950d05adc4a4efba5fe290f0675a131e2888d2d0032d5953 source_path: help/testing.md workflow: 16 --- -OpenClaw 有三個 Vitest 測試套件(單元/整合、e2e、live)和一小組 -Docker 執行器。本文件是「我們如何測試」指南: +OpenClaw 有三組 Vitest 測試套件(單元/整合、e2e、live),以及少量 Docker 執行器。這份文件是「我們如何測試」指南: -- 每個套件涵蓋的內容(以及它刻意_不_涵蓋的內容)。 -- 常見工作流程(本機、推送前、除錯)應執行哪些命令。 -- live 測試如何探索憑證並選擇模型/提供者。 -- 如何針對真實世界的模型/提供者問題新增迴歸測試。 +- 每個套件涵蓋的範圍(以及刻意 _不_ 涵蓋的範圍)。 +- 常見工作流程要執行哪些命令(本機、推送前、除錯)。 +- live 測試如何探索認證資料並選取模型/提供者。 +- 如何為真實世界的模型/提供者問題新增迴歸測試。 -**QA 堆疊(qa-lab、qa-channel、live 傳輸通道)**另有文件說明: +**QA 堆疊(qa-lab、qa-channel、live 傳輸通道)**已另行記錄: -- [QA 概覽](/zh-TW/concepts/qa-e2e-automation) — 架構、命令介面、情境撰寫。 -- [矩陣 QA](/zh-TW/concepts/qa-matrix) — `pnpm openclaw qa matrix` 的參考。 -- [QA channel](/zh-TW/channels/qa-channel) — repo 支援情境所使用的合成傳輸 Plugin。 +- [QA 總覽](/zh-TW/concepts/qa-e2e-automation) — 架構、命令介面、情境撰寫。 +- [Matrix QA](/zh-TW/concepts/qa-matrix) — `pnpm openclaw qa matrix` 的參考。 +- [QA channel](/zh-TW/channels/qa-channel) — 由 repo 支援的情境所使用的合成傳輸 Plugin。 -本頁涵蓋一般測試套件和 Docker/Parallels 執行器的執行方式。下方 QA 專用執行器章節([QA 專用執行器](#qa-specific-runners))列出具體的 `qa` 呼叫,並指回上面的參考資料。 +本頁涵蓋一般測試套件與 Docker/Parallels 執行器的執行方式。下方的 QA 專用執行器章節([QA 專用執行器](#qa-specific-runners))列出具體的 `qa` 呼叫方式,並指回上述參考。 ## 快速開始 -多數日常情況: +大多數時候: - 完整閘門(推送前預期執行):`pnpm build && pnpm check && pnpm check:test-types && pnpm test` -- 在資源充足機器上更快的本機完整套件執行:`pnpm test:max` -- 直接的 Vitest 監看迴圈:`pnpm test:watch` -- 直接指定檔案現在也會路由 extension/channel 路徑:`pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` +- 在資源充足機器上的較快本機完整套件執行:`pnpm test:max` +- 直接 Vitest 監看迴圈:`pnpm test:watch` +- 直接檔案目標現在也會路由擴充功能/通道路徑:`pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` - 當你正在迭代單一失敗時,優先使用目標式執行。 - Docker 支援的 QA 站台:`pnpm qa:lab:up` - Linux VM 支援的 QA 通道:`pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline` -當你修改測試或想要額外信心時: +當你變更測試或想要額外信心時: - 覆蓋率閘門:`pnpm test:coverage` - E2E 套件:`pnpm test:e2e` -除錯真實提供者/模型時(需要真實憑證): +當除錯真實提供者/模型時(需要真實認證資料): -- Live 套件(模型 + Gateway 工具/圖片探測):`pnpm test:live` -- 安靜地指定一個 live 檔案:`pnpm test:live -- src/agents/models.profiles.live.test.ts` +- Live 套件(模型 + Gateway 工具/影像探測):`pnpm test:live` +- 安靜地鎖定一個 live 檔案:`pnpm test:live -- src/agents/models.profiles.live.test.ts` - Docker live 模型掃描:`pnpm test:docker:live-models` - - 每個選取的模型現在會執行一個文字回合,以及一個小型類似檔案讀取的探測。 - 中繼資料宣告支援 `image` 輸入的模型,也會執行一個小型圖片回合。 + - 每個選取的模型現在會執行一個文字回合,加上一個小型檔案讀取風格探測。 + 中繼資料宣告支援 `image` 輸入的模型也會執行一個小型影像回合。 在隔離提供者失敗時,可用 `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` 或 `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0` 停用額外探測。 - - CI 覆蓋:每日 `OpenClaw Scheduled Live And E2E Checks` 和手動 - `OpenClaw Release Checks` 都會以 `include_live_suites: true` 呼叫可重用的 live/E2E workflow,其中包含依提供者分片的獨立 Docker live 模型 - 矩陣工作。 - - 若要進行聚焦的 CI 重新執行,請以 `include_live_suites: true` 和 `live_models_only: true` 觸發 `OpenClaw Live And E2E Checks (Reusable)`。 - - 將新的高訊號提供者 secrets 新增到 `scripts/ci-hydrate-live-auth.sh` - 以及 `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` 和其 - 排程/發布呼叫端。 + - CI 覆蓋:每日 `OpenClaw Scheduled Live And E2E Checks` 與手動 + `OpenClaw Release Checks` 都會以 `include_live_suites: true` 呼叫可重用的 live/E2E workflow,其中包含依提供者分片的獨立 Docker live 模型矩陣 jobs。 + - 若要進行聚焦的 CI 重新執行,請 dispatch `OpenClaw Live And E2E Checks (Reusable)`,並設定 `include_live_suites: true` 與 `live_models_only: true`。 + - 將新的高訊號提供者 secret 新增到 `scripts/ci-hydrate-live-auth.sh`, + 以及 `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` 和其排程/發行呼叫端。 - 原生 Codex 綁定聊天 smoke:`pnpm test:docker:live-codex-bind` - - 對 Codex app-server 路徑執行 Docker live 通道,使用 `/codex bind` 綁定合成的 - Slack DM,演練 `/codex fast` 和 - `/codex permissions`,接著驗證純文字回覆與圖片附件會透過原生 Plugin 綁定路由,而不是 ACP。 + - 針對 Codex app-server 路徑執行 Docker live 通道,使用 `/codex bind` 綁定合成 Slack DM,執行 `/codex fast` 與 + `/codex permissions`,然後驗證純文字回覆與影像附件會經由原生 Plugin 綁定路由,而不是 ACP。 - Codex app-server harness smoke:`pnpm test:docker:live-codex-harness` - - 透過 Plugin 擁有的 Codex app-server harness 執行 Gateway agent 回合, - 驗證 `/codex status` 和 `/codex models`,且預設會演練圖片、 - cron MCP、sub-agent 和 Guardian 探測。在隔離其他 Codex - app-server 失敗時,可用 `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0` 停用 sub-agent 探測。若要進行聚焦的 sub-agent 檢查,請停用其他探測: + - 透過 Plugin 擁有的 Codex app-server harness 執行 Gateway agent 回合,驗證 `/codex status` 與 `/codex models`,並預設執行影像、cron MCP、子 agent 與 Guardian 探測。隔離其他 Codex app-server 失敗時,可用 + `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0` 停用子 agent 探測。若要聚焦檢查子 agent,請停用其他探測: `OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=1 pnpm test:docker:live-codex-harness`。 - 除非設定 `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY=0`,否則這會在 sub-agent 探測後結束。 -- Crestodian rescue command smoke:`pnpm test:live:crestodian-rescue-channel` - - 針對 message-channel rescue command - 介面的選擇加入式加強檢查。它會演練 `/crestodian status`、排入持久化模型 - 變更、回覆 `/crestodian yes`,並驗證稽核/設定寫入路徑。 + 除非設定 `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY=0`,否則這會在子 agent 探測後結束。 +- Crestodian rescue 命令 smoke:`pnpm test:live:crestodian-rescue-channel` + - 針對訊息通道 rescue 命令介面的選擇性雙重保險檢查。它會執行 `/crestodian status`、佇列一個持久模型變更、回覆 `/crestodian yes`,並驗證稽核/設定寫入路徑。 - Crestodian planner Docker smoke:`pnpm test:docker:crestodian-planner` - - 在 `PATH` 上具有假 Claude CLI 的無設定容器中執行 Crestodian, - 並驗證模糊 planner fallback 會轉換成經稽核的具型別設定寫入。 + - 在無設定的容器中執行 Crestodian,並在 `PATH` 上放置假的 Claude CLI,驗證 fuzzy planner fallback 會轉譯成已稽核的型別化設定寫入。 - Crestodian first-run Docker smoke:`pnpm test:docker:crestodian-first-run` - - 從空的 OpenClaw 狀態目錄開始,將裸 `openclaw` 路由到 - Crestodian,套用 setup/model/agent/Discord Plugin + SecretRef 寫入, - 驗證設定,並驗證稽核項目。相同的 Ring 0 設定路徑 - 也在 QA Lab 中由 + - 從空的 OpenClaw 狀態目錄開始,將裸 `openclaw` 路由至 + Crestodian,套用 setup/model/agent/Discord Plugin + SecretRef 寫入,驗證設定,並驗證稽核項目。相同的 Ring 0 設定路徑也由 QA Lab 中的 `pnpm openclaw qa suite --scenario crestodian-ring-zero-setup` 涵蓋。 - Moonshot/Kimi 成本 smoke:設定 `MOONSHOT_API_KEY` 後,執行 - `openclaw models list --provider moonshot --json`,接著對 - `moonshot/kimi-k2.6` 執行隔離的 + `openclaw models list --provider moonshot --json`,接著針對 `moonshot/kimi-k2.6` 執行隔離的 `openclaw agent --local --session-id live-kimi-cost --message 'Reply exactly: KIMI_LIVE_OK' --thinking off --json`。 - 驗證 JSON 回報 Moonshot/K2.6,且 assistant transcript 儲存正規化後的 `usage.cost`。 + 驗證 JSON 回報 Moonshot/K2.6,且 assistant transcript 儲存標準化的 `usage.cost`。 -當你只需要一個失敗案例時,優先透過下方說明的 allowlist env vars 縮小 live 測試範圍。 +當你只需要一個失敗案例時,優先透過下方描述的 allowlist env vars 縮小 live 測試範圍。 ## QA 專用執行器 -當你需要 QA-lab 真實性時,這些命令與主要測試套件並列: +當你需要 QA-lab 真實度時,這些命令會與主要測試套件並列: -CI 會在專用 workflow 中執行 QA Lab。`Parity gate` 會在符合條件的 PR 上執行,並可透過手動觸發搭配 mock 提供者執行。`QA-Lab - All Lanes` 每晚在 -`main` 上執行,也可透過手動觸發,以 mock parity gate、live Matrix 通道、 -Convex 管理的 live Telegram 通道,以及 Convex 管理的 live Discord 通道作為 -平行工作執行。排程 QA 和發布檢查會明確傳入 Matrix `--profile fast`, -而 Matrix CLI 與手動 workflow 輸入的預設值仍為 -`all`;手動觸發可以將 `all` 分片成 `transport`、`media`、`e2ee-smoke`、 -`e2ee-deep` 和 `e2ee-cli` 工作。`OpenClaw Release Checks` 會在發布核准前執行 parity 加上 -fast Matrix 和 Telegram 通道,並使用 -`mock-openai/gpt-5.5` 進行發布傳輸檢查,讓它們保持決定性 -並避免一般提供者 Plugin 啟動。這些 live 傳輸 Gateway 會停用 -記憶搜尋;記憶行為仍由 QA parity 套件涵蓋。 +CI 會在專用 workflows 中執行 QA Lab。`Parity gate` 會在相符 PR 與手動 dispatch 時使用 mock providers 執行。`QA-Lab - All Lanes` 會每晚在 `main` 上執行,也可手動 dispatch,並將 mock parity gate、live Matrix 通道、Convex 管理的 live Telegram 通道,以及 Convex 管理的 live Discord 通道作為平行 jobs。排程 QA 與發行檢查會明確傳遞 Matrix `--profile fast`,而 Matrix CLI 與手動 workflow input 的預設值維持 +`all`;手動 dispatch 可將 `all` 分片成 `transport`、`media`、`e2ee-smoke`、 +`e2ee-deep` 與 `e2ee-cli` jobs。`OpenClaw Release Checks` 會在發行核准前執行 parity 加上 fast Matrix 與 Telegram 通道,並使用 +`mock-openai/gpt-5.5` 進行發行傳輸檢查,讓它們保持可決定性並避免一般提供者 Plugin 啟動。這些 live 傳輸 Gateway 會停用記憶體搜尋;記憶體行為仍由 QA parity 套件涵蓋。 -完整發布 live media 分片使用 -`ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04`,其中已具備 -`ffmpeg` 和 `ffprobe`。Docker live 模型/後端分片使用共用的 -`ghcr.io/openclaw/openclaw-live-test:` 映像檔,該映像檔會針對每個選取的 -commit 建置一次,接著以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 拉取,而不是在每個分片內重新建置。 +完整發行 live media 分片使用 +`ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04`,其中已包含 +`ffmpeg` 與 `ffprobe`。Docker live 模型/backend 分片使用共用的 +`ghcr.io/openclaw/openclaw-live-test:` 映像檔,該映像檔會為每個選取 commit 建置一次,之後以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 拉取,而不是在每個分片內重新建置。 - `pnpm openclaw qa suite` - - 直接在主機上執行 repo 支援的 QA 情境。 - - 預設使用隔離的 gateway worker 平行執行多個已選情境。 - `qa-channel` 預設並行度為 4(受已選情境數量限制)。使用 `--concurrency ` 調整 worker - 數量,或用 `--concurrency 1` 執行較舊的序列通道。 - - 當任何情境失敗時會以非零狀態結束。若你想取得 artifacts 而不要失敗結束碼,請使用 `--allow-failures`。 - - 支援提供者模式 `live-frontier`、`mock-openai` 和 `aimock`。 - `aimock` 會啟動本機 AIMock 支援的提供者伺服器,用於實驗性 - fixture 與 protocol-mock 覆蓋,而不取代情境感知的 + - 直接在 host 上執行由 repo 支援的 QA 情境。 + - 預設會使用隔離的 Gateway workers 平行執行多個選取情境。`qa-channel` 預設 concurrency 為 4(受選取情境數量限制)。使用 `--concurrency ` 調整 worker 數量,或使用 `--concurrency 1` 執行較舊的序列通道。 + - 任一情境失敗時會以非零狀態結束。當你想要產物但不想要失敗退出碼時,使用 `--allow-failures`。 + - 支援提供者模式 `live-frontier`、`mock-openai` 與 `aimock`。 + `aimock` 會啟動本機 AIMock 支援的提供者伺服器,用於實驗性 fixture 與 protocol-mock 覆蓋,而不取代情境感知的 `mock-openai` 通道。 - `pnpm test:gateway:cpu-scenarios` - - 執行 Gateway 啟動 bench,加上一小包 mock QA Lab 情境 + - 執行 Gateway 啟動 bench 加上一小組 mock QA Lab 情境套件 (`channel-chat-baseline`、`memory-failure-fallback`、 - `gateway-restart-inflight-run`),並在 - `.artifacts/gateway-cpu-scenarios/` 下寫入合併的 CPU 觀察 - 摘要。 - - 預設只標記持續性的高 CPU 觀察(`--cpu-core-warn` - 加上 `--hot-wall-warn-ms`),因此短暫啟動突增會被記錄為指標, - 而不會看起來像持續數分鐘的 Gateway peg 迴歸。 - - 使用已建置的 `dist` artifacts;當 checkout 尚未具備新的 runtime 輸出時,請先執行 build。 + `gateway-restart-inflight-run`),並在 `.artifacts/gateway-cpu-scenarios/` 下寫入合併的 CPU 觀察摘要。 + - 預設只標記持續性高 CPU 觀察(`--cpu-core-warn` 加上 `--hot-wall-warn-ms`),因此短暫啟動突增會被記錄為指標,而不會看起來像數分鐘 Gateway 滿載迴歸。 + - 使用已建置的 `dist` 產物;當 checkout 尚未有新鮮 runtime 輸出時,請先執行 build。 - `pnpm openclaw qa suite --runner multipass` - - 在可拋棄的 Multipass Linux VM 內執行相同的 QA 套件。 - - 保持與主機上 `qa suite` 相同的情境選擇行為。 - - 重用與 `qa suite` 相同的提供者/模型選擇旗標。 - - Live 執行會轉送對 guest 實際可行的支援 QA auth 輸入: - env 型提供者金鑰、QA live 提供者設定路徑,以及存在時的 `CODEX_HOME`。 - - 輸出目錄必須保留在 repo root 下,讓 guest 能透過掛載的工作區寫回。 - - 在 `.artifacts/qa-e2e/...` 下寫入一般 QA 報告 + 摘要以及 Multipass logs。 + - 在一次性 Multipass Linux VM 中執行相同 QA 套件。 + - 保持與 host 上 `qa suite` 相同的情境選取行為。 + - 重用與 `qa suite` 相同的提供者/模型選取 flags。 + - Live 執行會轉送對 guest 來說實用的支援 QA auth inputs: + env 型提供者 keys、QA live provider config path,以及存在時的 `CODEX_HOME`。 + - 輸出目錄必須保持在 repo root 下,讓 guest 能透過已掛載 workspace 寫回。 + - 在 `.artifacts/qa-e2e/...` 下寫入一般 QA report + summary 加上 Multipass logs。 - `pnpm qa:lab:up` - - 啟動 Docker 支援的 QA 站台,用於 operator 風格的 QA 工作。 + - 啟動 Docker 支援的 QA 站台,用於 operator 風格 QA 工作。 - `pnpm test:docker:npm-onboard-channel-agent` - - 從目前 checkout 建置 npm tarball,在 - Docker 中全域安裝它,執行非互動式 OpenAI API-key onboarding,預設設定 Telegram, - 驗證啟用 Plugin 會依需求安裝 runtime dependencies, - 執行 doctor,並對 mocked OpenAI - endpoint 執行一個本機 agent 回合。 - - 使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 以 Discord 執行相同的 packaged-install - 通道。 + - 從目前 checkout 建置 npm tarball,在 Docker 中全域安裝,執行非互動式 OpenAI API key onboarding,預設設定 Telegram,驗證啟用 Plugin 會依需求安裝 runtime dependencies,執行 doctor,並針對 mocked OpenAI endpoint 執行一個本機 agent 回合。 + - 使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 以 Discord 執行相同的 packaged-install 通道。 - `pnpm test:docker:session-runtime-context` - - 針對嵌入式 runtime context - transcripts 執行決定性的 built-app Docker smoke。它會驗證隱藏的 OpenClaw runtime context 會持久化為 - 非顯示的 custom message,而不是洩漏到可見的 user turn, - 接著植入受影響的破損 session JSONL,並驗證 - `openclaw doctor --fix` 會以備份將它重寫到 active branch。 + - 針對嵌入式 runtime context transcripts 執行可決定性的 built-app Docker smoke。它會驗證隱藏 OpenClaw runtime context 會作為非顯示 custom message 持久化,而不是洩漏到可見 user turn,然後植入受影響的損壞 session JSONL,並驗證 + `openclaw doctor --fix` 會將其改寫到 active branch 並建立備份。 - `pnpm test:docker:npm-telegram-live` - - 在 Docker 中安裝 OpenClaw package candidate,執行 installed-package - onboarding,透過已安裝的 CLI 設定 Telegram,接著將該已安裝 package 作為 SUT Gateway 重用 - live Telegram QA 通道。 + - 在 Docker 中安裝 OpenClaw package candidate,執行 installed-package onboarding,透過已安裝 CLI 設定 Telegram,接著重用 live Telegram QA 通道,並將該已安裝 package 作為 SUT Gateway。 - 預設為 `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta`;設定 `OPENCLAW_NPM_TELEGRAM_PACKAGE_TGZ=/path/to/openclaw-current.tgz` 或 - `OPENCLAW_CURRENT_PACKAGE_TGZ`,即可測試已解析的本機 tarball,而不是 - 從 registry 安裝。 - - 使用與 `pnpm openclaw qa telegram` 相同的 Telegram env 憑證或 Convex credential source。對於 CI/發布自動化,請設定 - `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex` 加上 - `OPENCLAW_QA_CONVEX_SITE_URL` 和 role secret。若 - `OPENCLAW_QA_CONVEX_SITE_URL` 和 Convex role secret 存在於 CI 中, - Docker wrapper 會自動選擇 Convex。 + `OPENCLAW_CURRENT_PACKAGE_TGZ`,可測試已解析的本機 tarball,而不是從 registry 安裝。 + - 使用與 `pnpm openclaw qa telegram` 相同的 Telegram env credentials 或 Convex credential source。對於 CI/發行自動化,設定 + `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex`,加上 + `OPENCLAW_QA_CONVEX_SITE_URL` 與 role secret。如果 + `OPENCLAW_QA_CONVEX_SITE_URL` 與 Convex role secret 存在於 CI 中, + Docker wrapper 會自動選取 Convex。 - `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintainer` 只會針對此通道覆寫共用的 `OPENCLAW_QA_CREDENTIAL_ROLE`。 - GitHub Actions 將此通道公開為手動 maintainer workflow - `NPM Telegram Beta E2E`。它不會在 merge 時執行。此 workflow 使用 - `qa-live-shared` environment 和 Convex CI credential leases。 -- GitHub Actions 也公開 `Package Acceptance`,用於對單一 candidate package 進行 side-run 產品證明。 - 它接受受信任的 ref、已發布的 npm spec、 - HTTPS tarball URL 加 SHA-256,或來自另一個 run 的 tarball artifact,上傳 - 正規化後的 `openclaw-current.tgz` 作為 `package-under-test`,接著以 smoke、package、product、full 或 custom - 通道 profile 執行既有的 Docker E2E scheduler。設定 `telegram_mode=mock-openai` 或 `live-frontier`,即可針對相同的 `package-under-test` artifact 執行 - Telegram QA workflow。 + `NPM Telegram Beta E2E`。它不會在 merge 時執行。該 workflow 使用 + `qa-live-shared` environment 與 Convex CI credential leases。 +- GitHub Actions 也公開 `Package Acceptance`,用於針對一個 candidate package 進行旁路產品證明。它接受受信任 ref、已發布 npm spec、HTTPS tarball URL 加上 SHA-256,或來自另一個 run 的 tarball artifact,將標準化的 `openclaw-current.tgz` 上傳為 `package-under-test`,然後使用 smoke、package、product、full 或 custom 通道 profiles 執行既有 Docker E2E scheduler。設定 `telegram_mode=mock-openai` 或 `live-frontier`,可針對相同的 `package-under-test` artifact 執行 Telegram QA workflow。 - 最新 beta 產品證明: ```bash @@ -209,7 +166,7 @@ gh workflow run package-acceptance.yml --ref main \ -f suite_profile=package ``` -- Artifact proof 會從另一個 Actions 執行作業下載 tarball Artifact: +- Artifact 證明會從另一個 Actions 執行下載 tarball Artifact: ```bash gh workflow run package-acceptance.yml --ref main \ @@ -220,60 +177,60 @@ gh workflow run package-acceptance.yml --ref main \ ``` - `pnpm test:docker:bundled-channel-deps` - - 在 Docker 中封裝並安裝目前的 OpenClaw 建置,啟動已設定 OpenAI 的 Gateway,然後透過設定編輯啟用內建 channel/plugins。 - - 驗證設定探索會讓未設定 Plugin 的執行階段依賴項保持不存在,第一次已設定的 Gateway 或 doctor 執行會按需安裝每個內建 Plugin 的執行階段依賴項,且第二次重新啟動不會重新安裝已啟用的依賴項。 - - 也會安裝已知的較舊 npm 基準版本,在執行 `openclaw update --tag ` 前啟用 Telegram,並驗證候選版本的更新後 doctor 會修復內建 channel 執行階段依賴項,而不需要 harness 端 postinstall 修復。 + - 在 Docker 中封裝並安裝目前的 OpenClaw 建置,啟動已設定 OpenAI 的 Gateway,然後透過設定編輯啟用內建通道/Plugin。 + - 驗證設定探索會讓未設定的 Plugin 執行階段相依性保持不存在,第一次設定後的 Gateway 或 doctor 執行會按需安裝每個內建 Plugin 的執行階段相依性,而第二次重新啟動不會重新安裝已啟用的相依性。 + - 也會安裝已知較舊的 npm 基準版本,在執行 `openclaw update --tag ` 前啟用 Telegram,並驗證候選版本的更新後 doctor 會修復內建通道執行階段相依性,而不需要測試框架端的 postinstall 修復。 - `pnpm test:parallels:npm-update` - - 跨 Parallels guest 執行原生封裝安裝更新 smoke。每個選取的平台會先安裝要求的基準套件,接著在同一個 guest 中執行已安裝的 `openclaw update` 命令,並驗證已安裝版本、更新狀態、Gateway 就緒狀態,以及一次本機 agent 回合。 - - 在針對單一 guest 反覆測試時,使用 `--platform macos`、`--platform windows` 或 `--platform linux`。使用 `--json` 取得摘要 Artifact 路徑與每個 lane 的狀態。 - - OpenAI lane 預設使用 `openai/gpt-5.5` 作為即時 agent 回合 proof。若刻意驗證另一個 OpenAI 模型,請傳入 `--model ` 或設定 `OPENCLAW_PARALLELS_OPENAI_MODEL`。 - - 將長時間本機執行包在主機 timeout 中,避免 Parallels 傳輸停滯耗盡剩餘測試時間: + - 跨 Parallels guest 執行原生封裝安裝更新 smoke。每個選定的平台會先安裝要求的基準套件,然後在同一個 guest 中執行已安裝的 `openclaw update` 命令,並驗證已安裝版本、更新狀態、Gateway 就緒狀態,以及一個本機代理回合。 + - 在針對單一 guest 反覆測試時,使用 `--platform macos`、`--platform windows` 或 `--platform linux`。使用 `--json` 取得摘要 Artifact 路徑和每條 lane 狀態。 + - OpenAI lane 預設使用 `openai/gpt-5.5` 作為即時代理回合證明。刻意驗證另一個 OpenAI 模型時,傳入 `--model ` 或設定 `OPENCLAW_PARALLELS_OPENAI_MODEL`。 + - 將長時間本機執行包在主機逾時中,避免 Parallels 傳輸停滯耗盡剩餘測試時段: ```bash timeout --foreground 150m pnpm test:parallels:npm-update -- --json timeout --foreground 90m pnpm test:parallels:npm-update -- --platform windows --json ``` - - 此腳本會在 `/tmp/openclaw-parallels-npm-update.*` 下寫入巢狀 lane 記錄檔。先檢查 `windows-update.log`、`macos-update.log` 或 `linux-update.log`,再判定外層 wrapper 是否卡住。 - - Windows 更新在冷 guest 上可能會花 10 到 15 分鐘進行更新後 doctor/執行階段依賴修復;只要巢狀 npm debug 記錄檔仍在推進,這仍屬正常。 - - 不要將這個彙總 wrapper 與個別 Parallels macOS、Windows 或 Linux smoke lane 並行執行。它們共用 VM 狀態,可能在 snapshot 還原、套件服務或 guest Gateway 狀態上發生衝突。 - - 更新後 proof 會執行一般內建 Plugin 表面,因為語音、影像生成與媒體理解等 capability facade 會透過內建執行階段 API 載入,即使 agent 回合本身只檢查簡單文字回應。 + - 腳本會在 `/tmp/openclaw-parallels-npm-update.*` 下寫入巢狀 lane 記錄。先檢查 `windows-update.log`、`macos-update.log` 或 `linux-update.log`,再判定外層 wrapper 已停住。 + - Windows 更新在冷 guest 上可能會花 10 到 15 分鐘執行更新後 doctor/執行階段相依性修復;只要巢狀 npm 偵錯記錄仍在前進,這仍是健康狀態。 + - 不要將這個聚合 wrapper 與個別 Parallels macOS、Windows 或 Linux smoke lane 並行執行。它們共用 VM 狀態,可能在 snapshot 還原、套件服務或 guest Gateway 狀態上發生衝突。 + - 更新後證明會執行一般內建 Plugin 介面,因為語音、影像生成和媒體理解等能力 facade 會透過內建執行階段 API 載入,即使代理回合本身只檢查簡單文字回應。 - `pnpm openclaw qa aimock` - - 只啟動本機 AIMock provider 伺服器,用於直接協定 smoke 測試。 + - 僅啟動本機 AIMock provider 伺服器,用於直接 protocol smoke 測試。 - `pnpm openclaw qa matrix` - - 對一次性 Docker 後端 Tuwunel homeserver 執行 Matrix 即時 QA lane。僅限原始碼 checkout,封裝安裝不會交付 `qa-lab`。 - - 完整 CLI、profile/scenario catalog、env vars 與 Artifact 配置:[Matrix QA](/zh-TW/concepts/qa-matrix)。 + - 針對一次性 Docker 後端的 Tuwunel homeserver 執行 Matrix 即時 QA lane。僅限 source checkout — 封裝安裝不會隨附 `qa-lab`。 + - 完整 CLI、profile/scenario 目錄、環境變數與 Artifact 版面配置:[Matrix QA](/zh-TW/concepts/qa-matrix)。 - `pnpm openclaw qa telegram` - - 使用來自 env 的 driver 與 SUT bot token,對真實私人群組執行 Telegram 即時 QA lane。 - - 需要 `OPENCLAW_QA_TELEGRAM_GROUP_ID`、`OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` 和 `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`。群組 ID 必須是數字 Telegram chat ID。 - - 支援 `--credential-source convex` 以使用共用池化憑證。預設使用 env 模式,或設定 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` 以選擇加入池化 lease。 - - 當任何 scenario 失敗時會以非零狀態結束。若想取得 Artifact 但不讓結束碼失敗,請使用 `--allow-failures`。 + - 使用來自環境的 driver 和 SUT bot token,針對真實私人群組執行 Telegram 即時 QA lane。 + - 需要 `OPENCLAW_QA_TELEGRAM_GROUP_ID`、`OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` 和 `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`。群組 ID 必須是數值型 Telegram chat ID。 + - 支援 `--credential-source convex` 以使用共用集區憑證。預設使用 env 模式,或設定 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` 以選用集區 lease。 + - 任何 scenario 失敗時會以非零狀態結束。當你想取得 Artifact 而不想要失敗結束碼時,使用 `--allow-failures`。 - 需要同一個私人群組中的兩個不同 bot,且 SUT bot 必須公開 Telegram 使用者名稱。 - - 為了穩定的 bot 對 bot 觀察,請在 `@BotFather` 中為兩個 bot 啟用 Bot-to-Bot Communication Mode,並確認 driver bot 可以觀察群組 bot 流量。 - - 會在 `.artifacts/qa-e2e/...` 下寫入 Telegram QA 報告、摘要與 observed-messages Artifact。回覆 scenario 包含從 driver 傳送請求到觀察到 SUT 回覆的 RTT。 + - 為了穩定的 bot 對 bot 觀察,請在 `@BotFather` 中為兩個 bot 啟用 Bot-to-Bot Communication Mode,並確保 driver bot 可以觀察群組 bot 流量。 + - 會在 `.artifacts/qa-e2e/...` 下寫入 Telegram QA 報告、摘要和 observed-messages Artifact。回覆 scenarios 包含從 driver 傳送要求到觀察到 SUT 回覆的 RTT。 -即時傳輸 lane 共用一個標準合約,讓新傳輸不會偏移;每個 lane 的涵蓋矩陣位於 [QA 概覽 → 即時傳輸涵蓋範圍](/zh-TW/concepts/qa-e2e-automation#live-transport-coverage)。`qa-channel` 是廣泛的合成套件,不屬於該矩陣。 +即時傳輸 lane 共用一個標準合約,讓新的傳輸不會偏移;每個 lane 的涵蓋矩陣位於 [QA 概觀 → 即時傳輸涵蓋範圍](/zh-TW/concepts/qa-e2e-automation#live-transport-coverage)。`qa-channel` 是廣泛的合成套件,不屬於該矩陣。 ### 透過 Convex 共用 Telegram 憑證 (v1) -當為 `openclaw qa telegram` 啟用 `--credential-source convex`(或 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`)時,QA lab 會從 Convex 後端池取得獨占 lease,在 lane 執行期間對該 lease 傳送 Heartbeat,並在關閉時釋放 lease。 +為 `openclaw qa telegram` 啟用 `--credential-source convex`(或 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`)時,QA lab 會從 Convex 後端集區取得獨佔 lease,在 lane 執行期間對該 lease 傳送 Heartbeat,並在關閉時釋放 lease。 參考 Convex 專案 scaffold: - `qa/convex-credential-broker/` -必要 env vars: +必要環境變數: - `OPENCLAW_QA_CONVEX_SITE_URL`(例如 `https://your-deployment.convex.site`) -- 針對選取角色的一個 secret: +- 所選角色的一個 secret: - `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER` 用於 `maintainer` - `OPENCLAW_QA_CONVEX_SECRET_CI` 用於 `ci` - 憑證角色選擇: - CLI:`--credential-role maintainer|ci` - Env 預設值:`OPENCLAW_QA_CREDENTIAL_ROLE`(在 CI 中預設為 `ci`,否則為 `maintainer`) -選用 env vars: +選用環境變數: - `OPENCLAW_QA_CREDENTIAL_LEASE_TTL_MS`(預設 `1200000`) - `OPENCLAW_QA_CREDENTIAL_HEARTBEAT_INTERVAL_MS`(預設 `30000`) @@ -281,13 +238,13 @@ gh workflow run package-acceptance.yml --ref main \ - `OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS`(預設 `15000`) - `OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX`(預設 `/qa-credentials/v1`) - `OPENCLAW_QA_CREDENTIAL_OWNER_ID`(選用 trace ID) -- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` 允許僅限本機開發使用 loopback `http://` Convex URL。 +- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` 允許 local-only 開發使用 loopback `http://` Convex URL。 `OPENCLAW_QA_CONVEX_SITE_URL` 在一般操作中應使用 `https://`。 -Maintainer 管理命令(pool add/remove/list)特別需要 `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`。 +Maintainer 管理命令(集區新增/移除/列出)特別需要 `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`。 -Maintainer 可用的 CLI helper: +供 maintainer 使用的 CLI helper: ```bash pnpm openclaw qa credentials doctor @@ -296,7 +253,7 @@ pnpm openclaw qa credentials list --kind telegram pnpm openclaw qa credentials remove --credential-id ``` -在即時執行前使用 `doctor` 檢查 Convex site URL、broker secret、endpoint prefix、HTTP timeout 與 admin/list 可達性,而不列印 secret 值。在腳本和 CI 工具中使用 `--json` 取得機器可讀輸出。 +在即時執行前使用 `doctor` 檢查 Convex site URL、broker secret、endpoint prefix、HTTP 逾時和 admin/list 可達性,且不列印 secret 值。在腳本和 CI 工具中使用 `--json` 取得機器可讀輸出。 預設 endpoint 合約(`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`): @@ -310,211 +267,212 @@ pnpm openclaw qa credentials remove --credential-id - `POST /release` - Request: `{ kind, ownerId, actorRole, credentialId, leaseToken }` - Success: `{ status: "ok" }`(或空的 `2xx`) -- `POST /admin/add`(僅限 maintainer secret) +- `POST /admin/add`(僅 maintainer secret) - Request: `{ kind, actorId, payload, note?, status? }` - Success: `{ status: "ok", credential }` -- `POST /admin/remove`(僅限 maintainer secret) +- `POST /admin/remove`(僅 maintainer secret) - Request: `{ credentialId, actorId }` - Success: `{ status: "ok", changed, credential }` - Active lease guard: `{ status: "error", code: "LEASE_ACTIVE", ... }` -- `POST /admin/list`(僅限 maintainer secret) +- `POST /admin/list`(僅 maintainer secret) - Request: `{ kind?, status?, includePayload?, limit? }` - Success: `{ status: "ok", credentials, count }` Telegram kind 的 payload 形狀: - `{ groupId: string, driverToken: string, sutToken: string }` -- `groupId` 必須是數字 Telegram chat ID 字串。 -- `admin/add` 會針對 `kind: "telegram"` 驗證此形狀,並拒絕格式錯誤的 payload。 +- `groupId` 必須是數值型 Telegram chat ID 字串。 +- `admin/add` 會針對 `kind: "telegram"` 驗證這個形狀,並拒絕格式錯誤的 payload。 -### 將 channel 加入 QA +### 將通道加入 QA -新 channel adapter 的架構與 scenario-helper 名稱位於 [QA 概覽 → 加入 channel](/zh-TW/concepts/qa-e2e-automation#adding-a-channel)。最低標準:在共用 `qa-lab` host seam 上實作 transport runner,在 Plugin manifest 中宣告 `qaRunners`,掛載為 `openclaw qa `,並在 `qa/scenarios/` 下編寫 scenario。 +新通道 adapter 的架構和 scenario-helper 名稱位於 [QA 概觀 → 新增通道](/zh-TW/concepts/qa-e2e-automation#adding-a-channel)。最低標準:在共用 `qa-lab` host seam 上實作 transport runner,在 Plugin manifest 中宣告 `qaRunners`,掛載為 `openclaw qa `,並在 `qa/scenarios/` 下撰寫 scenario。 -## 測試套件(何處執行何者) +## 測試套件(何處執行什麼) -可將這些套件視為「真實度逐步提高」(同時 flakiness/成本也逐步提高): +將套件視為「真實度逐步提高」(同時 flakiness/成本也逐步提高): ### Unit / integration(預設) -- Command: `pnpm test` -- Config: 非目標式執行會使用 `vitest.full-*.config.ts` shard set,並可能將多專案 shard 展開為逐專案設定,以便平行排程 -- Files: `src/**/*.test.ts`、`packages/**/*.test.ts` 和 `test/**/*.test.ts` 下的 core/unit inventory;UI unit test 會在專用 `unit-ui` shard 中執行 -- Scope: - - 純 unit test - - 同處理程序 integration test(Gateway auth、routing、tooling、parsing、config) - - 已知 bug 的確定性 regression -- Expectations: +- 命令:`pnpm test` +- 設定:未鎖定目標的執行會使用 `vitest.full-*.config.ts` shard 集合,並可能將多專案 shard 展開為每個專案的設定,以便平行排程 +- 檔案:`src/**/*.test.ts`、`packages/**/*.test.ts` 和 `test/**/*.test.ts` 下的 core/unit inventory;UI unit 測試在專用的 `unit-ui` shard 中執行 +- 範圍: + - 純 unit 測試 + - 程序內 integration 測試(Gateway auth、routing、tooling、parsing、config) + - 已知 bug 的決定性 regression +- 預期: - 在 CI 中執行 - 不需要真實 key - - 應快速且穩定 - - Resolver 與公開表面 loader test 必須使用產生的微型 Plugin fixture 證明廣泛 `api.js` 與 `runtime-api.js` fallback 行為,而不是使用真實內建 Plugin 原始碼 API。真實 Plugin API 載入應屬於 Plugin 擁有的 contract/integration suite。 + - 應該快速且穩定 + - Resolver 和公開介面 loader 測試必須使用產生的小型 Plugin fixture 證明廣泛的 `api.js` 和 `runtime-api.js` fallback 行為,而不是使用真實內建 Plugin source API。真實 Plugin API 載入屬於 Plugin 擁有的 contract/integration 套件。 - + - - 未指定目標的 `pnpm test` 會執行十二個較小的分片設定(`core-unit-fast`、`core-unit-src`、`core-unit-security`、`core-unit-ui`、`core-unit-support`、`core-support-boundary`、`core-contracts`、`core-bundled`、`core-runtime`、`agentic`、`auto-reply`、`extensions`),而不是一個龐大的原生根專案程序。這會降低高負載機器上的峰值 RSS,並避免 auto-reply/extension 工作讓無關套件得不到資源。 - - `pnpm test --watch` 仍使用原生根 `vitest.config.ts` 專案圖,因為多分片 watch 迴圈並不實際。 - - `pnpm test`、`pnpm test:watch` 和 `pnpm test:perf:imports` 會先透過作用域 lane 路由明確的檔案/目錄目標,因此 `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` 可避免付出完整根專案啟動成本。 - - `pnpm test:changed` 預設會把已變更的 git 路徑展開成成本低的作用域 lane:直接測試編輯、同層 `*.test.ts` 檔案、明確的原始碼映射,以及本機匯入圖相依項。設定/setup/package 編輯不會廣泛執行測試,除非你明確使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 - - `pnpm check:changed` 是窄範圍工作的標準智慧本機檢查 gate。它會將 diff 分類為核心、核心測試、extensions、extension 測試、apps、docs、release metadata、即時 Docker 工具和 tooling,然後執行相符的 typecheck、lint 和 guard 命令。它不會執行 Vitest 測試;若要測試證明,請呼叫 `pnpm test:changed` 或明確的 `pnpm test `。僅 release metadata 的版本 bump 會執行目標式版本/config/root-dependency 檢查,並有 guard 拒絕 top-level version 欄位以外的 package 變更。 - - 即時 Docker ACP harness 編輯會執行聚焦檢查:即時 Docker auth scripts 的 shell 語法,以及即時 Docker scheduler dry-run。只有當 diff 限於 `scripts["test:docker:live-*"]` 時才會包含 `package.json` 變更;dependency、export、version 和其他 package-surface 編輯仍使用較廣泛的 guard。 - - 來自 agents、commands、plugins、auto-reply helpers、`plugin-sdk` 和類似純工具區域的輕匯入單元測試,會透過 `unit-fast` lane 路由,該 lane 會略過 `test/setup-openclaw-runtime.ts`;有狀態/重 runtime 的檔案則保留在既有 lane。 - - 選定的 `plugin-sdk` 和 `commands` helper 原始碼檔案也會將 changed-mode 執行映射到這些輕量 lane 中的明確同層測試,因此 helper 編輯可避免重新執行該目錄完整的重型套件。 - - `auto-reply` 對頂層核心 helper、頂層 `reply.*` 整合測試,以及 `src/auto-reply/reply/**` 子樹有專用 bucket。CI 進一步將 reply 子樹拆分為 agent-runner、dispatch 和 commands/state-routing 分片,讓單一匯入繁重的 bucket 不會占用完整 Node 尾端時間。 - - 一般 PR/main CI 會刻意略過 extension 批次掃描和僅 release 用的 `agentic-plugins` 分片。完整 Release Validation 會針對 release candidates 派發獨立的 `Plugin Prerelease` 子工作流程,以執行那些 plugin/extension-heavy 套件。 + - 未指定目標的 `pnpm test` 會執行十二個較小的分片設定(`core-unit-fast`、`core-unit-src`、`core-unit-security`、`core-unit-ui`、`core-unit-support`、`core-support-boundary`、`core-contracts`、`core-bundled`、`core-runtime`、`agentic`、`auto-reply`、`extensions`),而不是單一巨大的原生根專案程序。這會降低高負載機器上的尖峰 RSS,並避免 auto-reply/extension 工作讓不相關的測試套件挨餓。 + - `pnpm test --watch` 仍使用原生根 `vitest.config.ts` 專案圖,因為多分片的監看迴圈並不實際。 + - `pnpm test`、`pnpm test:watch` 和 `pnpm test:perf:imports` 會先透過作用域車道處理明確的檔案/目錄目標,因此 `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` 可避免付出完整根專案啟動成本。 + - `pnpm test:changed` 預設會把變更的 git 路徑展開成便宜的作用域車道:直接測試編輯、同層 `*.test.ts` 檔案、明確來源對應,以及本機匯入圖相依項。除非你明確使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`,否則 config/setup/package 編輯不會廣泛執行測試。 + - `pnpm check:changed` 是窄範圍工作的標準智慧本機檢查閘門。它會將 diff 分類為 core、core tests、extensions、extension tests、apps、docs、release metadata、live Docker tooling 和 tooling,然後執行相符的 typecheck、lint 與 guard 指令。它不會執行 Vitest 測試;測試證明請呼叫 `pnpm test:changed` 或明確的 `pnpm test `。僅 release metadata 的版本升級會執行目標版本/config/root-dependency 檢查,並有 guard 拒絕頂層 version 欄位以外的 package 變更。 + - Live Docker ACP harness 編輯會執行聚焦檢查:live Docker auth scripts 的 shell 語法,以及 live Docker scheduler dry-run。只有當 diff 限於 `scripts["test:docker:live-*"]` 時,才會包含 `package.json` 變更;dependency、export、version 和其他 package-surface 編輯仍會使用較廣泛的 guard。 + - 來自 agents、commands、plugins、auto-reply helpers、`plugin-sdk` 和類似純工具區域的輕匯入單元測試會走 `unit-fast` 車道,該車道會略過 `test/setup-openclaw-runtime.ts`;有狀態/執行階段較重的檔案則留在現有車道。 + - 選定的 `plugin-sdk` 和 `commands` helper 原始檔也會把 changed-mode 執行對應到那些輕量車道中的明確同層測試,因此 helper 編輯可避免重新執行該目錄完整的重型套件。 + - `auto-reply` 有專用桶,分別處理頂層 core helpers、頂層 `reply.*` 整合測試,以及 `src/auto-reply/reply/**` 子樹。CI 會進一步把 reply 子樹拆成 agent-runner、dispatch 和 commands/state-routing 分片,因此單一匯入較重的桶不會擁有完整的 Node 尾端。 + - 一般 PR/main CI 會刻意略過 extension 批次掃描和僅 release 使用的 `agentic-plugins` 分片。Full Release Validation 會為 release candidates 派發獨立的 `Plugin Prerelease` 子工作流程,以涵蓋這些 plugin/extension-heavy 套件。 - + - - 當你變更 message-tool 探索輸入或 compaction runtime - context 時,請保留兩個層級的涵蓋範圍。 - - 為純路由和正規化邊界新增聚焦的 helper 迴歸測試。 - - 維持嵌入式執行器整合套件健康: + - 當你變更 message-tool 探索輸入或 Compaction 執行階段 + context 時,請保留兩個層級的覆蓋範圍。 + - 為純路由和正規化邊界新增聚焦的 helper 回歸測試。 + - 保持嵌入式執行器整合套件健康: `src/agents/pi-embedded-runner/compact.hooks.test.ts`、 - `src/agents/pi-embedded-runner/run.overflow-compaction.test.ts`,以及 + `src/agents/pi-embedded-runner/run.overflow-compaction.test.ts` 和 `src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts`。 - - 這些套件會驗證作用域 id 和 compaction 行為仍會流經真正的 - `run.ts` / `compact.ts` 路徑;僅 helper 的測試不足以取代那些整合路徑。 + - 這些套件會驗證作用域 id 和 Compaction 行為仍會流經真實的 + `run.ts` / `compact.ts` 路徑;只有 helper 的測試無法充分替代那些整合路徑。 - + - - 基礎 Vitest config 預設為 `threads`。 - - 共用 Vitest config 固定 `isolate: false`,並在根專案、e2e 和 live configs 中使用 - 非隔離 runner。 - - 根 UI lane 保留其 `jsdom` setup 和 optimizer,但同樣在 - 共用非隔離 runner 上執行。 - - 每個 `pnpm test` 分片都會從共用 Vitest config 繼承相同的 `threads` + `isolate: false` + - 基礎 Vitest 設定預設為 `threads`。 + - 共用 Vitest 設定固定 `isolate: false`,並在根專案、e2e 和 live config 中使用 + 非隔離執行器。 + - 根 UI 車道保留其 `jsdom` 設定和 optimizer,但也在共用的非隔離執行器上執行。 + - 每個 `pnpm test` 分片都會從共用 Vitest 設定繼承相同的 `threads` + `isolate: false` 預設值。 - - `scripts/run-vitest.mjs` 預設會為 Vitest child Node - processes 加上 `--no-maglev`,以降低大型本機執行期間的 V8 編譯耗損。 - 設定 `OPENCLAW_VITEST_ENABLE_MAGLEV=1` 可與標準 V8 + - `scripts/run-vitest.mjs` 預設會為 Vitest 子 Node + 程序加入 `--no-maglev`,以降低大型本機執行期間的 V8 編譯擾動。 + 設定 `OPENCLAW_VITEST_ENABLE_MAGLEV=1` 可與原生 V8 行為比較。 - + - - `pnpm changed:lanes` 會顯示 diff 觸發哪些架構 lane。 - - pre-commit hook 僅處理格式化。它會重新 stage 已格式化檔案, + - `pnpm changed:lanes` 會顯示 diff 觸發哪些架構車道。 + - pre-commit hook 只處理格式化。它會重新暫存已格式化的檔案, 不會執行 lint、typecheck 或測試。 - - 當你需要智慧本機檢查 gate 時,請在交接或 push 前明確執行 `pnpm check:changed`。 - - `pnpm test:changed` 預設會透過成本低的作用域 lane 路由。只有當 agent - 判定 harness、config、package 或 contract 編輯確實需要更廣泛的 - Vitest 涵蓋範圍時,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 - - `pnpm test:max` 和 `pnpm test:changed:max` 保持相同路由 + - 當你需要智慧本機檢查閘門時,請在 handoff 或 push 前明確執行 `pnpm check:changed`。 + - `pnpm test:changed` 預設會透過便宜的作用域車道處理。只有當 agent + 判斷 harness、config、package 或 contract 編輯確實需要更廣的 + Vitest 覆蓋範圍時,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 + - `pnpm test:max` 和 `pnpm test:changed:max` 保持相同的路由 行為,只是 worker 上限較高。 - - 本機 worker 自動擴縮刻意保守,並會在主機 load average 已經偏高時退避, + - 本機 worker 自動縮放刻意保守,並在主機負載平均值已經偏高時退讓, 因此多個並行 Vitest 執行預設造成的影響較小。 - - 基礎 Vitest config 將 projects/config files 標記為 - `forceRerunTriggers`,因此測試 wiring 變更時,changed-mode 重新執行仍保持正確。 - - config 會在支援的主機上保持啟用 `OPENCLAW_VITEST_FS_MODULE_CACHE`; - 如果你想為直接 profiling 使用單一明確快取位置,請設定 `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`。 + - 基礎 Vitest 設定會將 projects/config 檔案標記為 + `forceRerunTriggers`,因此測試 + wiring 變更時,changed-mode 重新執行仍保持正確。 + - 此設定會在支援的主機上保持 `OPENCLAW_VITEST_FS_MODULE_CACHE` 啟用; + 如果你想為直接 profiling 使用一個明確的快取位置,請設定 + `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`。 - + - - `pnpm test:perf:imports` 會啟用 Vitest 匯入耗時報告,加上 - 匯入細項輸出。 - - `pnpm test:perf:imports:changed` 會把相同的 profiling 視圖限定到 + - `pnpm test:perf:imports` 會啟用 Vitest 匯入耗時報告,以及 + import-breakdown 輸出。 + - `pnpm test:perf:imports:changed` 會將相同的 profiling 視圖限制在 自 `origin/main` 以來變更的檔案。 - 分片計時資料會寫入 `.artifacts/vitest-shard-timings.json`。 - Whole-config 執行會使用 config path 作為 key;include-pattern CI - 分片會附加分片名稱,讓已篩選分片可分開追蹤。 - - 當某個 hot test 仍把大部分時間花在啟動匯入時, - 請把重型相依項放在狹窄本機 `*.runtime.ts` seam 後面, - 並直接 mock 該 seam,而不是只為了傳入 `vi.mock(...)` - 就深層匯入 runtime helpers。 - - `pnpm test:perf:changed:bench -- --ref ` 會將路由後的 - `test:changed` 與該已提交 diff 的原生根專案路徑比較, - 並列印 wall time 加 macOS max RSS。 + 整個 config 執行會使用 config 路徑作為 key;include-pattern CI + 分片會附加分片名稱,讓過濾後的分片可被分開追蹤。 + - 當某個熱點測試仍把大部分時間花在啟動匯入時, + 請把重型相依項保留在狹窄的本機 `*.runtime.ts` 邊界後方,並直接 + mock 該邊界,而不是為了將 runtime helpers 傳入 `vi.mock(...)` + 而深度匯入它們。 + - `pnpm test:perf:changed:bench -- --ref ` 會針對該已提交 + diff,比較已路由的 `test:changed` 與原生根專案路徑,並列印 wall time + 以及 macOS max RSS。 - `pnpm test:perf:changed:bench -- --worktree` 會透過 - `scripts/test-projects.mjs` 和根 Vitest config 路由 changed file list, - 來 benchmark 目前的 dirty tree。 + `scripts/test-projects.mjs` 和根 Vitest config 路由變更檔案清單, + 來對目前 dirty tree 做 benchmark。 - `pnpm test:perf:profile:main` 會為 - Vitest/Vite 啟動和 transform overhead 寫入 main-thread CPU profile。 - - `pnpm test:perf:profile:runner` 會在停用檔案平行處理時,為 - 單元套件寫入 runner CPU+heap profiles。 + Vitest/Vite 啟動和 transform 開銷寫入主執行緒 CPU profile。 + - `pnpm test:perf:profile:runner` 會在停用檔案平行化的情況下, + 為單元套件寫入 runner CPU+heap profile。 -### 穩定性(Gateway) +### 穩定性(gateway) -- 命令:`pnpm test:stability:gateway` -- Config:`vitest.gateway.config.ts`,強制使用一個 worker +- 指令:`pnpm test:stability:gateway` +- 設定:`vitest.gateway.config.ts`,強制使用單一 worker - 範圍: - - 預設啟用 diagnostics,啟動真正的 loopback Gateway - - 透過 diagnostic event path 驅動 synthetic gateway message、memory 和 large-payload churn + - 預設啟用診斷,啟動真實的 loopback Gateway + - 透過診斷事件路徑驅動合成 gateway message、memory 和 large-payload churn - 透過 Gateway WS RPC 查詢 `diagnostics.stability` - - 涵蓋 diagnostic stability bundle persistence helpers - - 斷言 recorder 仍受限、synthetic RSS samples 維持在 pressure budget 以下,且 per-session queue depths 會排空回到零 + - 覆蓋診斷穩定性 bundle persistence helpers + - 斷言 recorder 保持有界、合成 RSS samples 維持在壓力預算以下,且每個 session queue depth 都會排空回到零 - 預期: - - CI 安全且不需要 key - - 用於 stability-regression 後續處理的窄 lane,不是完整 Gateway 套件的替代品 + - CI-safe 且無需 key + - 用於 stability-regression 後續處理的窄車道,不是完整 Gateway 套件的替代品 -### E2E(Gateway smoke) +### E2E(gateway smoke) -- 命令:`pnpm test:e2e` -- Config:`vitest.e2e.config.ts` +- 指令:`pnpm test:e2e` +- 設定:`vitest.e2e.config.ts` - 檔案:`src/**/*.e2e.test.ts`、`test/**/*.e2e.test.ts`,以及 `extensions/` 下的 bundled-plugin E2E tests -- Runtime 預設值: +- 執行階段預設值: - 使用 Vitest `threads` 搭配 `isolate: false`,與 repo 其餘部分一致。 - - 使用 adaptive workers(CI:最多 2,本機:預設 1)。 - - 預設以 silent mode 執行,以降低 console I/O overhead。 + - 使用自適應 workers(CI:最多 2,本機:預設 1)。 + - 預設以 silent mode 執行,以降低 console I/O 開銷。 - 實用覆寫: - - `OPENCLAW_E2E_WORKERS=` 可強制 worker count(上限 16)。 - - `OPENCLAW_E2E_VERBOSE=1` 可重新啟用 verbose console output。 + - `OPENCLAW_E2E_WORKERS=` 可強制 worker 數量(上限 16)。 + - `OPENCLAW_E2E_VERBOSE=1` 可重新啟用詳細 console 輸出。 - 範圍: - 多實例 gateway 端到端行為 - WebSocket/HTTP surfaces、node pairing,以及較重的 networking - 預期: - 在 CI 中執行(當 pipeline 啟用時) - - 不需要真實 key - - 比單元測試有更多移動部件(可能較慢) + - 不需要真實 keys + - 比單元測試有更多 moving parts(可能較慢) -### E2E:OpenShell backend smoke +### E2E:OpenShell 後端 smoke -- 命令:`pnpm test:e2e:openshell` +- 指令:`pnpm test:e2e:openshell` - 檔案:`extensions/openshell/src/backend.e2e.test.ts` - 範圍: - 透過 Docker 在主機上啟動隔離的 OpenShell gateway - 從臨時本機 Dockerfile 建立 sandbox - - 透過真實的 `sandbox ssh-config` + SSH exec 測試 OpenClaw 的 OpenShell backend - - 透過 sandbox fs bridge 驗證 remote-canonical filesystem 行為 + - 透過真實的 `sandbox ssh-config` + SSH exec 測試 OpenClaw 的 OpenShell 後端 + - 透過 sandbox fs bridge 驗證 remote-canonical 檔案系統行為 - 預期: - - 僅 opt-in;不屬於預設 `pnpm test:e2e` 執行 - - 需要本機 `openshell` CLI 加上可運作的 Docker daemon + - 僅 opt-in;不屬於預設 `pnpm test:e2e` 執行的一部分 + - 需要本機 `openshell` CLI 以及可運作的 Docker daemon - 使用隔離的 `HOME` / `XDG_CONFIG_HOME`,然後銷毀測試 gateway 和 sandbox - 實用覆寫: - - 手動執行較廣泛的 e2e 套件時,可用 `OPENCLAW_E2E_OPENSHELL=1` 啟用測試 + - `OPENCLAW_E2E_OPENSHELL=1` 可在手動執行較廣 e2e 套件時啟用測試 - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` 可指向非預設 CLI binary 或 wrapper script ### Live(真實 providers + 真實 models) -- 命令:`pnpm test:live` -- Config:`vitest.live.config.ts` +- 指令:`pnpm test:live` +- 設定:`vitest.live.config.ts` - 檔案:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下的 bundled-plugin live tests -- 預設:由 `pnpm test:live` **啟用**(設定 `OPENCLAW_LIVE_TEST=1`) +- 預設值:由 `pnpm test:live` **啟用**(設定 `OPENCLAW_LIVE_TEST=1`) - 範圍: - - 「這個 provider/model _今天_ 搭配真實 creds 是否真的可用?」 - - 捕捉 provider format changes、tool-calling quirks、auth issues 和 rate limit behavior + - 「這個 provider/model 在 _今天_ 使用真實 credentials 是否真的可運作?」 + - 捕捉 provider format changes、tool-calling quirks、auth issues,以及 rate limit behavior - 預期: - - 設計上不保證 CI 穩定(真實 networks、真實 provider policies、quotas、outages) + - 按設計並非 CI-stable(真實網路、真實 provider policies、quotas、outages) - 會花錢 / 使用 rate limits - - 偏好執行較窄子集,而不是「全部」 -- Live 執行會 source `~/.profile` 以取得遺漏的 API keys。 -- 預設情況下,live 執行仍會隔離 `HOME`,並將 config/auth material 複製到臨時測試 home,使單元 fixtures 無法修改你的真實 `~/.openclaw`。 + - 偏好執行較窄的子集,而不是「全部」 +- Live 執行會 source `~/.profile` 以取得缺少的 API keys。 +- 預設情況下,live 執行仍會隔離 `HOME`,並把 config/auth material 複製到暫時測試 home,因此單元 fixtures 無法改動你真實的 `~/.openclaw`。 - 只有當你刻意需要 live tests 使用真實 home directory 時,才設定 `OPENCLAW_LIVE_USE_REAL_HOME=1`。 -- `pnpm test:live` 現在預設為較安靜的模式:它保留 `[live] ...` progress output,但會隱藏額外的 `~/.profile` notice,並靜音 gateway bootstrap logs/Bonjour chatter。如果你想要完整 startup logs 回來,請設定 `OPENCLAW_LIVE_TEST_QUIET=0`。 -- API key rotation(provider-specific):使用逗號/分號格式設定 `*_API_KEYS`,或設定 `*_API_KEY_1`、`*_API_KEY_2`(例如 `OPENAI_API_KEYS`、`ANTHROPIC_API_KEYS`、`GEMINI_API_KEYS`),或透過 `OPENCLAW_LIVE_*_KEY` 設定 per-live override;測試會在 rate limit responses 時重試。 -- Progress/heartbeat output: - - Live suites 現在會將 progress lines 輸出到 stderr,因此即使 Vitest console capture 安靜時,長時間 provider calls 也會可見地保持活動。 - - `vitest.live.config.ts` 會停用 Vitest console interception,因此 provider/gateway progress lines 會在 live runs 期間立即串流。 +- `pnpm test:live` 現在預設使用較安靜的模式:它保留 `[live] ...` progress output,但會抑制額外的 `~/.profile` notice,並靜音 gateway bootstrap logs/Bonjour chatter。若你想取回完整 startup logs,請設定 `OPENCLAW_LIVE_TEST_QUIET=0`。 +- API key rotation(provider-specific):以逗號/分號格式設定 `*_API_KEYS`,或設定 `*_API_KEY_1`、`*_API_KEY_2`(例如 `OPENAI_API_KEYS`、`ANTHROPIC_API_KEYS`、`GEMINI_API_KEYS`),或透過 `OPENCLAW_LIVE_*_KEY` 做 per-live override;測試會在 rate limit responses 時重試。 +- Progress/heartbeat 輸出: + - Live 套件現在會把 progress lines 發到 stderr,因此即使 Vitest console capture 很安靜,長時間 provider calls 也會可見地保持 active。 + - `vitest.live.config.ts` 會停用 Vitest console interception,因此 provider/gateway progress lines 會在 live 執行期間立即串流。 - 使用 `OPENCLAW_LIVE_HEARTBEAT_MS` 調整 direct-model heartbeats。 - 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 調整 gateway/probe heartbeats。 @@ -522,234 +480,242 @@ Telegram kind 的 payload 形狀: 使用此決策表: -- 編輯邏輯/測試:執行 `pnpm test`(如果你改了很多內容,也執行 `pnpm test:coverage`) -- 觸及 Gateway 網路 / WS 協定 / 配對:加入 `pnpm test:e2e` -- 偵錯「我的 bot 掛了」/ 提供者特定失敗 / 工具呼叫:執行範圍縮小的 `pnpm test:live` +- 編輯邏輯/測試:執行 `pnpm test`(如果你變更了很多內容,也執行 `pnpm test:coverage`) +- 觸及 gateway 網路 / WS 通訊協定 / 配對:加上 `pnpm test:e2e` +- 偵錯「我的 bot 掛了」/ 供應商特定失敗 / 工具呼叫:執行範圍縮小的 `pnpm test:live` -## 即時(會觸及網路的)測試 +## 即時(觸及網路)測試 -關於即時模型矩陣、CLI 後端冒煙測試、ACP 冒煙測試、Codex 應用伺服器測試框架,以及所有媒體提供者即時測試(Deepgram、BytePlus、ComfyUI、圖片、音樂、影片、媒體測試框架),再加上即時執行的憑證處理,請參閱 +如需即時模型矩陣、CLI 後端冒煙測試、ACP 冒煙測試、Codex app-server +測試框架,以及所有媒體供應商即時測試(Deepgram、BytePlus、ComfyUI、影像、 +音樂、影片、媒體測試框架)— 以及即時執行的憑證處理 — 請參閱 [測試 — 即時套件](/zh-TW/help/testing-live)。 ## Docker 執行器(選用的「可在 Linux 運作」檢查) 這些 Docker 執行器分成兩類: -- 即時模型執行器:`test:docker:live-models` 和 `test:docker:live-gateway` 只會在 repo Docker 映像內執行各自符合設定檔鍵的即時檔案(`src/agents/models.profiles.live.test.ts` 和 `src/gateway/gateway-models.profiles.live.test.ts`),並掛載你的本機設定目錄與工作區(若有掛載,也會載入 `~/.profile`)。對應的本機進入點是 `test:live:models-profiles` 和 `test:live:gateway-profiles`。 -- Docker 即時執行器預設採用較小的冒煙上限,讓完整 Docker 掃描仍然實用: +- 即時模型執行器:`test:docker:live-models` 和 `test:docker:live-gateway` 只會在 repo Docker 映像中執行其對應 profile-key 的即時檔案(`src/agents/models.profiles.live.test.ts` 和 `src/gateway/gateway-models.profiles.live.test.ts`),掛載你的本機設定目錄與工作區(若有掛載,並會載入 `~/.profile`)。對應的本機進入點是 `test:live:models-profiles` 和 `test:live:gateway-profiles`。 +- Docker 即時執行器預設使用較小的冒煙上限,讓完整 Docker 掃描維持可行: `test:docker:live-models` 預設為 `OPENCLAW_LIVE_MAX_MODELS=12`,而 `test:docker:live-gateway` 預設為 `OPENCLAW_LIVE_GATEWAY_SMOKE=1`、 `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=8`、 `OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=45000`,以及 - `OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`。只有在你明確想要較大的完整掃描時,才覆寫這些環境變數。 -- `test:docker:all` 會先透過 `test:docker:live-build` 建置一次即時 Docker 映像,透過 `scripts/package-openclaw-for-docker.mjs` 將 OpenClaw 打包一次為 npm tarball,然後建置/重用兩個 `scripts/e2e/Dockerfile` 映像。裸映像只是用於安裝/更新/Plugin 相依性 lane 的 Node/Git 執行器;這些 lane 會掛載預先建置的 tarball。功能映像會將同一個 tarball 安裝到 `/app`,用於已建置應用程式功能 lane。Docker lane 定義位於 `scripts/lib/docker-e2e-scenarios.mjs`;規劃器邏輯位於 `scripts/lib/docker-e2e-plan.mjs`;`scripts/test-docker-all.mjs` 會執行選取的計畫。彙總流程使用加權本機排程器:`OPENCLAW_DOCKER_ALL_PARALLELISM` 控制程序槽位,而資源上限會避免繁重的即時、npm 安裝與多服務 lane 同時全部啟動。如果單一 lane 比作用中的上限更重,排程器仍可在集區為空時啟動它,並讓它單獨執行,直到再次有容量可用。預設值為 10 個槽位、`OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`、`OPENCLAW_DOCKER_ALL_NPM_LIMIT=10`,以及 `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`;只有在 Docker 主機有更多餘裕時,才調整 `OPENCLAW_DOCKER_ALL_WEIGHT_LIMIT` 或 `OPENCLAW_DOCKER_ALL_DOCKER_LIMIT`。執行器預設會執行 Docker 預檢、移除過期的 OpenClaw E2E 容器、每 30 秒列印狀態、將成功 lane 的時間記錄儲存在 `.artifacts/docker-tests/lane-timings.json`,並在後續執行時利用這些時間記錄先啟動較長的 lane。使用 `OPENCLAW_DOCKER_ALL_DRY_RUN=1` 可列印加權 lane 清單,而不建置或執行 Docker;或使用 `node scripts/test-docker-all.mjs --plan-json` 列印所選 lane、套件/映像需求與憑證的 CI 計畫。 -- `Package Acceptance` 是 GitHub 原生的套件 gate,用來回答「這個可安裝的 tarball 作為產品是否可用?」它會從 `source=npm`、`source=ref`、`source=url` 或 `source=artifact` 解析出一個候選套件,將其上傳為 `package-under-test`,然後針對該確切 tarball 執行可重用的 Docker E2E lane,而不是重新打包所選 ref。`workflow_ref` 選取受信任的 workflow/測試框架腳本,而 `package_ref` 會在 `source=ref` 時選取要打包的來源 commit/branch/tag;這讓目前的驗收邏輯能驗證較舊的受信任 commit。設定檔依涵蓋廣度排序:`smoke` 是快速安裝/channel/agent 加上 Gateway/設定,`package` 是套件/更新/Plugin 合約,也是大多數 Parallels 套件/更新涵蓋範圍的預設原生替代項,`product` 加入 MCP channels、cron/subagent 清理、OpenAI web search 和 OpenWebUI,而 `full` 會執行含 OpenWebUI 的發行路徑 Docker 區塊。發行驗證會執行自訂套件差異(`bundled-channel-deps-compat plugins-offline`)加上 Telegram 套件 QA,因為發行路徑 Docker 區塊已涵蓋重疊的套件/更新/Plugin lane。從成品產生的目標 GitHub Docker 重新執行命令,在可用時會包含先前的套件成品與已準備映像輸入,因此失敗的 lane 可以避免重新建置套件與映像。 -- 建置與發行檢查會在 tsdown 後執行 `scripts/check-cli-bootstrap-imports.mjs`。該 guard 會從 `dist/entry.js` 和 `dist/cli/run-main.js` 走訪靜態建置圖,若在命令分派前的啟動流程匯入 Commander、prompt UI、undici 或 logging 等套件相依性,就會失敗;它也會讓 bundled Gateway run chunk 維持在預算內,並拒絕靜態匯入已知的 cold Gateway 路徑。封裝後的 CLI 冒煙測試也涵蓋 root help、onboard help、doctor help、status、config schema 和 model-list 命令。 -- Package Acceptance 舊版相容性上限為 `2026.4.25`(包含 `2026.4.25-beta.*`)。在該截止點之前,測試框架只容忍已出貨套件的中繼資料缺口:省略的私有 QA inventory entries、缺少 `gateway install --wrapper`、tarball 衍生 git fixture 中缺少 patch 檔、缺少持久化的 `update.channel`、舊版 Plugin install-record 位置、缺少 marketplace install-record 持久化,以及 `plugins update` 期間的設定中繼資料遷移。對於 `2026.4.25` 之後的套件,這些路徑都是嚴格失敗。 -- 容器冒煙執行器:`test:docker:openwebui`、`test:docker:onboard`、`test:docker:npm-onboard-channel-agent`、`test:docker:update-channel-switch`、`test:docker:session-runtime-context`、`test:docker:agents-delete-shared-workspace`、`test:docker:gateway-network`、`test:docker:browser-cdp-snapshot`、`test:docker:mcp-channels`、`test:docker:pi-bundle-mcp-tools`、`test:docker:cron-mcp-cleanup`、`test:docker:plugins`、`test:docker:plugin-update` 和 `test:docker:config-reload` 會啟動一個或多個真實容器,並驗證較高層級的整合路徑。 + `OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`。只有在你明確想要更大的完整掃描時, + 才覆寫這些 env vars。 +- `test:docker:all` 會先透過 `test:docker:live-build` 建置即時 Docker 映像一次,透過 `scripts/package-openclaw-for-docker.mjs` 將 OpenClaw 封裝成 npm tarball 一次,接著建置/重用兩個 `scripts/e2e/Dockerfile` 映像。裸映像只是用於安裝/更新/Plugin 相依性 lane 的 Node/Git 執行器;這些 lane 會掛載預先建置的 tarball。功能映像會將同一個 tarball 安裝到 `/app`,供已建置 app 的功能 lane 使用。Docker lane 定義位於 `scripts/lib/docker-e2e-scenarios.mjs`;規劃器邏輯位於 `scripts/lib/docker-e2e-plan.mjs`;`scripts/test-docker-all.mjs` 會執行選定的計畫。彙總流程使用加權本機排程器:`OPENCLAW_DOCKER_ALL_PARALLELISM` 控制程序 slot,而資源上限會避免繁重的即時、npm-install 和多服務 lane 同時全部啟動。如果單一 lane 比目前上限更重,排程器仍可在 pool 為空時啟動它,並讓它單獨執行到容量再次可用。預設為 10 個 slot、`OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`、`OPENCLAW_DOCKER_ALL_NPM_LIMIT=10`,以及 `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`;只有在 Docker 主機有更多餘裕時,才調整 `OPENCLAW_DOCKER_ALL_WEIGHT_LIMIT` 或 `OPENCLAW_DOCKER_ALL_DOCKER_LIMIT`。執行器預設會執行 Docker 前置檢查、移除過期的 OpenClaw E2E 容器、每 30 秒列印狀態、將成功 lane 的耗時儲存在 `.artifacts/docker-tests/lane-timings.json`,並在後續執行時使用這些耗時先啟動較長的 lane。使用 `OPENCLAW_DOCKER_ALL_DRY_RUN=1` 可列印加權 lane manifest,而不建置或執行 Docker;或使用 `node scripts/test-docker-all.mjs --plan-json` 列印選定 lane、套件/映像需求與憑證的 CI 計畫。 +- `Package Acceptance` 是 GitHub 原生的套件閘門,用來驗證「這個可安裝的 tarball 是否能作為產品運作?」它會從 `source=npm`、`source=ref`、`source=url` 或 `source=artifact` 解析一個候選套件,將它上傳為 `package-under-test`,然後對該精確 tarball 執行可重用的 Docker E2E lane,而不是重新封裝選定的 ref。`workflow_ref` 會選擇受信任的 workflow/測試框架 scripts,而 `package_ref` 會在 `source=ref` 時選擇要封裝的來源 commit/branch/tag;這讓目前的驗收邏輯能驗證較舊的受信任 commit。Profile 依涵蓋廣度排序:`smoke` 是快速安裝/channel/agent 加上 gateway/config,`package` 是套件/更新/Plugin 合約加上 keyless upgrade-survivor fixture,並且是大多數 Parallels 套件/更新涵蓋範圍的預設原生替代項,`product` 會加入 MCP channels、cron/subagent 清理、OpenAI web search 和 OpenWebUI,而 `full` 會以 OpenWebUI 執行 release-path Docker 區塊。發布驗證會執行自訂套件差異(`bundled-channel-deps-compat plugins-offline`)加上 Telegram 套件 QA,因為 release-path Docker 區塊已涵蓋重疊的套件/更新/Plugin lane。從 artifact 產生的目標 GitHub Docker 重新執行命令,會在可用時包含先前的套件 artifact 和已準備的映像輸入,因此失敗的 lane 可避免重建套件與映像。 +- 建置與發布檢查會在 tsdown 後執行 `scripts/check-cli-bootstrap-imports.mjs`。該防護會從 `dist/entry.js` 和 `dist/cli/run-main.js` 走訪靜態建置圖,並在命令分派前的啟動流程匯入 Commander、prompt UI、undici 或 logging 等套件相依性時失敗;它也會讓 bundled gateway run chunk 維持在預算內,並拒絕已知 cold gateway 路徑的靜態匯入。封裝後的 CLI 冒煙測試也涵蓋 root help、onboard help、doctor help、status、config schema,以及 model-list 命令。 +- Package Acceptance 舊版相容性上限為 `2026.4.25`(包含 `2026.4.25-beta.*`)。在該截止版本以前,測試框架只容許已出貨套件的中繼資料缺口:省略的私有 QA inventory 項目、缺少 `gateway install --wrapper`、tarball 衍生 git fixture 中缺少 patch 檔、缺少持久化的 `update.channel`、舊版 Plugin install-record 位置、缺少 marketplace install-record 持久化,以及 `plugins update` 期間的 config metadata 遷移。對 `2026.4.25` 之後的套件,這些路徑都是嚴格失敗。 +- 容器冒煙執行器:`test:docker:openwebui`、`test:docker:onboard`、`test:docker:npm-onboard-channel-agent`、`test:docker:update-channel-switch`、`test:docker:upgrade-survivor`、`test:docker:session-runtime-context`、`test:docker:agents-delete-shared-workspace`、`test:docker:gateway-network`、`test:docker:browser-cdp-snapshot`、`test:docker:mcp-channels`、`test:docker:pi-bundle-mcp-tools`、`test:docker:cron-mcp-cleanup`、`test:docker:plugins`、`test:docker:plugin-update` 和 `test:docker:config-reload` 會啟動一個或多個真實容器,並驗證較高層級的整合路徑。 -即時模型 Docker 執行器也只會 bind-mount 需要的 CLI auth homes(或在執行未縮小範圍時掛載所有支援的 auth homes),然後在執行前將它們複製到容器 home,讓外部 CLI OAuth 可以重新整理 token,而不會變更主機 auth store: +即時模型 Docker 執行器也只會 bind-mount 所需的 CLI auth home(或在執行未縮小範圍時掛載所有支援項目),然後在執行前將它們複製到容器 home,讓外部 CLI OAuth 能重新整理權杖,而不會變更主機 auth store: - 直接模型:`pnpm test:docker:live-models`(指令碼:`scripts/test-live-models-docker.sh`) -- ACP 繫結冒煙測試:`pnpm test:docker:live-acp-bind`(指令碼:`scripts/test-live-acp-bind-docker.sh`;預設涵蓋 Claude、Codex 和 Gemini,並透過 `pnpm test:docker:live-acp-bind:droid` 與 `pnpm test:docker:live-acp-bind:opencode` 提供嚴格的 Droid/OpenCode 覆蓋) -- CLI 後端冒煙測試:`pnpm test:docker:live-cli-backend`(指令碼:`scripts/test-live-cli-backend-docker.sh`) -- Codex app-server harness 冒煙測試:`pnpm test:docker:live-codex-harness`(指令碼:`scripts/test-live-codex-harness-docker.sh`) +- ACP 綁定煙霧測試:`pnpm test:docker:live-acp-bind`(指令碼:`scripts/test-live-acp-bind-docker.sh`;預設涵蓋 Claude、Codex 和 Gemini,並透過 `pnpm test:docker:live-acp-bind:droid` 與 `pnpm test:docker:live-acp-bind:opencode` 嚴格涵蓋 Droid/OpenCode) +- CLI 後端煙霧測試:`pnpm test:docker:live-cli-backend`(指令碼:`scripts/test-live-cli-backend-docker.sh`) +- Codex 應用程式伺服器測試架煙霧測試:`pnpm test:docker:live-codex-harness`(指令碼:`scripts/test-live-codex-harness-docker.sh`) - Gateway + 開發代理:`pnpm test:docker:live-gateway`(指令碼:`scripts/test-live-gateway-models-docker.sh`) -- 可觀測性冒煙測試:`pnpm qa:otel:smoke` 是私有 QA 原始碼 checkout 路徑。它刻意不屬於套件 Docker 發行路徑,因為 npm tarball 省略 QA Lab。 -- Open WebUI 即時冒煙測試:`pnpm test:docker:openwebui`(指令碼:`scripts/e2e/openwebui-docker.sh`) -- Onboarding 精靈(TTY、完整鷹架):`pnpm test:docker:onboard`(指令碼:`scripts/e2e/onboard-docker.sh`) -- Npm tarball onboarding/channel/agent 冒煙測試:`pnpm test:docker:npm-onboard-channel-agent` 會在 Docker 中全域安裝已打包的 OpenClaw tarball,透過 env-ref onboarding 設定 OpenAI,並預設設定 Telegram,驗證 doctor 修復已啟用 Plugin 的執行階段依賴項,並執行一次模擬的 OpenAI 代理回合。使用 `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 重用預建 tarball,使用 `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` 跳過主機重建,或使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 切換通道。 -- 更新通道切換冒煙測試:`pnpm test:docker:update-channel-switch` 會在 Docker 中全域安裝已打包的 OpenClaw tarball,從套件 `stable` 切換到 git `dev`,驗證已保存的通道與 Plugin 更新後運作,接著切回套件 `stable` 並檢查更新狀態。 -- 工作階段執行階段內容冒煙測試:`pnpm test:docker:session-runtime-context` 驗證隱藏執行階段內容 transcript 持久化,以及 doctor 對受影響的重複 prompt-rewrite 分支進行修復。 -- Bun 全域安裝冒煙測試:`bash scripts/e2e/bun-global-install-smoke.sh` 會打包目前樹狀結構,在隔離的 home 中用 `bun install -g` 安裝,並驗證 `openclaw infer image providers --json` 回傳內建影像提供者而不是卡住。使用 `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 重用預建 tarball,使用 `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0` 跳過主機建置,或使用 `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local` 從已建置的 Docker 映像複製 `dist/`。 -- 安裝器 Docker 冒煙測試:`bash scripts/test-install-sh-docker.sh` 會在其 root、update 和 direct-npm 容器之間共用一個 npm 快取。更新冒煙測試預設使用 npm `latest` 作為升級到候選 tarball 前的穩定基準。在本機用 `OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22` 覆寫,或在 GitHub 上用 Install Smoke workflow 的 `update_baseline_version` 輸入覆寫。非 root 安裝器檢查會保留隔離的 npm 快取,避免 root 擁有的快取項目掩蓋使用者本機安裝行為。設定 `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache` 以在本機重跑時重用 root/update/direct-npm 快取。 -- Install Smoke CI 使用 `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1` 跳過重複的 direct-npm 全域更新;需要直接 `npm install -g` 覆蓋時,在本機不帶該 env 執行指令碼。 -- Agents 刪除共用工作區 CLI 冒煙測試:`pnpm test:docker:agents-delete-shared-workspace`(指令碼:`scripts/e2e/agents-delete-shared-workspace-docker.sh`)預設建置根 Dockerfile 映像,在隔離容器 home 中植入兩個代理與一個工作區,執行 `agents delete --json`,並驗證有效 JSON 與工作區保留行為。使用 `OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE=openclaw-dockerfile-smoke:local OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD=1` 重用 install-smoke 映像。 -- Gateway 網路(兩個容器、WS 驗證 + 健康狀態):`pnpm test:docker:gateway-network`(指令碼:`scripts/e2e/gateway-network-docker.sh`) -- 瀏覽器 CDP snapshot 冒煙測試:`pnpm test:docker:browser-cdp-snapshot`(指令碼:`scripts/e2e/browser-cdp-snapshot-docker.sh`)會建置原始碼 E2E 映像加上一層 Chromium,使用原始 CDP 啟動 Chromium,執行 `browser doctor --deep`,並驗證 CDP role snapshot 涵蓋連結 URL、cursor-promoted 可點擊項目、iframe refs 和 frame 中繼資料。 -- OpenAI Responses web_search minimal reasoning 迴歸:`pnpm test:docker:openai-web-search-minimal`(指令碼:`scripts/e2e/openai-web-search-minimal-docker.sh`)會透過 Gateway 執行模擬的 OpenAI 伺服器,驗證 `web_search` 將 `reasoning.effort` 從 `minimal` 提升到 `low`,接著強制提供者 schema 拒絕,並檢查原始 detail 出現在 Gateway 記錄中。 -- MCP 通道 bridge(植入資料的 Gateway + stdio bridge + 原始 Claude notification-frame 冒煙測試):`pnpm test:docker:mcp-channels`(指令碼:`scripts/e2e/mcp-channels-docker.sh`) -- Pi bundle MCP 工具(真實 stdio MCP 伺服器 + 內嵌 Pi profile allow/deny 冒煙測試):`pnpm test:docker:pi-bundle-mcp-tools`(指令碼:`scripts/e2e/pi-bundle-mcp-tools-docker.sh`) -- Cron/subagent MCP 清理(真實 Gateway + 在隔離 cron 與一次性 subagent 執行後拆除 stdio MCP 子程序):`pnpm test:docker:cron-mcp-cleanup`(指令碼:`scripts/e2e/cron-mcp-cleanup-docker.sh`) -- Plugins(安裝冒煙測試、ClawHub kitchen-sink 安裝/解除安裝、市集更新,以及 Claude-bundle 啟用/檢查):`pnpm test:docker:plugins`(指令碼:`scripts/e2e/plugins-docker.sh`) - 設定 `OPENCLAW_PLUGINS_E2E_CLAWHUB=0` 以跳過 ClawHub 區塊,或用 `OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC` 和 `OPENCLAW_PLUGINS_E2E_CLAWHUB_ID` 覆寫預設的 kitchen-sink 套件/執行階段組合。沒有 `OPENCLAW_CLAWHUB_URL`/`CLAWHUB_URL` 時,測試會使用 hermetic 本機 ClawHub fixture 伺服器。 -- Plugin 更新未變更冒煙測試:`pnpm test:docker:plugin-update`(指令碼:`scripts/e2e/plugin-update-unchanged-docker.sh`) -- 設定重新載入中繼資料冒煙測試:`pnpm test:docker:config-reload`(指令碼:`scripts/e2e/config-reload-source-docker.sh`) -- 內建 Plugin 執行階段依賴項:`pnpm test:docker:bundled-channel-deps` 預設建置小型 Docker runner 映像,在主機上建置並打包 OpenClaw 一次,接著將該 tarball 掛載到每個 Linux 安裝情境中。使用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 重用映像,在新的本機建置後用 `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0` 跳過主機重建,或用 `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 指向現有 tarball。完整 Docker 彙總與 release-path 內建通道 chunk 會先預先打包此 tarball 一次,接著將內建通道檢查分片成獨立路徑,包括 Telegram、Discord、Slack、Feishu、memory-lancedb 和 ACPX 的個別更新路徑。發行 chunk 會將通道冒煙測試、更新目標,以及設定/執行階段合約拆分為 `bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-b` 和 `bundled-channels-contracts`;彙總 `bundled-channels` chunk 仍可供手動重跑。發行 workflow 也會拆分提供者安裝器 chunk 和內建 Plugin 安裝/解除安裝 chunk;舊版 `package-update`、`plugins-runtime` 和 `plugins-integrations` chunk 仍作為手動重跑的彙總別名保留。直接執行內建路徑時,使用 `OPENCLAW_BUNDLED_CHANNELS=telegram,slack` 縮小通道矩陣,或使用 `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx` 縮小更新情境。每個情境的 Docker 執行預設為 `OPENCLAW_BUNDLED_CHANNEL_DOCKER_RUN_TIMEOUT=900s`;多目標更新情境預設為 `OPENCLAW_BUNDLED_CHANNEL_UPDATE_DOCKER_RUN_TIMEOUT=2400s`。此路徑也會驗證 `channels..enabled=false` 和 `plugins.entries..enabled=false` 會抑制 doctor/執行階段依賴項修復。 -- 迭代時可透過停用無關情境來縮小內建 Plugin 執行階段依賴項,例如: +- 可觀測性煙霧測試:`pnpm qa:otel:smoke` 是私有 QA 原始碼簽出通道。它刻意不屬於套件 Docker 發布通道,因為 npm tarball 省略了 QA Lab。 +- Open WebUI 即時煙霧測試:`pnpm test:docker:openwebui`(指令碼:`scripts/e2e/openwebui-docker.sh`) +- 入門精靈(TTY,完整鷹架):`pnpm test:docker:onboard`(指令碼:`scripts/e2e/onboard-docker.sh`) +- Npm tarball 入門/頻道/代理煙霧測試:`pnpm test:docker:npm-onboard-channel-agent` 會在 Docker 中全域安裝已封裝的 OpenClaw tarball,透過 env-ref 入門流程設定 OpenAI,並預設設定 Telegram,驗證 doctor 修復已啟用的 Plugin 執行階段依賴項,並執行一次模擬的 OpenAI 代理回合。使用 `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 重用預先建置的 tarball,使用 `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` 跳過主機重建,或使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 切換頻道。 +- 更新頻道切換煙霧測試:`pnpm test:docker:update-channel-switch` 會在 Docker 中全域安裝已封裝的 OpenClaw tarball,從套件 `stable` 切換到 git `dev`,驗證持久化頻道與 Plugin 更新後工作正常,然後切回套件 `stable` 並檢查更新狀態。 +- 升級存活煙霧測試:`pnpm test:docker:upgrade-survivor` 會將已封裝的 OpenClaw tarball 安裝到髒污的舊使用者 fixture 上,其中包含代理、頻道設定、Plugin 允許清單、過時的 Plugin 執行階段依賴狀態,以及既有工作區/工作階段檔案。它會在沒有即時提供者或頻道金鑰的情況下執行套件更新與非互動式 doctor,然後啟動一個 loopback Gateway,並檢查設定/狀態保留以及啟動/狀態預算。 +- 工作階段執行階段內容煙霧測試:`pnpm test:docker:session-runtime-context` 會驗證隱藏執行階段內容逐字稿持久化,以及 doctor 對受影響的重複提示重寫分支的修復。 +- Bun 全域安裝煙霧測試:`bash scripts/e2e/bun-global-install-smoke.sh` 會封裝目前樹狀內容,在隔離的 home 中使用 `bun install -g` 安裝,並驗證 `openclaw infer image providers --json` 回傳內建影像提供者,而不是卡住。使用 `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 重用預先建置的 tarball,使用 `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0` 跳過主機建置,或使用 `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local` 從已建置的 Docker 映像複製 `dist/`。 +- 安裝器 Docker 煙霧測試:`bash scripts/test-install-sh-docker.sh` 會在其 root、update 和 direct-npm 容器之間共用一個 npm 快取。更新煙霧測試預設使用 npm `latest` 作為穩定基準,再升級到候選 tarball。在本機使用 `OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22` 覆寫,或在 GitHub 上使用 Install Smoke 工作流程的 `update_baseline_version` 輸入覆寫。非 root 安裝器檢查會保留隔離的 npm 快取,因此 root 擁有的快取項目不會掩蓋使用者本機安裝行為。設定 `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache`,以便在本機重跑時重用 root/update/direct-npm 快取。 +- Install Smoke CI 會使用 `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1` 跳過重複的 direct-npm 全域更新;需要直接 `npm install -g` 涵蓋時,請在本機不帶該 env 執行指令碼。 +- 代理刪除共用工作區 CLI 煙霧測試:`pnpm test:docker:agents-delete-shared-workspace`(指令碼:`scripts/e2e/agents-delete-shared-workspace-docker.sh`)預設會建置根 Dockerfile 映像,在隔離的容器 home 中植入兩個代理與一個工作區,執行 `agents delete --json`,並驗證有效 JSON 與保留工作區行為。使用 `OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE=openclaw-dockerfile-smoke:local OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD=1` 重用 install-smoke 映像。 +- Gateway 網路(兩個容器,WS 驗證 + 健康狀態):`pnpm test:docker:gateway-network`(指令碼:`scripts/e2e/gateway-network-docker.sh`) +- 瀏覽器 CDP 快照煙霧測試:`pnpm test:docker:browser-cdp-snapshot`(指令碼:`scripts/e2e/browser-cdp-snapshot-docker.sh`)會建置原始碼 E2E 映像加上一層 Chromium,使用原始 CDP 啟動 Chromium,執行 `browser doctor --deep`,並驗證 CDP 角色快照涵蓋連結 URL、游標提升的可點擊項目、iframe 參照與框架中繼資料。 +- OpenAI Responses `web_search` 最小推理迴歸:`pnpm test:docker:openai-web-search-minimal`(指令碼:`scripts/e2e/openai-web-search-minimal-docker.sh`)會透過 Gateway 執行模擬的 OpenAI 伺服器,驗證 `web_search` 將 `reasoning.effort` 從 `minimal` 提升到 `low`,然後強制提供者結構描述拒絕,並檢查原始詳細資訊出現在 Gateway 記錄中。 +- MCP 頻道橋接(已植入的 Gateway + stdio 橋接 + 原始 Claude 通知框架煙霧測試):`pnpm test:docker:mcp-channels`(指令碼:`scripts/e2e/mcp-channels-docker.sh`) +- Pi bundle MCP 工具(真實 stdio MCP 伺服器 + 內嵌 Pi 設定檔允許/拒絕煙霧測試):`pnpm test:docker:pi-bundle-mcp-tools`(指令碼:`scripts/e2e/pi-bundle-mcp-tools-docker.sh`) +- Cron/子代理 MCP 清理(真實 Gateway + 在隔離 Cron 與一次性子代理執行後拆除 stdio MCP 子程序):`pnpm test:docker:cron-mcp-cleanup`(指令碼:`scripts/e2e/cron-mcp-cleanup-docker.sh`) +- Plugin(安裝煙霧測試、ClawHub kitchen-sink 安裝/解除安裝、市集更新,以及 Claude-bundle 啟用/檢查):`pnpm test:docker:plugins`(指令碼:`scripts/e2e/plugins-docker.sh`) + 設定 `OPENCLAW_PLUGINS_E2E_CLAWHUB=0` 可跳過 ClawHub 區塊,或使用 `OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC` 和 `OPENCLAW_PLUGINS_E2E_CLAWHUB_ID` 覆寫預設的 kitchen-sink 套件/執行階段組合。若沒有 `OPENCLAW_CLAWHUB_URL`/`CLAWHUB_URL`,測試會使用 hermetic 本機 ClawHub fixture 伺服器。 +- Plugin 更新未變更煙霧測試:`pnpm test:docker:plugin-update`(指令碼:`scripts/e2e/plugin-update-unchanged-docker.sh`) +- 設定重新載入中繼資料煙霧測試:`pnpm test:docker:config-reload`(指令碼:`scripts/e2e/config-reload-source-docker.sh`) +- 內建 Plugin 執行階段依賴項:`pnpm test:docker:bundled-channel-deps` 預設會建置一個小型 Docker 執行器映像,在主機上建置並封裝 OpenClaw 一次,然後將該 tarball 掛載到每個 Linux 安裝情境中。使用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 重用映像,在本機新建置後使用 `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0` 跳過主機重建,或使用 `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 指向既有 tarball。完整 Docker 彙總與發布路徑 bundled-channel 區塊會先預先封裝此 tarball 一次,然後將內建頻道檢查分片到獨立通道,包括 Telegram、Discord、Slack、Feishu、memory-lancedb 和 ACPX 的個別更新通道。發布區塊會將頻道煙霧測試、更新目標以及設定/執行階段合約拆分為 `bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-b` 和 `bundled-channels-contracts`;彙總 `bundled-channels` 區塊仍可供手動重跑使用。發布工作流程也會拆分提供者安裝器區塊,以及內建 Plugin 安裝/解除安裝區塊;舊版 `package-update`、`plugins-runtime` 和 `plugins-integrations` 區塊仍保留作為手動重跑的彙總別名。直接執行 bundled 通道時,使用 `OPENCLAW_BUNDLED_CHANNELS=telegram,slack` 縮小頻道矩陣,或使用 `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx` 縮小更新情境。每個情境的 Docker 執行預設為 `OPENCLAW_BUNDLED_CHANNEL_DOCKER_RUN_TIMEOUT=900s`;多目標更新情境預設為 `OPENCLAW_BUNDLED_CHANNEL_UPDATE_DOCKER_RUN_TIMEOUT=2400s`。該通道也會驗證 `channels..enabled=false` 和 `plugins.entries..enabled=false` 會抑制 doctor/執行階段依賴修復。 +- 反覆調整時,可透過停用無關情境來縮小內建 Plugin 執行階段依賴項,例如: `OPENCLAW_BUNDLED_CHANNEL_SCENARIOS=0 OPENCLAW_BUNDLED_CHANNEL_UPDATE_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_ROOT_OWNED_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_SETUP_ENTRY_SCENARIO=0 pnpm test:docker:bundled-channel-deps`。 -若要手動預建並重用共用功能映像: +若要手動預先建置並重用共用功能映像: ```bash OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local pnpm test:docker:e2e-build OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-channels ``` -設定時,像 `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE` 這類套件專用映像覆寫仍會優先。當 `OPENCLAW_SKIP_DOCKER_BUILD=1` 指向遠端共用映像時,如果本機尚未存在,指令碼會拉取它。QR 與安裝器 Docker 測試保留各自的 Dockerfile,因為它們驗證的是套件/安裝行為,而不是共用已建置應用程式執行階段。 +設定後,套件專用的映像覆寫(例如 `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE`)仍會優先。當 `OPENCLAW_SKIP_DOCKER_BUILD=1` 指向遠端共用映像時,如果本機尚未存在,指令碼會拉取它。QR 與安裝器 Docker 測試會保留自己的 Dockerfile,因為它們驗證的是套件/安裝行為,而不是共用已建置應用程式執行階段。 -即時模型 Docker runner 也會以唯讀方式 bind-mount 目前 checkout,並 -在容器內將它 staging 到暫存工作目錄。這能讓執行階段 -映像保持精簡,同時仍針對你的確切本機原始碼/設定執行 Vitest。 -staging 步驟會跳過大型本機專用快取和應用程式建置輸出,例如 -`.pnpm-store`、`.worktrees`、`__openclaw_vitest__`,以及應用程式本機 `.build` 或 -Gradle 輸出目錄,讓 Docker 即時執行不會花數分鐘複製 -機器專用 artifacts。 -它們也會設定 `OPENCLAW_SKIP_CHANNELS=1`,因此 Gateway 即時探測不會在容器內啟動 -真正的 Telegram/Discord 等通道 worker。 -`test:docker:live-models` 仍會執行 `pnpm test:live`,因此當你需要從該 Docker 路徑縮小或排除 Gateway -即時覆蓋時,也要傳入 +即時模型 Docker 執行器也會以唯讀方式綁定掛載目前的 checkout,並 +將其暫存到容器內的暫存工作目錄。這可讓執行階段 +映像保持精簡,同時仍能針對你確切的本機原始碼/設定執行 Vitest。 +暫存步驟會略過大型的僅限本機快取和應用程式建置輸出,例如 +`.pnpm-store`、`.worktrees`、`__openclaw_vitest__`,以及應用程式本機的 `.build` 或 +Gradle 輸出目錄,因此 Docker 即時執行不會花費數分鐘複製 +特定機器的成品。 +它們也會設定 `OPENCLAW_SKIP_CHANNELS=1`,因此 Gateway 即時探測不會在 +容器內啟動真正的 Telegram/Discord/等頻道 worker。 +`test:docker:live-models` 仍會執行 `pnpm test:live`,因此在需要縮小或排除該 Docker lane 中的 Gateway +即時覆蓋範圍時,也要傳入 `OPENCLAW_LIVE_GATEWAY_*`。 -`test:docker:openwebui` 是較高層級的相容性冒煙測試:它會啟動一個 -已啟用 OpenAI-compatible HTTP endpoints 的 OpenClaw gateway 容器, -啟動一個固定版本的 Open WebUI 容器並連到該 gateway,透過 -Open WebUI 登入,驗證 `/api/models` 暴露 `openclaw/default`,接著透過 Open WebUI 的 `/api/chat/completions` 代理傳送 -真實聊天請求。 -第一次執行可能明顯較慢,因為 Docker 可能需要拉取 -Open WebUI 映像,而 Open WebUI 可能需要完成自己的 cold-start 設定。 -此路徑需要可用的即時模型 key,而 `OPENCLAW_PROFILE_FILE` +`test:docker:openwebui` 是較高層級的相容性 smoke:它會啟動一個 +啟用 OpenAI 相容 HTTP 端點的 OpenClaw Gateway 容器, +啟動一個針對該 Gateway 的固定版本 Open WebUI 容器,透過 +Open WebUI 登入,驗證 `/api/models` 暴露 `openclaw/default`,接著透過 Open WebUI 的 `/api/chat/completions` proxy 傳送一個 +真正的聊天請求。 +第一次執行可能會明顯較慢,因為 Docker 可能需要拉取 +Open WebUI 映像,而 Open WebUI 可能需要完成自己的冷啟動設定。 +這個 lane 需要可用的即時模型 key,而 `OPENCLAW_PROFILE_FILE` (預設為 `~/.profile`)是在 Docker 化執行中提供它的主要方式。 成功執行會列印一小段 JSON payload,例如 `{ "ok": true, "model": "openclaw/default", ... }`。 -`test:docker:mcp-channels` 刻意保持決定性,且不需要 -真正的 Telegram、Discord 或 iMessage 帳號。它會啟動植入資料的 Gateway -容器,啟動第二個容器產生 `openclaw mcp serve`,接著 -驗證 routed conversation discovery、transcript 讀取、attachment 中繼資料、 -live event queue 行為、outbound send routing,以及透過真實 stdio MCP bridge 傳遞的 Claude 風格通道 + -權限通知。notification 檢查會直接檢查原始 stdio MCP frame,因此冒煙測試驗證的是 -bridge 實際 emit 的內容,而不只是特定 client SDK 剛好呈現的內容。 -`test:docker:pi-bundle-mcp-tools` 具決定性,且不需要即時 -模型 key。它會建置 repo Docker 映像,在容器內啟動真實 stdio MCP probe server, -透過內嵌 Pi bundle MCP 執行階段 materialize 該伺服器, -執行工具,接著驗證 `coding` 和 `messaging` 保留 -`bundle-mcp` 工具,而 `minimal` 和 `tools.deny: ["bundle-mcp"]` 會過濾它們。 -`test:docker:cron-mcp-cleanup` 具決定性,且不需要即時模型 -key。它會啟動帶有真實 stdio MCP probe server 的植入資料 Gateway,執行 -隔離的 cron 回合與 `/subagents spawn` 一次性子回合,接著驗證 -MCP 子程序會在每次執行後退出。 +`test:docker:mcp-channels` 是刻意設計為確定性的,且不需要 +真正的 Telegram、Discord 或 iMessage 帳號。它會啟動一個已植入種子的 Gateway +容器,啟動第二個會產生 `openclaw mcp serve` 的容器,接著 +驗證路由後的對話探索、逐字稿讀取、附件中繼資料、 +即時事件佇列行為、對外傳送路由,以及透過真正 stdio MCP bridge 傳遞的 Claude 風格頻道 + +權限通知。通知檢查會直接檢查原始 stdio MCP frame,因此該 smoke 驗證的是 +bridge 實際發出的內容,而不只是特定 client SDK 恰好暴露的內容。 +`test:docker:pi-bundle-mcp-tools` 是確定性的,且不需要即時 +模型 key。它會建置 repo Docker 映像,在容器內啟動真正的 stdio MCP probe server, +透過內嵌 Pi bundle +MCP runtime 具現化該 server,執行 tool,接著驗證 `coding` 和 `messaging` 保留 +`bundle-mcp` tools,而 `minimal` 和 `tools.deny: ["bundle-mcp"]` 會將其篩除。 +`test:docker:cron-mcp-cleanup` 是確定性的,且不需要即時模型 +key。它會以真正的 stdio MCP probe server 啟動已植入種子的 Gateway,執行 +隔離的 cron turn 和 `/subagents spawn` 一次性 child turn,接著驗證 +MCP child process 在每次執行後都會退出。 -手動 ACP 自然語言 thread 冒煙測試(非 CI): +手動 ACP 白話 thread smoke(非 CI): - `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel ...` -- 保留此腳本供迴歸/除錯工作流程使用。ACP thread 路由驗證之後可能還會再次需要它,因此不要刪除。 +- 保留此 script 供迴歸/除錯工作流程使用。ACP thread 路由驗證未來可能再次需要它,因此不要刪除。 -實用的環境變數: +實用的 env vars: - `OPENCLAW_CONFIG_DIR=...`(預設:`~/.openclaw`)掛載到 `/home/node/.openclaw` - `OPENCLAW_WORKSPACE_DIR=...`(預設:`~/.openclaw/workspace`)掛載到 `/home/node/.openclaw/workspace` -- `OPENCLAW_PROFILE_FILE=...`(預設:`~/.profile`)掛載到 `/home/node/.profile`,並在執行測試前載入 -- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` 僅驗證從 `OPENCLAW_PROFILE_FILE` 載入的環境變數,使用暫存的設定/工作區目錄,且不掛載外部 CLI auth -- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...`(預設:`~/.cache/openclaw/docker-cli-tools`)掛載到 `/home/node/.npm-global`,供 Docker 內快取 CLI 安裝使用 -- `$HOME` 下的外部 CLI auth 目錄/檔案會以唯讀方式掛載到 `/host-auth...` 下,然後在測試開始前複製到 `/home/node/...` +- `OPENCLAW_PROFILE_FILE=...`(預設:`~/.profile`)掛載到 `/home/node/.profile`,並在執行測試前 source +- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` 僅驗證從 `OPENCLAW_PROFILE_FILE` source 的 env vars,使用暫存設定/工作區目錄,且不掛載外部 CLI auth +- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...`(預設:`~/.cache/openclaw/docker-cli-tools`)掛載到 `/home/node/.npm-global`,用於 Docker 內快取 CLI 安裝 +- `$HOME` 底下的外部 CLI auth 目錄/檔案會以唯讀方式掛載到 `/host-auth...` 底下,然後在測試開始前複製到 `/home/node/...` - 預設目錄:`.minimax` - 預設檔案:`~/.codex/auth.json`、`~/.codex/config.toml`、`.claude.json`、`~/.claude/.credentials.json`、`~/.claude/settings.json`、`~/.claude/settings.local.json` - 縮小範圍的 provider 執行只會掛載從 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` 推斷出的必要目錄/檔案 - - 使用 `OPENCLAW_DOCKER_AUTH_DIRS=all`、`OPENCLAW_DOCKER_AUTH_DIRS=none`,或像 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` 這樣的逗號清單手動覆寫 + - 使用 `OPENCLAW_DOCKER_AUTH_DIRS=all`、`OPENCLAW_DOCKER_AUTH_DIRS=none` 或類似 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` 的逗號清單手動覆寫 - `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` 用於縮小執行範圍 - `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` 用於篩選容器內的 providers - `OPENCLAW_SKIP_DOCKER_BUILD=1` 用於在不需要重新建置的重跑中重用既有的 `openclaw:local-live` 映像 -- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 用於確保憑證來自 profile store(而非環境變數) -- `OPENCLAW_OPENWEBUI_MODEL=...` 用於選擇 Gateway 為 Open WebUI smoke 暴露的模型 -- `OPENCLAW_OPENWEBUI_PROMPT=...` 用於覆寫 Open WebUI smoke 使用的 nonce-check prompt -- `OPENWEBUI_IMAGE=...` 用於覆寫固定的 Open WebUI 映像標籤 +- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 用於確保 creds 來自 profile store(而不是 env) +- `OPENCLAW_OPENWEBUI_MODEL=...` 用於選擇 Gateway 暴露給 Open WebUI smoke 的模型 +- `OPENCLAW_OPENWEBUI_PROMPT=...` 用於覆寫 Open WebUI smoke 使用的 nonce 檢查 prompt +- `OPENWEBUI_IMAGE=...` 用於覆寫固定的 Open WebUI 映像 tag -## 文件健全性檢查 +## 文件健全性 文件編輯後執行文件檢查:`pnpm check:docs`。 -當你也需要頁內標題檢查時,執行完整的 Mintlify anchor 驗證:`pnpm docs:check-links:anchors`。 +當你也需要頁面內 heading 檢查時,執行完整的 Mintlify anchor 驗證:`pnpm docs:check-links:anchors`。 -## 離線迴歸(CI 安全) +## 離線迴歸(CI-safe) -這些是不使用真實 providers 的「真實 pipeline」迴歸: +這些是不使用真正 providers 的「真實 pipeline」迴歸: -- Gateway tool calling(mock OpenAI,真實 Gateway + agent loop):`src/gateway/gateway.test.ts`(案例:「透過 Gateway agent loop 端對端執行 mock OpenAI tool call」) -- Gateway wizard(WS `wizard.start`/`wizard.next`,寫入設定 + 強制 auth):`src/gateway/gateway.test.ts`(案例:「透過 ws 執行 wizard 並寫入 auth token 設定」) +- Gateway tool calling(mock OpenAI,真正的 gateway + agent loop):`src/gateway/gateway.test.ts`(case:「透過 gateway agent loop 端對端執行 mock OpenAI tool call」) +- Gateway wizard(WS `wizard.start`/`wizard.next`,寫入 config + 強制 auth):`src/gateway/gateway.test.ts`(case:「透過 ws 執行 wizard 並寫入 auth token config」) -## Agent 可靠性評估(Skills) +## Agent 可靠性 evals(skills) -我們已經有幾個 CI 安全測試,其行為類似「agent 可靠性評估」: +我們已經有一些 CI-safe 測試,行為類似「agent 可靠性 evals」: -- 透過真實 Gateway + agent loop 進行 mock tool-calling(`src/gateway/gateway.test.ts`)。 -- 驗證 session wiring 與設定效果的端對端 wizard flows(`src/gateway/gateway.test.ts`)。 +- 透過真正的 gateway + agent loop 進行 mock tool-calling(`src/gateway/gateway.test.ts`)。 +- 驗證 session wiring 和 config effects 的端對端 wizard flows(`src/gateway/gateway.test.ts`)。 -Skills 仍缺少的項目(見 [Skills](/zh-TW/tools/skills)): +Skills 仍缺少的項目(參見 [Skills](/zh-TW/tools/skills)): -- **決策:** 當 prompt 中列出 Skills 時,agent 是否會選擇正確的 skill(或避開不相關的項目)? -- **合規:** agent 是否會在使用前讀取 `SKILL.md`,並遵循必要步驟/參數? -- **工作流程契約:** 多回合情境,用於斷言 tool 順序、session history carryover 與 sandbox 邊界。 +- **決策:** 當 prompt 中列出 skills 時,agent 是否選擇正確的 skill(或避開無關的 skill)? +- **遵循:** agent 是否在使用前閱讀 `SKILL.md` 並遵循必要步驟/args? +- **工作流程合約:** 斷言 tool 順序、session history carryover 和 sandbox boundaries 的多輪情境。 -未來的評估應先保持決定性: +未來的 evals 應優先保持確定性: -- 使用 mock providers 的情境 runner,用來斷言 tool calls + 順序、skill 檔案讀取,以及 session wiring。 -- 一小組聚焦於 skill 的情境(使用 vs 避免、gating、prompt injection)。 -- 選用的 live evals(opt-in、env-gated)僅在 CI 安全套件到位後加入。 +- 使用 mock providers 的情境 runner,用於斷言 tool calls + 順序、skill 檔案讀取,以及 session wiring。 +- 一小組以 skill 為焦點的情境(使用 vs 避免、gating、prompt injection)。 +- 選用的即時 evals(opt-in、env-gated)僅在 CI-safe suite 到位後再加入。 -## 契約測試(Plugin 與通道形狀) +## 合約測試(plugin 與 channel 形狀) -契約測試會驗證每個已註冊的 Plugin 與通道都符合其介面契約。它們會逐一檢查所有探索到的 plugins,並執行一組形狀與行為斷言。預設的 `pnpm test` unit lane 會刻意略過這些 shared seam 與 smoke 檔案;當你觸及共用通道或 provider surfaces 時,請明確執行契約命令。 +合約測試會驗證每個已註冊的 plugin 和 channel 都符合其 +interface contract。它們會迭代所有探索到的 plugins,並執行一組 +形狀與行為斷言。預設的 `pnpm test` unit lane 會刻意 +略過這些共享 seam 和 smoke 檔案;當你觸及共享 channel 或 provider surface 時, +請明確執行合約命令。 ### 命令 -- 所有契約:`pnpm test:contracts` -- 僅通道契約:`pnpm test:contracts:channels` -- 僅 provider 契約:`pnpm test:contracts:plugins` +- 所有合約:`pnpm test:contracts` +- 僅 channel 合約:`pnpm test:contracts:channels` +- 僅 provider 合約:`pnpm test:contracts:plugins` -### 通道契約 +### Channel 合約 位於 `src/channels/plugins/contracts/*.contract.test.ts`: -- **Plugin** - 基本 Plugin 形狀(id、name、capabilities) -- **setup** - 設定 wizard 契約 +- **plugin** - 基本 plugin 形狀(id、name、capabilities) +- **setup** - 設定 wizard 合約 - **session-binding** - Session binding 行為 -- **outbound-payload** - 訊息 payload 結構 -- **inbound** - Inbound 訊息處理 -- **actions** - 通道 action handlers +- **outbound-payload** - Message payload 結構 +- **inbound** - Inbound message 處理 +- **actions** - Channel action handlers - **threading** - Thread ID 處理 - **directory** - Directory/roster API - **group-policy** - Group policy enforcement -### Provider 狀態契約 +### Provider status 合約 位於 `src/plugins/contracts/*.contract.test.ts`。 -- **status** - 通道狀態 probes +- **status** - Channel status probes - **registry** - Plugin registry 形狀 -### Provider 契約 +### Provider 合約 位於 `src/plugins/contracts/*.contract.test.ts`: -- **auth** - Auth flow 契約 +- **auth** - Auth flow 合約 - **auth-choice** - Auth choice/selection - **catalog** - Model catalog API - **discovery** - Plugin discovery - **loader** - Plugin loading - **runtime** - Provider runtime -- **shape** - Plugin 形狀/介面 +- **shape** - Plugin shape/interface - **wizard** - 設定 wizard -### 執行時機 +### 何時執行 - 變更 plugin-sdk exports 或 subpaths 後 -- 新增或修改通道或 provider Plugin 後 -- 重構 Plugin registration 或 discovery 後 +- 新增或修改 channel 或 provider plugin 後 +- 重構 plugin registration 或 discovery 後 -契約測試會在 CI 中執行,且不需要真實 API keys。 +合約測試會在 CI 中執行,且不需要真正的 API keys。 ## 新增迴歸(指引) -當你修正 live 中發現的 provider/model 問題時: +當你修復在即時環境中發現的 provider/model 問題時: -- 盡可能新增 CI 安全迴歸(mock/stub provider,或捕捉確切的 request-shape 轉換) -- 如果本質上只能 live-only(rate limits、auth policies),請保持 live test 範圍狹窄,並透過環境變數 opt-in +- 盡可能新增 CI-safe 迴歸(mock/stub provider,或擷取確切的 request-shape transformation) +- 如果本質上只能即時測試(rate limits、auth policies),請保持即時測試範圍狹窄,並透過 env vars opt-in - 優先鎖定能捕捉該 bug 的最小層級: - - provider request conversion/replay bug → 直接的 models test - - Gateway session/history/tool pipeline bug → Gateway live smoke 或 CI 安全 Gateway mock test + - provider request conversion/replay bug → direct models test + - gateway session/history/tool pipeline bug → gateway live smoke 或 CI-safe gateway mock test - SecretRef traversal guardrail: - - `src/secrets/exec-secret-ref-id-parity.test.ts` 會從 registry metadata(`listSecretTargetRegistryEntries()`)為每個 SecretRef class 推導一個 sampled target,然後斷言 traversal-segment exec ids 會被拒絕。 - - 如果你在 `src/secrets/target-registry-data.ts` 中新增 `includeInPlan` SecretRef target family,請更新該測試中的 `classifyTargetClass`。此測試會刻意在未分類的 target ids 上失敗,讓新的 classes 無法被靜默略過。 + - `src/secrets/exec-secret-ref-id-parity.test.ts` 會從 registry metadata(`listSecretTargetRegistryEntries()`)為每個 SecretRef class 衍生一個 sampled target,然後斷言 traversal-segment exec ids 會被拒絕。 + - 如果你在 `src/secrets/target-registry-data.ts` 新增新的 `includeInPlan` SecretRef target family,請更新該測試中的 `classifyTargetClass`。該測試會刻意在未分類的 target ids 上失敗,因此新的 classes 不會被靜默略過。 ## 相關 -- [Live 測試](/zh-TW/help/testing-live) +- [Testing live](/zh-TW/help/testing-live) - [CI](/zh-TW/ci) diff --git a/docs/zh-TW/reference/test.md b/docs/zh-TW/reference/test.md index 111a48eaa..67a1d69dd 100644 --- a/docs/zh-TW/reference/test.md +++ b/docs/zh-TW/reference/test.md @@ -1,58 +1,59 @@ --- read_when: - 執行或修復測試 -summary: 如何在本機執行測試(vitest),以及何時使用強制/涵蓋率模式 +summary: 如何在本機執行測試 (vitest),以及何時使用 force/coverage 模式 title: 測試 x-i18n: - generated_at: "2026-04-30T03:38:59Z" + generated_at: "2026-04-30T18:38:26Z" model: gpt-5.5 provider: openai - source_hash: 9328d6f0383b5067fa8bb5d0f1bf22a3b9048a267908bf85167842ddc3d12e42 + source_hash: 131f2bad3b2806d28394213cec38d632d106ddbf8ff04d06345ab8046fb8bcf2 source_path: reference/test.md workflow: 16 --- -- 完整測試工具包(套件、即時、Docker):[測試](/zh-TW/help/testing) +- 完整測試工具組(套件、即時、Docker):[測試](/zh-TW/help/testing) -- `pnpm test:force`:終止任何仍占用預設控制埠的殘留 Gateway 行程,接著使用隔離的 Gateway 埠執行完整 Vitest 套件,讓伺服器測試不會與執行中的實例衝突。當先前的 Gateway 執行讓埠 18789 被占用時,使用此指令。 -- `pnpm test:coverage`:使用 V8 覆蓋率執行單元套件(透過 `vitest.unit.config.ts`)。這是已載入檔案的單元覆蓋率關卡,不是整個儲存庫的全檔案覆蓋率。閾值為 70% 行數/函式/陳述式,以及 55% 分支。因為 `coverage.all` 為 false,這個關卡會測量單元覆蓋率套件載入的檔案,而不是把每個分割 lane 的原始碼檔案都視為未覆蓋。 +- `pnpm test:force`:終止任何仍占用預設控制連接埠的 Gateway 程序,然後以隔離的 Gateway 連接埠執行完整 Vitest 套件,避免伺服器測試與執行中的實例衝突。當先前的 Gateway 執行留下連接埠 18789 被占用時使用。 +- `pnpm test:coverage`:使用 V8 覆蓋率執行單元套件(透過 `vitest.unit.config.ts`)。這是已載入檔案的單元覆蓋率閘門,不是整個 repo 的全檔案覆蓋率。門檻為 70% 行數/函式/陳述式與 55% 分支。由於 `coverage.all` 為 false,此閘門會測量單元覆蓋率套件載入的檔案,而不是將每個分割 lane 原始檔視為未覆蓋。 - `pnpm test:coverage:changed`:只針對自 `origin/main` 以來變更的檔案執行單元覆蓋率。 -- `pnpm test:changed`:便宜的智慧變更測試執行。它會從直接測試編輯、相鄰的 `*.test.ts` 檔案、明確的原始碼對應,以及本機匯入圖執行精確目標。寬泛/設定/套件變更會被略過,除非它們對應到精確測試。 -- `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`:明確的寬泛變更測試執行。當測試工具/設定/套件編輯應該退回 Vitest 較寬泛的變更測試行為時使用。 -- `pnpm changed:lanes`:顯示相對於 `origin/main` 的差異所觸發的架構 lanes。 -- `pnpm check:changed`:針對相對於 `origin/main` 的差異執行智慧變更檢查關卡。它會為受影響的架構 lanes 執行型別檢查、lint 與守衛指令,但不會執行 Vitest 測試。測試證明請使用 `pnpm test:changed` 或明確的 `pnpm test `。 -- `pnpm test`:透過作用域化的 Vitest lanes 路由明確的檔案/目錄目標。未指定目標的執行會使用固定 shard 群組,並展開為 leaf 設定以便本機平行執行;extension 群組一律展開為每個 extension 的 shard 設定,而不是一個巨大的根專案行程。 -- 測試包裝器執行會以簡短的 `[test] passed|failed|skipped ... in ...` 摘要結束。Vitest 自己的持續時間行會保留為每個 shard 的細節。 -- 共享的 OpenClaw 測試狀態:當測試需要隔離的 `HOME`、`OPENCLAW_STATE_DIR`、`OPENCLAW_CONFIG_PATH`、設定 fixture、工作區、agent 目錄或 auth-profile 存放區時,從 Vitest 使用 `src/test-utils/openclaw-test-state.ts`。 -- 行程 E2E 輔助工具:當 Vitest 行程層級 E2E 測試需要執行中的 Gateway、CLI env、日誌擷取與清理集中在一處時,使用 `test/helpers/openclaw-test-instance.ts`。 -- Docker/Bash E2E 輔助工具:source `scripts/lib/docker-e2e-image.sh` 的 lanes 可以把 `docker_e2e_test_state_shell_b64