Skip to main content
私有 QA 栈以逼近真实渠道形态的方式测试 OpenClaw,这是单元测试无法做到的。 组成部分:
  • extensions/qa-channel:合成消息渠道,包含私信、频道、线程、表情回应、编辑和删除表面。
  • extensions/qa-lab:调试器 UI 和 QA 总线,用于观察转录、注入入站消息,并导出 Markdown 报告。
  • extensions/qa-matrix:实时传输适配器,在子 QA Gateway 网关内驱动真实的 Matrix 插件。
  • qa/:由仓库提供的启动任务种子资产和基线 QA 场景。
  • Mantis:针对需要真实传输协议、浏览器截图、VM 状态和 PR 证据的错误,提供前后对比实时验证。

命令界面

每个 QA 流程都在 pnpm openclaw qa <subcommand> 下运行。许多流程有 pnpm qa:* 脚本别名;两种形式都可用。
命令用途
qa run不带 --qa-profile 时运行内置 QA 自检;带 --qa-profile smoke-ci--qa-profile release--qa-profile all 时运行由分类法支持的成熟度 profile runner。
qa suite针对 QA Gateway 网关 lane 运行仓库支持的场景。--runner multipass 使用一次性 Linux VM,而不是主机。
qa coverage打印 YAML 场景覆盖率清单(--json 用于机器输出;--match <query> 用于查找某个被触及行为的场景;--tools 用于运行时工具 fixture 覆盖率)。
qa parity-report比较两个 qa-suite-summary.json 文件以进行模型轴一致性 gate,或使用 --runtime-axis --token-efficiency 写入 Codex 与 OpenClaw 的运行时一致性和 token 效率报告。
qa confidence-report根据清单对 QA 证据工件进行分类,生成零未知项的置信度报告。
qa confidence-self-test写入带种子的负控 canary,证明置信度 gate 能检测漂移。
qa jsonl-replay通过运行时一致性回放 harness 回放精选 JSONL 转录。
qa character-eval跨多个实时模型运行角色 QA 场景,并生成评审报告。见报告
qa manual针对所选提供商/模型 lane 运行一次性 prompt。
qa ui启动 QA 调试器 UI 和本地 QA 总线(别名:pnpm qa:lab:ui)。
qa docker-build-image构建预制 QA Docker 镜像。
qa docker-scaffold为 QA dashboard + Gateway 网关 lane 写入 docker-compose scaffold。
qa up构建 QA 站点,启动 Docker 支持的栈,并打印 URL(别名:pnpm qa:lab:up:fast 变体会添加 --use-prebuilt-image --bind-ui-dist --skip-ui-build)。
qa aimock仅启动 AIMock 提供商服务器。
qa mock-openai仅启动感知场景的 mock-openai 提供商服务器。
qa credentials doctor / add / list / remove管理共享 Convex 凭证池。
qa discord针对真实私有 Discord 公会频道的实时传输 lane。
qa matrix针对一次性 Tuwunel homeserver 的实时传输 lane。见 Matrix QA
qa slack针对真实私有 Slack 频道的实时传输 lane。
qa telegram针对真实私有 Telegram 群组的实时传输 lane。
qa whatsapp针对真实 WhatsApp Web 账号的实时传输 lane。
qa mantis面向实时传输错误的前后对比验证 runner,包含 Discord 状态表情回应证据、Crabbox 桌面/浏览器 smoke,以及 Slack-in-VNC smoke。见 MantisMantis Slack Desktop Runbook
qa matrix 注册为 runner 插件(extensions/qa-matrix);上面的其他所有 lane 都直接内置在 qa-lab 中。

由 profile 支持的 qa run

由 profile 支持的 qa runtaxonomy.yaml 读取成员关系,然后通过 qa suite 分发解析出的场景。--surface--category 会过滤所选 profile,而不是定义单独的 lane。生成的 qa-evidence.json 包含一个 profile 评分卡摘要,其中有已选类别计数和缺失覆盖率 ID;单个证据条目仍然是测试、覆盖率角色和结果的事实来源。分类法功能覆盖率 ID 是精确的证明目标,而不是别名:主场景覆盖率会满足匹配 ID,次要覆盖率保持建议性质。覆盖率 ID 使用带点的 namespace.behavior 形式,片段为小写字母数字/短横线;profile、surface 和 category ID 仍可使用现有的短横线或点分分类法 ID。 精简证据会省略每个条目的 execution,并设置 evidenceMode: "slim"smoke-ci 默认使用精简模式,--evidence-mode full 会恢复完整条目:
pnpm openclaw qa run \
  --qa-profile smoke-ci \
  --category channel-framework.conversation-routing-and-delivery \
  --provider-mode mock-openai \
  --output-dir .artifacts/qa-e2e/smoke-ci-profile-dispatch
使用 smoke-ci 配合 mock 模型提供商和 Crabline 本地提供商服务器,获取确定性的 profile 证明。使用 release 针对实时渠道进行 Stable/LTS 证明。仅在明确需要完整分类法证据运行时使用 all;它会选择每个活跃成熟度类别,并可通过 QA Profile Evidence GitHub Actions workflow 以 qa_profile=all 分发。当命令还需要 OpenClaw 根 profile 时,将根 profile 放在 QA 命令之前:
pnpm openclaw --profile work qa run --qa-profile smoke-ci

操作员流程

当前 QA 操作员流程是一个双栏 QA 站点:
  • 左侧:带有智能体的 Gateway 网关 dashboard(Control UI)。
  • 右侧:QA Lab,显示类似 Slack 的转录和场景计划。
运行方式:
pnpm qa:lab:up
这会构建 QA 站点,启动 Docker 支持的 Gateway 网关 lane,并公开 QA Lab 页面。在该页面中,操作员或自动化循环可以给智能体分配 QA 任务,观察真实渠道行为,并记录哪些有效、失败或仍然受阻。 为了在不每次重建 Docker 镜像的情况下更快迭代 QA Lab UI,请使用绑定挂载的 QA Lab bundle 启动栈:
pnpm openclaw qa docker-build-image
pnpm qa:lab:build
pnpm qa:lab:up:fast
pnpm qa:lab:watch
qa:lab:up:fast 会让 Docker 服务使用预构建镜像,并将 extensions/qa-lab/web/dist 绑定挂载到 qa-lab 容器中。qa:lab:watch 会在变更时重建该 bundle,当 QA Lab 资产哈希变化时,浏览器会自动重新加载。

可观测性 smoke

