环境与调试
测试
OpenClaw 有三个 Vitest 套件(单元/集成、e2e、live)以及 Docker 运行器。本页介绍每个套件覆盖的内容、给定工作流应运行哪个命令、live 测试如何发现凭证,以及如何为真实世界的提供商/模型 bug 添加回归测试。
快速开始
大多数时候:
- 完整门禁(推送前预期执行):
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 - 在迭代单个失败时,优先先运行目标测试。
- 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
测试临时目录
对测试拥有的临时目录使用 test/helpers/temp-dir.ts 中的共享辅助函数,这样所有权明确,清理也保留在测试生命周期中:
const tempDirs = useAutoCleanupTempDirTracker(afterEach); it("uses a temp workspace", () => { const workspace = tempDirs.make("openclaw-example-"); // use workspace});useAutoCleanupTempDirTracker(afterEach) 有意不暴露手动清理方法 - Vitest 拥有每个测试后的清理。较旧的底层辅助函数(makeTempDir、cleanupTempDirs、createTempDirTracker)仍然存在,用于尚未迁移的测试;避免新增使用它们,也避免新增裸 fs.mkdtemp* 调用,除非某个测试明确验证原始临时目录行为。当确实需要裸临时目录时,添加可审计的允许注释并说明原因:
// openclaw-temp-dir: allow verifies raw fs cleanup behaviorconst workspace = fs.mkdtempSync(prefix);node scripts/report-test-temp-creations.mjs 会报告新增 diff 行中的新裸临时目录创建和新手动共享辅助函数用法,而不会阻塞现有清理风格。它遵循与 scripts/changed-lanes.mjs 相同的测试路径分类,并跳过共享辅助函数实现本身。check:changed 会对已更改的测试路径运行此报告,作为仅警告的 CI 信号(GitHub 警告注解,而非失败)。
Live 和 Docker/Parallels 工作流
调试真实提供商/模型时(需要真实凭证):
- Live 套件(模型 + Gateway 网关工具/图像探针):
pnpm test:live - 静默定位一个 live 文件:
pnpm test:live -- src/agents/models.profiles.live.test.ts - 运行时性能报告:调度
OpenClaw Performance,使用live_openai_candidate=true进行一次真实的openai/gpt-5.5agent 轮次,或使用deep_profile=true获取 Kova CPU/堆/跟踪工件。当配置了CLAWGRIT_REPORTS_TOKEN时,每日计划运行会将 mock-provider、deep-profile 和 GPT 5.5 通道工件发布到openclaw/clawgrit-reports。mock-provider 报告还包括源码级 Gateway 网关启动、内存、插件压力、重复 fake-model hello-loop 和 CLI 启动指标。 - 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都会调用可复用的 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及其计划/发布调用方中。
- 每个选中的模型都会运行一个文本轮次加一个小型文件读取式探针。元数据声明支持
- Native Codex plugins 绑定聊天冒烟测试:
pnpm test:docker:live-codex-bind- 针对 Codex app-server 路径运行 Docker live 通道,使用
/codex bind绑定一个合成 Slack 私信,执行/codex fast和/codex permissions,然后验证普通回复和图像附件通过原生插件绑定而不是 ACP 路由。
- 针对 Codex app-server 路径运行 Docker live 通道,使用
- Codex app-server harness 冒烟测试:
pnpm test:docker:live-codex-harness- 通过插件拥有的 Codex app-server harness 运行 Gateway 网关 agent 轮次,验证
/codex status和/codex models,并默认执行图像、cron MCP、子智能体和 Guardian 探针。在隔离其他失败时,可用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,否则它会在子智能体探针后退出。
- 通过插件拥有的 Codex app-server harness 运行 Gateway 网关 agent 轮次,验证
- Codex 按需安装冒烟测试:
pnpm test:docker:codex-on-demand- 在 Docker 中安装打包后的 OpenClaw tarball,运行 OpenAI API-key 新手引导,并验证 Codex 插件以及
@openai/codex依赖已按需下载到托管 npm 项目根目录中。
- 在 Docker 中安装打包后的 OpenClaw tarball,运行 OpenAI API-key 新手引导,并验证 Codex 插件以及
- Live 插件工具依赖冒烟测试:
pnpm test:docker:live-plugin-tool- 打包一个带真实
slugify依赖的 fixture 插件,通过npm-pack:安装它,验证托管 npm 项目根目录下的依赖,然后要求 live OpenAI 模型调用插件工具并返回隐藏 slug。
- 打包一个带真实
- Crestodian 救援命令冒烟测试:
pnpm test:live:crestodian-rescue-channel- 对消息渠道救援命令界面的可选双保险检查。执行
/crestodian status,排队一个持久模型更改,回复/crestodian yes,并验证审计/配置写入路径。
- 对消息渠道救援命令界面的可选双保险检查。执行
- Crestodian 规划器 Docker 冒烟测试:
pnpm test:docker:crestodian-planner- 在无配置容器中运行 Crestodian,
PATH上带一个假的 Claude CLI,并验证模糊规划器 fallback 会转换为已审计的类型化配置写入。
- 在无配置容器中运行 Crestodian,
- Crestodian 首次运行 Docker 冒烟测试:
pnpm test:docker:crestodian-first-run- 从空 OpenClaw 状态目录开始,验证现代 onboard Crestodian 入口点,应用 setup/model/agent/Discord 插件 + SecretRef 写入,验证配置,并验证审计条目。QA Lab 中也通过
pnpm openclaw qa suite --scenario crestodian-ring-zero-setup覆盖相同的 Ring 0 设置路径。
- 从空 OpenClaw 状态目录开始,验证现代 onboard Crestodian 入口点,应用 setup/model/agent/Discord 插件 + SecretRef 写入,验证配置,并验证审计条目。QA Lab 中也通过
- Moonshot/Kimi 成本冒烟测试:设置
MOONSHOT_API_KEY后,运行openclaw models list --provider moonshot --json,然后针对moonshot/kimi-k2.6运行隔离的openclaw agent --local --session-id live-kimi-cost --message 'Reply exactly: KIMI_LIVE_OK' --thinking off --json。验证 JSON 报告 Moonshot/K2.6,并且 assistant 转录存储规范化的usage.cost。
QA 专用运行器
当你需要 QA-lab 真实感时,这些命令位于主测试套件旁边。
CI 在专用工作流中运行 QA Lab。Agentic parity 嵌套在 QA-Lab - All Lanes 和发布验证中,而不是独立的 PR 工作流。广泛验证应使用 Full Release Validation,并设置 rerun_group=qa-parity,或使用 release-checks QA 组。稳定版/默认发布检查将详尽的 live/Docker soak 保留在 run_release_soak=true 后面;full profile 会强制启用 soak。QA-Lab - All Lanes 每晚在 main 上运行,也可通过手动调度运行,并将 mock parity 通道、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 加快速 Matrix 和 Telegram 通道,使用 mock-openai/gpt-5.5 进行发布传输检查,以保持确定性并避免普通提供商插件启动。这些 live 传输 Gateway 网关会禁用记忆搜索;记忆行为仍由 QA parity 套件覆盖。
完整发布 live media 分片使用 ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04,其中已经包含 ffmpeg 和 ffprobe。Docker live 模型/后端分片使用共享的 ghcr.io/openclaw/openclaw-live-test:<sha> 镜像,该镜像会为选定提交构建一次,然后用 OPENCLAW_SKIP_DOCKER_BUILD=1 拉取它,而不是在每个分片中重新构建。
pnpm openclaw qa suite- 直接在主机上运行由仓库支持的 QA 场景。
- 为所选场景集写入顶层
qa-evidence.json、qa-suite-summary.json和qa-suite-report.md工件,包括混合流程、Vitest 和 Playwright 场景选择。 - 当由
pnpm openclaw qa run --qa-profile <profile>调度时,会在同一个qa-evidence.json中嵌入所选分类法配置的评分卡。smoke-ci写入精简证据(evidenceMode: "slim",没有逐条execution)。release覆盖精选的发布就绪切片;all选择每个活动成熟度类别,并在需要完整评分卡工件时面向显式 QA Profile Evidence 工作流调度。 - 默认使用隔离的 Gateway 网关 worker 并行运行多个所选场景。
qa-channel默认并发为 4(受所选场景数量限制)。使用--concurrency <count>调整 worker 数量,或使用--concurrency 1进入较旧的串行通道。 - 任何场景失败时以非零状态退出。使用
--allow-failures生成工件但不返回失败退出码。 - 支持提供商模式
live-frontier、mock-openai和aimock。aimock会启动一个本地 AIMock 支持的提供商服务器,用于实验性的 fixture 和协议 mock 覆盖,而不会替代场景感知的mock-openai通道。
pnpm openclaw qa coverage --match <query>- 搜索场景 ID、标题、表面、覆盖 ID、文档引用、代码引用、插件和提供商要求, 然后打印匹配的套件目标。
- 当你知道被触及的行为或文件路径,但不知道最小场景时,在 QA Lab 运行前使用它。仅作为建议 - 仍需根据正在变更的行为选择 mock、live、 Multipass、Matrix 或传输证明。
pnpm test:plugins:kitchen-sink-live- 通过 QA Lab 运行实时 OpenAI Kitchen Sink 插件考验。
安装外部 Kitchen Sink 包,验证插件 SDK 表面清单,探测
/healthz和/readyz,记录 Gateway 网关 CPU/RSS 证据,运行一个实时 OpenAI 轮次,并检查对抗性诊断。需要实时 OpenAI 凭证,例如OPENAI_API_KEY。 在已水合的 Testbox 会话中,如果存在openclaw-testbox-envhelper, 它会自动加载 Testbox 实时凭证配置。
- 通过 QA Lab 运行实时 OpenAI Kitchen Sink 插件考验。
安装外部 Kitchen Sink 包,验证插件 SDK 表面清单,探测
pnpm test:gateway:cpu-scenarios- 运行 Gateway 网关启动基准测试,加上一小组 mock QA Lab 场景包
(
channel-chat-baseline、memory-failure-fallback、gateway-restart-inflight-run),并在.artifacts/gateway-cpu-scenarios/下写入组合 CPU 观察摘要。 - 默认只标记持续的高 CPU 观察(
--cpu-core-warn,默认0.9;--hot-wall-warn-ms,默认30000),因此短暂启动峰值会记录为指标, 而不会看起来像持续数分钟的 Gateway 网关占满回归。 - 针对已构建的
dist工件运行;当 checkout 还没有新鲜运行时输出时, 先运行构建。
- 运行 Gateway 网关启动基准测试,加上一小组 mock QA Lab 场景包
(
pnpm openclaw qa suite --runner multipass- 在一次性 Multipass Linux VM 内运行相同的 QA 套件,保留与
qa suite相同的场景选择和提供商/模型标志。 - 实时运行会转发适合 guest 的 QA 凭证输入:基于环境变量的提供商密钥、
QA 实时提供商配置路径,以及存在时的
CODEX_HOME。 - 输出目录必须保持在仓库根目录下,以便 guest 能通过挂载的工作区写回。
- 在
.artifacts/qa-e2e/...下写入常规 QA 报告和摘要,以及 Multipass 日志。
- 在一次性 Multipass Linux VM 内运行相同的 QA 套件,保留与
pnpm qa:lab:up- 启动由 Docker 支持的 QA 站点,用于操作员风格的 QA 工作。
pnpm test:docker:npm-onboard-channel-agent- 从当前 checkout 构建 npm tarball,在 Docker 中全局安装它, 运行非交互式 OpenAI API 密钥新手引导,默认配置 Telegram, 验证打包的插件运行时无需启动依赖修复即可加载,运行 Doctor, 并针对 mock 的 OpenAI 端点运行一个本地智能体轮次。
- 使用
OPENCLAW_NPM_ONBOARD_CHANNEL=discord通过 Discord 运行同一条打包安装通道。
pnpm test:docker:session-runtime-context- 为嵌入式运行时上下文转录运行确定性的已构建应用 Docker smoke。
验证隐藏的 OpenClaw 运行时上下文会作为非显示自定义消息保留,
而不是泄漏到可见用户轮次中,然后种入一个受影响的损坏会话 JSONL,
并验证
openclaw doctor --fix会将其重写到活动分支且创建备份。
- 为嵌入式运行时上下文转录运行确定性的已构建应用 Docker smoke。
验证隐藏的 OpenClaw 运行时上下文会作为非显示自定义消息保留,
而不是泄漏到可见用户轮次中,然后种入一个受影响的损坏会话 JSONL,
并验证
pnpm test:docker:npm-telegram-live- 在 Docker 中安装 OpenClaw 包候选版本,运行已安装包的新手引导, 通过已安装的 CLI 配置 Telegram,然后复用实时 Telegram QA 通道, 并将该已安装包作为 SUT Gateway 网关。
- 该包装器只从 checkout 挂载
qa-labharness 源码;已安装包拥有dist、openclaw/plugin-sdk和内置插件运行时,因此该通道不会把当前 checkout 的插件混入被测包。 - 默认值为
OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta;设置OPENCLAW_NPM_TELEGRAM_PACKAGE_TGZ=/path/to/openclaw-current.tgz或OPENCLAW_CURRENT_PACKAGE_TGZ,可测试已解析的本地 tarball, 而不是从 registry 安装。 - 默认使用
OPENCLAW_NPM_TELEGRAM_RTT_SAMPLES=20在qa-evidence.json中发出重复 RTT 计时。覆盖OPENCLAW_NPM_TELEGRAM_RTT_SAMPLES、OPENCLAW_NPM_TELEGRAM_RTT_TIMEOUT_MS或OPENCLAW_NPM_TELEGRAM_RTT_MAX_FAILURES可调整运行。OPENCLAW_NPM_TELEGRAM_RTT_CHECKS接受逗号分隔的 Telegram QA 检查 ID 列表用于采样;未设置时,默认具备 RTT 能力的检查为telegram-mentioned-message-reply。 - 使用与
pnpm openclaw qa telegram相同的 Telegram 环境变量凭证或 Convex 凭证来源。对于 CI/发布自动化,设置OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex,以及OPENCLAW_QA_CONVEX_SITE_URL和一个角色 secret。如果OPENCLAW_QA_CONVEX_SITE_URL和一个 Convex 角色 secret 出现在 CI 中, Docker 包装器会自动选择 Convex。 - 包装器会在 Docker 构建/安装工作前,在主机上验证 Telegram 或 Convex
凭证环境变量。仅在刻意调试凭证前设置时才设置
OPENCLAW_NPM_TELEGRAM_SKIP_CREDENTIAL_PREFLIGHT=1。 OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintainer仅对该通道覆盖共享的OPENCLAW_QA_CREDENTIAL_ROLE。当选择 Convex 凭证且未设置角色时, 包装器在 CI 中使用ci,在 CI 外使用maintainer。- GitHub Actions 将此通道公开为手动维护者工作流
NPM Telegram Beta E2E。它不会在合并时运行。该工作流使用qa-live-shared环境和 Convex CI 凭证租约。
- GitHub Actions 还公开了
Package Acceptance,用于针对一个候选包进行旁路产品证明。 它接受 Git ref、已发布的 npm spec、HTTPS tarball URL 加 SHA-256、 可信 URL 策略,或来自另一次运行的 tarball 工件 (source=ref|npm|url|trusted-url|artifact),将规范化后的openclaw-current.tgz上传为package-under-test,然后使用smoke、package、product、full或custom通道配置运行现有 Docker E2E 调度器。设置telegram_mode=mock-openai或live-frontier,可针对同一个package-under-test工件运行 Telegram QA 工作流。- 最新 beta 产品证明:
gh workflow run package-acceptance.yml --ref main \ -f source=npm \ -f package_spec=openclaw@beta \ -f suite_profile=product \ -f telegram_mode=mock-openai- 精确 tarball URL 证明需要摘要,并使用公共 URL 安全策略:
gh workflow run package-acceptance.yml --ref main \ -f source=url \ -f package_url=https://registry.npmjs.org/openclaw/-/openclaw-VERSION.tgz \ -f package_sha256=<sha256> \ -f suite_profile=package- 企业/私有 tarball 镜像使用显式的可信来源策略:
gh workflow run package-acceptance.yml --ref main \ -f source=trusted-url \ -f trusted_source_id=enterprise-artifactory \ -f package_url=https://packages.example.internal:8443/artifactory/openclaw/openclaw-VERSION.tgz \ -f package_sha256=<sha256> \ -f suite_profile=packagesource=trusted-url 会从可信工作流 ref 读取 .github/package-trusted-sources.json,
且不接受 URL 凭证或工作流输入的私有网络绕过。如果命名策略声明了 bearer
认证,请配置固定的 OPENCLAW_TRUSTED_PACKAGE_TOKEN secret。
- 工件证明会从另一次 Actions 运行下载 tarball 工件:
gh workflow run package-acceptance.yml --ref main \ -f source=artifact \ -f artifact_run_id=<run-id> \ -f artifact_name=<artifact-name> \ -f suite_profile=smoke-
pnpm test:docker:plugins- 在 Docker 中打包并安装当前 OpenClaw 构建,启动已配置 OpenAI 的 Gateway 网关,然后通过配置编辑启用内置频道/插件。
- 验证设置发现会让未配置的可下载插件保持缺席,第一次配置后的 Doctor 修复会显式安装每个缺失的可下载插件,并且第二次重启不会运行隐藏的依赖修复。
- 还会安装一个已知的较旧 npm 基线,在运行
openclaw update --tag <candidate>前启用 Telegram,并验证候选版本的更新后 Doctor 会清理旧版插件依赖残留,而无需 harness 侧 postinstall 修复。
-
pnpm test:parallels:npm-update-
在 Parallels guest 上运行原生打包安装更新 smoke。每个所选平台先安装请求的基线包, 然后在同一个 guest 中运行已安装的
openclaw update命令,并验证已安装版本、 更新状态、Gateway 网关就绪状态和一个本地智能体轮次。 -
迭代单个 guest 时使用
--platform macos、--platform windows或--platform linux。使用--json获取摘要工件路径和逐通道状态。 -
OpenAI 通道默认使用
openai/gpt-5.5进行实时智能体轮次证明。 传入--model <provider/model>或设置OPENCLAW_PARALLELS_OPENAI_MODEL可验证另一个 OpenAI 模型。 -
用主机超时包装长时间本地运行,避免 Parallels 传输停滞耗尽剩余测试窗口:
bash timeout --foreground 150m pnpm test:parallels:npm-update -- --jsontimeout --foreground 90m pnpm test:parallels:npm-update -- --platform windows --json -
该脚本会在
/tmp/openclaw-parallels-npm-update.*下写入嵌套通道日志。 在假定外层包装器挂起前,先检查windows-update.log、macos-update.log或linux-update.log。 -
Windows 更新在冷 guest 上可能会花 10 到 15 分钟执行更新后 Doctor 和包更新工作;只要嵌套 npm 调试日志仍在推进,这仍然是健康状态。
-
不要将此聚合包装器与单独的 Parallels macOS、Windows 或 Linux smoke 通道并行运行。它们共享 VM 状态,可能会在快照恢复、包服务或 guest Gateway 网关状态上冲突。
-
更新后证明会运行常规内置插件表面,因为语音、图像生成和媒体理解等能力 facade 会通过内置运行时 API 加载,即使智能体轮次本身只检查简单文本响应。
-
-
pnpm openclaw qa aimock- 仅启动本地 AIMock 提供商服务器,用于直接协议冒烟测试。
-
pnpm openclaw qa matrix- 针对一次性 Docker 后端的 Tuwunel homeserver 运行 Matrix 实时 QA 通道。仅支持源代码检出;打包安装不随附
qa-lab。 - 完整 CLI、profile/scenario 目录、环境变量和产物布局: Matrix QA.
- 针对一次性 Docker 后端的 Tuwunel homeserver 运行 Matrix 实时 QA 通道。仅支持源代码检出;打包安装不随附
-
pnpm openclaw qa telegram- 使用来自环境变量的 driver 和 SUT bot token,针对真实私有群组运行 Telegram 实时 QA 通道。
- 需要
OPENCLAW_QA_TELEGRAM_GROUP_ID、OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN和OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN。群组 id 必须是数字形式的 Telegram chat id。 - 支持
--credential-source convex以使用共享池化凭证。默认使用 env 模式,或设置OPENCLAW_QA_CREDENTIAL_SOURCE=convex以启用池化租约。 - 默认覆盖 canary、mention gating、command addressing、
/status、bot 到 bot 的被提及回复,以及核心原生命令回复。mock-openai默认还覆盖确定性回复链和 Telegram 最终消息流式回归。使用--list-scenarios查看可选探针,例如session_status。 - 任一 scenario 失败时以非零退出。使用
--allow-failures可生成产物但不返回失败退出码。 - 需要同一私有群组中的两个不同 bot,且 SUT bot 需要公开 Telegram username。
- 为了稳定观察 bot 到 bot 通信,请在
@BotFather中为两个 bot 启用 Bot-to-Bot Communication Mode,并确保 driver bot 可以观察群组 bot 流量。 - 在
.artifacts/qa-e2e/...下写入 Telegram QA 报告、摘要和qa-evidence.json。回复类 scenario 包含从 driver 发送请求到观测到 SUT 回复的 RTT。
Mantis Telegram Live 是围绕此通道的 PR 证据封装器。它使用 Convex 租借的 Telegram 凭证运行候选 ref,在 Crabbox 桌面浏览器中渲染已脱敏的 QA 报告/证据包,录制 MP4 证据,生成运动裁剪后的 GIF,上传产物包,并在设置了 pr_number 时通过 Mantis GitHub App 发布内联 PR 证据。维护者可以通过 Actions UI 中的 Mantis Scenario(scenario_id: telegram-live)启动它,或直接从 pull request 评论启动:
@openclaw-mantis telegram@openclaw-mantis telegram scenario=telegram-status-command@openclaw-mantis telegram scenarios=telegram-status-command,telegram-mentioned-message-replyMantis Telegram Desktop Proof 是用于 PR 可视化证明的智能体式原生 Telegram Desktop 前后对比封装器。可在 Actions UI 中通过自由格式 instructions 启动,通过 Mantis Scenario(scenario_id: telegram-desktop-proof)启动,或从 PR 评论启动:
@openclaw-mantis telegram desktop proofMantis 智能体会读取 PR,决定哪些 Telegram 可见行为可以证明该变更,在 baseline 和 candidate refs 上运行真实用户 Crabbox Telegram Desktop 证明通道,迭代直到原生 GIF 足够有用,写入配对的 motionPreview manifest,并在设置了 pr_number 时通过 Mantis GitHub App 发布相同的 2 列 GIF 表格。
pnpm openclaw qa mantis telegram-desktop-builder- 租用或复用 Crabbox Linux 桌面,安装原生 Telegram Desktop,使用租借的 Telegram SUT bot token 配置 OpenClaw,启动 Gateway 网关,并从可见的 VNC 桌面录制截图/MP4 证据。
- 默认使用
--credential-source convex,因此 workflow 只需要 Convex broker secret。使用--credential-source env时需提供与pnpm openclaw qa telegram相同的OPENCLAW_QA_TELEGRAM_*变量。 - Telegram Desktop 仍然需要用户登录/profile。bot token 仅用于配置 OpenClaw。可使用
--telegram-profile-archive-env <name>提供 base64.tgzprofile 归档,或使用--keep-lease并通过 VNC 手动登录一次。 - 在输出目录下写入
mantis-telegram-desktop-builder-report.md、mantis-telegram-desktop-builder-summary.json、telegram-desktop-builder.png和telegram-desktop-builder.mp4。
实时传输通道共享一个标准契约,避免新增传输协议发生漂移;每个通道的覆盖矩阵位于
QA overview - Live transport coverage。
qa-channel 是宽泛的合成套件,不属于该矩阵。
通过 Convex 共享 Telegram 凭证(v1)
当为实时传输 QA 启用 --credential-source convex(或 OPENCLAW_QA_CREDENTIAL_SOURCE=convex)时,QA lab 会从 Convex 后端的池中获取独占租约,在通道运行期间对该租约发送 Heartbeat,并在关闭时释放租约。该小节名称早于 Discord、Slack 和 WhatsApp 支持;租约契约在不同 kind 之间共享。
参考 Convex 项目脚手架:qa/convex-credential-broker/
必需环境变量:
OPENCLAW_QA_CONVEX_SITE_URL(例如https://your-deployment.convex.site)- 所选角色的一个 secret:
OPENCLAW_QA_CONVEX_SECRET_MAINTAINER用于maintainerOPENCLAW_QA_CONVEX_SECRET_CI用于ci
- 凭证角色选择:
- CLI:
--credential-role maintainer|ci - Env 默认值:
OPENCLAW_QA_CREDENTIAL_ROLE(在 CI 中默认为ci,否则为maintainer)
- CLI:
可选环境变量:
OPENCLAW_QA_CREDENTIAL_LEASE_TTL_MS(默认1200000)OPENCLAW_QA_CREDENTIAL_HEARTBEAT_INTERVAL_MS(默认30000)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允许仅本地开发使用 loopbackhttp://Convex URL。
OPENCLAW_QA_CONVEX_SITE_URL 在正常运行中应使用 https://。
维护者管理命令(池 add/remove/list)明确需要 OPENCLAW_QA_CONVEX_SECRET_MAINTAINER。
面向维护者的 CLI 辅助命令:
pnpm openclaw qa credentials doctorpnpm openclaw qa credentials add --kind telegram --payload-file qa/telegram-credential.jsonpnpm openclaw qa credentials list --kind telegrampnpm openclaw qa credentials remove --credential-id <credential-id>在实时运行前使用 doctor 检查 Convex site URL、broker secrets、endpoint prefix、HTTP timeout 和 admin/list 可达性,且不会打印 secret 值。在脚本和 CI 工具中使用 --json 获取机器可读输出。
默认 endpoint 契约(OPENCLAW_QA_CONVEX_SITE_URL + /qa-credentials/v1)。
请求使用 Authorization: Bearer <role secret> header 进行认证;下面的 body 省略该 header:
POST /acquire- 请求:
{ kind, ownerId, actorRole, leaseTtlMs, heartbeatIntervalMs } - 成功:
{ status: "ok", credentialId, leaseToken, payload, leaseTtlMs?, heartbeatIntervalMs? } - 耗尽/可重试:
{ status: "error", code: "POOL_EXHAUSTED" | "NO_CREDENTIAL_AVAILABLE", ... }
- 请求:
POST /payload-chunk- 请求:
{ kind, ownerId, actorRole, credentialId, leaseToken, index } - 成功:
{ status: "ok", index, data }
- 请求:
POST /heartbeat- 请求:
{ kind, ownerId, actorRole, credentialId, leaseToken, leaseTtlMs } - 成功:
{ status: "ok" }(或空2xx)
- 请求:
POST /release- 请求:
{ kind, ownerId, actorRole, credentialId, leaseToken } - 成功:
{ status: "ok" }(或空2xx)
- 请求:
POST /admin/add(仅 maintainer secret)- 请求:
{ kind, actorId, payload, note?, status? } - 成功:
{ status: "ok", credential }
- 请求:
POST /admin/remove(仅 maintainer secret)- 请求:
{ credentialId, actorId } - 成功:
{ status: "ok", changed, credential } - 活跃租约保护:
{ status: "error", code: "LEASE_ACTIVE", ... }
- 请求:
POST /admin/list(仅 maintainer secret)- 请求:
{ kind?, status?, includePayload?, limit? } - 成功:
{ status: "ok", credentials, count }
- 请求:
Telegram kind 的 payload 形状:
{ groupId: string, driverToken: string, sutToken: string }groupId必须是数字形式的 Telegram chat id 字符串。admin/add会针对kind: "telegram"校验此形状并拒绝格式错误的 payload。
Telegram 真实用户 kind 的 payload 形状:
{ groupId: string, sutToken: string, testerUserId: string, testerUsername: string, telegramApiId: string, telegramApiHash: string, tdlibDatabaseEncryptionKey: string, tdlibArchiveBase64: string, tdlibArchiveSha256: string, desktopTdataArchiveBase64: string, desktopTdataArchiveSha256: string }groupId、testerUserId和telegramApiId必须是数字字符串。tdlibArchiveSha256和desktopTdataArchiveSha256必须是 SHA-256 十六进制字符串。kind: "telegram-user"保留给 Mantis Telegram Desktop proof workflow。通用 QA Lab 通道不得获取它。
Broker 校验的多渠道 payload:
- Discord:
{ guildId: string, channelId: string, driverBotToken: string, sutBotToken: string, sutApplicationId: string, voiceChannelId?: string } - WhatsApp:
{ driverPhoneE164: string, sutPhoneE164: string, driverAuthArchiveBase64: string, sutAuthArchiveBase64: string, groupJid?: string }
Slack 通道也可以从池中租用,但 Slack payload 校验当前位于 Slack QA runner 中,而不是 broker 中。Slack 行使用
{ channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string }。
向 QA 添加渠道
新增渠道适配器的架构和 scenario-helper 名称位于
QA overview - Adding a channel。
最低要求:在共享 qa-lab host seam 上实现传输 runner,为共享 scenario 添加 adapterFactory,在插件清单中声明 qaRunners,挂载为 openclaw qa <runner>,并在 qa/scenarios/ 下编写 scenario。
测试套件(在哪里运行什么)
可以把这些套件理解为“真实度递增”(同时不稳定性/成本也递增)。
单元 / 集成(默认)
- 命令:
pnpm test - 配置:非定向运行使用
vitest.full-*.config.tsshard 集合,并可能将多项目 shard 展开为按项目划分的配置以进行并行调度 - 文件:
src/**/*.test.ts、packages/**/*.test.ts和test/**/*.test.ts下的核心/单元清单;UI 单元测试在专用unit-uishard 中运行 - 范围:
- 纯单元测试
- 进程内集成测试(Gateway 网关 auth、routing、tooling、parsing、config)
- 已知 bug 的确定性回归测试
- 期望:
- 在 CI 中运行
- 不需要真实 key
- 应快速且稳定
- Resolver 和 public-surface loader 测试必须使用生成的微型插件 fixture 证明广义
api.js和runtime-api.jsfallback 行为,而不是使用真实内置插件源 API。真实插件 API 加载应放在插件自有的 contract/integration 套件中。
原生依赖策略:
- 默认测试安装会跳过可选的原生 Discord opus 构建。Discord 语音使用内置
libopus-wasm,并且@discordjs/opus在allowBuilds中保持禁用,这样本地测试和 Testbox 通道不会编译原生 addon。 - 在
libopus-wasmbenchmark repo 中比较原生 opus 性能,而不是在默认 OpenClaw install/test 循环中比较。不要在默认allowBuilds中将@discordjs/opus设为true;这会导致无关的 install/test 循环编译原生代码。
项目、shard 和作用域通道
- 未指定目标的
pnpm test会运行十三个更小的分片配置(core-unit-fast、core-unit-src、core-unit-security、core-unit-ui、core-unit-support、core-support-boundary、core-tooling、core-contracts、core-bundled、core-runtime、agentic、auto-reply、extensions),而不是一个巨大的原生根项目进程。这会降低高负载机器上的峰值 RSS,并避免 auto-reply/插件工作让无关套件饥饿。 pnpm test --watch仍使用原生根vitest.config.ts项目图,因为多分片 watch 循环并不实用。pnpm test、pnpm test:watch和pnpm test:perf:imports会先通过有作用域的 lane 路由显式文件/目录目标,因此pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts可以避免支付完整根项目启动成本。- 默认情况下,
pnpm test:changed会把已变更的 git 路径展开为廉价的有作用域 lane:直接测试编辑、同级*.test.ts文件、显式源映射,以及本地导入图依赖项。配置/设置/包编辑不会宽泛运行测试,除非你显式使用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 <target>。仅发布元数据的版本号递增会运行有针对性的版本/配置/根依赖检查,并带有一个 guard,用于拒绝顶层 version 字段之外的包变更。- Live Docker ACP harness 编辑会运行聚焦检查:live Docker 凭证脚本的 shell 语法检查,以及 live Docker 调度器 dry-run。只有当 diff 限定为
scripts["test:docker:live-*"]时才会包含package.json变更;依赖、导出、版本和其他包表面编辑仍使用更宽泛的 guard。 - 来自 agents、commands、plugins、auto-reply helper、
plugin-sdk和类似纯工具区域的轻量导入单元测试会路由到unit-fastlane,该 lane 会跳过test/setup-openclaw-runtime.ts;有状态/运行时较重的文件仍留在现有 lane 上。 - 选定的
plugin-sdk和commandshelper 源文件也会把 changed-mode 运行映射到这些轻量 lane 中的显式同级测试,因此 helper 编辑可以避免重新运行该目录的完整重型套件。 auto-reply为顶层 core helper、顶层reply.*集成测试,以及src/auto-reply/reply/**子树提供专用 bucket。CI 还会把 reply 子树进一步拆分为 agent-runner、dispatch 和 commands/state-routing 分片,避免一个导入较重的 bucket 占用完整 Node 尾部。- 常规 PR/main CI 有意跳过内置插件批量扫描和仅发布用的
agentic-plugins分片。完整发布验证会为候选发布版调度单独的Plugin Prerelease子工作流,以运行这些插件较重的套件。
Embedded runner coverage
- 当你更改 message-tool 设备发现输入或压缩运行时 上下文时,请保留两个层级的覆盖。
- 为纯路由和规范化边界添加聚焦的 helper 回归测试。
- 保持嵌入式 runner 集成套件健康:
src/agents/embedded-agent-runner/compact.hooks.test.ts、src/agents/embedded-agent-runner/run.overflow-compaction.test.ts和src/agents/embedded-agent-runner/run.overflow-compaction.loop.test.ts。 - 这些套件会验证有作用域的 id 和压缩行为仍然通过真实的
run.ts/compact.ts路径流动;仅有 helper 测试 不能充分替代这些集成路径。
Vitest pool and isolation defaults
- 基础 Vitest 配置默认使用
threads。 - 共享 Vitest 配置固定为
isolate: false,并在根项目、e2e 和 live 配置中使用 非隔离 runner。 - 根 UI lane 保留其
jsdom设置和 optimizer,但也运行在 共享非隔离 runner 上。 - 每个
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会在显式非 watch Vitest 运行 5 分钟没有 stdout 或 stderr 输出后终止它。设置OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS=0可为 有意静默的调查禁用 watchdog。
Fast local iteration
pnpm changed:lanes会显示一个 diff 触发哪些架构 lane。- pre-commit hook 仅执行格式化。它会重新暂存已格式化文件, 不运行 lint、typecheck 或测试。
- 当你需要智能本地检查门禁时,请在交接或推送前显式运行
pnpm check:changed。 - 默认情况下,
pnpm test:changed会通过廉价的有作用域 lane 路由。仅当智能体 判定某个 harness、配置、包或契约编辑确实需要 更宽的 Vitest 覆盖时,才使用OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed。 pnpm test:max和pnpm test:changed:max保持相同路由 行为,只是 worker 上限更高。- 本地 worker 自动缩放有意保持保守,并会在主机平均负载已经较高时退让, 因此多个并发 Vitest 运行默认会造成更小影响。
- 基础 Vitest 配置将项目/配置文件标记为
forceRerunTriggers,因此当测试接线发生变化时, changed-mode 重新运行仍保持正确。 - 配置会在受支持的主机上保持启用
OPENCLAW_VITEST_FS_MODULE_CACHE; 设置OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path可为直接 profiling 指定一个显式缓存位置。
Perf debugging
pnpm test:perf:imports会启用 Vitest 导入耗时报告以及 导入细分输出。pnpm test:perf:imports:changed会把同一 profiling 视图限定到 自origin/main以来变更的文件。- 分片耗时数据会写入
.artifacts/vitest-shard-timings.json。 整配置运行使用配置路径作为键;include-pattern CI 分片会追加分片名称,以便单独跟踪经过过滤的分片。 - 当某个热点测试仍把大部分时间花在启动导入上时,
请把重型依赖放在窄的本地
*.runtime.ts接缝之后,并 直接 mock 该接缝,而不是 deep-import 运行时 helper 只是为了把它们传给vi.mock(...)。 pnpm test:perf:changed:bench -- --ref <git-ref>会把路由后的test:changed与该已提交 diff 的原生根项目路径进行比较, 并打印墙钟时间以及 macOS 最大 RSS。pnpm test:perf:changed:bench -- --worktree会通过把已变更文件列表路由到scripts/test-projects.mjs和根 Vitest 配置, 对当前脏工作树进行基准测试。pnpm test:perf:profile:main会为 Vitest/Vite 启动和转换开销 写入一个主线程 CPU profile。pnpm test:perf:profile:runner会在禁用文件并行时,为 单元套件写入 runner CPU+heap profile。
稳定性(Gateway 网关)
- 命令:
pnpm test:stability:gateway - 配置:
test/vitest/vitest.gateway.config.ts、test/vitest/vitest.logging.config.ts和test/vitest/vitest.infra.config.ts,每个都强制使用一个 worker - 范围:
- 默认启动一个启用诊断的真实 loopback Gateway 网关
- 通过诊断事件路径驱动合成的 gateway 消息、记忆和大 payload 抖动
- 通过 Gateway 网关 WS RPC 查询
diagnostics.stability - 覆盖诊断稳定性 bundle 持久化 helper
- 断言 recorder 保持有界、合成 RSS 样本保持在压力预算以内,并且每会话队列深度会回落到零
- 预期:
- CI 安全且无需密钥
- 用于稳定性回归跟进的窄 lane,不能替代完整 Gateway 网关套件
E2E(仓库聚合)
- 命令:
pnpm test:e2e - 范围:
- 运行 gateway smoke E2E lane
- 运行 mocked Control UI 浏览器 E2E lane
- 预期:
- CI 安全且无需密钥
- 需要已安装 Playwright Chromium
E2E(gateway smoke)
- 命令:
pnpm test:e2e:gateway - 配置:
test/vitest/vitest.e2e.config.ts - 文件:
src/**/*.e2e.test.ts、test/**/*.e2e.test.ts,以及extensions/下的内置插件 E2E 测试 - 运行时默认值:
- 使用 Vitest
threads和isolate: false,与仓库其余部分一致。 - 使用自适应 worker(CI:最多 2 个,本地:默认 1 个)。
- 默认以 silent 模式运行,以减少控制台 I/O 开销。
- 使用 Vitest
- 常用覆盖项:
OPENCLAW_E2E_WORKERS=<n>强制指定 worker 数量(上限为 16)。OPENCLAW_E2E_VERBOSE=1重新启用详细控制台输出。
- 范围:
- 多实例 gateway 端到端行为
- WebSocket/HTTP 表面、节点配对和更重的网络
- 预期:
- 在 CI 中运行(当流水线中启用时)
- 不需要真实密钥
- 比单元测试有更多活动部件(可能更慢)
E2E(Control UI mocked browser)
- 命令:
pnpm test:ui:e2e - 配置:
test/vitest/vitest.ui-e2e.config.ts - 文件:
ui/src/**/*.e2e.test.ts - 范围:
- 启动 Vite Control UI
- 通过 Playwright 驱动真实 Chromium 页面
- 用确定性的浏览器内 mock 替换 Gateway 网关 WebSocket
- 预期:
- 作为
pnpm test:e2e的一部分在 CI 中运行 - 不需要真实 Gateway 网关、智能体或提供商密钥
- 必须存在浏览器依赖(
pnpm --dir ui exec playwright install chromium)
- 作为
E2E:OpenShell backend smoke
- 命令:
pnpm test:e2e:openshell - 文件:
extensions/openshell/src/backend.e2e.test.ts - 范围:
- 复用一个活动的本地 OpenShell gateway
- 从临时本地 Dockerfile 创建一个沙箱
- 通过真实
sandbox ssh-config+ SSH exec 演练 OpenClaw 的 OpenShell backend - 通过沙箱 fs bridge 验证远程规范文件系统行为
- 预期:
- 仅可选启用;不属于默认
pnpm test:e2e运行 - 需要本地
openshellCLI 以及可工作的 Docker daemon - 需要活动的本地 OpenShell gateway 及其配置源
- 使用隔离的
HOME/XDG_CONFIG_HOME,然后销毁测试沙箱
- 仅可选启用;不属于默认
- 常用覆盖项:
OPENCLAW_E2E_OPENSHELL=1在手动运行更宽泛的 e2e 套件时启用该测试OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell指向非默认 CLI 二进制文件或 wrapper 脚本OPENCLAW_E2E_OPENSHELL_CONFIG_HOME=/path/to/config将已注册 gateway 配置暴露给隔离测试OPENCLAW_E2E_OPENSHELL_HOST_IP=172.18.0.1覆盖主机策略 fixture 使用的 Docker gateway IP
Live(真实提供商 + 真实模型)
- 命令:
pnpm test:live - 配置:
test/vitest/vitest.live.config.ts - 文件:
src/**/*.live.test.ts、test/**/*.live.test.ts,以及extensions/下的内置插件实时测试 - 默认:由
pnpm test:live启用(设置OPENCLAW_LIVE_TEST=1) - 范围:
- “这个提供商/模型在_今天_使用真实凭据是否真的可用?”
- 捕获提供商格式变更、工具调用差异、鉴权问题和速率限制行为
- 预期:
- 按设计并非 CI 稳定(真实网络、真实提供商策略、配额、中断)
- 会产生成本/使用速率限制额度
- 优先运行缩小范围的子集,而不是“全部”
- 实时运行使用已导出的 API key 和已暂存的鉴权配置文件。
- 默认情况下,实时运行仍会隔离
HOME,并将配置/鉴权材料复制到临时测试主目录中,因此单元测试夹具不能修改你的真实~/.openclaw。 - 仅当你有意需要实时测试使用你的真实主目录时,才设置
OPENCLAW_LIVE_USE_REAL_HOME=1。 pnpm test:live默认使用更安静的模式:它保留[live] ...进度输出,并静默 Gateway 网关启动日志/Bonjour 噪声。如果你想恢复完整启动日志,请设置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设置单次实时覆盖;测试会在速率限制响应时重试。 - 进度/Heartbeat 输出:
- 实时套件会向 stderr 发出进度行,因此即使 Vitest 控制台捕获处于安静状态,长时间的提供商调用也会显示为活跃。
test/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
实时(触网)测试
关于实时模型矩阵、CLI 后端冒烟、ACP 冒烟、Codex 应用服务器 harness,以及所有媒体提供商实时测试(Deepgram、BytePlus、ComfyUI、 图片、音乐、视频、媒体 harness),以及实时运行的凭据处理
Docker 运行器(可选的“在 Linux 中可用”检查)
这些 Docker 运行器分为两类:
- 实时模型运行器:
test:docker:live-models和test:docker:live-gateway只会在仓库 Docker 镜像内运行其匹配配置文件键的实时文件(src/agents/models.profiles.live.test.ts和src/gateway/gateway-models.profiles.live.test.ts),并挂载你的本地配置目录、工作区和可选配置文件环境文件。匹配的本地入口点是test:live:models-profiles和test:live:gateway-profiles。 - Docker 实时运行器会在需要时保留各自的实用上限:
test:docker:live-models默认使用精选的受支持高信号集合,而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。当你明确想要更小上限或更大扫描时,设置OPENCLAW_LIVE_MAX_MODELS或 Gateway 网关环境变量。 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 安装和多服务通道同时全部启动。如果单个通道比当前上限更重,调度器仍可在池为空时启动它,然后让它单独运行,直到容量再次可用。默认值为 10 个槽位、OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9、OPENCLAW_DOCKER_ALL_NPM_LIMIT=5和OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7;仅当 Docker 主机有更多余量时,才调整OPENCLAW_DOCKER_ALL_WEIGHT_LIMIT或OPENCLAW_DOCKER_ALL_DOCKER_LIMIT(以及其他OPENCLAW_DOCKER_ALL_<RESOURCE>_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=trusted-url或source=artifact解析一个候选包,将其作为package-under-test上传,然后针对该精确 tarball 运行可复用的 Docker E2E 通道,而不是重新打包所选 ref。配置文件按覆盖范围排序:smoke、package、product和full(另有custom用于显式通道列表)。关于包/更新/插件契约、已发布升级幸存者矩阵、发布默认值和失败分诊,请参见 更新和插件测试。- 构建和发布检查会在 tsdown 之后运行
scripts/check-cli-bootstrap-imports.mjs。该守卫会从dist/entry.js和dist/cli/run-main.js遍历静态构建图,并在命令分派之前,如果预分派启动图静态导入任何外部包(Commander、提示 UI、undici、日志以及类似的启动重型依赖都算),则失败;它还会将内置 Gateway 网关运行 chunk 限制在 70 KB,并拒绝该 chunk 静态导入已知冷 Gateway 网关路径(control-ui-assets、diagnostic-stability-bundle、onboard-helpers、process-respawn、restart-sentinel、server-close、server-reload-handlers)。scripts/release-check.ts会另外用--help、onboard --help、doctor --help、status --json --timeout 1、config schema和models list --provider openai对已打包 CLI 做冒烟测试。 - 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:release-user-journey、test:docker:release-typed-onboarding、test:docker:release-media-memory、test:docker:release-upgrade-user-journey、test:docker:release-plugin-marketplace、test:docker:skill-install、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:agent-bundle-mcp-tools、test:docker:cron-mcp-cleanup、test:docker:plugins、test:docker:plugin-update、test:docker:plugin-lifecycle-matrix和test:docker:config-reload会启动一个或多个真实容器,并验证更高层级的集成路径。 - 通过
scripts/lib/openclaw-e2e-instance.sh安装已打包 OpenClaw tarball 的 Docker/Bash E2E 通道会将npm install限制在OPENCLAW_E2E_NPM_INSTALL_TIMEOUT(默认600s;设置为0可禁用该包装器以便调试)。
实时模型 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 应用服务器 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、pnpm qa:prometheus:smoke和pnpm qa:observability:smoke是私有 QA 源码检出通道。它们有意不属于包 Docker 发布通道,因为 npm tarball 会省略 QA Lab。 -
Open WebUI 实时冒烟:
pnpm test:docker:openwebui(脚本:scripts/e2e/openwebui-docker.sh) -
新手引导向导(TTY,完整脚手架):
pnpm test:docker:onboard(脚本:scripts/e2e/onboard-docker.sh) -
Npm tarball 新手引导/渠道/智能体冒烟:
pnpm test:docker:npm-onboard-channel-agent会在 Docker 中全局安装已打包的 OpenClaw tarball,通过 env-ref 新手引导配置 OpenAI,默认还会配置 Telegram,运行 Doctor,并运行一个模拟 OpenAI 智能体轮次。使用OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz复用预构建 tarball,使用OPENCLAW_NPM_ONBOARD_HOST_BUILD=0跳过主机重建,或使用OPENCLAW_NPM_ONBOARD_CHANNEL=discord或OPENCLAW_NPM_ONBOARD_CHANNEL=slack切换渠道。 -
发布用户旅程冒烟测试:
pnpm test:docker:release-user-journey会在干净的 Docker 主目录中全局安装打包后的 OpenClaw tarball,运行新手引导,配置模拟的 OpenAI provider,运行一次智能体轮次,安装/卸载外部插件,针对本地 fixture 配置 ClickClack,验证出站/入站消息,重启 Gateway 网关,并运行 Doctor。 -
发布类型化新手引导冒烟测试:
pnpm test:docker:release-typed-onboarding会安装打包后的 tarball,通过真实 TTY 驱动openclaw onboard,将 OpenAI 配置为环境变量引用提供商,验证不会持久化原始密钥,并运行一次模拟的智能体轮次。 -
发布媒体/记忆冒烟测试:
pnpm test:docker:release-media-memory会安装打包后的 tarball,验证从 PNG 附件进行图像理解、OpenAI 兼容的图像生成输出、记忆搜索召回,以及 Gateway 网关重启后的召回保留。 -
发布升级用户旅程冒烟测试:
pnpm test:docker:release-upgrade-user-journey默认安装比候选 tarball 更旧的最新已发布基线,在已发布包上配置提供商/插件/ClickClack 状态,升级到候选 tarball,然后重新运行核心智能体/插件/渠道旅程。如果不存在更旧的已发布基线,则复用候选版本。使用OPENCLAW_RELEASE_UPGRADE_BASELINE_SPEC=openclaw@<version>覆盖基线。 -
发布插件市场冒烟测试:
pnpm test:docker:release-plugin-marketplace会从本地 fixture 市场安装,更新已安装插件,卸载它,并验证插件 CLI 随安装元数据被剪除而消失。 -
Skills 安装冒烟测试:
pnpm test:docker:skill-install会在 Docker 中全局安装打包后的 OpenClaw tarball,在配置中禁用上传归档安装,通过搜索解析当前实时 ClawHub skill slug,用openclaw skills install安装它,并验证已安装的 skill 以及.clawhub来源/锁定元数据。 -
更新频道切换冒烟测试:
pnpm test:docker:update-channel-switch会在 Docker 中全局安装打包后的 OpenClaw tarball,从 packagestable切换到 gitdev,验证持久化的频道和插件更新后工作正常,然后切回 packagestable并检查更新状态。 -
升级幸存者冒烟测试:
pnpm test:docker:upgrade-survivor会把打包后的 OpenClaw tarball 安装到一个脏旧用户 fixture 上,其中包含智能体、渠道配置、插件 allowlist、过时的插件依赖状态,以及现有工作区/会话文件。它会在没有实时提供商或渠道密钥的情况下运行包更新和非交互式 Doctor,然后启动 loopback Gateway 网关,并检查配置/状态保留以及启动/状态预算。 -
已发布升级幸存者冒烟测试:
pnpm test:docker:published-upgrade-survivor默认安装openclaw@latest,填充真实的现有用户文件,用内置命令配方配置该基线,验证生成的配置,将该已发布安装更新到候选 tarball,运行非交互式 Doctor,写入.artifacts/upgrade-survivor/summary.json,然后启动 loopback Gateway 网关,并检查已配置意图、状态保留、启动、/healthz、/readyz和 RPC 状态预算。使用OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC覆盖一个基线,使用OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS要求聚合调度器展开精确本地基线,例如openclaw@2026.5.2 openclaw@2026.4.23 openclaw@2026.4.15,并使用OPENCLAW_UPGRADE_SURVIVOR_SCENARIOS展开 issue 形态的 fixture,例如reported-issues;reported-issues 集合包含configured-plugin-installs,用于自动修复外部 OpenClaw 插件安装。Package Acceptance 将这些暴露为published_upgrade_survivor_baseline、published_upgrade_survivor_baselines和published_upgrade_survivor_scenarios,解析last-stable-4或all-since-2026.4.23等元基线 token,并且 Full Release Validation 将 release-soak 包 gate 展开为last-stable-4 2026.4.23 2026.5.2 2026.4.15加上reported-issues。 -
会话运行时上下文冒烟测试:
pnpm test:docker:session-runtime-context会验证隐藏运行时上下文 transcript 持久化,以及 Doctor 修复受影响的重复 prompt-rewrite 分支。 -
Bun 全局安装冒烟测试:
bash scripts/e2e/bun-global-install-smoke.sh会打包当前树,在隔离主目录中用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 缓存。更新冒烟测试默认使用 npmlatest作为稳定基线,然后升级到候选 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 镜像,在隔离容器主目录中填充两个智能体和一个工作区,运行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 role 快照覆盖链接 URL、cursor-promoted 可点击项、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 拒绝,并检查原始 detail 出现在 Gateway 网关日志中。 -
MCP 渠道桥接(已填充的 Gateway 网关 + stdio bridge + 原始 Claude notification-frame 冒烟测试):
pnpm test:docker:mcp-channels(脚本:scripts/e2e/mcp-channels-docker.sh) -
OpenClaw bundle MCP 工具(真实 stdio MCP 服务器 + 嵌入式 OpenClaw profile allow/deny 冒烟测试):
pnpm test:docker:agent-bundle-mcp-tools(脚本:scripts/e2e/agent-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、格式错误的 npm 包元数据、git moving refs、ClawHub kitchen-sink、市场更新,以及 Claude-bundle 启用/检查的安装/更新冒烟测试):pnpm test:docker:plugins(脚本:scripts/e2e/plugins-docker.sh) 设置OPENCLAW_PLUGINS_E2E_CLAWHUB=0可跳过 ClawHub 块,或使用OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC和OPENCLAW_PLUGINS_E2E_CLAWHUB_ID覆盖默认的 kitchen-sink 包/运行时组合。如果没有OPENCLAW_CLAWHUB_URL/CLAWHUB_URL,测试会使用封闭的本地 ClawHub fixture 服务器。 -
插件未变更更新冒烟测试:
pnpm test:docker:plugin-update(脚本:scripts/e2e/plugin-update-unchanged-docker.sh) -
插件生命周期矩阵冒烟测试:
pnpm test:docker:plugin-lifecycle-matrix会在裸容器中安装打包后的 OpenClaw tarball,安装一个 npm 插件,切换启用/禁用,通过本地 npm registry 升级和降级它,删除已安装代码,然后验证卸载仍会移除过时状态,同时记录每个生命周期阶段的 RSS/CPU 指标。 -
配置重载元数据冒烟测试:
pnpm test:docker:config-reload(脚本:scripts/e2e/config-reload-source-docker.sh) -
插件:
pnpm test:docker:plugins覆盖本地路径、file:、带提升依赖的 npm registry、git moving refs、ClawHub fixture、市场更新,以及 Claude-bundle 启用/检查的安装/更新冒烟测试。pnpm test:docker:plugin-update覆盖已安装插件的未变更更新行为。pnpm test:docker:plugin-lifecycle-matrix覆盖带资源跟踪的 npm 插件安装、启用、禁用、升级、降级和缺失代码卸载。
手动预构建并复用共享功能镜像:
OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local pnpm test:docker:e2e-buildOPENCLAW_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,因为它们验证的是包/安装行为,而不是共享的已构建应用运行时。
实时模型 Docker runner 还会以只读方式 bind-mount 当前 checkout
并将其暂存到容器内的临时 workdir。这样可以保持运行时镜像精简,同时仍然针对你的精确本地
source/config 运行 Vitest。暂存步骤会跳过大型本地专用缓存和应用构建
输出,例如 .pnpm-store、.worktrees、__openclaw_vitest__,以及
应用本地 .build 或 Gradle 输出目录,避免 Docker 实时运行
花费数分钟复制机器特定产物。它们还会设置
OPENCLAW_SKIP_CHANNELS=1,使 Gateway 网关实时探针不会在容器内启动真实的
Telegram/Discord 等渠道 worker。
test:docker:live-models 仍会运行 pnpm test:live,因此当你需要缩小或排除该 Docker lane 中的 Gateway 网关
实时覆盖范围时,也要传入
OPENCLAW_LIVE_GATEWAY_*。
test:docker:openwebui 是更高层的兼容性冒烟测试:它会启动启用了 OpenAI 兼容 HTTP 端点的
OpenClaw Gateway 网关容器,
启动一个固定版本的 Open WebUI 容器并连接到该 Gateway 网关,通过
Open WebUI 登录,验证 /api/models 暴露 openclaw/default,然后通过 Open WebUI 的 /api/chat/completions 代理发送
真实聊天请求。对于应在 Open WebUI 登录和模型发现后停止、无需等待实时模型
completion 的发布路径 CI 检查,设置
OPENWEBUI_SMOKE_MODE=models。第一次运行可能明显更慢,因为 Docker 可能需要
拉取 Open WebUI 镜像,且 Open WebUI 可能需要完成自己的
冷启动设置。此 lane 需要可用的实时模型密钥,可通过
进程环境、暂存的认证 profile,或显式
OPENCLAW_PROFILE_FILE 提供。成功运行会打印一个小型 JSON payload,例如
{ "ok": true, "model": "openclaw/default", ... }。
test:docker:mcp-channels 是有意设计为确定性的,不需要真实的 Telegram、Discord 或 iMessage 账户。它会启动一个带种子数据的 Gateway 网关容器,启动第二个容器来生成 openclaw mcp serve,然后验证路由后的对话发现、转录读取、附件元数据、实时事件队列行为、出站发送路由,以及通过真实 stdio MCP 桥接传递的 Claude 风格频道和权限通知。通知检查会直接检查原始 stdio MCP 帧,因此该 smoke 验证的是桥接实际发出的内容,而不只是某个特定客户端 SDK 恰好暴露的内容。
test:docker:agent-bundle-mcp-tools 是确定性的,不需要实时模型密钥。它会构建仓库 Docker 镜像,在容器内启动一个真实的 stdio MCP 探测服务器,通过嵌入式 OpenClaw bundle MCP 运行时物化该服务器,执行工具,然后验证 coding 和 messaging 保留 bundle-mcp 工具,而 minimal 和 tools.deny: ["bundle-mcp"] 会过滤它们。
test:docker:cron-mcp-cleanup 是确定性的,不需要实时模型密钥。它会启动一个带种子数据的 Gateway 网关和一个真实的 stdio MCP 探测服务器,运行一个隔离的 cron 轮次和一个 sessions_spawn 一次性子轮次,然后验证 MCP 子进程会在每次运行后退出。
手动 ACP 自然语言线程 smoke(非 CI):
bun scripts/dev/discord-acp-plain-language-smoke.ts --channel <discord-channel-id> ...- 保留此脚本用于回归/调试工作流。ACP 线程路由验证以后可能还会再次需要它,所以不要删除。
有用的环境变量:
OPENCLAW_CONFIG_DIR=...(默认:~/.openclaw)挂载到/home/node/.openclawOPENCLAW_WORKSPACE_DIR=...(默认:~/.openclaw/workspace)挂载到/home/node/.openclaw/workspaceOPENCLAW_PROFILE_FILE=...会在运行测试前挂载并 sourceOPENCLAW_DOCKER_PROFILE_ENV_ONLY=1用于仅验证从OPENCLAW_PROFILE_FILEsource 的环境变量,使用临时配置/工作区目录且不挂载外部 CLI 凭证OPENCLAW_DOCKER_CLI_TOOLS_DIR=...(默认:~/.cache/openclaw/docker-cli-tools,除非本次运行已经使用 CI/托管 bind 目录)挂载到/home/node/.npm-global,用于 Docker 内缓存的 CLI 安装$HOME下的外部 CLI 凭证目录/文件会以只读方式挂载到/host-auth...下,然后在测试开始前复制到/home/node/...- 默认目录(当本次运行未缩小到特定提供商时使用):
.factory、.gemini、.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_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 smoke 暴露的模型OPENCLAW_OPENWEBUI_PROMPT=...用于覆盖 Open WebUI smoke 使用的 nonce 检查提示词OPENWEBUI_IMAGE=...用于覆盖固定的 Open WebUI 镜像标签
文档完整性检查
文档编辑后运行文档检查:pnpm check:docs。
当你还需要页内标题检查时,运行完整的 Mintlify 锚点验证:pnpm docs:check-links:anchors。
离线回归(CI 安全)
这些是没有真实提供商的“真实流水线”回归:
- Gateway 网关工具调用(mock OpenAI,真实 Gateway 网关 + Agent loop):
src/gateway/gateway.test.ts(用例:“通过 Gateway 网关 Agent loop 端到端运行 mock OpenAI 工具调用”) - Gateway 网关向导(WS
wizard.start/wizard.next,写入配置 + 强制执行凭证):src/gateway/gateway.test.ts(用例:“通过 ws 运行向导并写入凭证令牌配置”)
智能体可靠性评估(Skills)
我们已经有一些行为类似“智能体可靠性评估”的 CI 安全测试:
- 通过真实 Gateway 网关 + Agent loop 进行 mock 工具调用(
src/gateway/gateway.test.ts)。 - 验证会话接线和配置效果的端到端向导流程(
src/gateway/gateway.test.ts)。
Skills 仍然缺失的内容(见 Skills):
- 决策: 当提示词中列出 Skills 时,智能体是否会选择正确的 Skills(或避开无关的 Skills)?
- 合规性: 智能体是否会在使用前读取
SKILL.md并遵循必需的步骤/参数? - 工作流契约: 断言工具顺序、会话历史延续和沙箱边界的多轮场景。
未来评估应优先保持确定性:
- 使用 mock 提供商的场景运行器,用于断言工具调用和顺序、技能文件读取,以及会话接线。
- 一小套面向技能的场景(使用与避免、门控、提示词注入)。
- 可选实时评估(选择启用、环境变量门控)只应在 CI 安全套件就绪后添加。
契约测试(插件和渠道形态)
契约测试会验证每个已注册的插件和渠道是否符合其接口契约。它们会遍历所有发现的插件,并运行一组形态和行为断言。默认的 pnpm test 单元测试 lane 会有意跳过这些共享接缝和 smoke 文件;当你触及共享渠道或提供商表面时,请显式运行契约命令。
命令
- 所有契约:
pnpm test:contracts - 仅渠道契约:
pnpm test:contracts:channels - 仅提供商契约:
pnpm test:contracts:plugins
渠道契约
位于 src/channels/plugins/contracts/*.contract.test.ts。当前顶层类别:
- channel-catalog - 内置/注册表渠道目录条目元数据
- plugin(注册表支持,分片)- 基本插件注册形态
- surfaces-only(注册表支持,分片)- 对
actions、setup、status、outbound、messaging、threading、directory和gateway的按表面形态检查 - session-binding(注册表支持)- 会话绑定行为
- outbound-payload - 消息负载结构和规范化
- group-policy(fallback)- 每个渠道的默认群组策略强制执行
- threading(注册表支持,分片)- 线程 id 处理
- directory(注册表支持,分片)- 目录/成员名单 API
- registry 和 plugins-core.* - 渠道插件注册表、加载器和配置写入授权内部机制
这些套件使用的入站 dispatch-capture 和 outbound-payload harness 辅助函数通过 src/plugin-sdk/channel-contract-testing.ts 在内部暴露(npm 排除,不是公开 SDK 子路径);此目录中没有独立的 inbound.contract.test.ts 文件。
提供商契约
位于 src/plugins/contracts/*.contract.test.ts。当前类别包括:
- shape - 插件清单、API 和运行时导出形态
- plugin-registration(+ parallel)- 清单注册用例
- package-manifest - 包清单要求
- loader - 插件加载器设置/拆卸行为
- registry - 插件契约注册表内容和查找
- providers - 跨内置提供商的共享提供商行为,以及 web-search 提供商
- auth-choice - 凭证选择元数据和设置行为
- provider-catalog-deprecation - 已弃用的提供商目录元数据
- wizard.choice-resolution、wizard.model-picker、wizard.setup-options - 提供商设置向导契约
- embedding-provider、memory-embedding-provider、web-fetch-provider、tts - 特定能力提供商契约
- session-actions、session-attachments、session-entry-projection - 插件拥有的会话状态契约
- scheduled-turns - 插件定时轮次元数据和时间戳边界
- host-hooks、run-context-lifecycle、runtime-import-side-effects、runtime-seams - 插件宿主/运行时生命周期和导入边界契约
- extension-runtime-dependencies - 插件的运行时依赖放置
何时运行
- 更改 plugin-sdk 导出或子路径后
- 添加或修改渠道或提供商插件后
- 重构插件注册或设备发现后
契约测试会在 CI 中运行,不需要真实 API 密钥。
添加回归(指南)
当你修复实时中发现的提供商/模型问题时:
- 尽可能添加 CI 安全回归(mock/stub 提供商,或捕获精确的请求形态转换)
- 如果它本质上只能实时验证(速率限制、凭证策略),保持实时测试范围狭窄,并通过环境变量选择启用
- 优先定位到能捕获该 bug 的最小层:
- 提供商请求转换/重放 bug -> 直接模型测试
- Gateway 网关会话/历史/工具流水线 bug -> Gateway 网关实时 smoke 或 CI 安全 Gateway 网关 mock 测试
- SecretRef 遍历防护栏:
src/secrets/exec-secret-ref-id-parity.test.ts会从注册表元数据(listSecretTargetRegistryEntries())为每个 SecretRef 类派生一个采样目标,然后断言 traversal-segment exec id 会被拒绝。- 如果你在
src/secrets/target-registry-data.ts中添加新的includeInPlanSecretRef 目标家族,请更新该测试中的classifyTargetClass。该测试会有意在未分类的目标 id 上失败,确保新类别不会被静默跳过。