From eb626d89c5077cc425e0e7b01255f7e8e96fbe2c Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Sat, 2 May 2026 15:56:06 +0000 Subject: [PATCH] chore(i18n): refresh zh-CN translations --- docs/zh-CN/ci.md | 349 +++++++++--------- docs/zh-CN/help/testing.md | 701 ++++++++++++++++++++----------------- 2 files changed, 562 insertions(+), 488 deletions(-) diff --git a/docs/zh-CN/ci.md b/docs/zh-CN/ci.md index 5eaa88753..123ad0bb4 100644 --- a/docs/zh-CN/ci.md +++ b/docs/zh-CN/ci.md @@ -1,93 +1,94 @@ --- read_when: - - 你需要了解为什么某个 CI 作业运行了或没有运行 + - 你需要了解 CI 作业为何运行或为何没有运行 - 你正在调试一项失败的 GitHub Actions 检查 - 你正在协调一次发布验证运行或重新运行 - 你正在更改 ClawSweeper 调度或 GitHub 活动转发 -summary: CI 作业图、范围门控、发布总括项和本地命令等效项 +summary: CI 作业图、范围门禁、发布伞形流程和本地命令等效项 title: CI 流水线 x-i18n: - generated_at: "2026-05-02T12:52:22Z" + generated_at: "2026-05-02T15:53:12Z" model: gpt-5.5 provider: openai - source_hash: f773c5a8221e3e458373e80b689d66e8cc4243d0df63364a4766701c2f4344a4 + source_hash: 1cf280f1f46d49462656de86001b7f2bef7c63f133dbb8d208a7497c48fa3497 source_path: ci.md workflow: 16 --- -OpenClaw CI 会在每次推送到 `main` 以及每个拉取请求时运行。`preflight` 作业会对 diff 进行分类,并在只有无关区域发生变化时关闭昂贵的通道。手动 `workflow_dispatch` 运行会有意绕过智能作用域判定,并为发布候选版本和广泛验证展开完整图。Android 通道通过 `include_android` 保持选择启用。仅发布使用的插件覆盖率位于单独的 [`Plugin Prerelease`](#plugin-prerelease) 工作流中,并且只会从 [`Full Release Validation`](#full-release-validation) 或显式手动派发运行。 +OpenClaw CI 会在每次推送到 `main` 和每个拉取请求时运行。`preflight` 作业会对 diff 进行分类,并在只有无关区域发生变更时关闭高成本通道。手动 `workflow_dispatch` 运行会有意绕过智能范围限定,并为候选发布版本和广泛验证展开完整图。Android 通道通过 `include_android` 保持可选启用。仅发布使用的插件覆盖率位于单独的 [`插件预发布`](#plugin-prerelease) 工作流中,并且只会从 [`完整发布验证`](#full-release-validation) 或显式手动派发运行。 ## 流水线概览 -| 作业 | 用途 | 运行时机 | -| -------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------- | -| `preflight` | 检测仅文档变更、变更作用域、变更扩展,并构建 CI 清单 | 始终在非草稿推送和 PR 上运行 | -| `security-scm-fast` | 通过 `zizmor` 进行私钥检测和工作流审计 | 始终在非草稿推送和 PR 上运行 | -| `security-dependency-audit` | 针对 npm 公告进行无依赖的生产 lockfile 审计 | 始终在非草稿推送和 PR 上运行 | -| `security-fast` | 快速安全作业的必需聚合项 | 始终在非草稿推送和 PR 上运行 | -| `check-dependencies` | 生产 Knip 仅依赖检查,以及未使用文件 allowlist 防护 | Node 相关变更 | -| `build-artifacts` | 构建 `dist/`、Control UI、内置制品检查,以及可复用下游制品 | Node 相关变更 | -| `checks-fast-core` | 快速 Linux 正确性通道,例如内置/插件契约/协议检查 | Node 相关变更 | -| `checks-fast-contracts-channels` | 分片渠道契约检查,并提供稳定的聚合检查结果 | Node 相关变更 | -| `checks-node-core-test` | Core Node 测试分片,排除渠道、内置、契约和扩展通道 | Node 相关变更 | -| `check` | 分片的主本地门禁等价项:生产类型、lint、防护、测试类型和严格 smoke | Node 相关变更 | -| `check-additional` | 架构、边界、扩展表面防护、包边界和 gateway-watch 分片 | Node 相关变更 | -| `build-smoke` | 内置 CLI smoke 测试和启动内存 smoke | Node 相关变更 | -| `checks` | 内置制品渠道测试的验证器 | Node 相关变更 | -| `checks-node-compat-node22` | Node 22 兼容性构建和 smoke 通道 | 发布用手动 CI 派发 | -| `check-docs` | 文档格式、lint 和断链检查 | 文档已变更 | -| `skills-python` | 面向 Python 支持的 Skills 的 Ruff + pytest | Python 技能相关变更 | -| `checks-windows` | Windows 专用进程/路径测试,以及共享运行时导入说明符回归 | Windows 相关变更 | -| `macos-node` | 使用共享内置制品的 macOS TypeScript 测试通道 | macOS 相关变更 | -| `macos-swift` | macOS 应用的 Swift lint、构建和测试 | macOS 相关变更 | -| `android` | 两种 flavor 的 Android 单元测试,以及一次 debug APK 构建 | Android 相关变更 | -| `test-performance-agent` | 可信活动之后的每日 Codex 慢测试优化 | Main CI 成功或手动派发 | +| 作业 | 用途 | 运行时机 | +| -------------------------------- | --------------------------------------------------------------------------------------------------------- | ---------------------------------- | +| `preflight` | 检测仅文档变更、变更范围、变更扩展,并构建 CI 清单 | 始终在非草稿推送和 PR 上运行 | +| `security-scm-fast` | 通过 `zizmor` 进行私钥检测和工作流审计 | 始终在非草稿推送和 PR 上运行 | +| `security-dependency-audit` | 针对 npm 安全公告进行无依赖的生产 lockfile 审计 | 始终在非草稿推送和 PR 上运行 | +| `security-fast` | 快速安全作业所需的聚合项 | 始终在非草稿推送和 PR 上运行 | +| `check-dependencies` | 生产 Knip 仅依赖检查,以及未使用文件 allowlist 防护 | Node 相关变更 | +| `build-artifacts` | 构建 `dist/`、Control UI、构建产物检查,以及可复用的下游产物 | Node 相关变更 | +| `checks-fast-core` | 快速 Linux 正确性通道,例如内置/插件契约/协议检查 | Node 相关变更 | +| `checks-fast-contracts-channels` | 分片的渠道契约检查,并带有稳定的聚合检查结果 | Node 相关变更 | +| `checks-node-core-test` | 核心 Node 测试分片,不包括渠道、内置、契约和扩展通道 | Node 相关变更 | +| `check` | 分片的主要本地门禁等价项:生产类型、lint、防护、测试类型和严格 smoke | Node 相关变更 | +| `check-additional` | 架构、边界、扩展表面防护、包边界和 gateway-watch 分片 | Node 相关变更 | +| `build-smoke` | 已构建 CLI smoke 测试和启动内存 smoke | Node 相关变更 | +| `checks` | 已构建产物渠道测试的验证器 | Node 相关变更 | +| `checks-node-compat-node22` | Node 22 兼容性构建和 smoke 通道 | 发布用手动 CI 派发 | +| `check-docs` | 文档格式化、lint 和断链检查 | 文档已变更 | +| `skills-python` | 面向 Python 支持的 Skills 的 Ruff + pytest | Python Skills 相关变更 | +| `checks-windows` | Windows 特定进程/路径测试,以及共享运行时导入说明符回归测试 | Windows 相关变更 | +| `macos-node` | 使用共享构建产物的 macOS TypeScript 测试通道 | macOS 相关变更 | +| `macos-swift` | macOS 应用的 Swift lint、构建和测试 | macOS 相关变更 | +| `android` | 两种 flavor 的 Android 单元测试,以及一次 debug APK 构建 | Android 相关变更 | +| `test-performance-agent` | 可信活动后的每日 Codex 慢测试优化 | 主 CI 成功或手动派发 | +| `openclaw-performance` | 每日/按需 Kova 运行时性能报告,包含 mock-provider、deep-profile 和 GPT 5.4 实时通道 | 定时和手动派发 | -## 快速失败顺序 +## Fail-fast 顺序 -1. `preflight` 决定哪些通道实际存在。`docs-scope` 和 `changed-scope` 逻辑是此作业内的步骤,不是独立作业。 -2. `security-scm-fast`、`security-dependency-audit`、`security-fast`、`check`、`check-additional`、`check-docs` 和 `skills-python` 会快速失败,而无需等待更重的制品和平台矩阵作业。 -3. `build-artifacts` 会与快速 Linux 通道重叠运行,因此下游消费者可以在共享构建就绪后立即开始。 +1. `preflight` 决定哪些通道实际存在。`docs-scope` 和 `changed-scope` 逻辑是此作业内部的步骤,不是独立作业。 +2. `security-scm-fast`、`security-dependency-audit`、`security-fast`、`check`、`check-additional`、`check-docs` 和 `skills-python` 会快速失败,而不会等待更重的产物和平台矩阵作业。 +3. `build-artifacts` 会与快速 Linux 通道重叠运行,这样下游消费者可以在共享构建就绪后立即开始。 4. 更重的平台和运行时通道随后展开:`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 并发键带版本号(`CI-v7-*`),因此 GitHub 端旧队列组中的僵尸项无法无限期阻塞新的 main 运行。手动完整套件运行使用 `CI-manual-v1-*`,并且不会取消正在运行的运行。 +当同一 PR 或 `main` ref 上有更新的推送落地时,GitHub 可能会将被取代的作业标记为 `cancelled`。除非同一 ref 的最新运行也在失败,否则将其视为 CI 噪声。聚合分片检查使用 `!cancelled() && always()`,因此它们仍会报告正常的分片失败,但不会在整个工作流已被取代后继续排队。自动 CI 并发键带有版本号(`CI-v7-*`),因此 GitHub 侧旧队列组中的僵尸任务无法无限期阻塞更新的 main 运行。手动完整套件运行使用 `CI-manual-v1-*`,并且不会取消正在进行的运行。 -## 作用域和路由 +## 范围和路由 -作用域逻辑位于 `scripts/ci-changed-scope.mjs`,并由 `src/scripts/ci-changed-scope.test.ts` 中的单元测试覆盖。手动派发会跳过 changed-scope 检测,并让 preflight 清单表现得像每个作用域区域都发生了变化。 +范围逻辑位于 `scripts/ci-changed-scope.mjs`,并由 `src/scripts/ci-changed-scope.test.ts` 中的单元测试覆盖。手动派发会跳过变更范围检测,并让 preflight 清单表现得像每个限定范围区域都发生了变更。 -- **CI 工作流编辑**会验证 Node CI 图和工作流 lint,但本身不会强制 Windows、Android 或 macOS 原生构建;这些平台通道仍限定于平台源代码变更。 -- **仅 CI 路由编辑、选定的廉价 core-test fixture 编辑,以及窄范围插件契约 helper/test-routing 编辑**使用快速的仅 Node 清单路径:`preflight`、security,以及一个 `checks-fast-core` 任务。当变更仅限于快速任务直接执行的路由或 helper 表面时,该路径会跳过构建制品、Node 22 兼容性、渠道契约、完整 core 分片、内置插件分片和额外防护矩阵。 -- **Windows Node 检查**限定于 Windows 专用进程/路径包装器、npm/pnpm/UI runner helper、包管理器配置,以及执行该通道的 CI 工作流表面;无关源代码、插件、install-smoke 和仅测试变更仍留在 Linux Node 通道上。 +- **CI 工作流编辑**会验证 Node CI 图和工作流 lint,但其本身不会强制 Windows、Android 或 macOS 原生构建;这些平台通道仍限定到平台源代码变更。 +- **仅 CI 路由编辑、选定的低成本核心测试 fixture 编辑,以及窄范围插件契约辅助/测试路由编辑**会使用快速的仅 Node 清单路径:`preflight`、security 和单个 `checks-fast-core` 任务。当变更仅限于该快速任务直接覆盖的路由或辅助表面时,该路径会跳过构建产物、Node 22 兼容性、渠道契约、完整核心分片、内置插件分片和额外防护矩阵。 +- **Windows Node 检查**限定于 Windows 特定进程/路径包装器、npm/pnpm/UI 运行器辅助工具、包管理器配置,以及执行该通道的 CI 工作流表面;无关源码、插件、install-smoke 和仅测试变更仍保留在 Linux Node 通道上。 -最慢的 Node 测试族会被拆分或均衡,使每个作业保持较小规模,同时不过度预留 runner:渠道契约作为三个加权分片运行,小型 core 单元通道成对组合,auto-reply 作为四个均衡 worker 运行(reply 子树拆分为 agent-runner、dispatch 和 commands/state-routing 分片),agentic Gateway 网关/插件配置分散到现有仅源码 agentic Node 作业中,而不是等待构建制品。广泛的浏览器、QA、媒体和杂项插件测试使用其专用 Vitest 配置,而不是共享的插件 catch-all。include-pattern 分片使用 CI 分片名称记录计时条目,因此 `.artifacts/vitest-shard-timings.json` 可以区分整个配置与过滤后的分片。`check-additional` 会将包边界编译/canary 工作放在一起,并将运行时拓扑架构与 gateway watch 覆盖率分开;边界防护分片会在一个作业内并发运行其小型独立防护。Gateway watch、渠道测试和 core 支持边界分片会在 `dist/` 和 `dist-runtime/` 已构建后,于 `build-artifacts` 内并发运行。 +最慢的 Node 测试族会被拆分或平衡,以便每个作业保持较小规模而不过度预留 runner:渠道契约作为三个加权分片运行,小型核心单元通道成对运行,auto-reply 作为四个平衡 worker 运行(reply 子树拆分为 agent-runner、dispatch 和 commands/state-routing 分片),agentic gateway/plugin 配置分散到现有的仅源码 agentic Node 作业中,而不是等待构建产物。广泛的浏览器、QA、媒体和杂项插件测试使用其专用 Vitest 配置,而不是共享插件 catch-all。包含模式分片使用 CI 分片名称记录计时条目,因此 `.artifacts/vitest-shard-timings.json` 可以区分整个配置和筛选后的分片。`check-additional` 将包边界编译/canary 工作保持在一起,并将运行时拓扑架构与 gateway watch 覆盖率分离;边界防护分片会在一个作业内并发运行其小型独立防护。Gateway 网关 watch、渠道测试和核心支持边界分片会在 `dist/` 和 `dist-runtime/` 已构建后,在 `build-artifacts` 内并发运行。 -Android CI 会同时运行 `testPlayDebugUnitTest` 和 `testThirdPartyDebugUnitTest`,然后构建 Play debug APK。第三方 flavor 没有单独的 source set 或 manifest;其单元测试通道仍会使用 SMS/call-log BuildConfig 标志编译该 flavor,同时避免在每个 Android 相关推送上执行重复的 debug APK 打包作业。 +Android CI 会同时运行 `testPlayDebugUnitTest` 和 `testThirdPartyDebugUnitTest`,然后构建 Play debug APK。第三方 flavor 没有单独的 source set 或 manifest;其单元测试通道仍会使用 SMS/call-log BuildConfig 标志编译该 flavor,同时避免在每个 Android 相关推送上重复执行 debug APK 打包作业。 -`check-dependencies` 分片会运行 `pnpm deadcode:dependencies`(生产 Knip 仅依赖检查,固定到最新 Knip 版本,并为 `dlx` 安装禁用 pnpm 的最小发布年龄)和 `pnpm deadcode:unused-files`,后者会将 Knip 的生产未使用文件发现结果与 `scripts/deadcode-unused-files.allowlist.mjs` 进行比较。当 PR 添加新的未经审查未使用文件,或留下过时 allowlist 条目时,未使用文件防护会失败,同时保留 Knip 无法静态解析的有意动态插件、生成内容、构建、实时测试和包桥接表面。 +`check-dependencies` 分片运行 `pnpm deadcode:dependencies`(一个生产 Knip 仅依赖检查,固定到最新 Knip 版本,并在 `dlx` 安装时禁用 pnpm 的最小发布时间)和 `pnpm deadcode:unused-files`,后者会将 Knip 的生产未使用文件发现结果与 `scripts/deadcode-unused-files.allowlist.mjs` 进行比较。当 PR 新增了未审查的未使用文件,或留下陈旧的 allowlist 条目时,未使用文件防护会失败,同时保留 Knip 无法静态解析的有意动态插件、生成、构建、实时测试和包桥接表面。 ## ClawSweeper 活动转发 -`.github/workflows/clawsweeper-dispatch.yml` 是从 OpenClaw 仓库活动到 ClawSweeper 的目标端桥接。它不会 check out 或执行不受信任的拉取请求代码。该工作流会从 `CLAWSWEEPER_APP_PRIVATE_KEY` 创建 GitHub App token,然后向 `openclaw/clawsweeper` 派发紧凑的 `repository_dispatch` payload。 +`.github/workflows/clawsweeper-dispatch.yml` 是从 OpenClaw 仓库活动到 ClawSweeper 的目标侧桥接。它不会签出或执行不可信的拉取请求代码。该工作流会从 `CLAWSWEEPER_APP_PRIVATE_KEY` 创建 GitHub App token,然后向 `openclaw/clawsweeper` 派发紧凑的 `repository_dispatch` payload。 该工作流有四个通道: -- `clawsweeper_item` 用于精确的 issue 和拉取请求评审请求; +- `clawsweeper_item` 用于精确的 issue 和拉取请求 review 请求; - `clawsweeper_comment` 用于 issue 评论中的显式 ClawSweeper 命令; -- `clawsweeper_commit_review` 用于 `main` 推送上的提交级评审请求; -- `github_activity` 用于 ClawSweeper 智能体可以检查的一般 GitHub 活动。 +- `clawsweeper_commit_review` 用于 `main` 推送上的提交级 review 请求; +- `github_activity` 用于 ClawSweeper 智能体可能检查的一般 GitHub 活动。 -`github_activity` 通道只转发规范化元数据:事件类型、动作、actor、仓库、条目编号、URL、标题、状态,以及评论或评审存在时的短摘录。它有意避免转发完整 webhook body。`openclaw/clawsweeper` 中的接收工作流是 `.github/workflows/github-activity.yml`,它会将规范化事件发布到 ClawSweeper 智能体的 OpenClaw Gateway 网关 hook。 +`github_activity` 通道只转发规范化元数据:事件类型、动作、actor、仓库、条目编号、URL、标题、状态,以及存在评论或 review 时的简短摘录。它有意避免转发完整 webhook body。`openclaw/clawsweeper` 中的接收工作流是 `.github/workflows/github-activity.yml`,它会将规范化事件发布到 OpenClaw Gateway 网关 hook,供 ClawSweeper 智能体使用。 -一般活动是观察,不是默认投递。ClawSweeper 智能体会在其提示中收到 Discord 目标,并且只有当事件令人意外、可操作、有风险或对运营有用时,才应发布到 `#clawsweeper`。常规打开、编辑、机器人 churn、重复 webhook 噪声和正常评审流量应得到 `NO_REPLY`。 +一般活动是观察,而不是默认投递。ClawSweeper 智能体会在其提示中收到 Discord 目标,并且只应在事件令人意外、可操作、有风险或对运维有用时发布到 `#clawsweeper`。例行打开、编辑、机器人扰动、重复 webhook 噪声和正常 review 流量应产生 `NO_REPLY`。 -在整个路径中,都应将 GitHub 标题、评论、正文、评审文本、分支名称和提交消息视为不受信任的数据。它们是用于摘要和分诊的输入,不是工作流或智能体运行时的指令。 +在整个路径中,将 GitHub 标题、评论、正文、review 文本、分支名称和提交消息视为不可信数据。它们是用于摘要和分诊的输入,而不是工作流或智能体运行时的指令。 ## 手动派发 -手动 CI 派发运行与普通 CI 相同的作业图,但会强制启用每个非 Android 作用域通道:Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、build smoke、文档检查、Python Skills、Windows、macOS 和 Control UI i18n。独立手动 CI 派发只有在 `include_android=true` 时才会运行 Android;完整发布伞形流程会通过传递 `include_android=true` 启用 Android。插件预发布静态检查、仅发布使用的 `agentic-plugins` 分片、完整扩展批量扫描和插件预发布 Docker 通道被排除在 CI 之外。Docker 预发布套件只会在 `Full Release Validation` 启用 release-validation 门禁后派发单独的 `Plugin Prerelease` 工作流时运行。 +手动 CI 调度运行与常规 CI 相同的作业图,但会强制开启每个非 Android 范围的通道:Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建冒烟、文档检查、Python Skills、Windows、macOS 和 Control UI i18n。独立的手动 CI 调度仅在 `include_android=true` 时运行 Android;完整发布伞形流程会通过传入 `include_android=true` 启用 Android。插件预发布静态检查、仅发布使用的 `agentic-plugins` 分片、完整扩展批量扫描以及插件预发布 Docker 通道均不包含在 CI 中。Docker 预发布套件仅在 `Full Release Validation` 通过启用发布验证门禁来调度单独的 `Plugin Prerelease` 工作流时运行。 -手动运行使用唯一的并发组,因此发布候选完整套件不会被同一 ref 上的另一次推送或 PR 运行取消。可选的 `target_ref` 输入允许可信调用方在使用所选派发 ref 中工作流文件的同时,针对分支、标签或完整提交 SHA 运行该图。 +手动运行会使用唯一的并发组,因此候选发布版本的完整套件不会被同一 ref 上的另一个 push 或 PR 运行取消。可选的 `target_ref` 输入允许受信任的调用方在使用所选调度 ref 中的工作流文件的同时,针对分支、标签或完整提交 SHA 运行该作业图。 ```bash gh workflow run ci.yml --ref release/YYYY.M.D @@ -99,15 +100,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`、较轻量的插件分片、`checks-fast-core`、`checks-node-compat-node22`、`check-prod-types` 和 `check-test-types` | +| `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 预检也使用 GitHub 托管的 Ubuntu,以便 Blacksmith 矩阵可以更早排队 | +| `blacksmith-4vcpu-ubuntu-2404` | `CodeQL Critical Quality`、较低权重的扩展分片、`checks-fast-core`、`checks-node-compat-node22`、`check-prod-types` 和 `check-test-types` | | `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`、build-smoke、Linux Node 测试分片、内置插件测试分片、`android` | -| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`(对 CPU 足够敏感,8 vCPU 的成本高于节省的时间);install-smoke Docker 构建(32 vCPU 的排队时间成本高于节省的时间) | +| `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 @@ -131,15 +132,33 @@ node scripts/ci-run-timings.mjs --latest-main # ignore issue/comment noise and c node scripts/ci-run-timings.mjs --recent 10 # compare recent successful main CI runs pnpm test:perf:groups --full-suite --allow-failures --output .artifacts/test-perf/baseline-before.json pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifacts/test-perf/after-agent.json +pnpm perf:kova:summary --report .artifacts/kova/reports/mock-provider/report.json --output .artifacts/kova/summary.md ``` +## OpenClaw 性能 + +`OpenClaw Performance` 是产品/运行时性能工作流。它每天在 `main` 上运行,也可以手动调度: + +```bash +gh workflow run openclaw-performance.yml --ref main -f profile=diagnostic -f repeat=3 +gh workflow run openclaw-performance.yml --ref main -f profile=smoke -f repeat=1 -f deep_profile=true -f live_gpt54=true +``` + +该工作流会从固定发布版本安装 OCM,并从固定的 `kova_ref` 输入安装 Kova,然后运行三个通道: + +- `mock-provider`:针对本地构建运行时运行 Kova 诊断场景,并使用确定性的假 OpenAI 兼容认证。 +- `mock-deep-profile`:针对启动、Gateway 网关和智能体回合热点进行 CPU/堆/跟踪剖析。 +- `live-gpt54`:一次真实的 OpenAI `openai/gpt-5.4` 智能体回合,在 `OPENAI_API_KEY` 不可用时跳过。 + +每个通道都会上传 GitHub 工件。配置 `CLAWGRIT_REPORTS_TOKEN` 后,该工作流还会将 `report.json`、`report.md`、bundle 和 `index.md` 提交到 `openclaw/clawgrit-reports` 的 `openclaw-performance//-//` 下。当前分支指针会写入为 `openclaw-performance//latest-.json`。 + ## 完整发布验证 -`Full Release Validation` 是用于“发布前运行所有内容”的手动总括工作流。它接受一个分支、标签或完整提交 SHA,使用该目标分发手动 `CI` 工作流,分发 `Plugin Prerelease` 以提供仅发布所需的插件/包/静态/Docker 证明,并分发 `OpenClaw Release Checks` 以运行安装冒烟、包验收、Docker 发布路径套件、live/E2E、OpenWebUI、QA Lab 一致性、Matrix 和 Telegram 通道。使用 `rerun_group=all` 和 `release_profile=full` 时,它还会针对来自发布检查的 `release-package-under-test` 工件运行 `NPM Telegram Beta E2E`。发布后,传入 `npm_telegram_package_spec` 可针对已发布的 npm 包重新运行同一个 Telegram 包通道。 +`Full Release Validation` 是用于“发布前运行所有内容”的手动伞形工作流。它接受分支、标签或完整提交 SHA,使用该目标调度手动 `CI` 工作流,调度 `Plugin Prerelease` 以提供仅发布使用的插件/包/静态/Docker 证明,并调度 `OpenClaw Release Checks` 以执行安装冒烟、包验收、Docker 发布路径套件、live/E2E、OpenWebUI、QA Lab parity、Matrix 和 Telegram 通道。使用 `rerun_group=all` 和 `release_profile=full` 时,它还会针对发布检查中的 `release-package-under-test` 工件运行 `NPM Telegram Beta E2E`。发布后,传入 `npm_telegram_package_spec` 可针对已发布的 npm 包重新运行同一 Telegram 包通道。 -请参阅[完整发布验证](/zh-CN/reference/full-release-validation),了解阶段矩阵、确切的工作流作业名称、配置差异、工件和聚焦重跑句柄。 +请参阅[完整发布验证](/zh-CN/reference/full-release-validation),了解阶段矩阵、确切的工作流作业名称、配置文件差异、工件和聚焦重运行句柄。 -`OpenClaw Release Publish` 是会产生变更的手动发布工作流。在发布标签存在且 OpenClaw npm preflight 已成功后,从 `release/YYYY.M.D` 或 `main` 分发它。它会验证 `pnpm plugins:sync:check`,为所有可发布的插件包分发 `Plugin NPM Release`,为相同的发布 SHA 分发 `Plugin ClawHub Release`,然后才使用保存的 `preflight_run_id` 分发 `OpenClaw NPM Release`。 +`OpenClaw Release Publish` 是会产生变更的手动发布工作流。在发布标签存在且 OpenClaw npm 预检成功后,从 `release/YYYY.M.D` 或 `main` 调度它。它会验证 `pnpm plugins:sync:check`,为所有可发布的插件包调度 `Plugin NPM Release`,为同一发布 SHA 调度 `Plugin ClawHub Release`,然后才使用保存的 `preflight_run_id` 调度 `OpenClaw NPM Release`。 ```bash gh workflow run openclaw-release-publish.yml \ @@ -149,31 +168,31 @@ gh workflow run openclaw-release-publish.yml \ -f npm_dist_tag=beta ``` -对于快速移动分支上的固定提交证明,请使用辅助命令,而不是 `gh workflow run ... --ref main -f ref=`: +对于快速变化分支上的固定提交证明,请使用辅助命令,而不是 `gh workflow run ... --ref main -f ref=`: ```bash pnpm ci:full-release --sha ``` -GitHub 工作流分发 ref 必须是分支或标签,不能是原始提交 SHA。该辅助命令会在目标 SHA 上推送一个临时 `release-ci/-...` 分支,从该固定 ref 分发 `Full Release Validation`,验证每个子工作流的 `headSha` 都与目标匹配,并在运行完成后删除临时分支。如果任何子工作流在不同 SHA 上运行,总括验证器也会失败。 +GitHub 工作流调度 ref 必须是分支或标签,不能是原始提交 SHA。该辅助命令会在目标 SHA 处推送一个临时 `release-ci/-...` 分支,从该固定 ref 调度 `Full Release Validation`,验证每个子工作流的 `headSha` 都与目标匹配,并在运行完成后删除临时分支。如果任何子工作流运行在不同 SHA 上,伞形验证器也会失败。 -`release_profile` 控制传入发布检查的 live/提供商覆盖范围。手动发布工作流默认使用 `stable`;只有在你明确想要宽泛的咨询型提供商/媒体矩阵时才使用 `full`。 +`release_profile` 控制传入发布检查的 live/提供商覆盖范围。手动发布工作流默认使用 `stable`;仅在你有意需要广泛的建议性提供商/媒体矩阵时才使用 `full`。 - `minimum` 保留最快的 OpenAI/核心发布关键通道。 - `stable` 添加稳定的提供商/后端集合。 -- `full` 运行宽泛的咨询型提供商/媒体矩阵。 +- `full` 运行广泛的建议性提供商/媒体矩阵。 -总括工作流会记录已分发的子运行 ID,最终的 `Verify full validation` 作业会重新检查当前子运行结论,并为每个子运行追加最慢作业表。如果某个子工作流重跑后变绿,只需重跑父验证器作业即可刷新总括结果和耗时摘要。 +伞形流程会记录已调度的子运行 ID,最终的 `Verify full validation` 作业会重新检查当前子运行结论,并为每个子运行追加最慢作业表。如果某个子工作流被重新运行并变为绿色,只需重新运行父验证器作业即可刷新伞形结果和计时摘要。 -对于恢复,`Full Release Validation` 和 `OpenClaw Release Checks` 都接受 `rerun_group`。对发布候选版本使用 `all`,仅针对普通完整 CI 子项使用 `ci`,仅针对插件预发布子项使用 `plugin-prerelease`,针对每个发布子项使用 `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`,仅插件预发布子流程使用 `plugin-prerelease`,每个发布子流程使用 `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,然后把该工件传给 live/E2E 发布路径 Docker 工作流和包验收分片。这能保持不同发布环境中的包字节一致,并避免在多个子作业中重新打包同一个候选版本。 +`OpenClaw Release Checks` 使用受信任的工作流引用,将选定的引用解析一次为 `release-package-under-test` tarball,然后把该构件传给 live/E2E 发布路径 Docker 工作流和包验收分片。这样可以让各个发布环境中的包字节保持一致,并避免在多个子作业中重新打包同一个候选版本。 -对于 `ref=main` 和 `rerun_group=all` 的重复 `Full Release Validation` 运行,新运行会取代旧的总括运行。父监视器在父运行被取消时,会取消它已经分发的任何子工作流,因此较新的 main 验证不会排在过期的两小时发布检查运行后面。发布分支/标签验证和聚焦重跑组会保持 `cancel-in-progress: false`。 +对于 `ref=main` 和 `rerun_group=all` 的重复 `Full Release Validation` 运行会取代较旧的伞形流程。父监控器在父流程被取消时,会取消它已调度的任何子工作流,因此较新的 main 验证不会排在陈旧的两小时 release-check 运行后面。发布分支/标签验证和聚焦重新运行组会保持 `cancel-in-progress: false`。 ## Live 和 E2E 分片 -发布 live/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` @@ -185,59 +204,59 @@ GitHub 工作流分发 ref 必须是分支或标签,不能是原始提交 SHA - `native-live-extensions-openai` - `native-live-extensions-o-z-other` - `native-live-extensions-xai` -- 拆分的媒体音频/视频分片以及提供商过滤的音乐分片 +- 拆分后的媒体音频/视频分片,以及提供商过滤的音乐分片 -这会保持相同的文件覆盖范围,同时让缓慢的 live 提供商失败更容易重跑和诊断。聚合 `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` 分片名称仍可用于手动一次性重新运行。 -原生 live 媒体分片在 `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04` 中运行,该镜像由 `Live Media Runner Image` 工作流构建。该镜像预安装了 `ffmpeg` 和 `ffprobe`;媒体作业只会在设置前验证二进制文件。请将 Docker 支持的 live 套件保留在普通 Blacksmith 运行器上,容器作业不是启动嵌套 Docker 测试的合适位置。 +原生 live 媒体分片在 `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04` 中运行,该镜像由 `Live Media Runner Image` 工作流构建。该镜像预装 `ffmpeg` 和 `ffprobe`;媒体作业只在设置前验证这些二进制文件。让 Docker 支持的 live 套件保持在普通 Blacksmith 运行器上运行,容器作业不适合启动嵌套 Docker 测试。 -Docker 支持的实时模型/后端分片会为每个选定提交使用单独的共享 `ghcr.io/openclaw/openclaw-live-test:` 镜像。实时发布工作流会构建并推送该镜像一次,然后 Docker 实时模型、按提供商分片的 Gateway 网关、CLI 后端、ACP 绑定和 Codex harness 分片会以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 运行。Gateway 网关 Docker 分片在脚本级别带有明确的 `timeout` 上限,低于工作流作业超时,因此卡住的容器或清理路径会快速失败,而不是耗尽整个发布检查预算。如果这些分片独立重新构建完整源码 Docker 目标,则发布运行配置错误,并会在重复镜像构建上浪费实际耗时。 +Docker 支持的 live 模型/后端分片会为每个选定提交使用单独的共享 `ghcr.io/openclaw/openclaw-live-test:` 镜像。live 发布工作流会构建并推送该镜像一次,然后 Docker live 模型、按提供商分片的 Gateway 网关、CLI 后端、ACP bind 和 Codex harness 分片都会以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 运行。Gateway 网关 Docker 分片在脚本层带有显式 `timeout` 上限,低于工作流作业超时,因此卡住的容器或清理路径会快速失败,而不是耗尽整个 release-check 预算。如果这些分片独立重建完整源 Docker 目标,则说明发布运行配置错误,并会在重复镜像构建上浪费实际耗时。 -## 软件包验收 +## 包验收 -当问题是“这个可安装的 OpenClaw 软件包是否作为产品正常工作?”时,使用 `Package Acceptance`。它不同于常规 CI:常规 CI 验证源码树,而软件包验收会通过用户安装或更新后使用的同一 Docker E2E harness 验证单个 tarball。 +当问题是“这个可安装的 OpenClaw 包作为产品是否可用?”时,使用 `Package Acceptance`。它不同于普通 CI:普通 CI 验证源代码树,而包验收会通过用户在安装或更新后实际使用的同一个 Docker E2E harness 验证单个 tarball。 ### 作业 -1. `resolve_package` 会检出 `workflow_ref`,解析一个候选软件包,写入 `.artifacts/docker-e2e-package/openclaw-current.tgz`,写入 `.artifacts/docker-e2e-package/package-candidate.json`,将两者作为 `package-under-test` 构件上传,并在 GitHub 步骤摘要中打印来源、工作流 ref、软件包 ref、版本、SHA-256 和配置文件。 -2. `docker_acceptance` 会以 `ref=workflow_ref` 和 `package_artifact_name=package-under-test` 调用 `openclaw-live-and-e2e-checks-reusable.yml`。可复用工作流会下载该构件,验证 tarball 清单,在需要时准备软件包摘要 Docker 镜像,并针对该软件包运行选定的 Docker 运行道,而不是打包工作流检出内容。当某个配置文件选择多个目标 `docker_lanes` 时,可复用工作流会先准备一次软件包和共享镜像,然后将这些运行道扇出为并行的目标 Docker 作业,并使用唯一构件。 -3. `package_telegram` 可选调用 `NPM Telegram Beta E2E`。当 `telegram_mode` 不是 `none` 时运行;如果软件包验收已解析出一个软件包,它会安装同一个 `package-under-test` 构件;独立 Telegram 调度仍可安装已发布的 npm 规格。 -4. 如果软件包解析、Docker 验收或可选 Telegram 运行道失败,`summary` 会让工作流失败。 +1. `resolve_package` 检出 `workflow_ref`,解析一个包候选项,写入 `.artifacts/docker-e2e-package/openclaw-current.tgz`,写入 `.artifacts/docker-e2e-package/package-candidate.json`,将两者作为 `package-under-test` 构件上传,并在 GitHub 步骤摘要中打印来源、工作流引用、包引用、版本、SHA-256 和配置文件。 +2. `docker_acceptance` 使用 `ref=workflow_ref` 和 `package_artifact_name=package-under-test` 调用 `openclaw-live-and-e2e-checks-reusable.yml`。可复用工作流会下载该构件,验证 tarball 清单,在需要时准备 package-digest Docker 镜像,并针对该包运行选定的 Docker 通道,而不是打包工作流检出内容。当某个配置文件选择多个目标 `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` 分支、标签或完整提交 SHA。解析器会获取 OpenClaw 分支/标签,验证选定提交可从仓库分支历史或发布标签到达,在分离 worktree 中安装依赖,并使用 `scripts/package-openclaw-for-docker.mjs` 打包。 -- `source=url` 会下载一个 HTTPS `.tgz`;`package_sha256` 是必填项。 -- `source=artifact` 会从 `artifact_run_id` 和 `artifact_name` 下载一个 `.tgz`;`package_sha256` 可选,但应为外部共享构件提供它。 +- `source=npm` 只接受 `openclaw@beta`、`openclaw@latest`,或精确的 OpenClaw 发布版本,例如 `openclaw@2026.4.27-beta.2`。用它进行已发布 beta/稳定版验收。 +- `source=ref` 会打包受信任的 `package_ref` 分支、标签或完整提交 SHA。解析器会获取 OpenClaw 分支/标签,验证选定提交可从仓库分支历史或发布标签到达,在分离工作树中安装依赖,并用 `scripts/package-openclaw-for-docker.mjs` 打包。 +- `source=url` 下载 HTTPS `.tgz`;`package_sha256` 为必填。 +- `source=artifact` 从 `artifact_run_id` 和 `artifact_name` 下载一个 `.tgz`;`package_sha256` 可选,但对于外部共享的构件应提供。 -保持 `workflow_ref` 和 `package_ref` 分离。`workflow_ref` 是运行测试的受信任工作流/harness 代码。`package_ref` 是在 `source=ref` 时被打包的源码提交。这使当前测试 harness 可以验证较旧的受信任源码提交,而无需运行旧的工作流逻辑。 +保持 `workflow_ref` 和 `package_ref` 分离。`workflow_ref` 是运行测试的受信任工作流/harness 代码。`package_ref` 是 `source=ref` 时会被打包的源提交。这样当前测试 harness 就能验证较旧的受信任源提交,而无需运行旧的工作流逻辑。 ### 套件配置文件 - `smoke` — `npm-onboard-channel-agent`、`gateway-network`、`config-reload` - `package` — `npm-onboard-channel-agent`、`doctor-switch`、`update-channel-switch`、`upgrade-survivor`、`published-upgrade-survivor`、`plugins-offline`、`plugin-update` - `product` — `package` 加上 `mcp-channels`、`cron-mcp-cleanup`、`openai-web-search-minimal`、`openwebui` -- `full` — 带有 OpenWebUI 的完整 Docker 发布路径分块 +- `full` — 带 OpenWebUI 的完整 Docker 发布路径块 - `custom` — 精确的 `docker_lanes`;当 `suite_profile=custom` 时必填 -`package` 配置文件使用离线插件覆盖,因此已发布软件包验证不会受实时 ClawHub 可用性限制。可选 Telegram 运行道会在 `NPM Telegram Beta E2E` 中复用 `package-under-test` 构件,并为独立调度保留已发布 npm 规格路径。 +`package` 配置文件使用离线插件覆盖,因此已发布包验证不会受 live ClawHub 可用性限制。可选 Telegram 通道会在 `NPM Telegram Beta E2E` 中复用 `package-under-test` 构件,同时为独立调度保留已发布 npm 规范路径。 -有关专用更新和插件测试策略,包括本地命令、Docker 运行道、软件包验收输入、发布默认值和故障分诊,请参阅[更新和插件测试](/zh-CN/help/testing-updates-plugins)。 +有关专门的更新和插件测试策略,包括本地命令、Docker 通道、Package Acceptance 输入、发布默认值和失败分诊,请参阅 [更新和插件测试](/zh-CN/help/testing-updates-plugins)。 -发布检查会调用软件包验收,并使用 `source=artifact`、已准备的发布软件包构件、`suite_profile=custom`、`docker_lanes='doctor-switch update-channel-switch upgrade-survivor published-upgrade-survivor plugins-offline plugin-update'`、`published_upgrade_survivor_baselines=release-history`、`published_upgrade_survivor_scenarios=reported-issues` 和 `telegram_mode=mock-openai`。这会让软件包迁移、更新、陈旧插件依赖清理、离线插件、插件更新和 Telegram 证明都基于同一个已解析的软件包 tarball。跨 OS 发布检查仍覆盖 OS 特定的新手引导、安装器和平台行为;软件包/更新产品验证应从软件包验收开始。`published-upgrade-survivor` Docker 运行道每次运行验证一个已发布软件包基线。在软件包验收中,解析出的 `package-under-test` tarball 始终是候选项,而 `published_upgrade_survivor_baseline` 选择回退的已发布基线,默认为 `openclaw@latest`;失败运行道的重跑命令会保留该基线。设置 `published_upgrade_survivor_baselines=release-history` 可将运行道扩展到去重后的历史矩阵:最新六个稳定版本、`2026.4.23`,以及 `2026-03-15` 之前的最新稳定版本。设置 `published_upgrade_survivor_scenarios=reported-issues` 可将同一组基线扩展到按问题形态构造的 fixture,覆盖 Feishu 配置、保留的 bootstrap/persona 文件、波浪号日志路径,以及陈旧旧版插件依赖根。单独的 `Update Migration` 工作流使用 `update-migration` Docker 运行道,并带有 `all-since-2026.4.23` 和 `plugin-deps-cleanup`,用于问题是穷尽式已发布更新清理,而不是常规完整发布 CI 覆盖范围。本地聚合运行可以通过 `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS` 传入精确的软件包规格,也可以通过 `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC` 保持单个运行道,例如 `openclaw@2026.4.15`,或设置 `OPENCLAW_UPGRADE_SURVIVOR_SCENARIOS` 来使用场景矩阵。已发布运行道会通过内置的 `openclaw config set` 命令配方配置基线,在 `summary.json` 中记录配方步骤,并在 Gateway 网关启动后探测 `/healthz`、`/readyz` 以及 RPC 状态。Windows 打包和安装器全新安装运行道还会验证已安装的软件包可以从原始绝对 Windows 路径导入 browser-control 覆盖。OpenAI 跨 OS agent-turn 冒烟测试在设置时默认使用 `OPENCLAW_CROSS_OS_OPENAI_MODEL`,否则使用 `openai/gpt-5.4`,因此安装和 Gateway 网关证明会保留在 GPT-5 测试模型上,同时避免 GPT-4.x 默认值。 +发布检查会使用 `source=artifact`、已准备好的发布包构件、`suite_profile=custom`、`docker_lanes='doctor-switch update-channel-switch upgrade-survivor published-upgrade-survivor plugins-offline plugin-update'`、`published_upgrade_survivor_baselines=release-history`、`published_upgrade_survivor_scenarios=reported-issues` 和 `telegram_mode=mock-openai` 调用 Package Acceptance。这样可以让包迁移、更新、过时插件依赖清理、离线插件、plugin-update 和 Telegram 证明都基于同一个已解析包 tarball。跨 OS 发布检查仍覆盖 OS 特定的新手引导、安装器和平台行为;包/更新产品验证应从 Package Acceptance 开始。`published-upgrade-survivor` Docker 通道每次运行验证一个已发布包基线。在 Package Acceptance 中,解析出的 `package-under-test` tarball 始终是候选项,`published_upgrade_survivor_baseline` 选择回退的已发布基线,默认值为 `openclaw@latest`;失败通道的重新运行命令会保留该基线。设置 `published_upgrade_survivor_baselines=release-history` 可将该通道扩展到去重后的历史矩阵:最新六个稳定版本、`2026.4.23`,以及 `2026-03-15` 之前的最新稳定版本。设置 `published_upgrade_survivor_scenarios=reported-issues` 可将相同基线扩展到按 issue 形态构造的 fixture,覆盖 Feishu 配置、保留的 bootstrap/persona 文件、波浪号日志路径和陈旧旧版插件依赖根。单独的 `Update Migration` 工作流在问题是穷尽式已发布更新清理,而不是普通 Full Release CI 广度时,会使用 `update-migration` Docker 通道及 `all-since-2026.4.23` 和 `plugin-deps-cleanup`。本地聚合运行可以用 `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS` 传入精确包规范,用 `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC` 保持单个通道,例如 `openclaw@2026.4.15`,或设置 `OPENCLAW_UPGRADE_SURVIVOR_SCENARIOS` 来使用场景矩阵。已发布通道会使用内置的 `openclaw config set` 命令配方配置基线,在 `summary.json` 中记录配方步骤,并在 Gateway 网关启动后探测 `/healthz`、`/readyz` 以及 RPC 状态。Windows 打包版和安装器全新安装通道还会验证已安装包能否从原始绝对 Windows 路径导入浏览器控制覆盖。OpenAI 跨 OS agent-turn smoke 在设置时默认使用 `OPENCLAW_CROSS_OS_OPENAI_MODEL`,否则使用 `openai/gpt-5.4`,因此安装和 Gateway 网关证明会停留在 GPT-5 测试模型上,同时避免 GPT-4.x 默认值。 ### 旧版兼容窗口 -软件包验收为已发布软件包提供有界旧版兼容窗口。直到 `2026.4.25` 的软件包(包括 `2026.4.25-beta.*`)可以使用兼容路径: +Package Acceptance 为已发布包提供有界的旧版兼容窗口。直到 `2026.4.25` 的包(包括 `2026.4.25-beta.*`)可以使用兼容路径: -- `dist/postinstall-inventory.json` 中已知的私有 QA 条目可以指向 tarball 中省略的文件; -- 当软件包未暴露 `gateway install --wrapper` 标志时,`doctor-switch` 可以跳过其持久化子用例; -- `update-channel-switch` 可以从 tarball 派生的假 git fixture 中剪除缺失的 `pnpm.patchedDependencies`,并可记录缺失的持久化 `update.channel`; -- 插件冒烟测试可以读取旧版安装记录位置,或接受缺失的 marketplace 安装记录持久化; -- `plugin-update` 可以允许配置元数据迁移,同时仍要求安装记录和无重装行为保持不变。 +- `dist/postinstall-inventory.json` 中已知的私有 QA 条目可以指向 tarball 省略的文件; +- 当包未暴露 `gateway install --wrapper` 标志时,`doctor-switch` 可以跳过持久化子用例; +- `update-channel-switch` 可以从 tarball 派生的伪 git fixture 中剪除缺失的 `pnpm.patchedDependencies`,并可以记录缺失的持久化 `update.channel`; +- 插件 smoke 可以读取旧版安装记录位置,或接受缺少 marketplace 安装记录持久化; +- `plugin-update` 可以允许配置元数据迁移,同时仍要求安装记录和不重新安装行为保持不变。 -已发布的 `2026.4.26` 软件包也可以对已经发布的本地构建元数据戳文件发出警告。更晚的软件包必须满足现代契约;相同条件会失败,而不是警告或跳过。 +已发布的 `2026.4.26` 包也可以对已经发布的本地构建元数据戳文件发出警告。更晚的包必须满足现代合约;相同条件会失败,而不是警告或跳过。 ### 示例 @@ -280,111 +299,111 @@ gh workflow run package-acceptance.yml \ -f docker_lanes='install-e2e plugin-update' ``` -调试失败的软件包验收运行时,先查看 `resolve_package` 摘要,确认软件包来源、版本和 SHA-256。然后检查 `docker_acceptance` 子运行及其 Docker 构件:`.artifacts/docker-tests/**/summary.json`、`failures.json`、运行道日志、阶段计时和重跑命令。优先重跑失败的软件包配置文件或精确 Docker 运行道,而不是重跑完整发布验证。 +调试失败的包验收运行时,先从 `resolve_package` 摘要开始,确认包来源、版本和 SHA-256。然后检查 `docker_acceptance` 子运行及其 Docker 工件:`.artifacts/docker-tests/**/summary.json`、`failures.json`、lane 日志、阶段耗时和重新运行命令。优先重新运行失败的包 profile 或精确的 Docker lane,而不是重新运行完整发布验证。 ## 安装冒烟测试 -单独的 `Install Smoke` 工作流通过自己的 `preflight` 作业复用同一个作用域脚本。它将冒烟覆盖拆分为 `run_fast_install_smoke` 和 `run_full_install_smoke`。 +独立的 `Install Smoke` 工作流通过自己的 `preflight` 作业复用同一个范围脚本。它将冒烟覆盖拆分为 `run_fast_install_smoke` 和 `run_full_install_smoke`。 -- **快速路径**会在拉取请求触及 Docker/软件包表面、内置插件软件包/manifest 变更,或 Docker 冒烟作业会覆盖的核心插件/渠道/Gateway 网关/插件 SDK 表面时运行。仅源码的内置插件变更、仅测试编辑和仅文档编辑不会预留 Docker worker。快速路径会构建一次根 Dockerfile 镜像,检查 CLI,运行 agents delete shared-workspace CLI 冒烟测试,运行容器 gateway-network e2e,验证一个内置扩展构建参数,并在 240 秒聚合命令超时内运行有界内置插件 Docker 配置文件(每个场景的 Docker 运行单独设定上限)。 -- **完整路径**保留 QR 软件包安装和安装器 Docker/更新覆盖,用于夜间定时运行、手动调度、workflow-call 发布检查,以及真正触及安装器/软件包/Docker 表面的拉取请求。在完整模式下,install-smoke 会准备或复用一个目标 SHA 的 GHCR 根 Dockerfile 冒烟镜像,然后将 QR 软件包安装、根 Dockerfile/Gateway 网关冒烟测试、安装器/更新冒烟测试,以及快速内置插件 Docker E2E 作为独立作业运行,因此安装器工作无需等待根镜像冒烟测试完成。 +- **快速路径**会在 pull request 触及 Docker/包表面、内置插件包/清单变更,或 Docker 冒烟作业覆盖的核心插件/渠道/Gateway 网关/插件 SDK 表面时运行。仅源码的内置插件变更、仅测试编辑和仅文档编辑不会预留 Docker worker。快速路径会构建一次根 Dockerfile 镜像,检查 CLI,运行 agents delete shared-workspace CLI 冒烟测试,运行容器 gateway-network e2e,验证一个内置扩展构建参数,并在 240 秒的聚合命令超时内运行有界的内置插件 Docker profile(每个场景的 Docker 运行单独设置上限)。 +- **完整路径**为夜间计划运行、手动分发、workflow-call 发布检查,以及真正触及安装器/包/Docker 表面的 pull request 保留 QR 包安装和安装器 Docker/更新覆盖。在完整模式下,install-smoke 会准备或复用一个目标 SHA 的 GHCR 根 Dockerfile 冒烟镜像,然后将 QR 包安装、根 Dockerfile/Gateway 网关冒烟测试、安装器/更新冒烟测试,以及快速内置插件 Docker E2E 作为独立作业运行,这样安装器工作就不会排在根镜像冒烟测试后面等待。 -`main` 推送(包括合并提交)不会强制完整路径;当变更作用域逻辑会在推送上请求完整覆盖时,工作流会保留快速 Docker 冒烟测试,并将完整安装冒烟测试留给夜间或发布验证。 +`main` 推送(包括 merge commit)不会强制使用完整路径;当变更范围逻辑会在推送上请求完整覆盖时,工作流会保留快速 Docker 冒烟测试,并将完整安装冒烟测试留给夜间运行或发布验证。 -较慢的 Bun 全局安装 image-provider 冒烟测试由 `run_bun_global_install_smoke` 单独控制。它会在夜间计划和发布检查工作流中运行,手动 `Install Smoke` 调度也可以选择启用它,但拉取请求和 `main` 推送不会运行它。QR 和安装器 Docker 测试保留各自以安装为重点的 Dockerfile。 +较慢的 Bun 全局安装 image-provider 冒烟测试由 `run_bun_global_install_smoke` 单独门控。它会在夜间计划和发布检查工作流中运行,手动 `Install Smoke` 分发也可以选择加入它,但 pull request 和 `main` 推送不会运行它。QR 和安装器 Docker 测试保留各自专注安装的 Dockerfile。 ## 本地 Docker E2E -`pnpm test:docker:all` 会预构建一个共享 live-test 镜像,将 OpenClaw 打包一次为 npm tarball,并构建两个共享 `scripts/e2e/Dockerfile` 镜像: +`pnpm test:docker:all` 会预构建一个共享的 live-test 镜像,将 OpenClaw 打包一次为 npm tarball,并构建两个共享的 `scripts/e2e/Dockerfile` 镜像: -- 一个用于安装器/更新/插件依赖运行道的裸 Node/Git runner; -- 一个将同一个 tarball 安装到 `/app` 的功能镜像,用于常规功能运行道。 +- 一个用于安装器/更新/插件依赖 lane 的裸 Node/Git runner; +- 一个功能镜像,将同一个 tarball 安装到 `/app`,用于普通功能 lane。 -Docker lane 定义位于 `scripts/lib/docker-e2e-scenarios.mjs`,规划器逻辑位于 `scripts/lib/docker-e2e-plan.mjs`,运行器只执行选中的计划。调度器使用 `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`,规划器逻辑位于 `scripts/lib/docker-e2e-plan.mjs`,runner 只执行选中的计划。调度器通过 `OPENCLAW_DOCKER_E2E_BARE_IMAGE` 和 `OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE` 为每个 lane 选择镜像,然后使用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 运行 lane。 -### 可调项 +### 可调参数 -| 变量 | 默认值 | 目的 | +| 变量 | 默认值 | 用途 | | -------------------------------------- | ------- | --------------------------------------------------------------------------------------------- | -| `OPENCLAW_DOCKER_ALL_PARALLELISM` | 10 | 普通 lane 的主池槽位数。 | -| `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM` | 10 | 对提供商敏感的尾池槽位数。 | -| `OPENCLAW_DOCKER_ALL_LIVE_LIMIT` | 9 | 并发 live lane 上限,避免提供商限流。 | +| `OPENCLAW_DOCKER_ALL_PARALLELISM` | 10 | 普通 lane 的主池 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 守护进程创建风暴;设置为 `0` 表示不做错峰。 | -| `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS` | 7200000 | 每个 lane 的兜底超时(120 分钟);选定的 live/tail lane 使用更严格的上限。 | -| `OPENCLAW_DOCKER_ALL_DRY_RUN` | 未设置 | `1` 会打印调度器计划,而不运行 lane。 | -| `OPENCLAW_DOCKER_ALL_LANES` | 未设置 | 逗号分隔的精确 lane 列表;跳过清理烟测,以便智能体复现某个失败的 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 列表;跳过清理冒烟测试,以便智能体复现单个失败 lane。 | -比有效上限更重的 lane 仍然可以从空池启动,然后独占运行,直到释放容量。本地聚合会预检 Docker、移除陈旧的 OpenClaw E2E 容器、输出活跃 lane 状态、持久化 lane 耗时以支持最长优先排序,并且默认在第一次失败后停止调度新的池化 lane。 +比有效上限更重的 lane 仍可从空池启动,然后独占运行,直到释放容量。本地聚合会预检 Docker,移除陈旧的 OpenClaw E2E 容器,发出活跃 lane 状态,持久化 lane 耗时以支持最长优先排序,并默认在第一次失败后停止调度新的池化 lane。 ### 可复用 live/E2E 工作流 -可复用 live/E2E 工作流会询问 `scripts/test-docker-all.mjs --plan-json` 需要哪个包、镜像类型、live 镜像、lane 和凭据覆盖范围。随后 `scripts/docker-e2e.mjs` 会把该计划转换为 GitHub 输出和摘要。它会通过 `scripts/package-openclaw-for-docker.mjs` 打包 OpenClaw,下载当前运行的包产物,或从 `package_artifact_run_id` 下载包产物;验证 tarball 清单;当计划需要包安装式 lane 时,通过 Blacksmith 的 Docker layer cache 构建并推送带有包摘要标签的 bare/functional GHCR Docker E2E 镜像;并复用提供的 `docker_e2e_bare_image`/`docker_e2e_functional_image` 输入或现有的包摘要镜像,而不是重新构建。Docker 镜像拉取会使用有界的每次尝试 180 秒超时进行重试,使卡住的 registry/cache 流能够快速重试,而不是占用 CI 关键路径的大部分时间。 +可复用 live/E2E 工作流会询问 `scripts/test-docker-all.mjs --plan-json` 需要哪些包、镜像类型、live 镜像、lane 和凭据覆盖。随后 `scripts/docker-e2e.mjs` 会将该计划转换为 GitHub 输出和摘要。它会通过 `scripts/package-openclaw-for-docker.mjs` 打包 OpenClaw,下载当前运行的包工件,或从 `package_artifact_run_id` 下载包工件;验证 tarball 清单;当计划需要已安装包的 lane 时,通过 Blacksmith 的 Docker layer cache 构建并推送带有包摘要标签的裸/功能 GHCR Docker E2E 镜像;并复用提供的 `docker_e2e_bare_image`/`docker_e2e_functional_image` 输入或已有的包摘要镜像,而不是重新构建。Docker 镜像拉取会以每次尝试 180 秒的有界超时重试,因此卡住的 registry/cache 流会快速重试,而不是消耗大部分 CI 关键路径时间。 ### 发布路径分块 -发布 Docker 覆盖会用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 运行较小的分块作业,这样每个分块只拉取自己需要的镜像类型,并通过同一个加权调度器执行多个 lane: +发布 Docker 覆盖会使用带有 `OPENCLAW_SKIP_DOCKER_BUILD=1` 的更小分块作业,这样每个分块只拉取它需要的镜像类型,并通过同一个加权调度器执行多个 lane: - `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` -当前发布 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`。`plugins-runtime-core`、`plugins-runtime` 和 `plugins-integrations` 仍然是聚合插件/运行时别名。`install-e2e` lane 别名仍然是两个提供商安装器 lane 的聚合手动重跑别名。 +当前发布 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`。`plugins-runtime-core`、`plugins-runtime` 和 `plugins-integrations` 仍是聚合插件/运行时别名。`install-e2e` lane 别名仍是两个 provider 安装器 lane 的聚合手动重新运行别名。 -当完整 release-path 覆盖请求 OpenWebUI 时,OpenWebUI 会折叠到 `plugins-runtime-services` 中,并且仅为只调度 OpenWebUI 的情况保留独立的 `openwebui` 分块。内置渠道更新 lane 会针对临时 npm 网络失败重试一次。 +当完整 release-path 覆盖请求 OpenWebUI 时,它会并入 `plugins-runtime-services`,并且只为仅 OpenWebUI 的分发保留独立的 `openwebui` 分块。内置渠道更新 lane 会针对临时 npm 网络失败重试一次。 -每个分块都会上传 `.artifacts/docker-tests/`,其中包含 lane 日志、耗时、`summary.json`、`failures.json`、阶段耗时、调度器计划 JSON、慢 lane 表以及每个 lane 的重跑命令。工作流 `docker_lanes` 输入会针对已准备的镜像运行选中的 lane,而不是运行分块作业,这会把失败 lane 调试限制在一个定向 Docker 作业内,并为该次运行准备、下载或复用包产物;如果选中的 lane 是 live Docker lane,则定向作业会在本地为该次重跑构建 live-test 镜像。生成的每个 lane GitHub 重跑命令会在这些值存在时包含 `package_artifact_run_id`、`package_artifact_name` 和已准备的镜像输入,因此失败的 lane 可以复用失败运行中的精确包和镜像。 +每个分块都会上传 `.artifacts/docker-tests/`,其中包含 lane 日志、耗时、`summary.json`、`failures.json`、阶段耗时、调度器计划 JSON、慢 lane 表和每个 lane 的重新运行命令。工作流 `docker_lanes` 输入会用已准备的镜像运行选定 lane,而不是运行分块作业,这会将失败 lane 调试限定在一个有目标的 Docker 作业中,并为该运行准备、下载或复用包工件;如果选中的 lane 是 live Docker lane,则目标作业会为该重新运行在本地构建 live-test 镜像。生成的每 lane GitHub 重新运行命令会在这些值存在时包含 `package_artifact_run_id`、`package_artifact_name` 和已准备镜像输入,因此失败的 lane 可以复用失败运行中的精确包和镜像。 ```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 ``` -定时 live/E2E 工作流每天运行完整的 release-path Docker 套件。 +计划 live/E2E 工作流每天运行完整 release-path Docker 套件。 ## 插件预发布 -`Plugin Prerelease` 是成本更高的产品/包覆盖,因此它是一个独立工作流,由 `Full Release Validation` 或显式操作员调度。普通拉取请求、`main` 推送和独立手动 CI 调度不会启用该套件。它会在八个扩展 worker 之间均衡内置插件测试;这些扩展分片作业一次最多运行两个插件配置组,每组使用一个 Vitest worker 和更大的 Node 堆,因此导入繁重的插件批次不会创建额外的 CI 作业。仅发布使用的 Docker 预发布路径会把定向 Docker lane 按小组批处理,避免为一到三分钟的作业预留数十个 runner。 +`Plugin Prerelease` 是成本更高的产品/包覆盖,因此它是一个由 `Full Release Validation` 或显式 operator 分发的独立工作流。普通 pull request、`main` 推送和独立的手动 CI 分发都会关闭该套件。它将内置插件测试均衡分配到八个扩展 worker;这些扩展分片作业一次最多运行两个插件配置组,每组一个 Vitest worker,并使用更大的 Node heap,这样 import 密集的插件批次不会创建额外 CI 作业。仅发布的 Docker 预发布路径会以小组批量运行有目标的 Docker lane,避免为一到三分钟的作业预留几十个 runner。 ## QA Lab -QA Lab 在主智能作用域工作流之外有专用 CI lane。 +QA Lab 在主智能范围工作流之外有专用 CI lane。 -- `Parity gate` 工作流会在匹配的 PR 变更和手动调度时运行;它会构建私有 QA 运行时,并比较模拟 GPT-5.5 和 Opus 4.6 的 agentic 包。 -- `QA-Lab - All Lanes` 工作流每晚在 `main` 上运行,也可手动调度;它会把模拟 parity gate、live Matrix lane,以及 live Telegram 和 Discord lane 扇出为并行作业。Live 作业使用 `qa-live-shared` 环境,Telegram/Discord 使用 Convex 租约。 +- `Parity gate` 工作流在匹配的 PR 变更和手动分发时运行;它会构建私有 QA 运行时,并比较 mock GPT-5.5 和 Opus 4.6 agentic 包。 +- `QA-Lab - All Lanes` 工作流每晚在 `main` 上运行,也可手动分发;它会将 mock parity gate、live Matrix lane,以及 live Telegram 和 Discord lane 作为并行作业展开。Live 作业使用 `qa-live-shared` 环境,Telegram/Discord 使用 Convex 租约。 -发布检查会使用确定性模拟提供商和模拟限定模型(`mock-openai/gpt-5.5` 与 `mock-openai/gpt-5.5-alt`)运行 Matrix 和 Telegram live 传输 lane,因此渠道契约会与 live 模型延迟和普通提供商插件启动隔离。Live 传输 Gateway 网关会禁用记忆搜索,因为 QA parity 会单独覆盖记忆行为;提供商连通性由单独的 live 模型、原生提供商和 Docker 提供商套件覆盖。 +发布检查会使用确定性的 mock provider 和 mock-qualified 模型(`mock-openai/gpt-5.5` 和 `mock-openai/gpt-5.5-alt`)运行 Matrix 和 Telegram live 传输 lane,因此渠道契约与 live 模型延迟和普通 provider-plugin 启动隔离。live 传输 Gateway 网关会禁用记忆搜索,因为 QA parity 会单独覆盖记忆行为;provider 连接性由独立的 live 模型、原生 provider 和 Docker provider 套件覆盖。 -Matrix 在定时和发布门禁中使用 `--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 lane;它的 QA parity gate 会把候选包和基线包作为并行 lane 作业运行,然后把两个产物下载到一个小型报告作业中进行最终 parity 比较。 +`OpenClaw Release Checks` 还会在发布审批前运行发布关键的 QA Lab lane;其 QA parity gate 将候选包和基线包作为并行 lane 作业运行,然后将两个工件下载到一个小型报告作业中,用于最终 parity 比较。 -除非变更确实触及 QA 运行时、模型包 parity 或 parity 工作流拥有的表面,否则不要把 PR 落地路径置于 `Parity gate` 之后。对于普通渠道、配置、文档或单元测试修复,将其视为可选信号,并遵循作用域内 CI/检查证据。 +不要将 PR 落地路径置于 `Parity gate` 之后,除非变更确实触及 QA 运行时、模型包 parity,或 parity 工作流拥有的表面。对于普通渠道、配置、文档或单元测试修复,将其视为可选信号,并遵循范围化的 CI/检查证据。 ## CodeQL -`CodeQL` 工作流有意作为窄范围的第一遍安全扫描器,而不是完整仓库扫描。每日、手动和非草稿拉取请求防护运行会扫描 Actions 工作流代码以及风险最高的 JavaScript/TypeScript 表面,并使用高置信度安全查询,筛选高/关键 `security-severity`。 +`CodeQL` 工作流有意作为窄范围的第一轮安全扫描器,而不是完整仓库扫描。每日、手动和非草稿 pull request 防护运行会扫描 Actions 工作流代码以及最高风险的 JavaScript/TypeScript 表面,并使用高置信度安全查询,过滤到高/严重 `security-severity`。 -拉取请求防护保持轻量:它只会针对 `.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` | 核心渠道实现契约,加上渠道插件运行时、gateway、插件 SDK、密钥、审计接触点 | -| `/codeql-security-high/network-ssrf-boundary` | 核心 SSRF、IP 解析、网络保护、web-fetch 和插件 SDK SSRF 策略表面 | -| `/codeql-security-high/mcp-process-tool-boundary` | MCP 服务器、进程执行助手、出站投递和智能体工具执行门禁 | -| `/codeql-security-high/plugin-trust-boundary` | 插件安装、加载器、manifest、registry、package-manager install、source-loading 和插件 SDK 包契约信任表面 | +| `/codeql-security-high/core-auth-secrets` | 认证、密钥、沙箱、cron 和 Gateway 网关基线 | +| `/codeql-security-high/channel-runtime-boundary` | 核心渠道实现契约,以及渠道插件运行时、Gateway 网关、插件 SDK、密钥、审计触点 | +| `/codeql-security-high/network-ssrf-boundary` | 核心 SSRF、IP 解析、网络防护、web-fetch 和插件 SDK SSRF 策略表面 | +| `/codeql-security-high/mcp-process-tool-boundary` | MCP 服务器、进程执行辅助工具、出站投递,以及智能体工具执行关卡 | +| `/codeql-security-high/plugin-trust-boundary` | 插件安装、加载器、清单、注册表、包管理器安装、源码加载,以及插件 SDK 包契约信任表面 | ### 平台特定安全分片 -- `CodeQL Android Critical Security` — 定时 Android 安全分片。在 workflow sanity 接受的最小 Blacksmith Linux runner 上为 CodeQL 手动构建 Android 应用。上传到 `/codeql-critical-security/android` 下。 -- `CodeQL macOS Critical Security` — 每周/手动 macOS 安全分片。在 Blacksmith macOS 上为 CodeQL 手动构建 macOS 应用,从上传的 SARIF 中过滤依赖构建结果,并上传到 `/codeql-critical-security/macos` 下。由于即使干净运行,macOS 构建也主导运行时间,因此它被保留在每日默认项之外。 +- `CodeQL Android Critical Security` — 定时 Android 安全分片。在工作流健全性检查接受的最小 Blacksmith Linux runner 上为 CodeQL 手动构建 Android 应用。上传到 `/codeql-critical-security/android`。 +- `CodeQL macOS Critical Security` — 每周/手动 macOS 安全分片。在 Blacksmith macOS 上为 CodeQL 手动构建 macOS 应用,从上传的 SARIF 中过滤掉依赖构建结果,并上传到 `/codeql-critical-security/macos`。它被排除在每日默认项之外,因为即使结果干净,macOS 构建也会主导运行时间。 ### 关键质量类别 -`CodeQL Critical Quality` 是对应的非安全分片。它只在较小的 Blacksmith Linux runner 上,对窄范围高价值表面运行 error-severity、非安全 JavaScript/TypeScript 质量查询。它的拉取请求防护有意小于定时配置文件:非草稿 PR 只会为智能体命令/模型/工具执行和回复分发代码、配置 schema/迁移/IO 代码、认证/密钥/沙箱/安全代码、核心渠道和内置渠道插件运行时、gateway 协议/服务器方法、记忆运行时/SDK 胶水、MCP/进程/出站投递、提供商运行时/模型目录、会话诊断/投递队列、插件加载器、插件 SDK/包契约,或插件 SDK 回复运行时变更,运行匹配的 `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 质量查询。它的拉取请求守卫有意小于定时配置:非草稿 PR 只会为智能体命令/模型/工具执行和回复分发代码、配置 schema/迁移/IO 代码、认证/密钥/沙箱/安全代码、核心渠道和内置渠道插件运行时、Gateway 网关协议/服务器方法、记忆运行时/SDK 胶水代码、MCP/进程/出站投递、提供商运行时/模型目录、会话诊断/投递队列、插件加载器、插件 SDK/包契约,或插件 SDK 回复运行时变更,运行对应的 `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 质量分片。 手动调度接受: @@ -392,40 +411,40 @@ Matrix 在定时和发布门禁中使用 `--profile fast`,仅当检出的 CLI 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 ``` -窄配置文件是教学/迭代钩子,用于单独运行一个质量分片。 +窄配置是用于单独运行一个质量分片的教学/迭代钩子。 -| 类别 | 范围 | +| 类别 | 表面 | | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `/codeql-critical-quality/core-auth-secrets` | 认证、密钥、沙箱、cron 和 Gateway 网关安全边界代码 | | `/codeql-critical-quality/config-boundary` | 配置 schema、迁移、规范化和 IO 契约 | | `/codeql-critical-quality/gateway-runtime-boundary` | Gateway 网关协议 schema 和服务器方法契约 | | `/codeql-critical-quality/channel-runtime-boundary` | 核心渠道和内置渠道插件实现契约 | | `/codeql-critical-quality/agent-runtime-boundary` | 命令执行、模型/提供商分发、自动回复分发和队列,以及 ACP 控制平面运行时契约 | -| `/codeql-critical-quality/mcp-process-runtime-boundary` | MCP 服务器和工具桥接、进程监督 helper,以及出站投递契约 | -| `/codeql-critical-quality/memory-runtime-boundary` | 记忆宿主 SDK、记忆运行时 facade、记忆插件 SDK 别名、记忆运行时激活胶水代码,以及记忆 Doctor 命令 | -| `/codeql-critical-quality/session-diagnostics-boundary` | 回复队列内部机制、会话投递队列、出站会话绑定/投递 helper、诊断事件/日志包表面,以及会话 Doctor CLI 契约 | -| `/codeql-critical-quality/plugin-sdk-reply-runtime` | 插件 SDK 入站回复分发、回复 payload/分块/运行时 helper、渠道回复选项、投递队列,以及会话/线程绑定 helper | +| `/codeql-critical-quality/mcp-process-runtime-boundary` | MCP 服务器和工具桥、进程监督辅助工具,以及出站投递契约 | +| `/codeql-critical-quality/memory-runtime-boundary` | 记忆主机 SDK、记忆运行时门面、记忆插件 SDK 别名、记忆运行时激活胶水代码,以及记忆 Doctor 命令 | +| `/codeql-critical-quality/session-diagnostics-boundary` | 回复队列内部机制、会话投递队列、出站会话绑定/投递辅助工具、诊断事件/日志包表面,以及会话 Doctor CLI 契约 | +| `/codeql-critical-quality/plugin-sdk-reply-runtime` | 插件 SDK 入站回复分发、回复载荷/分块/运行时辅助工具、渠道回复选项、投递队列,以及会话/线程绑定辅助工具 | | `/codeql-critical-quality/provider-runtime-boundary` | 模型目录规范化、提供商认证和设备发现、提供商运行时注册、提供商默认值/目录,以及 Web/搜索/抓取/嵌入注册表 | -| `/codeql-critical-quality/ui-control-plane` | 控制 UI 启动、本地持久化、Gateway 网关控制流,以及任务控制平面运行时契约 | -| `/codeql-critical-quality/web-media-runtime-boundary` | 核心 Web 抓取/搜索、媒体 IO、媒体理解、图像生成和媒体生成运行时契约 | -| `/codeql-critical-quality/plugin-boundary` | 加载器、注册表、公共表面和插件 SDK 入口点契约 | -| `/codeql-critical-quality/plugin-sdk-package-contract` | 已发布包侧插件 SDK 源码和插件包契约 helper | +| `/codeql-critical-quality/ui-control-plane` | 控制 UI 引导、本地持久化、Gateway 网关控制流,以及任务控制平面运行时契约 | +| `/codeql-critical-quality/web-media-runtime-boundary` | 核心 Web 抓取/搜索、媒体 IO、媒体理解、图像生成,以及媒体生成运行时契约 | +| `/codeql-critical-quality/plugin-boundary` | 加载器、注册表、公开表面,以及插件 SDK 入口点契约 | +| `/codeql-critical-quality/plugin-sdk-package-contract` | 已发布包侧插件 SDK 源码和插件包契约辅助工具 | -质量与安全保持分离,这样质量发现可以被排期、衡量、禁用或扩展,而不会掩盖安全信号。Swift、Python 和内置插件 CodeQL 扩展只应在这些窄配置文件具有稳定运行时和信号之后,作为有范围或分片的后续工作加回。 +质量与安全保持分离,这样质量发现就可以被定时运行、衡量、禁用或扩展,而不会遮蔽安全信号。Swift、Python 和内置插件的 CodeQL 扩展,只有在窄配置具备稳定运行时间和信号之后,才应作为有范围或分片的后续工作重新加入。 ## 维护工作流 ### Docs Agent -`Docs Agent` 工作流是事件驱动的 Codex 维护通道,用于让现有文档与最近落地的变更保持一致。它没有纯定时计划:`main` 上一次成功的非 bot push CI 运行可以触发它,手动调度也可以直接运行它。当 `main` 已继续前进,或过去一小时内已经创建过另一个未跳过的 Docs Agent 运行时,workflow-run 调用会跳过。运行时,它会审阅从上一个未跳过的 Docs Agent 源 SHA 到当前 `main` 的提交范围,因此一次每小时运行可以覆盖自上次文档处理以来累积的所有 main 变更。 +`Docs Agent` 工作流是一个事件驱动的 Codex 维护通道,用于让现有文档与最近落地的变更保持一致。它没有纯定时计划:`main` 上一次成功的非机器人 push CI 运行可以触发它,也可以通过手动调度直接运行。工作流运行触发时,如果 `main` 已经推进,或过去一小时内已创建另一个未跳过的 Docs Agent 运行,则会跳过。运行时,它会审查从上一个未跳过的 Docs Agent 源 SHA 到当前 `main` 的提交范围,因此一次每小时运行可以覆盖自上次文档检查以来累积的所有 main 变更。 ### Test Performance Agent -`Test Performance Agent` 工作流是事件驱动的 Codex 维护通道,用于处理慢测试。它没有纯定时计划:`main` 上一次成功的非 bot push CI 运行可以触发它,但如果同一个 UTC 日已经有另一个 workflow-run 调用运行过或正在运行,它会跳过。手动调度会绕过这个每日活动门禁。该通道会构建一次全套分组 Vitest 性能报告,让 Codex 只做小范围、保持覆盖率的测试性能修复,而不是大范围重构,然后重新运行全套报告,并拒绝会降低通过基线测试数量的变更。如果基线有失败测试,Codex 只能修复明显失败,并且 agent 之后的全套报告必须通过,才会提交任何内容。当 `main` 在 bot push 落地前前进时,该通道会 rebase 已验证的补丁,重新运行 `pnpm check:changed`,并重试 push;有冲突的过期补丁会被跳过。它使用 GitHub 托管的 Ubuntu,因此 Codex action 可以保持与 docs agent 相同的 drop-sudo 安全姿态。 +`Test Performance Agent` 工作流是一个事件驱动的 Codex 维护通道,用于慢测试。它没有纯定时计划:`main` 上一次成功的非机器人 push CI 运行可以触发它,但如果另一个工作流运行触发当天(UTC)已经运行或正在运行,它会跳过。手动调度会绕过该每日活动关卡。该通道会构建完整套件分组的 Vitest 性能报告,让 Codex 只做小型、保留覆盖率的测试性能修复,而不是广泛重构,然后重新运行完整套件报告,并拒绝会降低通过基线测试数量的变更。如果基线存在失败测试,Codex 只能修复明显失败项,并且智能体之后的完整套件报告必须通过,之后才会提交任何内容。当 `main` 在机器人推送落地前推进时,该通道会 rebase 已验证的补丁,重新运行 `pnpm check:changed`,并重试推送;存在冲突的过期补丁会被跳过。它使用 GitHub 托管的 Ubuntu,因此 Codex action 可以保持与 docs 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 \ @@ -434,29 +453,29 @@ gh workflow run duplicate-after-merge.yml \ -f apply=true ``` -## 本地检查门禁和变更路由 +## 本地检查关卡和变更路由 -本地变更通道路由逻辑位于 `scripts/changed-lanes.mjs`,并由 `scripts/check-changed.mjs` 执行。该本地检查门禁在架构边界上比宽泛的 CI 平台范围更严格: +本地变更通道逻辑位于 `scripts/changed-lanes.mjs`,并由 `scripts/check-changed.mjs` 执行。该本地检查关卡对架构边界的要求比广泛的 CI 平台范围更严格: -- 核心生产变更会运行核心生产和核心测试 typecheck,以及核心 lint/guard; -- 仅核心测试变更只会运行核心测试 typecheck 和核心 lint; -- 插件生产变更会运行插件生产和插件测试 typecheck,以及插件 lint; -- 仅插件测试变更会运行插件测试 typecheck 和插件 lint; -- 公共插件 SDK 或插件契约变更会扩展到插件 typecheck,因为插件依赖这些核心契约(Vitest 插件扫测仍然是显式测试工作); -- 仅发布元数据的版本 bump 会运行定向的版本/配置/根依赖检查; -- 未知的根目录/配置变更会保守失败到所有检查通道。 +- 核心生产变更会运行核心生产和核心测试类型检查,以及核心 lint/守卫; +- 仅核心测试变更只运行核心测试类型检查,以及核心 lint; +- 插件生产变更会运行插件生产和插件测试类型检查,以及插件 lint; +- 仅插件测试变更会运行插件测试类型检查,以及插件 lint; +- 公开插件 SDK 或插件契约变更会扩展到插件类型检查,因为插件依赖这些核心契约(Vitest 插件扫描仍然是显式测试工作); +- 仅发布元数据的版本提升会运行定向版本/配置/根依赖检查; +- 未知根目录/配置变更会保守失败到所有检查通道。 -本地变更测试路由位于 `scripts/test-projects.test-support.mjs`,并且刻意比 `check:changed` 更便宜:直接测试编辑运行自身,源码编辑优先使用显式映射,然后是同级测试和导入图依赖项。共享群组房间投递配置是显式映射之一:对群组可见回复配置、源回复投递模式或 message-tool system prompt 的变更,会经过核心回复测试以及 Discord 和 Slack 投递回归测试,这样共享默认值变更会在第一次 PR push 前失败。只有当变更在 harness 范围内足够大,以至于便宜的映射集合不是可信代理时,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 +本地变更测试路由位于 `scripts/test-projects.test-support.mjs`,并且有意比 `check:changed` 更低成本:直接测试编辑会运行它们自身,源码编辑优先使用显式映射,然后是同级测试和导入图依赖项。共享群组房间投递配置是显式映射之一:对群组可见回复配置、源回复投递模式或消息工具系统提示词的变更,会路由到核心回复测试以及 Discord 和 Slack 投递回归测试,这样共享默认值变更会在第一次 PR 推送之前失败。只有当变更在 harness 范围内足够广,以至于低成本映射集合不是可信代理时,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 ## Testbox 验证 -从仓库根目录运行 Testbox,并且对于宽泛证明,优先使用一个全新预热的 box。在一个复用、过期或刚报告了异常大同步的 box 上投入慢门禁之前,先在 box 内运行 `pnpm testbox:sanity`。 +从仓库根目录运行 Testbox,并优先为广泛证明使用新预热的 box。在把慢关卡花费到一个被复用、已过期或刚报告了异常大同步的 box 上之前,先在该 box 内运行 `pnpm testbox:sanity`。 -当所需根文件(例如 `pnpm-lock.yaml`)消失,或 `git status --short` 显示至少 200 个已跟踪删除时,完整性检查会快速失败。这通常意味着远程同步状态不是 PR 的可信副本;停止该 box,并预热一个新的,而不是调试产品测试失败。对于有意的大量删除 PR,请为该完整性检查运行设置 `OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1`。 +当必需的根文件(例如 `pnpm-lock.yaml`)消失,或 `git status --short` 显示至少 200 个已跟踪删除项时,健全性检查会快速失败。这通常意味着远程同步状态不是 PR 的可信副本;应停止该 box 并预热一个新的,而不是调试产品测试失败。对于有意进行大量删除的 PR,为该健全性运行设置 `OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1`。 -如果本地 Blacksmith CLI 调用在同步阶段停留超过五分钟且没有同步后的输出,`pnpm testbox:run` 也会终止该调用。设置 `OPENCLAW_TESTBOX_SYNC_TIMEOUT_MS=0` 可禁用该保护,或为异常大的本地 diff 使用更大的毫秒值。 +`pnpm testbox:run` 还会终止本地 Blacksmith CLI 调用:如果它停留在同步阶段超过五分钟且没有同步后输出。设置 `OPENCLAW_TESTBOX_SYNC_TIMEOUT_MS=0` 可禁用该保护,或者为异常大的本地 diff 使用更大的毫秒值。 -当 Blacksmith 不可用,或更适合使用自有云容量时,Crabbox 是仓库自有的第二条远程 box Linux 证明路径。预热一个 box,通过项目工作流对它 hydrate,然后通过 Crabbox CLI 运行命令: +Crabbox 是仓库自有的第二条远程 box 路径,用于在 Blacksmith 不可用,或更适合使用自有云容量时提供 Linux 验证。预热一个 box,通过项目工作流完成初始化,然后通过 Crabbox CLI 运行命令: ```bash pnpm crabbox:warmup -- --idle-timeout 90m @@ -465,7 +484,7 @@ pnpm crabbox:run -- --id --shell "OPENCLAW_TESTBOX=1 pnpm check:changed pnpm crabbox:stop -- ``` -`.crabbox.yaml` 负责提供商、同步和 GitHub Actions hydrate 默认值。它会排除本地 `.git`,这样 hydrate 后的 Actions checkout 会保留自己的远程 Git 元数据,而不是同步维护者本地 remote 和对象存储;它还会排除绝不应传输的本地运行时/构建产物。`.github/workflows/crabbox-hydrate.yml` 负责 checkout、Node/pnpm 设置、`origin/main` 抓取,以及后续 `crabbox run --id ` 命令会 source 的非密钥环境交接。 +`.crabbox.yaml` 负责提供商、同步和 GitHub Actions 初始化默认值。它会排除本地 `.git`,这样已初始化的 Actions checkout 会保留自己的远程 Git 元数据,而不是同步维护者本地的远程配置和对象存储;它还会排除绝不应传输的本地运行时/构建产物。`.github/workflows/crabbox-hydrate.yml` 负责 checkout、Node/pnpm 设置、`origin/main` 获取,以及后续 `crabbox run --id ` 命令会读取的非 secret 环境交接。 ## 相关内容 diff --git a/docs/zh-CN/help/testing.md b/docs/zh-CN/help/testing.md index af9e38f7d..4ee56ddbf 100644 --- a/docs/zh-CN/help/testing.md +++ b/docs/zh-CN/help/testing.md @@ -1,34 +1,35 @@ --- read_when: - 在本地或 CI 中运行测试 - - 为模型/提供商 bug 添加回归测试 + - 添加针对模型/提供商缺陷的回归测试 - 调试 Gateway 网关 + 智能体行为 -summary: 测试工具包:unit/e2e/live 测试套件、Docker 运行器,以及每项测试的覆盖内容 +summary: 测试工具包:单元/端到端/实时套件、Docker 运行器,以及每个测试覆盖的内容 title: 测试 x-i18n: - generated_at: "2026-05-02T02:01:41Z" + generated_at: "2026-05-02T15:53:11Z" model: gpt-5.5 provider: openai - source_hash: 9778143e73683fde493e9652f20b8301455b53adbe6c70e997f5af2f54b3fe6b + source_hash: eae3bda71caeb2c2ea8842c940897dc79e4e99be6c337967be41e557b44a41fc source_path: help/testing.md workflow: 16 --- -OpenClaw 有三个 Vitest 套件(单元/集成、e2e、live)和一小组 Docker 运行器。本文档是一份“我们如何测试”的指南: +OpenClaw 有三个 Vitest 测试套件(单元/集成、e2e、live)和一小组 +Docker 运行器。本文档是“我们如何测试”的指南: -- 每个套件覆盖什么(以及它有意 _不_ 覆盖什么)。 -- 常见工作流(本地、推送前、调试)应运行哪些命令。 +- 每个套件覆盖什么(以及它刻意 _不_ 覆盖什么)。 +- 常见工作流(本地、推送前、调试)要运行哪些命令。 - live 测试如何发现凭证并选择模型/提供商。 - 如何为真实世界的模型/提供商问题添加回归测试。 -**QA 栈(qa-lab、qa-channel、live 传输通道)**单独记录在: +**QA 栈(qa-lab、qa-channel、live 传输通道)** 单独记录: -- [QA overview](/zh-CN/concepts/qa-e2e-automation) — 架构、命令面、场景编写。 +- [QA overview](/zh-CN/concepts/qa-e2e-automation) — 架构、命令界面、场景编写。 - [Matrix QA](/zh-CN/concepts/qa-matrix) — `pnpm openclaw qa matrix` 的参考。 -- [QA channel](/zh-CN/channels/qa-channel) — 仓库支持的场景使用的合成传输插件。 +- [QA channel](/zh-CN/channels/qa-channel) — 由仓库支持的场景使用的合成传输插件。 -本页覆盖常规测试套件和 Docker/Parallels 运行器的运行方式。下面的 QA 专用运行器小节([QA 专用运行器](#qa-specific-runners))列出具体的 `qa` 调用,并指回上面的参考资料。 +本页涵盖常规测试套件以及 Docker/Parallels 运行器的运行方式。下面的 QA 专用运行器部分([QA-specific runners](#qa-specific-runners))列出了具体的 `qa` 调用,并指回上面的参考资料。 ## 快速开始 @@ -36,54 +37,65 @@ OpenClaw 有三个 Vitest 套件(单元/集成、e2e、live)和一小组 Doc 大多数时候: - 完整门禁(推送前预期运行):`pnpm build && pnpm check && pnpm check:test-types && pnpm test` -- 在资源充足的机器上更快地运行本地完整套件:`pnpm test:max` -- 直接的 Vitest 监听循环:`pnpm test:watch` -- 直接文件定位现在也会路由扩展/渠道路径:`pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` -- 当你在迭代单个失败时,优先运行有针对性的命令。 +- 在资源充足的机器上更快运行本地完整套件:`pnpm test:max` +- 直接 Vitest 监视循环:`pnpm test:watch` +- 直接文件定位现在也会路由 extension/channel 路径:`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` +- 运行时性能报告:派发 `OpenClaw Performance`,并设置 + `live_gpt54=true` 来进行一次真实的 `openai/gpt-5.4` 智能体轮次,或设置 + `deep_profile=true` 来生成 Kova CPU/堆/跟踪工件。每日定时运行会在配置 + `CLAWGRIT_REPORTS_TOKEN` 时,将 mock-provider、deep-profile 和 GPT 5.4 通道工件发布到 + `openclaw/clawgrit-reports`。 - Docker live 模型扫描:`pnpm test:docker:live-models` - - 每个选中的模型现在会运行一次文本轮次以及一个小型文件读取风格探针。 - 元数据声明支持 `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 工作流,其中包括按提供商分片的独立 Docker live 模型矩阵作业。 - - 对于聚焦的 CI 重跑,使用 `include_live_suites: true` 和 `live_models_only: true` 触发 `OpenClaw Live And E2E Checks (Reusable)`。 + - 每个选中的模型现在会运行一个文本轮次,以及一个小型的文件读取风格探测。 + 元数据声明支持 `image` 输入的模型还会运行一个小型图片轮次。 + 在隔离提供商失败时,可用 `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` 或 + `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0` 禁用额外探测。 + - CI 覆盖范围:每日 `OpenClaw Scheduled Live And E2E Checks` 和手动 + `OpenClaw Release Checks` 都会调用可复用 live/E2E 工作流,并设置 + `include_live_suites: true`,其中包含按提供商分片的独立 Docker live 模型 + 矩阵作业。 + - 对于聚焦的 CI 重跑,派发 `OpenClaw Live And E2E Checks (Reusable)`, + 并设置 `include_live_suites: true` 和 `live_models_only: true`。 - 将新的高信号提供商密钥添加到 `scripts/ci-hydrate-live-auth.sh`, 以及 `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` 和它的 定时/发布调用方。 - 原生 Codex 绑定聊天冒烟测试:`pnpm test:docker:live-codex-bind` - - 针对 Codex app-server 路径运行一个 Docker live 通道,绑定一个合成 - Slack 私信并使用 `/codex bind`,执行 `/codex fast` 和 - `/codex permissions`,然后验证普通回复和图像附件会通过原生插件绑定路由,而不是 ACP。 + - 针对 Codex app-server 路径运行 Docker live 通道,使用 `/codex bind` 绑定一个合成 + Slack 私信,执行 `/codex fast` 和 + `/codex permissions`,然后验证一条普通回复和一个图片附件 + 通过原生插件绑定而不是 ACP 路由。 - Codex app-server harness 冒烟测试:`pnpm test:docker:live-codex-harness` - 通过插件拥有的 Codex app-server harness 运行 Gateway 网关智能体轮次, - 验证 `/codex status` 和 `/codex models`,默认还会执行图像、 - cron MCP、子智能体和 Guardian 探针。在隔离其他 Codex - app-server 失败时,可使用 - `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0` 禁用子智能体探针。对于聚焦的子智能体检查,禁用其他探针: + 验证 `/codex status` 和 `/codex models`,并默认执行图片、 + cron MCP、子智能体和 Guardian 探测。在隔离其他 Codex + app-server 失败时,可用 + `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0` 禁用子智能体探测。对于聚焦的子智能体检查,禁用其他探测: `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`,否则这会在子智能体探针后退出。 + 除非设置 + `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY=0`,否则它会在子智能体探测后退出。 - Crestodian 救援命令冒烟测试:`pnpm test:live:crestodian-rescue-channel` - - 消息渠道救援命令表面的可选双保险检查。 - 它会执行 `/crestodian status`,排队一个持久模型变更, - 回复 `/crestodian yes`,并验证审计/配置写入路径。 + - 可选的双保险检查,用于消息渠道救援命令 + 界面。它会执行 `/crestodian status`、排队一个持久模型 + 变更、回复 `/crestodian yes`,并验证审计/配置写入路径。 - Crestodian 规划器 Docker 冒烟测试:`pnpm test:docker:crestodian-planner` - - 在无配置容器中运行 Crestodian,并在 `PATH` 上放置一个假的 Claude CLI, - 然后验证模糊规划器回退会转换为经过审计的类型化配置写入。 + - 在无配置容器中运行 Crestodian,并在 `PATH` + 上放置一个假的 Claude CLI,验证模糊规划器回退会转换为经过审计的类型化 + 配置写入。 - Crestodian 首次运行 Docker 冒烟测试:`pnpm test:docker:crestodian-first-run` - - 从空的 OpenClaw 状态目录开始,将裸 `openclaw` 路由到 + - 从空的 OpenClaw 状态目录启动,将裸 `openclaw` 路由到 Crestodian,应用设置/模型/智能体/Discord 插件 + SecretRef 写入, 验证配置,并验证审计条目。相同的 Ring 0 设置路径也由 QA Lab 中的 `pnpm openclaw qa suite --scenario crestodian-ring-zero-setup` 覆盖。 @@ -91,72 +103,65 @@ OpenClaw 有三个 Vitest 套件(单元/集成、e2e、live)和一小组 Doc `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,并且助手转录存储了规范化的 `usage.cost`。 + 验证 JSON 报告 Moonshot/K2.6,并且助手转录记录存储规范化后的 `usage.cost`。 -当你只需要一个失败用例时,优先通过下面描述的 allowlist 环境变量来收窄 live 测试。 +当你只需要一个失败用例时,优先通过下面描述的 allowlist 环境变量缩小 live 测试范围。 ## QA 专用运行器 -当你需要 QA-lab 真实度时,这些命令与主测试套件并列: +当你需要 QA-lab 真实度时,这些命令与主测试套件并列使用: -CI 在专用工作流中运行 QA Lab。`Parity gate` 会在匹配的 PR 上运行,也可通过手动触发并使用模拟提供商运行。`QA-Lab - All Lanes` 每晚在 `main` 上运行,也可通过手动触发运行,并将模拟 parity gate、live Matrix 通道、Convex 托管的 live Telegram 通道和 Convex 托管的 live Discord 通道作为并行作业。定时 QA 和发布检查会显式传递 Matrix `--profile fast`,而 Matrix CLI 和手动工作流输入的默认值仍为 `all`;手动触发可将 `all` 分片为 `transport`、`media`、`e2ee-smoke`、`e2ee-deep` 和 `e2ee-cli` 作业。`OpenClaw Release Checks` 会在发布批准前运行 parity 加 fast Matrix 和 Telegram 通道,发布传输检查使用 `mock-openai/gpt-5.5`,以保持确定性并避免常规提供商插件启动。这些 live 传输 Gateway 网关会禁用记忆搜索;记忆行为仍由 QA parity 套件覆盖。 +CI 在专用工作流中运行 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 和手动工作流输入默认值仍为 +`all`;手动派发可以将 `all` 分片为 `transport`、`media`、`e2ee-smoke`、 +`e2ee-deep` 和 `e2ee-cli` 作业。`OpenClaw Release Checks` 会在发布批准前运行 parity 以及 +fast Matrix 和 Telegram 通道,并使用 +`mock-openai/gpt-5.5` 进行发布传输检查,从而保持确定性 +并避免普通提供商插件启动。这些 live 传输 Gateway 网关会禁用 +记忆搜索;记忆行为仍由 QA parity 套件覆盖。 -完整发布 live 媒体分片使用 +完整发布 live media 分片使用 `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04`,其中已经包含 `ffmpeg` 和 `ffprobe`。Docker live 模型/后端分片使用共享的 -`ghcr.io/openclaw/openclaw-live-test:` 镜像,该镜像会为每个选中的提交构建一次,然后通过 `OPENCLAW_SKIP_DOCKER_BUILD=1` 拉取,而不是在每个分片内部重建。 +`ghcr.io/openclaw/openclaw-live-test:` 镜像,该镜像会为每个选定的 +提交构建一次,然后用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 拉取它,而不是在每个分片中重新构建。 - `pnpm openclaw qa suite` - - 直接在主机上运行仓库支持的 QA 场景。 - - 默认使用隔离的 Gateway 网关 worker 并行运行多个选中的场景。 - `qa-channel` 默认并发为 4(受选中场景数量限制)。使用 `--concurrency ` 调整 worker 数量,或使用 `--concurrency 1` 运行较旧的串行通道。 - - 当任何场景失败时以非零状态退出。当你想要产物但不想要失败退出码时,使用 `--allow-failures`。 - - 支持提供商模式 `live-frontier`、`mock-openai` 和 `aimock`。 - `aimock` 会启动一个本地 AIMock 支持的提供商服务器,用于实验性 fixture 和协议模拟覆盖,同时不替代场景感知的 - `mock-openai` 通道。 + - 直接在主机上运行由仓库支持的 QA 场景。 + - 默认通过隔离的 Gateway 网关 worker 并行运行多个选定场景。`qa-channel` 默认并发数为 4(受选定场景数量限制)。使用 `--concurrency ` 调整 worker 数量,或使用 `--concurrency 1` 运行较旧的串行通道。 + - 当任何场景失败时以非零状态退出。当你想要保留产物但不想要失败退出码时,使用 `--allow-failures`。 + - 支持提供商模式 `live-frontier`、`mock-openai` 和 `aimock`。`aimock` 会启动一个本地 AIMock 支持的提供商服务器,用于实验性夹具和协议模拟覆盖,同时不会替换具备场景感知能力的 `mock-openai` 通道。 - `pnpm test:gateway:cpu-scenarios` - - 运行 Gateway 网关启动基准测试,以及一个小型模拟 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 网关占满回归。 - - 使用构建好的 `dist` 产物;当检出目录还没有新的运行时输出时,先运行构建。 + - 运行 Gateway 网关启动基准测试以及一个小型模拟 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 网关占满回归。 + - 使用构建好的 `dist` 产物;当检出目录还没有最新运行时输出时,先运行构建。 - `pnpm openclaw qa suite --runner multipass` - - 在一次性 Multipass Linux VM 内运行相同的 QA 套件。 + - 在一次性 Multipass Linux VM 内运行同一套 QA。 - 保持与主机上 `qa suite` 相同的场景选择行为。 - 复用与 `qa suite` 相同的提供商/模型选择标志。 - - Live 运行会转发对 guest 来说实用的受支持 QA 认证输入: - 基于环境变量的提供商密钥、QA live 提供商配置路径,以及存在时的 `CODEX_HOME`。 - - 输出目录必须保持在仓库根目录下,以便 guest 通过挂载的工作区写回。 - - 在 `.artifacts/qa-e2e/...` 下写入常规 QA 报告 + 摘要以及 Multipass 日志。 + - 实时运行会转发对 guest 实用的受支持 QA 凭证输入:基于环境变量的提供商密钥、QA 实时提供商配置路径,以及存在时的 `CODEX_HOME`。 + - 输出目录必须保留在仓库根目录下,这样 guest 才能通过挂载的工作区写回。 + - 在 `.artifacts/qa-e2e/...` 下写入常规 QA 报告、摘要以及 Multipass 日志。 - `pnpm qa:lab:up` - - 启动 Docker 支持的 QA 站点,用于操作员风格的 QA 工作。 + - 启动 Docker 支持的 QA 站点,用于操作员式 QA 工作。 - `pnpm test:docker:npm-onboard-channel-agent` - - 从当前检出构建 npm tarball,在 Docker 中全局安装它,运行非交互式 OpenAI API key 新手引导,默认配置 Telegram,验证打包的插件运行时无需启动依赖修复即可加载,运行 Doctor,并针对模拟的 OpenAI 端点运行一次本地智能体轮次。 - - 使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 可用 Discord 运行相同的打包安装通道。 + - 从当前检出构建 npm tarball,在 Docker 中全局安装它,运行非交互式 OpenAI API 密钥新手引导,默认配置 Telegram,验证打包后的插件运行时可在无启动依赖修复的情况下加载,运行 Doctor,并针对一个模拟的 OpenAI 端点运行一次本地智能体轮次。 + - 使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 通过 Discord 运行同一打包安装通道。 - `pnpm test:docker:session-runtime-context` - - 为嵌入式运行时上下文转录运行确定性的构建应用 Docker 冒烟测试。它验证隐藏的 OpenClaw 运行时上下文会作为非显示自定义消息持久化,而不会泄漏到可见用户轮次中,然后植入一个受影响的损坏会话 JSONL,并验证 - `openclaw doctor --fix` 会将其重写到活动分支并创建备份。 + - 为嵌入式运行时上下文转录运行一个确定性的已构建应用 Docker 冒烟测试。它会验证隐藏的 OpenClaw 运行时上下文作为非显示自定义消息持久化,而不是泄漏到可见的用户轮次中,然后植入一个受影响的损坏会话 JSONL,并验证 `openclaw doctor --fix` 会将其重写到当前活跃分支并创建备份。 - `pnpm test:docker:npm-telegram-live` - - 在 Docker 中安装一个 OpenClaw 包候选,运行已安装包的新手引导,通过已安装的 CLI 配置 Telegram,然后用该已安装包作为被测系统 Gateway 网关,复用 live Telegram QA 通道。 - - 默认值为 `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 环境凭证或 Convex 凭证来源。对于 CI/发布自动化,设置 - `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex` 加 - `OPENCLAW_QA_CONVEX_SITE_URL` 和角色密钥。如果 - `OPENCLAW_QA_CONVEX_SITE_URL` 和 Convex 角色密钥存在于 CI 中, - Docker 包装器会自动选择 Convex。 - - `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintainer` 仅针对这个通道覆盖共享的 `OPENCLAW_QA_CREDENTIAL_ROLE`。 - - GitHub Actions 将这个通道公开为手动维护者工作流 - `NPM Telegram Beta E2E`。它不会在合并时运行。该工作流使用 - `qa-live-shared` 环境和 Convex CI 凭证租约。 -- GitHub Actions 也公开了 `Package Acceptance`,用于针对一个候选包进行旁路产品证明。它接受受信任的 ref、已发布的 npm spec、HTTPS tarball URL 加 SHA-256,或来自另一个运行的 tarball artifact,将规范化的 - `openclaw-current.tgz` 上传为 `package-under-test`,然后用 smoke、package、product、full 或 custom 通道 profile 运行现有的 Docker E2E 调度器。设置 `telegram_mode=mock-openai` 或 `live-frontier` 可让 Telegram QA 工作流针对同一个 `package-under-test` 产物运行。 - - 最新 beta 产品证明: + - 在 Docker 中安装一个 OpenClaw 包候选版本,运行已安装包的新手引导,通过已安装的 CLI 配置 Telegram,然后复用实时 Telegram QA 通道,并将该已安装包作为被测系统 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 环境变量凭据或 Convex 凭据来源。对于 CI/发布自动化,设置 `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex`,再加上 `OPENCLAW_QA_CONVEX_SITE_URL` 和角色密钥。如果 CI 中存在 `OPENCLAW_QA_CONVEX_SITE_URL` 和 Convex 角色密钥,Docker 包装器会自动选择 Convex。 + - `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintainer` 仅针对该通道覆盖共享的 `OPENCLAW_QA_CREDENTIAL_ROLE`。 + - GitHub Actions 将该通道作为手动维护者工作流 `NPM Telegram Beta E2E` 暴露。它不会在合并时运行。该工作流使用 `qa-live-shared` 环境和 Convex CI 凭据租约。 +- GitHub Actions 还暴露 `Package Acceptance`,用于针对一个候选包进行旁路产品验证。它接受可信 ref、已发布的 npm spec、HTTPS tarball URL 加 SHA-256,或来自另一次运行的 tarball 产物,将标准化后的 `openclaw-current.tgz` 上传为 `package-under-test`,然后使用冒烟、包、产品、完整或自定义通道配置文件运行现有 Docker E2E 调度器。设置 `telegram_mode=mock-openai` 或 `live-frontier` 可让 Telegram QA 工作流针对同一个 `package-under-test` 产物运行。 + - 最新 beta 产品验证: ```bash gh workflow run package-acceptance.yml --ref main \ @@ -166,7 +171,7 @@ gh workflow run package-acceptance.yml --ref main \ -f telegram_mode=mock-openai ``` -- 精确 tarball URL 证明需要摘要: +- 精确 tarball URL 验证需要摘要: ```bash gh workflow run package-acceptance.yml --ref main \ @@ -176,7 +181,7 @@ gh workflow run package-acceptance.yml --ref main \ -f suite_profile=package ``` -- Artifact 证明会从另一个 Actions 运行下载一个 tarball artifact: +- 产物验证会从另一次 Actions 运行下载 tarball 产物: ```bash gh workflow run package-acceptance.yml --ref main \ @@ -187,59 +192,58 @@ gh workflow run package-acceptance.yml --ref main \ ``` - `pnpm test:docker:plugins` - - 在 Docker 中打包并安装当前 OpenClaw 构建,启动配置了 OpenAI 的 Gateway 网关,然后通过配置编辑启用内置渠道/插件。 - - 验证设置发现会让未配置的可下载插件保持缺失,第一次配置的 Doctor 修复会显式安装每个缺失的可下载插件,并且第二次重启不会运行隐藏依赖修复。 - - 还会安装一个已知的旧 npm 基线,在运行 `openclaw update --tag ` 之前启用 Telegram,并验证候选版本的更新后 Doctor 会清理旧版插件依赖残留,而不依赖 harness 侧的 postinstall 修复。 + - 在 Docker 中打包并安装当前 OpenClaw 构建,启动已配置 OpenAI 的 Gateway 网关,然后通过配置编辑启用内置渠道/插件。 + - 验证设置发现会让未配置的可下载插件保持缺失,第一次配置后的 Doctor 修复会显式安装每个缺失的可下载插件,并且第二次重启不会运行隐藏依赖修复。 + - 还会安装一个已知较旧的 npm 基线,在运行 `openclaw update --tag ` 之前启用 Telegram,并验证候选版本的更新后 Doctor 会清理遗留插件依赖残留,而不需要 harness 侧 postinstall 修复。 - `pnpm test:parallels:npm-update` - - 跨 Parallels 客户机运行原生打包安装更新冒烟测试。每个选定平台先安装请求的基线包,然后在同一客户机中运行已安装的 `openclaw update` 命令,并验证已安装版本、更新状态、Gateway 网关就绪状态,以及一次本地智能体回合。 - - 在迭代单个客户机时使用 `--platform macos`、`--platform windows` 或 `--platform linux`。使用 `--json` 获取摘要 artifact 路径和每条 lane 的状态。 - - OpenAI lane 默认使用 `openai/gpt-5.5` 作为实时智能体回合证明。仅在有意验证另一个 OpenAI 模型时,传入 `--model ` 或设置 `OPENCLAW_PARALLELS_OPENAI_MODEL`。 - - 将较长的本地运行包在主机超时中,避免 Parallels 传输卡顿耗尽剩余测试窗口: + - 跨 Parallels guest 运行原生打包安装更新冒烟测试。每个选定平台会先安装请求的基线包,然后在同一个 guest 中运行已安装的 `openclaw update` 命令,并验证已安装版本、更新状态、Gateway 网关就绪性,以及一次本地智能体轮次。 + - 迭代单个 guest 时使用 `--platform macos`、`--platform windows` 或 `--platform linux`。使用 `--json` 获取摘要产物路径和每个通道的状态。 + - OpenAI 通道默认使用 `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 日志。 - 在假设外层 wrapper 卡住之前,先检查 `windows-update.log`、`macos-update.log` 或 `linux-update.log`。 - - 在冷启动客户机上,Windows 更新可能在更新后 Doctor 和包更新工作中花费 10 到 15 分钟;只要嵌套 npm 调试日志仍在推进,这仍是健康状态。 - - 不要将这个聚合 wrapper 与单独的 Parallels macOS、Windows 或 Linux 冒烟 lane 并行运行。它们共享 VM 状态,可能在快照恢复、包服务或客户机 Gateway 网关状态上发生冲突。 - - 更新后证明会运行普通的内置插件 surface,因为语音、图像生成和媒体理解等能力 facade 是通过内置运行时 API 加载的,即使智能体回合本身只检查一个简单文本响应。 + - 该脚本会在 `/tmp/openclaw-parallels-npm-update.*` 下写入嵌套通道日志。在假设外层包装器挂起之前,先检查 `windows-update.log`、`macos-update.log` 或 `linux-update.log`。 + - 在冷 guest 上,Windows 更新可能会在更新后 Doctor 和包更新工作中花费 10 到 15 分钟;只要嵌套 npm 调试日志在推进,这仍然是健康状态。 + - 不要将此聚合包装器与单独的 Parallels macOS、Windows 或 Linux 冒烟通道并行运行。它们共享 VM 状态,可能会在快照恢复、包服务或 guest Gateway 网关状态上发生冲突。 + - 更新后验证会运行常规内置插件表面,因为语音、图像生成和媒体理解等能力 facade 会通过内置运行时 API 加载,即使智能体轮次本身只检查一个简单文本响应。 - `pnpm openclaw qa aimock` - 仅启动本地 AIMock 提供商服务器,用于直接协议冒烟测试。 - `pnpm openclaw qa matrix` - - 针对一次性 Docker 支持的 Tuwunel homeserver 运行 Matrix 实时 QA lane。仅限源码检出 — 打包安装不会发布 `qa-lab`。 - - 完整 CLI、profile/scenario 目录、环境变量和 artifact 布局:[Matrix QA](/zh-CN/concepts/qa-matrix)。 + - 针对一次性 Docker 支持的 Tuwunel homeserver 运行 Matrix 实时 QA 通道。仅限源码检出目录——打包安装不会随附 `qa-lab`。 + - 完整 CLI、配置文件/场景目录、环境变量和产物布局:[Matrix QA](/zh-CN/concepts/qa-matrix)。 - `pnpm openclaw qa telegram` - - 使用来自环境变量的 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` 用于共享池化凭证。默认使用环境变量模式,或设置 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` 以选择使用池化租约。 - - 当任何 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 token,针对真实私有群组运行 Telegram 实时 QA 通道。 + - 需要 `OPENCLAW_QA_TELEGRAM_GROUP_ID`、`OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` 和 `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`。群组 id 必须是数字形式的 Telegram 聊天 id。 + - 支持 `--credential-source convex` 以使用共享池化凭据。默认使用环境变量模式,或设置 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` 以选择池化租约。 + - 当任何场景失败时以非零状态退出。当你想要保留产物但不想要失败退出码时,使用 `--allow-failures`。 + - 需要同一私有群组中的两个不同 bot,且被测系统 bot 需暴露 Telegram 用户名。 + - 为获得稳定的 bot 到 bot 观察效果,请在 `@BotFather` 中为两个 bot 启用 Bot-to-Bot Communication Mode,并确保驱动 bot 可以观察群组 bot 流量。 + - 在 `.artifacts/qa-e2e/...` 下写入 Telegram QA 报告、摘要和 observed-messages 产物。回复场景包含从驱动发送请求到观察到被测系统回复的 RTT。 -实时传输 lane 共享一套标准契约,避免新传输发生漂移;每条 lane 的覆盖矩阵位于 [QA overview → 实时传输覆盖](/zh-CN/concepts/qa-e2e-automation#live-transport-coverage)。`qa-channel` 是广义合成套件,不属于该矩阵。 +实时传输通道共享一个标准契约,避免新传输发生漂移;每个通道的覆盖矩阵位于 [QA overview → 实时传输覆盖范围](/zh-CN/concepts/qa-e2e-automation#live-transport-coverage)。`qa-channel` 是广泛的合成套件,不属于该矩阵。 -### 通过 Convex 共享 Telegram 凭证(v1) +### 通过 Convex 共享 Telegram 凭据(v1) -当为 `openclaw qa telegram` 启用 `--credential-source convex`(或 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`)时,QA lab 会从 Convex 支持的池中获取一个独占租约,在 lane 运行期间为该租约发送 Heartbeat,并在关闭时释放该租约。 +为 `openclaw qa telegram` 启用 `--credential-source convex`(或 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`)时,QA lab 会从 Convex 支持的池中获取独占租约,在通道运行期间对该租约发送 Heartbeat,并在关闭时释放租约。 -参考 Convex 项目 scaffold: +参考 Convex 项目脚手架: - `qa/convex-credential-broker/` 必需环境变量: - `OPENCLAW_QA_CONVEX_SITE_URL`(例如 `https://your-deployment.convex.site`) -- 所选角色的一个 secret: +- 所选角色的一个密钥: - `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER` 用于 `maintainer` - `OPENCLAW_QA_CONVEX_SECRET_CI` 用于 `ci` -- 凭证角色选择: +- 凭据角色选择: - CLI:`--credential-role maintainer|ci` - - 环境变量默认值:`OPENCLAW_QA_CREDENTIAL_ROLE`(在 CI 中默认为 `ci`,否则为 `maintainer`) + - 环境变量默认值:`OPENCLAW_QA_CREDENTIAL_ROLE`(在 CI 中默认为 `ci`,其他情况下默认为 `maintainer`) 可选环境变量: @@ -248,14 +252,14 @@ gh workflow run package-acceptance.yml --ref main \ - `OPENCLAW_QA_CREDENTIAL_ACQUIRE_TIMEOUT_MS`(默认 `90000`) - `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_CREDENTIAL_OWNER_ID`(可选跟踪 id) +- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` 允许用于仅本地开发的 loopback `http://` Convex URL。 -`OPENCLAW_QA_CONVEX_SITE_URL` 在正常运行中应使用 `https://`。 +正常运行中,`OPENCLAW_QA_CONVEX_SITE_URL` 应使用 `https://`。 -Maintainer 管理命令(pool add/remove/list)特别需要 `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`。 +维护者管理员命令(池 add/remove/list)明确需要 `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`。 -面向 maintainer 的 CLI helper: +维护者 CLI 辅助命令: ```bash pnpm openclaw qa credentials doctor @@ -264,9 +268,9 @@ 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 值。使用 `--json` 为脚本和 CI 工具生成机器可读输出。 +实时运行前使用 `doctor` 检查 Convex 站点 URL、broker 密钥、端点前缀、HTTP 超时,以及 admin/list 可达性,且不会打印密钥值。在脚本和 CI 工具中使用 `--json` 获取机器可读输出。 -默认 endpoint 契约(`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`): +默认端点契约(`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`): - `POST /acquire` - 请求:`{ kind, ownerId, actorRole, leaseTtlMs, heartbeatIntervalMs }` @@ -278,74 +282,76 @@ pnpm openclaw qa credentials remove --credential-id - `POST /release` - 请求:`{ kind, ownerId, actorRole, credentialId, leaseToken }` - 成功:`{ status: "ok" }`(或空 `2xx`) -- `POST /admin/add`(仅 maintainer secret) +- `POST /admin/add`(仅限维护者密钥) - 请求:`{ kind, actorId, payload, note?, status? }` - 成功:`{ status: "ok", credential }` -- `POST /admin/remove`(仅 maintainer secret) +- `POST /admin/remove`(仅限维护者密钥) - 请求:`{ credentialId, actorId }` - 成功:`{ status: "ok", changed, credential }` - 活跃租约保护:`{ status: "error", code: "LEASE_ACTIVE", ... }` -- `POST /admin/list`(仅 maintainer secret) +- `POST /admin/list`(仅限维护者密钥) - 请求:`{ kind?, status?, includePayload?, limit? }` - 成功:`{ status: "ok", credentials, count }` -Telegram kind 的 payload 形状: +Telegram 类型的载荷形状: - `{ groupId: string, driverToken: string, sutToken: string }` -- `groupId` 必须是数字 Telegram chat id 字符串。 -- `admin/add` 会为 `kind: "telegram"` 验证此形状,并拒绝格式错误的 payload。 +- `groupId` 必须是数字形式的 Telegram 聊天 ID 字符串。 +- `admin/add` 会对 `kind: "telegram"` 校验此形状,并拒绝格式错误的载荷。 -### 将渠道添加到 QA +### 向 QA 添加渠道 -新渠道适配器的架构和 scenario helper 名称位于 [QA overview → 添加渠道](/zh-CN/concepts/qa-e2e-automation#adding-a-channel)。最低要求:在共享 `qa-lab` host seam 上实现传输 runner,在插件 manifest 中声明 `qaRunners`,挂载为 `openclaw qa `,并在 `qa/scenarios/` 下编写 scenario。 +新渠道适配器的架构和场景辅助函数名称位于 [QA overview → 添加渠道](/zh-CN/concepts/qa-e2e-automation#adding-a-channel)。最低要求:在共享的 `qa-lab` 主机衔接层上实现传输运行器,在插件清单中声明 `qaRunners`,挂载为 `openclaw qa `,并在 `qa/scenarios/` 下编写场景。 -## 测试套件(哪里运行什么) +## 测试套件(在哪里运行什么) -可以把这些套件理解为“真实度逐步提高”(同时 flaky 程度/成本也逐步提高): +可以把这些套件理解为“现实程度递增”(同时不稳定性/成本也递增): ### 单元 / 集成(默认) - 命令:`pnpm test` -- 配置:非定向运行使用 `vitest.full-*.config.ts` shard 集合,并且可能将多项目 shard 展开为每项目配置,以便并行调度 -- 文件:`src/**/*.test.ts`、`packages/**/*.test.ts` 和 `test/**/*.test.ts` 下的 core/unit inventory;UI 单元测试在专用 `unit-ui` shard 中运行 +- 配置:未定向运行使用 `vitest.full-*.config.ts` 分片集,并且可能会将多项目分片展开为每项目配置,以便并行调度 +- 文件:`src/**/*.test.ts`、`packages/**/*.test.ts` 和 `test/**/*.test.ts` 下的核心/单元清单;UI 单元测试在专用的 `unit-ui` 分片中运行 - 范围: - 纯单元测试 - 进程内集成测试(Gateway 网关认证、路由、工具、解析、配置) - - 已知 bug 的确定性回归 + - 已知 bug 的确定性回归测试 - 预期: - 在 CI 中运行 - - 不需要真实 key + - 不需要真实密钥 - 应该快速且稳定 - - Resolver 和 public-surface loader 测试必须用生成的微型插件 fixture 证明广义 `api.js` 和 `runtime-api.js` fallback 行为,而不是使用真实内置插件源码 API。真实插件 API 加载属于插件拥有的 contract/integration 套件。 + - 解析器和公共表面加载器测试必须使用生成的微型插件夹具证明广义 `api.js` 和 + `runtime-api.js` 回退行为,而不是使用真实内置插件源 API。真实插件 API 加载应属于 + 插件自有的契约/集成套件。 - + - - 未指定目标的 `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` 会先通过作用域车道处理显式文件/目录目标,所以 `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`。 - - `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 `。仅发布元数据的版本 bump 会运行定向版本/配置/根依赖检查,并带有一个 guard,用于拒绝顶层 version 字段之外的 package 变更。 - - Live Docker ACP harness 编辑会运行聚焦检查:live Docker auth 脚本的 shell 语法,以及 live Docker scheduler dry-run。只有当 diff 限于 `scripts["test:docker:live-*"]` 时才包含 `package.json` 变更;依赖、export、version 和其他 package 表面编辑仍使用更广泛的 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/**` 子树提供了专用 bucket。CI 还会进一步把 reply 子树拆分为 agent-runner、dispatch 和 commands/state-routing 分片,避免一个导入较重的 bucket 独占完整 Node 尾部时间。 - - 常规 PR/main CI 会有意跳过 extension 批量扫测和仅发布使用的 `agentic-plugins` 分片。完整 Release Validation 会为候选发布触发单独的 `Plugin Prerelease` 子工作流,以运行这些 plugin/extension 密集的测试套件。 + - 未定向的 `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/插件工作饿死无关套件。 + - `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` 文件、明确源映射,以及本地导入图依赖项。配置/设置/package 编辑不会广泛运行测试,除非你明确使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 + - `pnpm check:changed` 是窄范围工作的常规智能本地检查门禁。它会将差异分类为核心、核心测试、插件、插件测试、应用、文档、发布元数据、实时 Docker 工具和工具链,然后运行匹配的类型检查、lint 和保护命令。它不会运行 Vitest 测试;如需测试证明,请调用 `pnpm test:changed` 或明确的 `pnpm test `。仅发布元数据的版本提升会运行定向版本/配置/根依赖检查,并带有一个保护项,用于拒绝顶层版本字段之外的 package 变更。 + - 实时 Docker ACP harness 编辑会运行聚焦检查:实时 Docker 认证脚本的 shell 语法和实时 Docker 调度器空跑。仅当差异局限于 `scripts["test:docker:live-*"]` 时,才会包含 `package.json` 变更;依赖、导出、版本和其他 package 表面编辑仍使用更广的保护项。 + - 来自智能体、命令、插件、auto-reply 辅助函数、`plugin-sdk` 和类似纯工具区域的轻导入单元测试会通过 `unit-fast` 通道路由,该通道会跳过 `test/setup-openclaw-runtime.ts`;有状态/运行时较重的文件仍留在现有通道上。 + - 选定的 `plugin-sdk` 和 `commands` 辅助源文件也会将 changed-mode 运行映射到这些轻量通道中的明确同级测试,因此辅助函数编辑可以避免重新运行该目录的完整重型套件。 + - `auto-reply` 为顶层核心辅助函数、顶层 `reply.*` 集成测试,以及 `src/auto-reply/reply/**` 子树提供了专用桶。CI 还会进一步把 reply 子树拆分为 agent-runner、dispatch 和 commands/state-routing 分片,避免某个导入较重的桶独占完整 Node 尾部耗时。 + - 常规 PR/main CI 会有意跳过插件批量扫描和仅发布使用的 `agentic-plugins` 分片。完整发布验证会为发布候选版本上的这些插件/扩展较重套件分派单独的 `Plugin Prerelease` 子工作流。 - + - - 当你更改 message-tool 发现输入或 compaction 运行时 - 上下文时,请保留两级覆盖。 + - 当你变更消息工具发现输入或压缩运行时 + 上下文时,请保留两个层级的覆盖。 - 为纯路由和规范化 - 边界添加聚焦的 helper 回归测试。 - - 保持嵌入式 runner 集成套件健康: + 边界添加聚焦的辅助函数回归测试。 + - 保持嵌入式运行器集成套件健康: `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.loop.test.ts`。 - - 这些套件会验证作用域 id 和 compaction 行为仍会 - 通过真实的 `run.ts` / `compact.ts` 路径流动;仅 helper 的测试 + - 这些套件会验证作用域 ID 和压缩行为仍然通过 + 真实的 `run.ts` / `compact.ts` 路径流动;仅辅助函数测试 不能充分替代这些集成路径。 @@ -353,63 +359,65 @@ Telegram kind 的 payload 形状: - 基础 Vitest 配置默认使用 `threads`。 - - 共享 Vitest 配置固定为 `isolate: false`,并在根项目、e2e 和 live 配置中使用 - 非隔离 runner。 - - 根 UI 车道保留其 `jsdom` 设置和优化器,但也运行在 - 共享非隔离 runner 上。 + - 共享 Vitest 配置固定 `isolate: false`,并在根项目、e2e 和实时配置中使用 + 非隔离运行器。 + - 根 UI 通道保留其 `jsdom` 设置和优化器,但也运行在 + 共享非隔离运行器上。 - 每个 `pnpm test` 分片都会从共享 Vitest 配置继承相同的 `threads` + `isolate: false` 默认值。 - - `scripts/run-vitest.mjs` 默认为 Vitest 子 Node - 进程添加 `--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 触发哪些架构车道。 - - pre-commit hook 仅做格式化。它会重新暂存已格式化的文件,并且 - 不运行 lint、typecheck 或测试。 - - 当你需要智能本地检查门禁时,请在 handoff 或 push 前显式运行 - `pnpm check:changed`。 - - `pnpm test:changed` 默认通过低成本的作用域车道路由。仅当智能体 - 判定 harness、配置、包或契约编辑确实需要更广的 + - `pnpm changed:lanes` 会显示差异触发哪些架构通道。 + - 预提交钩子只做格式化。它会重新暂存格式化后的文件, + 不会运行 lint、类型检查或测试。 + - 当你需要智能本地检查门禁时,在交接或推送前明确运行 `pnpm check:changed`。 + - `pnpm test:changed` 默认会通过便宜的作用域通道路由。仅当智能体 + 判断 harness、配置、package 或契约编辑确实需要更广的 Vitest 覆盖时,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 - - `pnpm test:max` 和 `pnpm test:changed:max` 保持相同路由 + - `pnpm test:max` 和 `pnpm test:changed:max` 保持相同的路由 行为,只是 worker 上限更高。 - - 本地 worker 自动缩放有意保持保守,并会在主机负载平均值已经很高时 - 退避,因此多个并发 - Vitest 运行默认造成的影响更小。 + - 本地 worker 自动扩缩有意保守,并且在主机平均负载已经很高时会回退, + 因此多个并发 + Vitest 运行默认会造成更少影响。 - 基础 Vitest 配置将项目/配置文件标记为 - `forceRerunTriggers`,以便测试 - wiring 变更时 changed-mode rerun 仍保持正确。 - - 配置会在受支持主机上保持启用 `OPENCLAW_VITEST_FS_MODULE_CACHE`; - 如果你想为直接 profiling 指定一个显式缓存位置,请设置 `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`。 + `forceRerunTriggers`,因此当测试 + 接线变更时,changed-mode 重跑仍保持正确。 + - 配置会在受支持的 + 主机上保持启用 `OPENCLAW_VITEST_FS_MODULE_CACHE`;如果你想为直接性能分析使用 + 一个明确的缓存位置,请设置 `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`。 - `pnpm test:perf:imports` 会启用 Vitest 导入耗时报告以及 - import-breakdown 输出。 - - `pnpm test:perf:imports:changed` 会把同一 profiling 视图限定到 + 导入分解输出。 + - `pnpm test:perf:imports:changed` 会将同一性能分析视图限制到 自 `origin/main` 以来变更的文件。 - 分片计时数据会写入 `.artifacts/vitest-shard-timings.json`。 - 全配置运行使用配置路径作为键;include-pattern CI - 分片会追加分片名称,以便分别跟踪过滤后的分片。 - - 当某个热点测试仍把大部分时间花在启动导入上时, - 请把重型依赖放在狭窄的本地 `*.runtime.ts` seam 后面,并 - 直接 mock 该 seam,而不是 deep-import 运行时 helper 只为把它们传给 `vi.mock(...)`。 - - `pnpm test:perf:changed:bench -- --ref ` 会比较路由后的 - `test:changed` 与该已提交 diff 的原生根项目路径,并打印 wall time 以及 macOS max RSS。 - - `pnpm test:perf:changed:bench -- --worktree` 会通过把 changed file list 路由到 - `scripts/test-projects.mjs` 和根 Vitest 配置,对当前 - dirty tree 做基准测试。 + 整配置运行使用配置路径作为键;include-pattern CI + 分片会追加分片名称,因此可以单独跟踪过滤后的分片。 + - 当某个热点测试仍然把大部分时间花在启动导入上时, + 请把重型依赖放在窄范围本地 `*.runtime.ts` 衔接层后面,并 + 直接 mock 该衔接层,而不是仅仅为了通过 `vi.mock(...)` + 传递它们就深度导入运行时辅助函数。 + - `pnpm test:perf:changed:bench -- --ref ` 会对比已提交 + 差异中路由后的 `test:changed` 和原生根项目路径, + 并打印墙钟时间以及 macOS 最大 RSS。 + - `pnpm test:perf:changed:bench -- --worktree` 会对当前 + 脏工作树进行基准测试,方法是将变更文件列表通过 + `scripts/test-projects.mjs` 和根 Vitest 配置路由。 - `pnpm test:perf:profile:main` 会为 - Vitest/Vite 启动和 transform 开销写入 main-thread CPU profile。 - - `pnpm test:perf:profile:runner` 会在禁用文件并行的情况下,为 - 单元套件写入 runner CPU+heap profiles。 + Vitest/Vite 启动和转换开销写入主线程 CPU profile。 + - `pnpm test:perf:profile:runner` 会为 + 禁用文件并行的单元套件写入运行器 CPU+heap profile。 @@ -417,208 +425,255 @@ Telegram kind 的 payload 形状: ### 稳定性(Gateway 网关) - 命令:`pnpm test:stability:gateway` -- 配置:`vitest.gateway.config.ts`,强制使用一个 worker +- 配置:`vitest.gateway.config.ts`,强制为一个 worker - 范围: - - 默认启动一个启用 diagnostics 的真实 loopback Gateway 网关 - - 通过 diagnostic event path 驱动合成 gateway message、memory 和 large-payload churn + - 启动一个真实的 loopback Gateway 网关,并默认启用诊断 + - 通过诊断事件路径驱动合成 Gateway 网关消息、记忆和大载荷抖动 - 通过 Gateway 网关 WS RPC 查询 `diagnostics.stability` - - 覆盖 diagnostic stability bundle persistence helpers - - 断言 recorder 保持有界,合成 RSS 样本低于压力预算,并且每会话队列深度会排空回零 + - 覆盖诊断稳定性包持久化辅助函数 + - 断言记录器保持有界、合成 RSS 样本保持在压力预算内,并且每会话队列深度回落到零 - 预期: - - CI 安全且无需密钥 - - 用于 stability-regression 后续处理的窄车道,不能替代完整 Gateway 网关套件 + - CI 安全且不需要密钥 + - 用于稳定性回归跟进的窄通道,不是完整 Gateway 网关套件的替代品 -### E2E(Gateway 网关 smoke) +### E2E(Gateway 网关冒烟) - 命令:`pnpm test:e2e` - 配置:`vitest.e2e.config.ts` - 文件:`src/**/*.e2e.test.ts`、`test/**/*.e2e.test.ts`,以及 `extensions/` 下的内置插件 E2E 测试 - 运行时默认值: - - 使用 Vitest `threads`,并设置 `isolate: false`,与仓库其余部分一致。 + - 使用 Vitest `threads` 和 `isolate: false`,与仓库其余部分一致。 - 使用自适应 worker(CI:最多 2 个,本地:默认 1 个)。 - - 默认以 silent 模式运行,以减少控制台 I/O 开销。 + - 默认以静默模式运行,以减少控制台 I/O 开销。 - 有用的覆盖项: - `OPENCLAW_E2E_WORKERS=` 用于强制 worker 数量(上限为 16)。 - `OPENCLAW_E2E_VERBOSE=1` 用于重新启用详细控制台输出。 - 范围: - 多实例 Gateway 网关端到端行为 - - WebSocket/HTTP 表面、node pairing,以及更重的网络功能 + - WebSocket/HTTP 表面、节点配对和更重的网络行为 - 预期: - - 在 CI 中运行(当 pipeline 中启用时) + - 在 CI 中运行(当流水线中启用时) - 不需要真实密钥 - - 比单元测试有更多移动部件(可能更慢) + - 比单元测试有更多活动部件(可能更慢) -### E2E:OpenShell 后端 smoke +### E2E:OpenShell 后端冒烟 - 命令:`pnpm test:e2e:openshell` - 文件:`extensions/openshell/src/backend.e2e.test.ts` - 范围: - - 通过 Docker 在主机上启动一个隔离的 OpenShell gateway + - 通过 Docker 在主机上启动一个隔离的 OpenShell Gateway 网关 - 从临时本地 Dockerfile 创建一个沙箱 - 通过真实的 `sandbox ssh-config` + SSH exec 运行 OpenClaw 的 OpenShell 后端 - - 通过沙箱 fs bridge 验证 remote-canonical filesystem 行为 + - 通过沙箱 fs 桥验证远程规范化文件系统行为 - 预期: - - 仅 opt-in;不是默认 `pnpm test:e2e` 运行的一部分 - - 需要本地 `openshell` CLI 和可用的 Docker daemon - - 使用隔离的 `HOME` / `XDG_CONFIG_HOME`,然后销毁测试 gateway 和沙箱 -- 有用的覆盖项: - - `OPENCLAW_E2E_OPENSHELL=1` 用于在手动运行更广的 e2e 套件时启用该测试 - - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` 用于指向非默认 CLI 二进制或 wrapper script + - 仅按需启用;不是默认 `pnpm test:e2e` 运行的一部分 + - 需要本地 `openshell` CLI 和可用的 Docker 守护进程 + - 使用隔离的 `HOME` / `XDG_CONFIG_HOME`,然后销毁测试 Gateway 网关和沙箱 +- 实用覆盖项: + - `OPENCLAW_E2E_OPENSHELL=1`,用于在手动运行更广的 e2e 套件时启用该测试 + - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell`,用于指向非默认 CLI 二进制文件或包装脚本 -### Live(真实提供商 + 真实模型) +### 实时(真实提供商 + 真实模型) - 命令:`pnpm test:live` - 配置:`vitest.live.config.ts` -- 文件:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下的内置插件 live 测试 -- 默认值:由 `pnpm test:live` **启用**(设置 `OPENCLAW_LIVE_TEST=1`) +- 文件:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下内置插件的实时测试 +- 默认:由 `pnpm test:live` **启用**(设置 `OPENCLAW_LIVE_TEST=1`) - 范围: - - “这个提供商/模型在 _今天_ 使用真实凭证是否真的能工作?” - - 捕获提供商格式变更、tool-calling quirks、auth 问题和 rate limit 行为 + - “这个提供商/模型在 _今天_ 使用真实凭证时是否实际可用?” + - 捕获提供商格式变化、工具调用差异、认证问题和速率限制行为 - 预期: - - 设计上不保证 CI 稳定(真实网络、真实提供商策略、配额、中断) - - 会产生成本 / 使用 rate limits - - 优先运行收窄后的子集,而不是“全部” -- Live 运行会 source `~/.profile` 以获取缺失的 API keys。 -- 默认情况下,live 运行仍会隔离 `HOME`,并把配置/auth material 复制到临时测试 home 中,因此单元 fixture 无法修改你的真实 `~/.openclaw`。 -- 仅当你有意需要 live 测试使用你的真实 home 目录时,才设置 `OPENCLAW_LIVE_USE_REAL_HOME=1`。 -- `pnpm test:live` 现在默认使用更安静的模式:它保留 `[live] ...` progress output,但抑制额外的 `~/.profile` notice,并静音 gateway bootstrap logs/Bonjour chatter。如果你想恢复完整启动日志,请设置 `OPENCLAW_LIVE_TEST_QUIET=0`。 -- API key 轮换(特定于提供商):设置逗号/分号格式的 `*_API_KEYS`,或设置 `*_API_KEY_1`、`*_API_KEY_2`(例如 `OPENAI_API_KEYS`、`ANTHROPIC_API_KEYS`、`GEMINI_API_KEYS`),也可以通过 `OPENCLAW_LIVE_*_KEY` 做 per-live 覆盖;测试会在 rate limit 响应时重试。 + - 设计上不保证 CI 稳定(真实网络、真实提供商策略、配额、故障) + - 会产生费用 / 使用速率限制额度 + - 优先运行收窄后的子集,而不是“一切” +- 实时运行会加载 `~/.profile`,以获取缺失的 API 密钥。 +- 默认情况下,实时运行仍会隔离 `HOME`,并将配置/认证材料复制到临时测试主目录中,因此单元测试夹具无法修改你的真实 `~/.openclaw`。 +- 仅在你有意需要实时测试使用真实主目录时,才设置 `OPENCLAW_LIVE_USE_REAL_HOME=1`。 +- `pnpm test:live` 现在默认使用更安静的模式:它保留 `[live] ...` 进度输出,但抑制额外的 `~/.profile` 提示,并静音 Gateway 网关引导日志/Bonjour 杂音。如果你想恢复完整启动日志,请设置 `OPENCLAW_LIVE_TEST_QUIET=0`。 +- API 密钥轮换(提供商特定):用逗号/分号格式设置 `*_API_KEYS`,或设置 `*_API_KEY_1`、`*_API_KEY_2`(例如 `OPENAI_API_KEYS`、`ANTHROPIC_API_KEYS`、`GEMINI_API_KEYS`),也可以通过 `OPENCLAW_LIVE_*_KEY` 设置单次实时覆盖;测试会在收到速率限制响应时重试。 - 进度/Heartbeat 输出: - - Live 套件现在会向 stderr 发出进度行,因此即使 Vitest 控制台捕获处于安静状态,长时间的提供商调用也能看到仍在活动。 - - `vitest.live.config.ts` 会禁用 Vitest 控制台拦截,因此提供商/Gateway 网关进度行会在 live 运行期间立即流式输出。 - - 使用 `OPENCLAW_LIVE_HEARTBEAT_MS` 调整 direct-model heartbeats。 - - 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 gateway/probe heartbeats。 + - 实时套件现在会向 stderr 输出进度行,因此即使 Vitest 控制台捕获较安静,长时间的提供商调用也能看到活动状态。 + - `vitest.live.config.ts` 会禁用 Vitest 控制台拦截,因此在实时运行期间,提供商/Gateway 网关进度行会立即流式输出。 + - 用 `OPENCLAW_LIVE_HEARTBEAT_MS` 调整直接模型 Heartbeat。 + - 用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 Gateway 网关/探测 Heartbeat。 ## 我应该运行哪个套件? -使用此决策表: +使用这个决策表: - 编辑逻辑/测试:运行 `pnpm test`(如果改动很多,也运行 `pnpm test:coverage`) - 触及 Gateway 网关网络 / WS 协议 / 配对:添加 `pnpm test:e2e` -- 调试“我的 bot 挂了”/ 提供商特定故障 / 工具调用:运行收窄范围的 `pnpm test:live` +- 调试“我的 bot 挂了” / 提供商特定失败 / 工具调用:运行收窄后的 `pnpm test:live` -## 实时(触及网络的)测试 +## 实时(触网)测试 -对于实时模型矩阵、CLI 后端冒烟测试、ACP 冒烟测试、Codex app-server 测试框架,以及所有媒体提供商实时测试(Deepgram、BytePlus(国际版)、ComfyUI、图像、音乐、视频、媒体测试框架)以及实时运行的凭证处理,请参阅[实时测试套件](/zh-CN/help/testing-live)。有关专用的更新和插件验证清单,请参阅[更新和插件测试](/zh-CN/help/testing-updates-plugins)。 +有关实时模型矩阵、CLI 后端冒烟测试、ACP 冒烟测试、Codex 应用服务器 +harness,以及所有媒体提供商实时测试(Deepgram、BytePlus、ComfyUI、图像、 +音乐、视频、媒体 harness)以及实时运行的凭证处理,请参阅 +[测试实时套件](/zh-CN/help/testing-live)。有关专用更新和 +插件验证检查清单,请参阅 +[更新和插件测试](/zh-CN/help/testing-updates-plugins)。 -## Docker 运行器(可选的“可在 Linux 中运行”检查) +## Docker 运行器(可选的“在 Linux 中可用”检查) 这些 Docker 运行器分为两类: -- 实时模型运行器:`test:docker:live-models` 和 `test:docker:live-gateway` 仅在仓库 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`、 +- 实时模型运行器:`test:docker:live-models` 和 `test:docker:live-gateway` 只在仓库 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` 镜像。裸镜像只是用于安装/更新/插件依赖 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` 可在不构建或运行 Docker 的情况下打印加权 lane 清单,或使用 `node scripts/test-docker-all.mjs --plan-json` 打印所选 lane、package/image 需求和凭证的 CI 计划。 -- `Package Acceptance` 是 GitHub 原生的 package gate,用于验证“这个可安装 tarball 是否能作为产品正常工作?”它会从 `source=npm`、`source=ref`、`source=url` 或 `source=artifact` 解析一个候选 package,将其作为 `package-under-test` 上传,然后针对该精确 tarball 运行可复用的 Docker E2E lane,而不是重新打包所选 ref。Profile 按覆盖范围排序:`smoke`、`package`、`product` 和 `full`。有关 package/update/plugin 合约、已发布升级幸存者矩阵、发布默认值和失败分诊,请参阅[更新和插件测试](/zh-CN/help/testing-updates-plugins)。 -- 构建和发布检查会在 tsdown 后运行 `scripts/check-cli-bootstrap-imports.mjs`。该防护会从 `dist/entry.js` 和 `dist/cli/run-main.js` 遍历静态构建图;如果命令分发前的启动流程导入了 Commander、prompt UI、undici 或日志等 package 依赖,它会失败;它还会让内置 Gateway 网关运行 chunk 保持在预算内,并拒绝已知冷启动 Gateway 网关路径的静态导入。打包后的 CLI 冒烟测试还覆盖 root help、onboard help、doctor help、Status、配置 schema 和模型列表命令。 -- Package Acceptance 旧版兼容性封顶于 `2026.4.25`(包括 `2026.4.25-beta.*`)。在该截止版本之前,测试框架仅容忍已发布 package 的元数据缺口:省略的私有 QA inventory 条目、缺失的 `gateway install --wrapper`、tarball 派生 git fixture 中缺失的 patch 文件、缺失的持久化 `update.channel`、旧版插件安装记录位置、缺失的 marketplace 安装记录持久化,以及 `plugins update` 期间的配置元数据迁移。对于 `2026.4.25` 之后的 package,这些路径都是严格失败。 + `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` 镜像。裸镜像只是用于安装/更新/插件依赖通道的 Node/Git 运行器;这些通道会挂载预构建 tarball。功能镜像会将同一个 tarball 安装到 `/app`,用于已构建应用的功能通道。Docker 通道定义位于 `scripts/lib/docker-e2e-scenarios.mjs`;规划器逻辑位于 `scripts/lib/docker-e2e-plan.mjs`;`scripts/test-docker-all.mjs` 执行选定计划。聚合器使用加权本地调度器:`OPENCLAW_DOCKER_ALL_PARALLELISM` 控制进程槽位,而资源上限会防止繁重的实时、npm-install 和多服务通道同时全部启动。如果单个通道比当前上限更重,调度器仍可在池为空时启动它,并让它独占运行,直到再次有容量可用。默认值为 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 秒打印状态,将成功通道计时存储在 `.artifacts/docker-tests/lane-timings.json`,并在后续运行中使用这些计时优先启动更长的通道。使用 `OPENCLAW_DOCKER_ALL_DRY_RUN=1` 可在不构建或运行 Docker 的情况下打印加权通道清单,或使用 `node scripts/test-docker-all.mjs --plan-json` 打印所选通道、包/镜像需求和凭证的 CI 计划。 +- `Package Acceptance` 是 GitHub 原生的包门禁,用于检查“这个可安装 tarball 作为产品是否可用?”它会从 `source=npm`、`source=ref`、`source=url` 或 `source=artifact` 解析一个候选包,将其上传为 `package-under-test`,然后针对该精确 tarball 运行可复用 Docker E2E 通道,而不是重新打包所选 ref。Profile 按覆盖广度排序:`smoke`、`package`、`product` 和 `full`。有关包/更新/插件契约、已发布升级幸存者矩阵、发布默认值和失败分诊,请参阅[更新和插件测试](/zh-CN/help/testing-updates-plugins)。 +- 构建和发布检查会在 tsdown 之后运行 `scripts/check-cli-bootstrap-imports.mjs`。该守卫会从 `dist/entry.js` 和 `dist/cli/run-main.js` 遍历静态构建图,并在命令分派前的启动导入了 Commander、prompt UI、undici 或日志等包依赖时失败;它还会确保打包后的 Gateway 网关运行 chunk 保持在预算内,并拒绝静态导入已知的冷 Gateway 网关路径。打包 CLI 冒烟测试还覆盖根帮助、onboard 帮助、doctor 帮助、Status、配置 schema 和模型列表命令。 +- Package Acceptance 旧版兼容性上限为 `2026.4.25`(包括 `2026.4.25-beta.*`)。在该截止点之前,harness 仅容忍已发布包的元数据缺口:省略的私有 QA 清单条目、缺失的 `gateway install --wrapper`、tarball 派生 git 夹具中缺失的补丁文件、缺失的持久化 `update.channel`、旧版插件安装记录位置、缺失的 marketplace 安装记录持久化,以及 `plugins update` 期间的配置元数据迁移。对于 `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:published-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 home(如果运行未收窄,则挂载所有支持的 home),然后在运行前将它们复制到容器 home 中,使外部 CLI OAuth 可以刷新 token,而不会修改主机 auth store: +实时模型 Docker 运行器还只会绑定挂载所需的 CLI 认证主目录(或在运行未收窄时挂载所有受支持的主目录),然后在运行前将它们复制到容器主目录中,这样外部 CLI OAuth 就能刷新令牌,而不会修改主机认证存储: - 直接模型:`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 测试框架冒烟测试:`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 app-server harness 烟测:`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 源码检出通道。它有意不属于包 Docker 发布通道,因为 npm tarball 会省略 QA Lab。 -- Open WebUI 实时冒烟测试:`pnpm test:docker:openwebui`(脚本:`scripts/e2e/openwebui-docker.sh`) +- 可观测性烟测:`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,通过环境变量引用的新手引导配置 OpenAI,并默认配置 Telegram,运行 Doctor,然后运行一次模拟的 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`,验证持久化的渠道和插件更新后工作正常,然后切回包 `stable` 并检查更新状态。 -- 升级幸存者冒烟测试:`pnpm test:docker:upgrade-survivor` 会把打包后的 OpenClaw tarball 安装到一个脏旧用户 fixture 上,该 fixture 包含智能体、渠道配置、插件 allowlist、过期的插件依赖状态,以及已有工作区/会话文件。它会运行包更新和非交互式 Doctor,不需要实时提供商或渠道密钥,然后启动 local loopback Gateway 网关,并检查配置/状态保留以及启动/Status 预算。 -- 已发布升级幸存者冒烟测试:`pnpm test:docker:published-upgrade-survivor` 默认安装 `openclaw@latest`,写入真实的现有用户文件,用内置命令配方配置该基线,验证生成的配置,将该已发布安装更新到候选 tarball,运行非交互式 Doctor,写入 `.artifacts/upgrade-survivor/summary.json`,然后启动 local loopback Gateway 网关,并检查已配置意图、状态保留、启动、`/healthz`、`/readyz` 和 RPC Status 预算。使用 `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC` 覆盖一个基线,使用 `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS` 让聚合调度器展开精确基线,并使用 `OPENCLAW_UPGRADE_SURVIVOR_SCENARIOS` 展开问题形状的 fixture,例如 `reported-issues`;Package Acceptance 会将这些公开为 `published_upgrade_survivor_baseline`、`published_upgrade_survivor_baselines` 和 `published_upgrade_survivor_scenarios`。 -- 会话运行时上下文冒烟测试:`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 工作流的 `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` 时,在本地运行脚本且不要设置该环境变量。 -- 智能体删除共享工作区 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 引用和 frame 元数据。 -- OpenAI Responses web_search 最小 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 拒绝并检查原始详情出现在 Gateway 网关日志中。 -- MCP 渠道桥接(已写入种子的 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 网关 + stdio MCP 子进程在隔离 cron 和一次性 subagent 运行后被拆除):`pnpm test:docker:cron-mcp-cleanup`(脚本:`scripts/e2e/cron-mcp-cleanup-docker.sh`) -- 插件(本地路径、`file:`、带 hoisted 依赖的 npm registry、git 移动引用、ClawHub kitchen-sink、marketplace 更新,以及 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 服务器。 -- 插件更新无变化冒烟测试:`pnpm test:docker:plugin-update`(脚本:`scripts/e2e/plugin-update-unchanged-docker.sh`) -- 配置重载元数据冒烟测试:`pnpm test:docker:config-reload`(脚本:`scripts/e2e/config-reload-source-docker.sh`) -- 插件:`pnpm test:docker:plugins` 覆盖本地路径、`file:`、带 hoisted 依赖的 npm registry、git 移动引用、ClawHub fixture、marketplace 更新,以及 Claude-bundle 启用/检查的安装/更新冒烟测试。`pnpm test:docker:plugin-update` 覆盖已安装插件的无变化更新行为。 +- Npm tarball 新手引导/渠道/智能体烟测:`pnpm test:docker:npm-onboard-channel-agent` 会在 Docker 中全局安装打包后的 OpenClaw tarball,通过 env-ref 新手引导配置 OpenAI,并默认配置 Telegram,运行 Doctor,然后运行一次模拟的 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`,验证持久化的渠道和插件更新后工作正常,然后切回包 `stable` 并检查更新 Status。 +- 升级幸存者烟测:`pnpm test:docker:upgrade-survivor` 会把打包后的 OpenClaw tarball 安装到一个脏的旧用户 fixture 上,其中包含智能体、渠道配置、插件允许列表、过期的插件依赖状态,以及现有工作区/会话文件。它会在没有实时提供商或渠道密钥的情况下运行包更新和非交互式 Doctor,然后启动一个 loopback Gateway 网关,并检查配置/状态保留以及启动/Status 预算。 +- 已发布版本升级幸存者烟测:`pnpm test:docker:published-upgrade-survivor` 默认安装 `openclaw@latest`,播种真实的现有用户文件,用内置命令配方配置该基线,验证生成的配置,将该已发布安装更新到候选 tarball,运行非交互式 Doctor,写入 `.artifacts/upgrade-survivor/summary.json`,然后启动一个 loopback Gateway 网关,并检查已配置意图、状态保留、启动、`/healthz`、`/readyz` 和 RPC Status 预算。用 `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC` 覆盖一个基线,用 `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS` 让聚合调度器展开精确基线,并用 `OPENCLAW_UPGRADE_SURVIVOR_SCENARIOS` 展开 issue 形状的 fixture,例如 `reported-issues`;Package Acceptance 将这些暴露为 `published_upgrade_survivor_baseline`、`published_upgrade_survivor_baselines` 和 `published_upgrade_survivor_scenarios`。 +- 会话运行时上下文烟测:`pnpm test:docker:session-runtime-context` 会验证隐藏运行时上下文转录持久化,以及 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 缓存。Update 烟测默认使用 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` 时,在本地不带该环境变量运行脚本。 +- 智能体删除共享工作区 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 ref 和 frame 元数据。 +- OpenAI Responses web_search 最小 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 拒绝,并检查原始详情出现在 Gateway 网关日志中。 +- MCP 渠道桥接(已播种 Gateway 网关 + stdio bridge + 原始 Claude notification-frame 烟测):`pnpm test:docker:mcp-channels`(脚本:`scripts/e2e/mcp-channels-docker.sh`) +- Pi bundle MCP 工具(真实 stdio MCP 服务器 + 嵌入式 Pi profile 允许/拒绝烟测):`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`) +- 插件(对本地路径、`file:`、带提升依赖的 npm registry、git moving refs、ClawHub kitchen-sink、marketplace 更新,以及 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 服务器。 +- 插件更新不变烟测:`pnpm test:docker:plugin-update`(脚本:`scripts/e2e/plugin-update-unchanged-docker.sh`) +- 配置重载元数据烟测:`pnpm test:docker:config-reload`(脚本:`scripts/e2e/config-reload-source-docker.sh`) +- 插件:`pnpm test:docker:plugins` 覆盖对本地路径、`file:`、带提升依赖的 npm registry、git moving refs、ClawHub fixture、marketplace 更新,以及 Claude-bundle 启用/检查的安装/更新烟测。`pnpm test:docker:plugin-update` 覆盖已安装插件的不变更新行为。 -要手动预构建并复用共享功能镜像: +如需手动预构建并复用共享功能镜像: ```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 运行器还会以只读方式 bind-mount 当前检出,并在容器内将其暂存到临时工作目录。这会保持运行时镜像精简,同时仍然针对你的精确本地源码/配置运行 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 通道缩小或排除 Gateway 网关实时覆盖时,也要传入 `OPENCLAW_LIVE_GATEWAY_*`。`test:docker:openwebui` 是更高层的兼容性冒烟测试:它会启动一个启用了 OpenAI 兼容 HTTP 端点的 OpenClaw Gateway 网关容器,启动一个固定版本的 Open WebUI 容器并连接到该 Gateway 网关,通过 Open WebUI 登录,验证 `/api/models` 暴露 `openclaw/default`,然后通过 Open WebUI 的 `/api/chat/completions` 代理发送真实聊天请求。第一次运行可能明显更慢,因为 Docker 可能需要拉取 Open WebUI 镜像,且 Open WebUI 可能需要完成自己的冷启动设置。此通道需要可用的实时模型密钥,`OPENCLAW_PROFILE_FILE`(默认是 `~/.profile`)是在 Docker 化运行中提供该密钥的主要方式。成功运行会打印一个小型 JSON payload,例如 `{ "ok": true, "model": "openclaw/default", ... }`。`test:docker:mcp-channels` 有意保持确定性,不需要真实 Telegram、Discord 或 iMessage 账号。它会启动一个已写入种子的 Gateway 网关容器,启动第二个容器来生成 `openclaw mcp serve`,然后验证路由后的会话发现、transcript 读取、附件元数据、实时事件队列行为、出站发送路由,以及通过真实 stdio MCP bridge 发送的 Claude 风格渠道 + 权限通知。通知检查会直接检查原始 stdio MCP frame,因此该冒烟测试验证的是 bridge 实际发出的内容,而不只是某个特定客户端 SDK 恰好暴露的内容。`test:docker:pi-bundle-mcp-tools` 是确定性的,不需要实时模型密钥。它会构建仓库 Docker 镜像,在容器内启动真实 stdio MCP 探针服务器,通过嵌入式 Pi bundle MCP 运行时物化该服务器,执行工具,然后验证 `coding` 和 `messaging` 保留 `bundle-mcp` 工具,而 `minimal` 和 `tools.deny: ["bundle-mcp"]` 会过滤它们。`test:docker:cron-mcp-cleanup` 是确定性的,不需要实时模型密钥。它会启动带有真实 stdio MCP 探针服务器的已写入种子 Gateway 网关,运行一个隔离 cron 轮次和一个 `/subagents spawn` 一次性子轮次,然后验证 MCP 子进程在每次运行后退出。 +live 模型 Docker 运行器还会以只读方式绑定挂载当前检出,并 +将其暂存到容器内的临时工作目录。这能让运行时镜像保持精简, +同时仍然针对你的确切本地源代码/配置运行 Vitest。 +暂存步骤会跳过大型本地专用缓存和应用构建输出,例如 +`.pnpm-store`、`.worktrees`、`__openclaw_vitest__`,以及应用本地的 `.build` 或 +Gradle 输出目录,这样 Docker live 运行就不会花费数分钟复制 +特定于机器的工件。 +它们还会设置 `OPENCLAW_SKIP_CHANNELS=1`,这样 Gateway 网关 live 探针就不会在 +容器内启动真实的 Telegram/Discord 等渠道 worker。 +`test:docker:live-models` 仍会运行 `pnpm test:live`,因此当你需要从该 Docker lane +缩小或排除 Gateway 网关 live 覆盖范围时,也要传入 +`OPENCLAW_LIVE_GATEWAY_*`。 +`test:docker:openwebui` 是更高层级的兼容性冒烟测试:它会启动一个 +启用了 OpenAI 兼容 HTTP 端点的 OpenClaw Gateway 网关容器, +再启动一个固定版本的 Open WebUI 容器连接到该 Gateway 网关,通过 +Open WebUI 登录,验证 `/api/models` 暴露 `openclaw/default`,然后通过 +Open WebUI 的 `/api/chat/completions` 代理发送真实聊天请求。 +首次运行可能会明显更慢,因为 Docker 可能需要拉取 +Open WebUI 镜像,且 Open WebUI 可能需要完成自己的冷启动设置。 +此 lane 需要可用的 live 模型密钥,而 `OPENCLAW_PROFILE_FILE` +(默认是 `~/.profile`)是在 Docker 化运行中提供它的主要方式。 +成功运行会打印一个小型 JSON payload,例如 `{ "ok": true, "model": +"openclaw/default", ... }`。 +`test:docker:mcp-channels` 是有意设计为确定性的,并且不需要真实的 +Telegram、Discord 或 iMessage 账户。它会启动一个已播种的 Gateway 网关 +容器,启动第二个容器并在其中生成 `openclaw mcp serve`,然后 +验证路由后的对话发现、transcript 读取、附件元数据、 +live 事件队列行为、出站发送路由,以及通过真实 stdio MCP bridge 发送的 Claude 风格渠道 + +权限通知。通知检查会直接检查原始 stdio MCP frame,因此该冒烟测试验证的是 +bridge 实际发出的内容,而不只是某个特定客户端 SDK 恰好暴露的内容。 +`test:docker:pi-bundle-mcp-tools` 是确定性的,并且不需要 live +模型密钥。它会构建仓库 Docker 镜像,在容器内启动一个真实的 stdio MCP 探针服务器, +通过嵌入式 Pi bundle MCP 运行时实例化该服务器, +执行工具,然后验证 `coding` 和 `messaging` 会保留 +`bundle-mcp` 工具,而 `minimal` 和 `tools.deny: ["bundle-mcp"]` 会过滤它们。 +`test:docker:cron-mcp-cleanup` 是确定性的,并且不需要 live 模型 +密钥。它会启动一个带有真实 stdio MCP 探针服务器的已播种 Gateway 网关,运行一个 +隔离的 cron turn 和一个 `/subagents spawn` 一次性子 turn,然后验证 +MCP 子进程会在每次运行后退出。 -手动 ACP 自然语言线程冒烟测试(不属于 CI): +手动 ACP 自然语言 thread 冒烟测试(不在 CI 中): - `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel ...` -- 保留此脚本用于回归/调试工作流。ACP 线程路由验证以后可能还会需要它,因此不要删除。 +- 保留此脚本用于回归/调试工作流。ACP thread 路由验证可能再次需要它,因此不要删除它。 有用的环境变量: - `OPENCLAW_CONFIG_DIR=...`(默认:`~/.openclaw`)挂载到 `/home/node/.openclaw` - `OPENCLAW_WORKSPACE_DIR=...`(默认:`~/.openclaw/workspace`)挂载到 `/home/node/.openclaw/workspace` -- `OPENCLAW_PROFILE_FILE=...`(默认:`~/.profile`)挂载到 `/home/node/.profile`,并在运行测试前 source -- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` 仅验证从 `OPENCLAW_PROFILE_FILE` source 的环境变量,使用临时配置/工作区目录,并且不挂载外部 CLI 认证 +- `OPENCLAW_PROFILE_FILE=...`(默认:`~/.profile`)挂载到 `/home/node/.profile`,并在运行测试前加载 +- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` 仅验证从 `OPENCLAW_PROFILE_FILE` 加载的环境变量,使用临时配置/工作区目录且不挂载外部 CLI 认证 - `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...`(默认:`~/.cache/openclaw/docker-cli-tools`)挂载到 `/home/node/.npm-global`,用于 Docker 内缓存的 CLI 安装 - `$HOME` 下的外部 CLI 认证目录/文件会以只读方式挂载到 `/host-auth...` 下,然后在测试开始前复制到 `/home/node/...` - 默认目录:`.minimax` - 默认文件:`~/.codex/auth.json`、`~/.codex/config.toml`、`.claude.json`、`~/.claude/.credentials.json`、`~/.claude/settings.json`、`~/.claude/settings.local.json` - - 缩小范围的提供商运行只会挂载从 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` 推断出的所需目录/文件 - - 可用 `OPENCLAW_DOCKER_AUTH_DIRS=all`、`OPENCLAW_DOCKER_AUTH_DIRS=none` 或类似 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` 的逗号列表手动覆盖 + - 缩小范围的提供商运行只挂载从 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` 推断出的所需目录/文件 + - 使用 `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=...` 用于在容器内筛选提供商 -- `OPENCLAW_SKIP_DOCKER_BUILD=1` 用于在不需要重新构建的重跑中复用现有 `openclaw:local-live` 镜像 -- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 用于确保凭证来自配置文件存储(而不是环境) -- `OPENCLAW_OPENWEBUI_MODEL=...` 用于选择 Gateway 网关为 Open WebUI 冒烟测试暴露的模型 -- `OPENCLAW_OPENWEBUI_PROMPT=...` 用于覆盖 Open WebUI 冒烟测试使用的 nonce 检查提示词 +- `OPENCLAW_SKIP_DOCKER_BUILD=1` 用于在不需要重新构建的重复运行中复用现有 `openclaw:local-live` 镜像 +- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 用于确保凭据来自配置文件存储(而不是环境) +- `OPENCLAW_OPENWEBUI_MODEL=...` 用于选择 Gateway 网关为 Open WebUI 冒烟测试公开的模型 +- `OPENCLAW_OPENWEBUI_PROMPT=...` 用于覆盖 Open WebUI 冒烟测试使用的随机值检查提示词 - `OPENWEBUI_IMAGE=...` 用于覆盖固定的 Open WebUI 镜像标签 ## 文档完整性检查 文档编辑后运行文档检查:`pnpm check:docs`。 -当你还需要页内标题检查时,运行完整的 Mintlify 锚点验证:`pnpm docs:check-links:anchors`。 +当你也需要页内标题检查时,运行完整的 Mintlify 锚点验证:`pnpm docs:check-links:anchors`。 -## 离线回归测试(CI 安全) +## 离线回归(CI 安全) -这些是不使用真实提供商的“真实流水线”回归测试: +这些是不使用真实提供商的“真实流水线”回归: -- Gateway 网关工具调用(mock OpenAI,真实 Gateway 网关 + Agent loop):`src/gateway/gateway.test.ts`(用例:"runs a mock OpenAI tool call end-to-end via gateway agent loop") +- Gateway 网关工具调用(模拟 OpenAI,真实 Gateway 网关 + Agent loop):`src/gateway/gateway.test.ts`(用例:"runs a mock OpenAI tool call end-to-end via gateway agent loop") - Gateway 网关向导(WS `wizard.start`/`wizard.next`,写入配置 + 强制认证):`src/gateway/gateway.test.ts`(用例:"runs wizard over ws and writes auth token config") -## 智能体可靠性评测(Skills) +## 智能体可靠性评估(Skills) -我们已经有一些像“智能体可靠性评测”一样运行的 CI 安全测试: +我们已经有一些 CI 安全测试,其行为类似“智能体可靠性评估”: -- 通过真实 Gateway 网关 + Agent loop 进行 mock 工具调用(`src/gateway/gateway.test.ts`)。 -- 验证会话接线和配置效果的端到端向导流程(`src/gateway/gateway.test.ts`)。 +- 通过真实 Gateway 网关 + Agent loop 进行模拟工具调用(`src/gateway/gateway.test.ts`)。 +- 端到端向导流程,用于验证会话接线和配置效果(`src/gateway/gateway.test.ts`)。 -Skills 仍缺失的内容(见 [Skills](/zh-CN/tools/skills)): +Skills 仍然缺失的内容(见 [Skills](/zh-CN/tools/skills)): -- **决策:** 当提示中列出 Skills 时,智能体是否会选择正确的 Skill(或避开无关的 Skill)? -- **合规:** 智能体是否会在使用前读取 `SKILL.md` 并遵循必需步骤/参数? -- **工作流契约:** 断言工具顺序、会话历史延续和沙箱边界的多轮场景。 +- **决策:**当提示词中列出 Skills 时,智能体是否会选择正确的 skill(或避开不相关的)? +- **合规:**智能体是否在使用前读取 `SKILL.md`,并遵循必需步骤/参数? +- **工作流契约:**多轮场景,用于断言工具顺序、会话历史继承和沙箱边界。 -未来评测应优先保持确定性: +未来评估应优先保持确定性: -- 使用 mock 提供商的场景运行器,用于断言工具调用 + 顺序、Skill 文件读取和会话接线。 -- 一小组面向 Skill 的场景(使用与避开、门控、提示注入)。 -- 可选的 live 评测(选择加入、通过环境变量门控)仅在 CI 安全套件就位后再添加。 +- 一个使用模拟提供商的场景运行器,用于断言工具调用 + 顺序、skill 文件读取和会话接线。 +- 一小套聚焦 skill 的场景(使用与避免、门控、提示注入)。 +- 可选的实时评估(选择加入、由环境变量门控)仅在 CI 安全套件就位后再添加。 -## 契约测试(插件和渠道形态) +## 契约测试(插件和渠道结构) -契约测试会验证每个已注册插件和渠道是否符合其接口契约。它们会遍历所有发现的插件,并运行一组形态和行为断言。默认的 `pnpm test` 单元测试通道会有意跳过这些共享边界和冒烟测试文件;当你触碰共享渠道或提供商表面时,请显式运行契约命令。 +契约测试会验证每个已注册的插件和渠道是否符合其 +接口契约。它们会遍历所有已发现的插件,并运行一组 +结构和行为断言。默认的 `pnpm test` 单元测试通道会有意 +跳过这些共享边界和冒烟测试文件;当你触碰共享渠道或提供商表面时, +请显式运行契约命令。 ### 命令 @@ -630,22 +685,22 @@ Skills 仍缺失的内容(见 [Skills](/zh-CN/tools/skills)): 位于 `src/channels/plugins/contracts/*.contract.test.ts`: -- **plugin** - 基本插件形态(id、name、capabilities) +- **plugin** - 基本插件结构(id、名称、能力) - **setup** - 设置向导契约 - **session-binding** - 会话绑定行为 - **outbound-payload** - 消息载荷结构 - **inbound** - 入站消息处理 -- **actions** - 渠道动作处理器 +- **actions** - 渠道操作处理器 - **threading** - 线程 ID 处理 -- **directory** - 目录/成员列表 API -- **group-policy** - 群组策略执行 +- **directory** - 目录/成员名单 API +- **group-policy** - 群组策略强制执行 ### 提供商 Status 契约 位于 `src/plugins/contracts/*.contract.test.ts`。 - **status** - 渠道 Status 探测 -- **registry** - 插件注册表形态 +- **registry** - 插件注册表结构 ### 提供商契约 @@ -654,35 +709,35 @@ Skills 仍缺失的内容(见 [Skills](/zh-CN/tools/skills)): - **auth** - 认证流程契约 - **auth-choice** - 认证选择/选取 - **catalog** - 模型目录 API -- **discovery** - 插件发现 +- **discovery** - 插件设备发现 - **loader** - 插件加载 - **runtime** - 提供商运行时 -- **shape** - 插件形态/接口 +- **shape** - 插件结构/接口 - **wizard** - 设置向导 ### 何时运行 - 更改 plugin-sdk 导出或子路径后 - 添加或修改渠道或提供商插件后 -- 重构插件注册或发现后 +- 重构插件注册或设备发现后 -契约测试会在 CI 中运行,并且不需要真实 API key。 +契约测试会在 CI 中运行,不需要真实 API key。 -## 添加回归测试(指南) +## 添加回归(指南) -当你修复在 live 中发现的提供商/模型问题时: +当你修复在实时测试中发现的提供商/模型问题时: -- 尽可能添加 CI 安全的回归测试(mock/stub 提供商,或捕获精确的请求形态转换) -- 如果它本质上只能 live 测试(速率限制、认证策略),保持 live 测试范围窄,并通过环境变量选择加入 -- 优先定位能捕获 bug 的最小层级: - - 提供商请求转换/重放 bug → 直接模型测试 - - Gateway 网关会话/历史/工具流水线 bug → Gateway 网关 live 冒烟测试或 CI 安全的 Gateway 网关 mock 测试 -- SecretRef 遍历防护栏: - - `src/secrets/exec-secret-ref-id-parity.test.ts` 会从注册表元数据(`listSecretTargetRegistryEntries()`)中为每个 SecretRef 类派生一个采样目标,然后断言带遍历片段的 exec id 会被拒绝。 - - 如果你在 `src/secrets/target-registry-data.ts` 中添加新的 `includeInPlan` SecretRef 目标族,请更新该测试中的 `classifyTargetClass`。该测试会有意在未分类目标 id 上失败,因此新类不能被静默跳过。 +- 如果可能,添加 CI 安全回归(模拟/桩提供商,或捕获精确的请求结构转换) +- 如果它本质上只能实时测试(速率限制、认证策略),请保持实时测试范围狭窄,并通过环境变量选择加入 +- 优先针对能捕获该 bug 的最小层: + - 提供商请求转换/重放 bug → 直接的模型测试 + - Gateway 网关会话/历史/工具流水线 bug → Gateway 网关实时冒烟测试或 CI 安全的 Gateway 网关模拟测试 +- SecretRef 遍历护栏: + - `src/secrets/exec-secret-ref-id-parity.test.ts` 会从注册表元数据(`listSecretTargetRegistryEntries()`)为每个 SecretRef 类派生一个采样目标,然后断言包含遍历片段的 exec id 会被拒绝。 + - 如果你在 `src/secrets/target-registry-data.ts` 中添加新的 `includeInPlan` SecretRef 目标系列,请更新该测试中的 `classifyTargetClass`。该测试会有意在未分类目标 id 上失败,因此新类不能被静默跳过。 ## 相关 -- [Testing live](/zh-CN/help/testing-live) +- [实时测试](/zh-CN/help/testing-live) - [更新和插件测试](/zh-CN/help/testing-updates-plugins) - [CI](/zh-CN/ci)