可观测性 QA 仅保留在源码 checkout 中。npm tarball 有意省略 QA Lab(以及 qa-channel/qa-matrix),因此包 Docker 发布 lane 不会运行 qa 命令。修改诊断插桩时,请从已构建的源码 checkout 运行这些命令。
别名运行内容
pnpm qa:otel:smoke本地 OpenTelemetry 接收器,以及启用 diagnostics-otelotel-trace-smoke 场景。
pnpm qa:otel:collector-smoke在真实 OpenTelemetry Collector Docker 容器后运行的同一验证通道。更改端点接线或 collector/OTLP 兼容性时使用它。
pnpm qa:prometheus:smoke启用 diagnostics-prometheusdocker-prometheus-smoke 场景。
pnpm qa:observability:smoke先运行 qa:otel:smoke,再运行 qa:prometheus:smoke
pnpm qa:observability:collector-smoke先运行 qa:otel:collector-smoke,再运行 qa:prometheus:smoke
qa:otel:smoke 会启动本地 OTLP/HTTP 接收器,运行一个最小化的 QA-channel 智能体轮次,然后断言 traces、metrics 和日志已导出。它会解码 导出的 protobuf trace spans,并检查发布关键形状: openclaw.runopenclaw.harness.run、一个最新 GenAI 语义约定的 模型调用 span、openclaw.context.assembledopenclaw.message.delivery 都必须存在。该 smoke 会强制设置 OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental,因此模型调用 span 必须使用 {gen_ai.operation.name} {gen_ai.request.model} 名称;模型 调用在成功轮次中不得导出 StreamAbandoned;原始诊断 ID 和 openclaw.content.* 属性必须留在 trace 之外。该场景 prompt 要求模型回复一个固定标记,并隐藏一个固定 secret 字符串;原始 OTLP payload 不得包含其中任何一个,也不得包含从场景 id 派生的 QA 会话键。它会在 QA suite artifacts 旁写入 otel-smoke-summary.json qa:prometheus:smoke 会验证未认证的 scrape 被拒绝,然后 检查认证后的 scrape 是否包含发布关键 metric families, 且不含 prompt 内容、response 内容、原始诊断标识符、auth tokens 或本地路径。

Matrix smoke 验证通道

对于不需要模型提供商 凭据的真实传输 Matrix smoke 验证通道,请使用确定性 mock OpenAI provider 运行 fast profile:
OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS=3000 \
  pnpm openclaw qa matrix --provider-mode mock-openai --profile fast --fail-fast
对于 live-frontier provider 验证通道,请显式提供 OpenAI 兼容凭据:
OPENCLAW_LIVE_OPENAI_KEY="${OPENAI_API_KEY}" \
OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS=3000 \
  pnpm openclaw qa matrix --provider-mode live-frontier --profile fast --fail-fast
此验证通道的完整 CLI 参考、profile/scenario 目录、环境变量和 artifact 布局见 Matrix QA。概览:它会 在 Docker 中预置一个一次性 Tuwunel homeserver,注册临时的 driver/SUT/observer 用户,在限定到该传输协议的子 QA gateway 中运行真实 Matrix 插件(不使用 qa-channel),然后在 .artifacts/qa-e2e/matrix-<timestamp>/ 下写入 Markdown 报告、JSON 摘要、observed-events artifact 和合并输出日志。 这些场景覆盖单元测试无法端到端证明的传输行为: mention gating、allow-bot policies、allowlists、顶层和 threaded replies、私信路由、reaction handling、inbound edit suppression、restart replay dedupe、homeserver interruption recovery、approval metadata delivery、 media handling,以及 Matrix E2EE bootstrap/recovery/verification flows。E2EE CLI profile 还会通过同一个一次性 homeserver 驱动 openclaw matrix encryption setup 和 verification 命令,然后再检查 gateway 回复。 CI 在 .github/workflows/qa-live-transports-convex.yml 中使用同一命令 surface。计划任务和默认 手动运行会使用 QA 提供的 live-frontier 凭据、--fastOPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS=3000 执行 fast Matrix profile。手动 matrix_profile=all 会 fan out 到五个 profile shards:transportmediae2ee-smokee2ee-deepe2ee-cli

Discord Mantis 场景

Discord 也有仅限 Mantis 的 opt-in 场景,用于 bug 复现。使用 --scenario discord-status-reactions-tool-only 可运行显式状态 reaction timeline,或使用 --scenario discord-thread-reply-filepath-attachment 创建真实 Discord thread,并验证 message.thread-reply 保留 filePath attachment。这些场景不在默认 live Discord 验证通道中,因为它们是前后对照复现探针,而不是 广泛的 smoke 覆盖。thread-attachment Mantis 工作流还可以在 QA 环境中配置了 MANTIS_DISCORD_VIEWER_CHROME_PROFILE_DIRMANTIS_DISCORD_VIEWER_CHROME_PROFILE_TGZ_B64 时添加一个 已登录 Discord Web witness 视频。该 viewer profile 仅用于视觉捕获;pass/fail 判定仍来自 Discord REST oracle。 对于真实传输 Discord、Slack、Telegram 和 WhatsApp smoke 验证通道:
pnpm openclaw qa discord
pnpm openclaw qa slack
pnpm openclaw qa telegram
pnpm openclaw qa whatsapp
它们会面向一个预先存在的真实渠道,使用两个 bot 或账号(driver + SUT)。必需环境变量、scenario 列表、输出 artifacts 和 Convex 凭据池记录在下方的 Discord、Slack、Telegram 和 WhatsApp QA 参考 中。

Mantis Slack 桌面和视觉任务运行器

要使用 VNC rescue 运行完整 Slack 桌面 VM,请运行:
pnpm openclaw qa mantis slack-desktop-smoke \
  --gateway-setup \
  --scenario slack-canary \
  --keep-lease
该命令会租用一台 Crabbox desktop/browser 机器,在 VM 内运行 Slack live 验证通道,在 VNC 浏览器中打开 Slack Web,捕获桌面, 并将 slack-qa/slack-desktop-smoke.pngslack-desktop-smoke.mp4(当视频捕获可用时)复制回 Mantis artifact 目录。Crabbox desktop/browser 租约会预先提供捕获 工具和 browser/native-build helper packages,因此该场景 只应在较旧租约上安装 fallback。Mantis 会在 mantis-slack-desktop-smoke-report.md 中报告总耗时和 各阶段耗时,因此慢速运行会显示时间花在 lease warmup、credential acquisition、remote setup 还是 artifact copy 上。通过 VNC 手动登录 Slack Web 后,可复用 --lease-id <cbx_...>; 复用的租约也会保持 Crabbox 的 pnpm store cache 热态。默认 --hydrate-mode source 会从 source checkout 验证,并在 VM 中运行 install/build。仅当 复用的远程工作区已经有 node_modules 和已构建的 dist/ 时, 才使用 --hydrate-mode prehydrated;该模式会跳过昂贵的 install/build 步骤,并在 工作区未就绪时 fail closed。使用 --gateway-setup 时,Mantis 会在 VM 内端口 38973 上保留一个持久 OpenClaw Slack gateway 运行;不使用时,该 命令会运行正常的 bot-to-bot Slack QA 验证通道,并在 artifact 捕获后退出。 要用桌面证据证明原生 Slack approval UI,请运行 Mantis approval checkpoint 模式:
pnpm openclaw qa mantis slack-desktop-smoke \
  --approval-checkpoints \
  --credential-source convex \
  --credential-role maintainer
此模式与 --gateway-setup 互斥。它会运行 Slack approval 场景,拒绝非 approval scenario ids,在每个 pending 和 resolved approval 状态等待,将观察到的 Slack API 消息渲染为 approval-checkpoints/<scenario>-pending.pngapproval-checkpoints/<scenario>-resolved.png,然后在任何 checkpoint、 message evidence、acknowledgement 或渲染截图缺失或 为空时失败。冷 CI 租约可能仍会在 slack-desktop-smoke.png 中显示 Slack sign-in;approval checkpoint 图片是此验证通道的视觉 证明。 默认 checkpoint run 会保留两个标准 Slack approval 场景。 要捕获任一 opt-in Codex approval route,请用 --scenario slack-codex-approval-exec-native--scenario slack-codex-approval-plugin-native 显式选择;Mantis 会接受两者并发出 相同的 pending/resolved 截图对。运行器会为每个选定的 Codex route 扩展其 checkpoint 和 remote-command deadlines,以便完整的 approval、智能体完成和 resolved-update sequence 可以结束。 operator checklist、GitHub workflow dispatch 命令、evidence-comment contract、hydrate-mode decision table、timing interpretation 和 failure handling steps 见 Mantis Slack Desktop Runbook 对于 agent/CV 风格的桌面任务,请运行:
pnpm openclaw qa mantis visual-task \
  --browser-url https://example.net \
  --expect-text "Example Domain" \
  --vision-model openai/gpt-5.5
visual-task 会租用或复用一台 Crabbox desktop/browser 机器,启动 crabbox record --while,通过嵌套 visual-driver 驱动可见浏览器,捕获 visual-task.png,在选择 --vision-mode image-describe 时 针对截图运行 openclaw infer image describe,并写入 visual-task.mp4mantis-visual-task-summary.jsonmantis-visual-task-driver-result.jsonmantis-visual-task-report.md。设置 --expect-text 时,vision prompt 会要求结构化 JSON verdict(visibleevidencereason),并且只有当模型报告 visible: true 且 evidence 引用预期文本时才通过;仅引用目标文本的 visible: false 响应仍会使断言失败。使用 --vision-mode metadata 可运行一个 不调用 image-understanding provider 的 no-model smoke,用于证明桌面、浏览器、截图和视频 plumbing。Recording 是 visual-task 的必需 artifact;如果 Crabbox 没有录制到非空 visual-task.mp4,即使 visual driver 已通过,任务也会失败。失败时,Mantis 会为 VNC 保留租约,除非任务已经通过 且未设置 --keep-lease

凭据池健康检查

使用池化 live credentials 前,请运行:
pnpm openclaw qa credentials doctor
Doctor 会检查 Convex broker env(OPENCLAW_QA_CONVEX_SITE_URLOPENCLAW_QA_CONVEX_ENDPOINT_PREFIX),验证 endpoint settings,仅报告 OPENCLAW_QA_CONVEX_SECRET_CIOPENCLAW_QA_CONVEX_SECRET_MAINTAINER 的 set/missing 状态,并在 maintainer secret 存在时验证 admin/list 可达性。

Live transport 覆盖

Live transport 验证通道共享一个 contract,而不是各自发明 scenario list shape。qa-channel 是广泛的合成 product-behavior suite,不属于 live transport coverage matrix。 Live transport 运行器会从 openclaw/plugin-sdk/qa-live-transport-scenarios 导入共享 scenario ids、baseline coverage helpers 和 scenario-selection helper。
线路金丝雀提及门控机器人到机器人允许名单拦截顶层回复引用回复重启恢复线程跟进线程隔离表情回应观察帮助命令原生命令注册
Discordxxxx
Matrixxxxxxxxxx
Slackxxxxxxxx
Telegramxxxx
WhatsAppxxxxxxxx
这让 qa-channel 保持为覆盖面广的产品行为套件,同时 Matrix、 Telegram 和其他实时传输协议共享一份明确的传输协议契约 检查清单。 如需一个一次性的 Linux VM 线路,且不把 Docker 带入 QA 路径,请运行:
pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline
这会启动一个全新的 Multipass 客户机,安装依赖,在客户机内构建 OpenClaw, 运行 qa suite,然后把常规 QA 报告和 摘要复制回主机上的 .artifacts/qa-e2e/...。它复用与主机上 qa suite 相同的场景选择行为。 主机和 Multipass 套件运行默认会通过隔离的 Gateway 网关 worker 并行执行多个选定场景。 qa-channel 默认并发数为 4,并受选定场景数量限制。使用 --concurrency <count> 调整 worker 数量,或使用 --concurrency 1 串行执行。 使用 --pack personal-agent 运行个人助理基准包(10 个场景)。包选择器会与重复的 --scenario 标志叠加: 显式场景先运行,然后包场景按包顺序运行,并移除 重复项。当自定义 QA runner 已经提供 OpenTelemetry 收集器设置时, 使用 --pack observability 一并选择 otel-trace-smokedocker-prometheus-smoke 场景。 当任何场景失败时,该命令会以非零状态退出。如果你想获得 artifacts 但不希望退出码失败,请使用 --allow-failures 实时运行会转发客户机可实际使用的受支持 QA 凭证输入: 基于环境变量的提供商密钥、QA 实时提供商配置路径,以及 存在时的 CODEX_HOME。请将 --output-dir 放在 repo 根目录下,这样 客户机才能通过挂载的工作区写回。

Discord、Slack、Telegram 和 WhatsApp QA 参考

Matrix 有一个专用页面,因为它的场景 数量较多,并且需要基于 Docker 的 homeserver 供应。Discord、Slack、Telegram 和 WhatsApp 针对预先存在的真实传输协议运行,因此它们的参考 放在这里。

共享 CLI 标志

这些线路通过 extensions/qa-lab/src/live-transports/shared/live-transport-cli.ts 注册,并 接受相同的标志:
标志默认值描述
--scenario <id>-只运行此场景。可重复。
--output-dir <path><repo>/.artifacts/qa-e2e/<transport>-<timestamp>写入报告、摘要、证据、传输协议特定 artifacts 和输出日志的位置。相对路径基于 --repo-root 解析。
--repo-root <path>process.cwd()从中立 cwd 调用时的仓库根目录。
--sut-account <id>sutQA Gateway 网关配置中的临时账户 ID。
--provider-mode <mode>live-frontiermock-openailive-frontier(旧版 live-openai 仍然可用)。
--model <ref> / --alt-model <ref>提供商默认值主/备模型引用。
--fast关闭受支持时的提供商快速模式。
--credential-source <env|convex>env参见 Convex 凭证池
--credential-role <maintainer|ci>CI 中为 ci,否则为 maintainer--credential-source convex 时使用的角色。
任何场景失败时,每条线路都会以非零状态退出。--allow-failures 会写入 artifacts,但不会设置失败退出码。Telegram 还接受 --list-scenarios 来打印可用场景 ID 并退出;其他线路 不暴露该标志。

Telegram QA

pnpm openclaw qa telegram
目标是一个真实的私有 Telegram 群组,其中有两个不同的 bot(driver + SUT)。SUT bot 必须有 Telegram 用户名;当两个 bot 都在 @BotFather 中启用 Bot-to-Bot Communication Mode 时,机器人到机器人观察效果 最佳。 使用 --credential-source env 时所需环境变量:
  • OPENCLAW_QA_TELEGRAM_GROUP_ID - 数字聊天 ID(字符串)。
  • OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN
  • OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN
场景(extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts):
  • telegram-canary
  • telegram-mention-gating
  • telegram-mentioned-message-reply
  • telegram-help-command
  • telegram-commands-command
  • telegram-tools-compact-command
  • telegram-whoami-command
  • telegram-status-command
  • telegram-repeated-command-authorization
  • telegram-other-bot-command-gating
  • telegram-context-command
  • telegram-current-session-status-tool
  • telegram-tool-only-usage-footer
  • telegram-reply-chain-exact-marker
  • telegram-stream-final-single-message
  • telegram-long-final-reuses-preview
  • telegram-long-final-three-chunks
隐式默认集合始终覆盖金丝雀、提及门控、原生命令 回复、命令寻址,以及机器人到机器人群组回复。mock-openai 默认值还包括确定性的回复链和最终消息流式传输 检查。telegram-current-session-status-tooltelegram-tool-only-usage-footer 仍然是选择加入:前者只有在 直接接在金丝雀之后按线程运行时才稳定,后者是真实 Telegram 中 工具专用回复上 /usage 页脚的证明。使用 pnpm openclaw qa telegram --list-scenarios --provider-mode mock-openai 打印当前 默认/可选拆分以及回归引用。 输出 artifacts:
  • telegram-qa-report.md
  • qa-evidence.json - 实时传输协议检查的证据条目, 包括 profile、coverage、provider、channel、artifacts、result 和 RTT 字段。
包级 Telegram 运行使用相同的 Telegram 凭证契约。重复 RTT 测量是常规包级 Telegram 实时线路的一部分;RTT 分布会折叠进所选 RTT 检查的 qa-evidence.json 中的 result.timing
OPENCLAW_QA_CREDENTIAL_SOURCE=convex \
pnpm test:docker:npm-telegram-live
设置 OPENCLAW_QA_CREDENTIAL_SOURCE=convex 时,包级实时 wrapper 会租用一个 kind: "telegram" 凭证,将租用的群组/driver/SUT bot 环境变量导出到已安装包运行中,对租约发送 heartbeat,并在 关闭时释放它。选择 Convex 时,包级 wrapper 在 CI 外默认执行 20 次 telegram-mentioned-message-reply 的 RTT 检查、30 秒 RTT 超时,以及 Convex 角色 maintainer。覆盖 OPENCLAW_NPM_TELEGRAM_RTT_SAMPLESOPENCLAW_NPM_TELEGRAM_RTT_TIMEOUT_MSOPENCLAW_NPM_TELEGRAM_RTT_MAX_FAILURES,即可调整 RTT 测量,而无需 创建单独的 RTT 命令或 Telegram 专用摘要格式。

Discord QA

pnpm openclaw qa discord
目标是一个真实的私有 Discord guild 渠道,其中有两个 bot:由 harness 控制的 driver bot,以及由子 OpenClaw Gateway 网关 通过内置 Discord 插件启动的 SUT bot。它会验证频道提及处理、 SUT bot 已向 Discord 注册原生 /help 命令,以及 选择加入的 Mantis 证据场景。 使用 --credential-source env 时所需环境变量:
  • OPENCLAW_QA_DISCORD_GUILD_ID
  • OPENCLAW_QA_DISCORD_CHANNEL_ID
  • OPENCLAW_QA_DISCORD_DRIVER_BOT_TOKEN
  • OPENCLAW_QA_DISCORD_SUT_BOT_TOKEN
  • OPENCLAW_QA_DISCORD_SUT_APPLICATION_ID - 必须匹配 Discord 返回的 SUT bot 用户 ID (否则该线路会快速失败)。
可选:
  • OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1 会在 observed-message artifacts 中保留消息正文。
  • OPENCLAW_QA_DISCORD_VOICE_CHANNEL_IDdiscord-voice-autojoin 选择语音/舞台频道;如果未设置,场景会为 SUT bot 选择第一个可见的 语音/舞台频道。
场景(extensions/qa-lab/src/live-transports/discord/discord-live.runtime.ts:36):
  • discord-canary
  • discord-mention-gating
  • discord-native-help-command-registration
  • discord-voice-autojoin - 选择加入的语音场景。单独运行, 启用 channels.discord.voice.autoJoin,并验证 SUT bot 当前的 Discord 语音状态是目标语音/舞台频道。Convex Discord 凭证可以包含可选的 voiceChannelId;否则 runner 会发现 guild 中第一个可见的语音/舞台频道。
  • discord-status-reactions-tool-only - 选择加入的 Mantis 场景。它会 单独运行,因为它会将 SUT 切换为始终开启的、仅工具 guild 回复, 并设置 messages.statusReactions.enabled=true,然后捕获 REST 表情回应时间线以及 HTML/PNG 视觉 artifacts。Mantis 前/后 报告还会将场景提供的 MP4 artifacts 保留为 baseline.mp4candidate.mp4
  • discord-thread-reply-filepath-attachment - 选择加入的 Mantis 场景;参见 Discord Mantis 场景
显式运行 Discord 语音自动加入场景:
pnpm openclaw qa discord \
  --scenario discord-voice-autojoin \
  --provider-mode mock-openai
显式运行 Mantis 状态表情回应场景:
pnpm openclaw qa discord \
  --scenario discord-status-reactions-tool-only \
  --provider-mode live-frontier \
  --model openai/gpt-5.5 \
  --alt-model openai/gpt-5.5 \
  --fast
输出产物:
  • discord-qa-report.md
  • qa-evidence.json - 实时传输检查的证据条目。
  • discord-qa-observed-messages.json - 正文会被遮盖,除非设置 OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1
  • discord-qa-reaction-timelines.jsondiscord-status-reactions-tool-only-timeline.png,在状态表情回应场景运行时生成。

Slack QA

pnpm openclaw qa slack
目标是一个真实的私有 Slack 渠道,使用两个不同的 Bot:一个由 harness 控制的驱动 Bot,以及一个由子 OpenClaw Gateway 网关通过内置 Slack 插件启动的 SUT Bot。 使用 --credential-source env 时需要的环境变量:
  • OPENCLAW_QA_SLACK_CHANNEL_ID
  • OPENCLAW_QA_SLACK_DRIVER_BOT_TOKEN
  • OPENCLAW_QA_SLACK_SUT_BOT_TOKEN
  • OPENCLAW_QA_SLACK_SUT_APP_TOKEN
可选:
  • OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1 会在 observed-message 产物中保留消息正文。
  • OPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_DIR 会为 Mantis 启用可视化审批检查点。运行器会写入 <scenario>.pending.json<scenario>.resolved.json,然后等待匹配的 .ack.json 文件。
  • OPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_TIMEOUT_MS 会覆盖检查点确认超时。默认值是 120000
场景(extensions/qa-lab/src/live-transports/slack/slack-live.runtime.ts):
  • slack-canary
  • slack-mention-gating
  • slack-allowlist-block
  • slack-top-level-reply-shape
  • slack-restart-resume
  • slack-thread-follow-up
  • slack-thread-isolation
  • slack-reaction-glyph-native - 选择启用的实时消息工具表情回应场景。指示智能体传入精确的 字形,并确认 Slack 为目标消息上的 SUT Bot 存储了 white_check_mark
  • slack-approval-exec-native - 选择启用的原生 Slack Exec 审批场景。通过 Gateway 网关请求一次 Exec 审批,验证 Slack 消息包含原生审批按钮,完成审批,并验证已完成的 Slack 更新。
  • slack-approval-plugin-native - 选择启用的原生 Slack 插件审批场景。同时启用 Exec 和插件审批转发,以便插件事件不会被 Exec 审批路由抑制,然后验证同一条待处理/已完成的原生 Slack UI 路径。
  • slack-codex-approval-exec-native - 选择启用的 Codex Guardian 命令审批场景。在 Guardian 模式下启用 Codex 插件,将源自 Slack 的 Gateway 网关智能体轮次通过 Codex app-server harness 路由,等待 openclaw-codex-app-server 的原生 Slack 插件审批提示,完成审批,并验证 Codex 轮次以预期的命令输出和 Assistant 标记结束。
  • slack-codex-approval-plugin-native - 选择启用的 Codex Guardian 文件审批场景。使用工作区外的 apply_patch 指令,使 Codex 发出 app-server 文件变更审批路由,然后在清理前验证同一条原生 Slack 待处理/已完成审批路径、最终 Assistant 标记和精确文件内容。
Codex 审批场景需要一个 openai/*codex/* --model、常规实时模型凭证,以及 Codex 插件接受的 Codex 凭证或 API-key 凭证。Slack 报告会包含 Codex app-server 方法、选定的 Codex 模型键、最终 Codex 轮次状态,以及操作标记验证,并附带已遮盖的 Slack 审批元数据。 输出产物:
  • slack-qa-report.md
  • qa-evidence.json - 实时传输检查的证据条目。
  • slack-qa-observed-messages.json - 正文会被遮盖,除非设置 OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1
  • approval-checkpoints/ - 仅在 Mantis 设置 OPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_DIR 时生成;包含检查点 JSON、确认 JSON,以及待处理/已完成截图。

设置 Slack 工作区

该通道需要同一工作区中的两个不同 Slack 应用,以及一个两个 Bot 都是成员的频道:
  • channelId - 两个 Bot 都已受邀加入的频道的 Cxxxxxxxxxx ID。请使用专用频道;该通道每次运行都会发帖。
  • driverBotToken - Driver 应用的 Bot Token(xoxb-...)。
  • sutBotToken - SUT 应用的 Bot Token(xoxb-...),它必须是不同于 Driver 的单独 Slack 应用,以便其 Bot 用户 ID 不同。
  • sutAppToken - SUT 应用的应用级 Token(xapp-...),带有 connections:write,供 Socket Mode 使用,以便 SUT 应用可以接收事件。
优先使用专用于 QA 的 Slack 工作区,而不是复用生产工作区。 下面的 SUT 清单有意将内置 Slack 插件的生产安装(extensions/slack/src/setup-shared.ts:12)缩小到实时 Slack QA 套件覆盖的权限和事件。对于用户看到的生产频道设置,请参阅 Slack 频道快速设置;QA Driver/SUT 对有意保持独立,因为该通道需要同一工作区中的两个不同 Bot 用户 ID。 1. 创建 Driver 应用 前往 api.slack.com/appsCreate New AppFrom a manifest → 选择 QA 工作区,粘贴以下清单,然后 Install to Workspace
{
  "display_information": {
    "name": "OpenClaw QA Driver",
    "description": "Test driver bot for OpenClaw QA Slack live lane"
  },
  "features": {
    "bot_user": {
      "display_name": "OpenClaw QA Driver",
      "always_online": true
    }
  },
  "oauth_config": {
    "scopes": {
      "bot": ["chat:write", "channels:history", "groups:history", "users:read"]
    }
  },
  "settings": {
    "socket_mode_enabled": false
  }
}
复制 Bot User OAuth Tokenxoxb-...)- 它会成为 driverBotToken。Driver 只需要发布消息并识别自身;不需要事件,也不需要 Socket Mode。 2. 创建 SUT 应用 在同一工作区重复 Create New App → From a manifest。这个 QA 应用有意使用内置 Slack 插件生产清单(extensions/slack/src/setup-shared.ts:12)的更窄版本:省略了表情回应权限和事件,因为实时 Slack QA 套件尚未覆盖表情回应处理。
{
  "display_information": {
    "name": "OpenClaw QA SUT",
    "description": "OpenClaw QA SUT connector for OpenClaw"
  },
  "features": {
    "bot_user": {
      "display_name": "OpenClaw QA SUT",
      "always_online": true
    },
    "app_home": {
      "home_tab_enabled": true,
      "messages_tab_enabled": true,
      "messages_tab_read_only_enabled": false
    }
  },
  "oauth_config": {
    "scopes": {
      "bot": [
        "app_mentions:read",
        "assistant:write",
        "channels:history",
        "channels:read",
        "chat:write",
        "commands",
        "emoji:read",
        "files:read",
        "files:write",
        "groups:history",
        "groups:read",
        "im:history",
        "im:read",
        "im:write",
        "mpim:history",
        "mpim:read",
        "mpim:write",
        "pins:read",
        "pins:write",
        "usergroups:read",
        "users:read"
      ]
    }
  },
  "settings": {
    "socket_mode_enabled": true,
    "event_subscriptions": {
      "bot_events": [
        "app_home_opened",
        "app_mention",
        "channel_rename",
        "member_joined_channel",
        "member_left_channel",
        "message.channels",
        "message.groups",
        "message.im",
        "message.mpim",
        "pin_added",
        "pin_removed"
      ]
    }
  }
}
Slack 创建应用后,在其设置页执行两件事:
  • Install to Workspace → 复制 Bot User OAuth Token → 它会成为 sutBotToken
  • Basic Information → App-Level Tokens → Generate Token and Scopes → 添加 scope connections:write → 保存 → 复制 xapp-... 值 → 它会成为 sutAppToken
通过分别对每个 Token 调用 auth.test,验证两个 Bot 具有不同的用户 ID。运行时通过用户 ID 区分 Driver 和 SUT;对二者复用同一个应用会立刻导致 mention-gating 失败。 3. 创建频道 在 QA 工作区中创建一个频道(例如 #openclaw-qa),并在频道内邀请两个 Bot:
/invite @OpenClaw QA Driver
/invite @OpenClaw QA SUT
channel info → About → Channel ID 复制 Cxxxxxxxxxx ID - 它会成为 channelId。公共频道可以使用;如果你使用私有频道,两个应用已经拥有 groups:history,因此 harness 的历史读取仍会成功。 4. 注册凭证 有两种选项。使用环境变量进行单机调试(设置四个 OPENCLAW_QA_SLACK_* 变量并传入 --credential-source env),或填充共享 Convex 池,以便 CI 和其他维护者可以租用它们。 对于 Convex 池,将四个字段写入一个 JSON 文件:
{
  "channelId": "Cxxxxxxxxxx",
  "driverBotToken": "xoxb-...",
  "sutBotToken": "xoxb-...",
  "sutAppToken": "xapp-..."
}
在你的 shell 中导出 OPENCLAW_QA_CONVEX_SITE_URLOPENCLAW_QA_CONVEX_SECRET_MAINTAINER 后,注册并验证:
pnpm openclaw qa credentials add \
  --kind slack \
  --payload-file slack-creds.json \
  --note "QA Slack pool seed"

pnpm openclaw qa credentials list --kind slack --status all --json
预期结果为 count: 1status: "active",没有 lease 字段。 5. 端到端验证 在本地运行该通道,确认两个 Bot 可以通过 broker 彼此通信:
pnpm openclaw qa slack \
  --credential-source convex \
  --credential-role maintainer \
  --output-dir .artifacts/qa-e2e/slack-local
一次绿色运行会在远低于 30 秒内完成,并且 slack-qa-report.md 显示 slack-canaryslack-mention-gating 的状态均为 pass。如果该通道挂起约 90 秒并以 Convex credential pool exhausted for kind "slack" 退出,要么池为空,要么每一行都已被租用 - qa credentials list --kind slack --status all --json 会告诉你是哪一种。

WhatsApp QA

pnpm openclaw qa whatsapp
目标是两个专用 WhatsApp Web 账号:一个由 harness 控制的驱动账号,以及一个由子 OpenClaw Gateway 网关通过内置 WhatsApp 插件启动的 SUT 账号。 使用 --credential-source env 时需要的环境变量:
  • OPENCLAW_QA_WHATSAPP_DRIVER_PHONE_E164
  • OPENCLAW_QA_WHATSAPP_SUT_PHONE_E164
  • OPENCLAW_QA_WHATSAPP_DRIVER_AUTH_ARCHIVE_BASE64
  • OPENCLAW_QA_WHATSAPP_SUT_AUTH_ARCHIVE_BASE64
可选:
  • OPENCLAW_QA_WHATSAPP_GROUP_JID 启用群组场景,例如 whatsapp-mention-gatingwhatsapp-group-pending-history-contextwhatsapp-broadcast-group-fanoutwhatsapp-group-activation-alwayswhatsapp-group-reply-to-bot-triggers、群组动作/媒体/投票场景,以及 whatsapp-group-allowlist-block
  • OPENCLAW_QA_WHATSAPP_CAPTURE_CONTENT=1 会在 observed-message 产物中保留消息正文。
场景目录(extensions/qa-lab/src/live-transports/whatsapp/whatsapp-live.runtime.ts):
  • 基线和群组门控:whatsapp-canarywhatsapp-pairing-blockwhatsapp-mention-gatingwhatsapp-group-pending-history-contextwhatsapp-group-activation-alwayswhatsapp-group-reply-to-bot-triggerswhatsapp-top-level-reply-shapewhatsapp-restart-resumewhatsapp-group-allowlist-block
  • 原生命令:whatsapp-help-commandwhatsapp-status-commandwhatsapp-commands-commandwhatsapp-tools-compact-commandwhatsapp-whoami-commandwhatsapp-context-commandwhatsapp-native-new-command
  • 回复和最终输出行为:whatsapp-tool-only-usage-footerwhatsapp-reply-to-messagewhatsapp-group-reply-to-messagewhatsapp-reply-to-mode-batchedwhatsapp-reply-context-isolationwhatsapp-reply-delivery-shapewhatsapp-stream-final-message-accounting
  • 用户路径消息操作:whatsapp-agent-message-action-react 从真实驱动私信开始, 让模型调用 message 工具,并观察原生 WhatsApp 表情回应。whatsapp-agent-message-action-upload-filemessage(action=upload-file) 使用相同姿态,并观察原生 WhatsApp 媒体。 whatsapp-group-agent-message-action-reactwhatsapp-group-agent-message-action-upload-file 在真实 WhatsApp 群组中证明相同的 用户可见操作。
  • 群组扇出:whatsapp-broadcast-group-fanout 从一条被提及的 WhatsApp 群组消息开始,并验证来自 mainqa-second 的不同可见回复。
  • 群组激活:whatsapp-group-activation-always 将真实群组会话改为 /activation always,证明未提及的群组消息会唤醒智能体,然后恢复 /activation mentionwhatsapp-group-reply-to-bot-triggers 先播种一条 Bot 回复,再向它发送一条没有显式提及的原生引用回复, 并验证智能体会从该回复上下文中唤醒。
  • 入站媒体和结构化消息:whatsapp-inbound-image-captionwhatsapp-audio-preflightwhatsapp-inbound-structured-messageswhatsapp-group-audio-gatingwhatsapp-inbound-reaction-no-trigger。 这些场景会通过驱动发送真实 WhatsApp 图片、音频、文档、位置、联系人、 贴纸和表情回应事件。
  • 直接 Gateway 网关契约探针:whatsapp-outbound-media-matrixwhatsapp-outbound-document-preserves-filenamewhatsapp-outbound-pollwhatsapp-outbound-send-serializationwhatsapp-group-outbound-mediawhatsapp-group-outbound-pollwhatsapp-message-actionswhatsapp-reply-context-isolationwhatsapp-reply-delivery-shape。这些有意绕过模型提示, 并证明确定性的 Gateway 网关/渠道 sendpollmessage.action 契约。
  • 访问控制覆盖:whatsapp-access-control-dm-openwhatsapp-access-control-dm-disabledwhatsapp-access-control-group-openwhatsapp-access-control-group-disabledwhatsapp-group-allowlist-block
  • 原生审批:whatsapp-approval-exec-deny-nativewhatsapp-approval-exec-nativewhatsapp-approval-exec-reaction-nativewhatsapp-approval-exec-group-reaction-nativewhatsapp-approval-plugin-native
  • 状态表情回应:whatsapp-status-reactionswhatsapp-status-reaction-lifecycle
目录当前包含 52 个场景。live-frontier 默认通道保持较小规模,为 10 个场景, 用于快速冒烟覆盖。mock-openai 默认通道通过真实 WhatsApp 传输确定性地运行 45 个场景, 只模拟模型输出;审批场景和少数较重/阻塞型检查仍需通过场景 ID 显式运行。 WhatsApp QA 驱动会观察结构化实时事件(textmedialocationreactionpoll),并且可以主动发送媒体、投票、 联系人、位置和贴纸。QA Lab 通过 @openclaw/whatsapp/api.js 包表面导入该驱动, 而不是访问私有 WhatsApp 运行时文件。对于群组观察,fromJid 是群组 JID, 而 participantJidfromPhoneE164 标识参与者发送者。 消息内容默认会被编辑隐藏。直接 Gateway 网关投票、upload-file、 媒体、群组投票、群组媒体和回复形状探针是传输/API 契约检查; 它们不会被视为用户提示让智能体选择相同操作的证明。用户路径操作证明来自 whatsapp-agent-message-action-reactwhatsapp-group-agent-message-action-react 等场景,在这些场景中,驱动会发送普通 WhatsApp 消息,QA Lab 会观察由此产生的原生 WhatsApp 工件。 WhatsApp 报告包含每个场景的姿态(user-pathdirect-gatewaynative-approval),因此证据不会被误认为证明了比实际更强的契约。 输出工件:
  • whatsapp-qa-report.md
  • qa-evidence.json - 实时传输检查的证据条目。
  • whatsapp-qa-observed-messages.json - 正文会被编辑隐藏,除非设置 OPENCLAW_QA_WHATSAPP_CAPTURE_CONTENT=1

Convex 凭据池

Discord、Slack、Telegram 和 WhatsApp 通道可以从共享 Convex 池租用凭据, 而不是读取上述环境变量。传入 --credential-source convex(或设置 OPENCLAW_QA_CREDENTIAL_SOURCE=convex);QA Lab 会获取独占租约,在运行期间为其发送心跳, 并在关闭时释放它。池类型为 "discord""slack""telegram""whatsapp" 代理在 admin/add 上验证的负载形状:
  • Discord(kind: "discord"):{ guildId: string, channelId: string, driverBotToken: string, sutBotToken: string, sutApplicationId: string }
  • Telegram(kind: "telegram"):{ groupId: string, driverToken: string, sutToken: string } - groupId 必须是数字聊天 ID 字符串。
  • Telegram 真实用户(kind: "telegram-user"):{ groupId: string, sutToken: string, testerUserId: string, testerUsername: string, telegramApiId: string, telegramApiHash: string, tdlibDatabaseEncryptionKey: string, tdlibArchiveBase64: string, tdlibArchiveSha256: string, desktopTdataArchiveBase64: string, desktopTdataArchiveSha256: string } - 仅限 Mantis Telegram Desktop 证明。通用 QA Lab 通道不得获取此类型。
  • WhatsApp(kind: "whatsapp"):{ driverPhoneE164: string, sutPhoneE164: string, driverAuthArchiveBase64: string, sutAuthArchiveBase64: string, groupJid?: string } - 电话号码必须是不同的 E.164 字符串。
Mantis Telegram Desktop 证明工作流会为 TDLib CLI 驱动和 Telegram Desktop 见证者持有一个独占 Convex telegram-user 租约,然后在发布证明后释放它。 当 PR 需要确定性视觉差异时,Mantis 可以在 main 和 PR head 上使用相同的模拟模型回复, 同时更改 Telegram 格式化器或交付层。捕获默认值针对 PR 评论进行了调优:标准 Crabbox 类、24fps 桌面录制、24fps 运动 GIF 和 1920px 预览宽度。 前后对比评论应发布一个干净的包,其中只包含预期 GIF。 Slack 通道也可以使用该池。Slack 负载形状检查目前位于 Slack QA runner 中, 而不是代理中;请使用 { channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string },并使用类似 Cxxxxxxxxxx 的 Slack 频道 ID。有关应用和权限范围配置,请参阅 设置 Slack 工作区 运行环境变量和 Convex 代理端点契约位于 测试 → 通过 Convex 共享 Telegram 凭据 (该小节名称早于多渠道池;租约语义在各类型之间共享)。

仓库支持的种子

种子资产位于 qa/
  • qa/scenarios/index.yaml
  • qa/scenarios/<theme>/*.yaml
这些内容有意放在 git 中,因此 QA 计划对人类和智能体都可见。 qa-lab 保持为通用 YAML 场景运行器。每个场景 YAML 文件都是一次测试运行的事实来源, 并应定义:
  • 顶层 title
  • scenario 元数据
  • scenario 中可选的类别、能力、通道和风险元数据
  • scenario 中的文档和代码引用
  • scenario 中可选的插件要求
  • scenario 中可选的 Gateway 网关配置补丁
  • 用于流程场景的可执行顶层 flow,或用于 Vitest 和 Playwright 场景的 scenario.execution.kind / scenario.execution.path
支撑 flow 的可复用运行时表面保持通用且跨领域。例如,YAML 场景可以组合传输侧辅助工具与浏览器侧辅助工具, 通过 Gateway 网关 browser.request 接缝驱动嵌入式 Control UI,而无需添加特殊情况 runner。 场景文件应按产品能力分组,而不是按源代码树文件夹分组。文件移动时保持场景 ID 稳定; 使用 docsRefscodeRefs 实现实现可追溯性。 基线列表应保持足够宽,以覆盖:
  • 私信和渠道聊天
  • 线程行为
  • 消息操作生命周期
  • cron 回调
  • 记忆回忆
  • 模型切换
  • 子智能体交接
  • 仓库读取和文档读取
  • 一个小型构建任务,例如 Lobster Invaders

提供商模拟通道

qa suite 有两个本地提供商模拟通道:
  • mock-openai 是感知场景的 OpenClaw 模拟。它仍然是仓库支持的 QA 和一致性门控的默认确定性模拟通道。
  • aimock 会启动由 AIMock 支撑的提供商服务器,用于实验性协议、fixture、录制/回放和混沌覆盖。 它是增量能力,不会替代 mock-openai 场景调度器。
提供商通道实现位于 extensions/qa-lab/src/providers/ 下。 每个提供商拥有自己的默认值、本地服务器启动、Gateway 网关模型配置、 auth-profile 暂存需求以及实时/模拟能力标志。共享套件和 Gateway 网关代码通过提供商注册表路由, 而不是按提供商名称分支。

传输适配器

qa-lab 为 YAML QA 场景拥有通用传输接缝。qa-channel 是合成默认值。 crabline 会启动本地提供商形状的服务器,并让 OpenClaw 的常规渠道插件与它们一起运行。 live 预留给真实提供商凭据和外部渠道。 在架构层面,划分如下:
  • qa-lab 拥有通用场景执行、工作器并发、工件写入和报告。
  • 传输适配器拥有 Gateway 网关配置、就绪检查、入站和出站观察、传输操作以及规范化传输状态。
  • qa/scenarios/ 下的 YAML 场景文件定义测试运行;qa-lab 提供执行它们的可复用运行时表面。

添加渠道

向 YAML QA 系统添加渠道需要渠道实现,以及一个用于覆盖渠道契约的场景包。对于冒烟 CI 覆盖, 请添加匹配的 Crabline 本地提供商服务器,并通过 crabline 驱动暴露它。 当共享 qa-lab 主机可以拥有该流程时,不要添加新的顶层 QA 命令根。 qa-lab 拥有共享主机机制:
  • openclaw qa 命令根
  • 套件启动和拆除
  • 工作器并发
  • 工件写入
  • 报告生成
  • 场景执行
  • 旧版 qa-channel 场景的兼容别名
Runner 插件拥有传输契约:
  • openclaw qa <runner> 如何挂载到共享 qa 根下面
  • 如何为该传输配置 Gateway 网关
  • 如何检查就绪状态
  • 如何注入入站事件
  • 如何观察出站消息
  • 如何暴露转录和规范化传输状态
  • 如何执行由传输支撑的操作
  • 如何处理传输特定的重置或清理
新渠道的最低采用门槛:
  1. 保持 qa-lab 作为共享 qa 根命令的所有者。
  2. 在共享的 qa-lab 主机接缝上实现传输运行器。
  3. 将传输专属机制保留在运行器插件或渠道 harness 内。
  4. 将运行器挂载为 openclaw qa <runner>,而不是注册一个竞争性的根命令。运行器插件应在 openclaw.plugin.json 中声明 qaRunners,并从 runtime-api.ts 导出匹配的 qaRunnerCliRegistrations 数组。保持 runtime-api.ts 轻量;延迟 CLI 和运行器执行应放在单独的入口点后面。可选的 adapterFactory 会向共享场景暴露传输,而不改变命令现有的场景目录。
  5. 在主题化的 qa/scenarios/ 目录下编写或改编 YAML 场景。
  6. 为新场景使用通用场景辅助函数。
  7. 除非仓库正在进行有意迁移,否则保持现有兼容别名可用。
决策规则很严格:
  • 如果行为可以在 qa-lab 中表达一次,就把它放在 qa-lab
  • 如果行为依赖某个渠道传输,就把它保留在该运行器插件或插件 harness 中。
  • 如果某个场景需要多个渠道都能使用的新能力,请添加通用辅助函数,而不是在 suite.ts 中添加渠道专属分支。
  • 如果某个行为只对一种传输有意义,就保持场景传输专属,并在场景契约中明确说明。

场景辅助函数名称

新场景首选的通用辅助函数:
  • waitForTransportReady
  • waitForChannelReady
  • injectInboundMessage
  • injectOutboundMessage
  • waitForTransportOutboundMessage
  • waitForChannelOutboundMessage
  • waitForNoTransportOutbound
  • getTransportSnapshot
  • readTransportMessage
  • readTransportTranscript
  • formatTransportTranscript
  • resetTransport
兼容别名仍可用于现有场景 - waitForQaChannelReadywaitForOutboundMessagewaitForNoOutboundformatConversationTranscriptresetBus - 但新场景编写应使用通用名称。这些别名的存在是为了避免一次性强制迁移,而不是作为未来的模型。

报告

qa-lab 会从观测到的总线时间线导出一份 Markdown 协议报告。 报告应回答:
  • 哪些工作正常
  • 哪些失败了
  • 哪些仍被阻塞
  • 哪些后续场景值得添加
如需查看可用场景清单(在评估后续工作规模或接入新传输时很有用),请运行 pnpm openclaw qa coverage(添加 --json 可获得机器可读输出)。为被触及的行为或文件路径选择聚焦证明时,运行 pnpm openclaw qa coverage --match <query>。匹配报告会搜索场景元数据、文档引用、代码引用、覆盖 ID、插件和提供商要求,然后打印匹配的 qa suite --scenario ... 目标。 每次 qa suite 运行都会为选定的场景集写入顶层 qa-evidence.jsonqa-suite-summary.jsonqa-suite-report.md 工件。声明 execution.kind: vitestexecution.kind: playwright 的场景会运行匹配的测试路径,并且也会写入逐场景日志。声明 execution.kind: script 的场景会通过 node --import tsx 运行 execution.path 处的证据生产器(会在 execution.args 中展开 ${outputDir}${scenarioId});生产器会写入自己的 qa-evidence.json,其条目会被导入套件输出,其工件路径会相对于该生产器的 qa-evidence.json 解析。当通过 qa run --qa-profile 进入 qa suite 时,同一个 qa-evidence.json 还会包含所选分类法类别的 profile 评分卡摘要。 将覆盖输出视为发现辅助,而不是门禁替代;所选场景仍需要适合被测行为的提供商模式、实时传输、Multipass、Testbox 或发布通道。评分卡上下文请参阅成熟度评分卡 对于角色和风格检查,请在多个实时模型引用上运行同一场景,并写入经评审的 Markdown 报告:
pnpm openclaw qa character-eval \
  --model openai/gpt-5.5,thinking=medium,fast \
  --model openai/gpt-5.2,thinking=xhigh \
  --model openai/gpt-5,thinking=xhigh \
  --model anthropic/claude-opus-4-8,thinking=high \
  --model anthropic/claude-sonnet-4-6,thinking=high \
  --model zai/glm-5.1,thinking=high \
  --model moonshot/kimi-k2.5,thinking=high \
  --model google/gemini-3.1-pro-preview,thinking=high \
  --judge-model openai/gpt-5.5,thinking=xhigh,fast \
  --judge-model anthropic/claude-opus-4-8,thinking=high \
  --blind-judge-models \
  --concurrency 16 \
  --judge-concurrency 16
该命令运行本地 QA Gateway 网关子进程,而不是 Docker。角色评估场景应通过 SOUL.md 设置人格,然后运行普通用户轮次,例如聊天、工作区帮助和小型文件任务。候选模型不应被告知它正在接受评估。该命令会保留每个完整转录,记录基本运行统计,然后在支持的情况下使用带 xhigh 推理的 fast 模式询问评审模型,按自然度、气质和幽默感对运行进行排名。比较提供商时使用 --blind-judge-models:评审提示仍会获得每份转录和运行状态,但候选引用会被替换为 candidate-01 等中性标签;报告会在解析后将排名映射回真实引用。 候选运行默认使用 high thinking,GPT-5.5 使用 medium,支持它的较旧 OpenAI 评估引用使用 xhigh。用 --model provider/model,thinking=<level> 内联覆盖特定候选;内联选项也支持 fastno-fastfast=<bool>--thinking <level> 仍会设置全局回退,而较旧的 --model-thinking <provider/model=level> 形式会保留用于兼容。OpenAI 候选引用默认使用 fast 模式,以便在提供商支持时使用优先处理。仅当你想为每个候选模型强制启用 fast 模式时,才传入 --fast。候选和评审耗时会记录在报告中,用于基准分析,但评审提示会明确说明不要按速度排名。候选和评审模型运行默认并发均为 16。当提供商限制或本地 Gateway 网关压力让运行噪声过大时,降低 --concurrency--judge-concurrency 未传入候选 --model 时,角色评估默认使用 openai/gpt-5.5openai/gpt-5.2openai/gpt-5anthropic/claude-opus-4-8anthropic/claude-sonnet-4-6zai/glm-5.1moonshot/kimi-k2.5google/gemini-3.1-pro-preview。未传入 --judge-model 时,评审默认使用 openai/gpt-5.5,thinking=xhigh,fastanthropic/claude-opus-4-8,thinking=high

相关文档