chore(i18n): refresh zh-CN translations
This commit is contained in:
parent
52e4d41957
commit
f849875950
@ -1,65 +1,65 @@
|
||||
---
|
||||
read_when:
|
||||
- 为 OpenClaw 缺陷构建或运行实时可视化质量验证
|
||||
- 为 OpenClaw 缺陷构建或运行实时视觉 QA
|
||||
- 为拉取请求添加前后验证
|
||||
- 添加 Discord、Slack、WhatsApp 或其他实时传输场景
|
||||
- 调试需要截图、浏览器自动化或 VNC 访问的 QA 运行
|
||||
summary: Mantis 是用于在实时传输协议上复现 OpenClaw 缺陷、捕获前后对比证据并将工件附加到 PR 的可视化端到端验证系统。
|
||||
summary: Mantis 是一种可视化端到端验证系统,用于在真实传输协议上复现 OpenClaw 缺陷、捕获修复前后的证据,并将工件附加到 PR。
|
||||
title: Mantis
|
||||
x-i18n:
|
||||
generated_at: "2026-05-04T01:25:51Z"
|
||||
generated_at: "2026-05-04T02:52:01Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 5a86ab4bc876d1c53ada1c30580034165f028194a072f559eb54a898a369211d
|
||||
source_hash: 9d3f3fa3db111b1b5c85f8efeccd749fbd5885cee6b7843ca4c8d049acfd9164
|
||||
source_path: concepts/mantis.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
Mantis 是 OpenClaw 端到端验证系统,用于需要真实运行时、真实传输协议和可见证明的 bug。它会针对一个已知有问题的 ref 运行场景、捕获证据,再针对候选 ref 运行相同场景,并将对比结果发布为工件,维护者可以从 PR 或本地命令中检查这些工件。
|
||||
Mantis 是 OpenClaw 端到端验证系统,用于需要真实运行时、真实传输协议和可见证据的 bug。它会针对已知有问题的 ref 运行场景,捕获证据,再针对候选 ref 运行相同场景,并将对比结果发布为工件,维护者可以从 PR 或本地命令中检查这些工件。
|
||||
|
||||
Mantis 从 Discord 开始,因为 Discord 为我们提供了一条高价值的首条通道:真实机器人凭证、真实公会频道、回应、帖子、原生命令,以及一个人类可以直观看到传输协议所展示内容的浏览器 UI。
|
||||
Mantis 从 Discord 开始,因为 Discord 为我们提供了一条高价值的首条通道:真实 bot 凭证、真实服务器渠道、reaction、thread、原生命令,以及可供人类直观看到传输协议显示内容的浏览器 UI。
|
||||
|
||||
## 目标
|
||||
|
||||
- 用用户看到的相同传输协议形态,复现来自 GitHub issue 或 PR 的 bug。
|
||||
- 在应用修复之前,在基线 ref 上捕获一个 **before** 工件。
|
||||
- 在应用修复之后,在候选 ref 上捕获一个 **after** 工件。
|
||||
- 尽可能使用确定性判定器,例如读取 Discord REST 回应或检查频道记录。
|
||||
- 使用用户看到的相同传输协议形态,复现 GitHub issue 或 PR 中的 bug。
|
||||
- 在应用修复之前,在基线 ref 上捕获 **before** 工件。
|
||||
- 在应用修复之后,在候选 ref 上捕获 **after** 工件。
|
||||
- 尽可能使用确定性的判定器,例如 Discord REST reaction 读取或渠道 transcript 检查。
|
||||
- 当 bug 有可见 UI 表面时捕获截图。
|
||||
- 从智能体控制的 CLI 本地运行,并从 GitHub 远程运行。
|
||||
- 当登录、浏览器自动化或提供商凭证卡住时,保留足够的机器状态用于 VNC 救援。
|
||||
- 当运行被阻塞、需要人工 VNC 协助或完成时,向操作员 Discord 频道发布简洁 Status。
|
||||
- 当运行被阻塞、需要人工 VNC 帮助或完成时,向 operator Discord 渠道发布简洁 Status。
|
||||
|
||||
## 非目标
|
||||
|
||||
- Mantis 不是单元测试的替代品。理解修复后,一次 Mantis 运行通常应转化为更小的回归测试。
|
||||
- Mantis 不是常规的快速 CI 门禁。它更慢,使用实时凭证,并且只保留给实时环境很重要的 bug。
|
||||
- Mantis 不应要求人类参与常规操作。手动 VNC 是救援路径,不是正常路径。
|
||||
- Mantis 不是单元测试的替代品。理解修复后,Mantis 运行通常应该转化为一个更小的回归测试。
|
||||
- Mantis 不是常规的快速 CI 门禁。它更慢,会使用实时凭证,并且只用于实时环境很重要的 bug。
|
||||
- Mantis 的正常操作不应该需要人工介入。手动 VNC 是救援路径,而不是正常路径。
|
||||
- Mantis 不会在工件、日志、截图、Markdown 报告或 PR 评论中存储原始密钥。
|
||||
|
||||
## 所有权
|
||||
## 归属范围
|
||||
|
||||
Mantis 位于 OpenClaw QA 栈中。
|
||||
|
||||
- OpenClaw 拥有场景运行时、传输协议适配器、证据 schema,以及 `pnpm openclaw qa mantis` 下的本地 CLI。
|
||||
- QA Lab 拥有实时传输协议 harness 组件、浏览器捕获辅助工具和工件写入器。
|
||||
- QA Lab 拥有实时传输协议 harness 组件、浏览器捕获助手和工件写入器。
|
||||
- 当需要远程 VM 时,Crabbox 拥有预热的 Linux 机器。
|
||||
- GitHub Actions 拥有远程工作流入口点和工件保留。
|
||||
- ClawSweeper 拥有 GitHub 评论路由:解析维护者命令、分派工作流,并发布最终 PR 评论。
|
||||
- 当场景需要智能体式设置、调试或卡住状态报告时,OpenClaw 智能体会通过 Codex 驱动 Mantis。
|
||||
- GitHub Actions 拥有远程 workflow 入口点和工件保留。
|
||||
- ClawSweeper 拥有 GitHub 评论路由:解析维护者命令、分发 workflow,并发布最终 PR 评论。
|
||||
- 当场景需要智能体式设置、调试或卡住状态报告时,OpenClaw 智能体通过 Codex 驱动 Mantis。
|
||||
|
||||
该边界将传输协议知识保留在 OpenClaw 中,将机器调度保留在 Crabbox 中,并将维护者工作流胶水保留在 ClawSweeper 中。
|
||||
这个边界让传输协议知识保留在 OpenClaw 中,机器调度保留在 Crabbox 中,维护者 workflow 胶水保留在 ClawSweeper 中。
|
||||
|
||||
## 命令形式
|
||||
## 命令形态
|
||||
|
||||
第一个本地命令会验证 Discord 机器人、公会、频道、消息发送、回应发送和工件路径:
|
||||
第一个本地命令会验证 Discord bot、服务器、渠道、消息发送、reaction 发送和工件路径:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa mantis discord-smoke \
|
||||
--output-dir .artifacts/qa-e2e/mantis/discord-smoke
|
||||
```
|
||||
|
||||
本地 before 和 after 运行器接受以下形式:
|
||||
本地 before 和 after 运行器接受以下形态:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa mantis run \
|
||||
@ -72,37 +72,69 @@ pnpm openclaw qa mantis run \
|
||||
|
||||
运行器会在输出目录下创建分离的基线和候选 worktree,安装依赖,构建每个 ref,使用 `--allow-failures` 运行场景,然后写入 `baseline/`、`candidate/`、`comparison.json` 和 `mantis-report.md`。对于第一个 Discord 场景,成功验证意味着基线 Status 为 `fail`,候选 Status 为 `pass`。
|
||||
|
||||
第一个 VM/浏览器原语是桌面 smoke:
|
||||
第一个 VM/browser 原语是桌面 smoke:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa mantis desktop-browser-smoke \
|
||||
--output-dir .artifacts/qa-e2e/mantis/desktop-browser
|
||||
```
|
||||
|
||||
它会租用或复用一台 Crabbox 桌面机器,在 VNC 会话内启动可见浏览器,捕获桌面,将工件拉回本地输出目录,并将重连命令写入报告。该命令默认使用 Hetzner 提供商,因为它是 Mantis 通道中第一个具备可用桌面/VNC 覆盖的提供商。针对另一个 Crabbox 机群运行时,可使用 `--provider`、`--crabbox-bin` 或 `OPENCLAW_MANTIS_CRABBOX_PROVIDER` 覆盖。
|
||||
它会租用或复用 Crabbox 桌面机器,在 VNC 会话中启动可见浏览器,捕获桌面,将工件拉回本地输出目录,并把重连命令写入报告。该命令默认使用 Hetzner 提供商,因为它是 Mantis 通道中第一个具备可用桌面/VNC 覆盖的提供商。针对另一个 Crabbox 机群运行时,可用 `--provider`、`--crabbox-bin` 或 `OPENCLAW_MANTIS_CRABBOX_PROVIDER` 覆盖。
|
||||
|
||||
有用的桌面 smoke 标志:
|
||||
|
||||
- `--lease-id <cbx_...>` 或 `OPENCLAW_MANTIS_CRABBOX_LEASE_ID` 会复用预热的桌面。
|
||||
- `--browser-url <url>` 会更改在可见浏览器中打开的页面。
|
||||
- `--html-file <path>` 会在可见浏览器中渲染一个仓库本地 HTML 工件。Mantis 使用它通过真实 Crabbox 桌面捕获生成的 Discord Status 回应时间线。
|
||||
- `--keep-lease` 或 `OPENCLAW_MANTIS_KEEP_VM=1` 会让新创建且通过的 lease 保持打开,供 VNC 检查。失败运行在创建了 lease 时默认保留 lease,以便操作员可以重新连接。
|
||||
- `--class`、`--idle-timeout` 和 `--ttl` 可调整机器规格和 lease 生命周期。
|
||||
- `--lease-id <cbx_...>` 或 `OPENCLAW_MANTIS_CRABBOX_LEASE_ID` 复用已预热的桌面。
|
||||
- `--browser-url <url>` 更改可见浏览器中打开的页面。
|
||||
- `--html-file <path>` 在可见浏览器中渲染仓库本地 HTML 工件。Mantis 使用它通过真实 Crabbox 桌面捕获生成的 Discord status-reaction 时间线。
|
||||
- `--keep-lease` 或 `OPENCLAW_MANTIS_KEEP_VM=1` 会让新创建且通过的 lease 保持打开,以便 VNC 检查。失败运行在创建了 lease 时默认保留它,以便 operator 重新连接。
|
||||
- `--class`、`--idle-timeout` 和 `--ttl` 调整机器规格和 lease 生命周期。
|
||||
|
||||
GitHub smoke 工作流是 `Mantis Discord Smoke`。第一个真实场景的 before 和 after GitHub 工作流是 `Mantis Discord Status Reactions`。它接受:
|
||||
第一个完整桌面传输协议原语是 Slack 桌面 smoke:
|
||||
|
||||
- `baseline_ref`:预期会复现仅 queued 行为的 ref。
|
||||
```bash
|
||||
pnpm openclaw qa mantis slack-desktop-smoke \
|
||||
--output-dir .artifacts/qa-e2e/mantis/slack-desktop \
|
||||
--gateway-setup \
|
||||
--scenario slack-canary \
|
||||
--keep-lease
|
||||
```
|
||||
|
||||
它会租用或复用 Crabbox 桌面机器,将当前 checkout 同步到 VM 中,在该 VM 内运行 `pnpm openclaw qa slack`,在 VNC 浏览器中打开 Slack Web,捕获可见桌面,并将 Slack QA 工件和 VNC 截图都复制回本地输出目录。这是第一个 Mantis 形态,其中 SUT OpenClaw Gateway 网关和浏览器都位于同一个 Linux 桌面 VM 中。
|
||||
|
||||
使用 `--gateway-setup` 时,该命令会在 `$HOME/.openclaw-mantis/slack-openclaw` 准备一个持久的一次性 OpenClaw home,为选定渠道修补 Slack Socket Mode 配置,在端口 `38973` 上启动 `openclaw gateway run`,并让 Chrome 保持运行在 VNC 会话中。这是“给我留一个运行着 Slack 和 claw 的 Linux 桌面”模式;省略 `--gateway-setup` 时,bot-to-bot Slack QA 通道仍是默认模式。
|
||||
|
||||
`--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_LIVE_OPENAI_KEY`。如果本地只设置了 `OPENAI_API_KEY`,Mantis 会在调用 Crabbox 前将它映射到 `OPENCLAW_LIVE_OPENAI_KEY`,这样 Crabbox 的 `OPENCLAW_*` 环境变量转发就能把它带入 VM。
|
||||
|
||||
有用的 Slack 桌面标志:
|
||||
|
||||
- `--lease-id <cbx_...>` 针对 operator 已经通过 VNC 登录 Slack Web 的机器重新运行。
|
||||
- `--gateway-setup` 在 VM 中启动持久 OpenClaw Slack Gateway 网关,而不是只运行 bot-to-bot QA 通道。
|
||||
- `--slack-url <url>` 打开指定 Slack Web URL。若未提供,当 SUT bot token 可用时,Mantis 会从 Slack `auth.test` 派生 `https://app.slack.com/client/<team>/<channel>`。
|
||||
- `--slack-channel-id <id>` 控制 Gateway 网关设置使用的 Slack 渠道 allowlist。
|
||||
- `OPENCLAW_MANTIS_SLACK_BROWSER_PROFILE_DIR` 控制 VM 内的持久 Chrome profile。默认值为 `$HOME/.config/openclaw-mantis/slack-chrome-profile`,因此手动 Slack Web 登录会在同一 lease 的重新运行中保留。
|
||||
- `--credential-source convex --credential-role ci` 使用共享凭证池,而不是直接使用 Slack 环境变量 token。
|
||||
- `--provider-mode`、`--model`、`--alt-model` 和 `--fast` 会透传给 Slack 实时通道。
|
||||
|
||||
GitHub smoke workflow 是 `Mantis Discord Smoke`。第一个真实场景的 before 和 after GitHub workflow 是 `Mantis Discord Status Reactions`。它接受:
|
||||
|
||||
- `baseline_ref`:预期会复现 queued-only 行为的 ref。
|
||||
- `candidate_ref`:预期会显示 `queued -> thinking -> done` 的 ref。
|
||||
|
||||
它会检出工作流 harness ref,构建独立的基线和候选 worktree,针对每个 worktree 运行 `discord-status-reactions-tool-only`,并将 `baseline/`、`candidate/`、`comparison.json` 和 `mantis-report.md` 作为 Actions 工件上传。它还会在 Crabbox 桌面浏览器中渲染每条通道的时间线 HTML,并在 PR 评论中将这些 VNC 截图与确定性的时间线 PNG 一起发布。该工作流会从 `openclaw/crabbox` main 构建 Crabbox CLI,以便在下一个 Crabbox 二进制版本发布之前使用当前的桌面/浏览器 lease 标志。
|
||||
它会 checkout workflow harness ref,构建单独的基线和候选 worktree,针对每个 worktree 运行 `discord-status-reactions-tool-only`,并将 `baseline/`、`candidate/`、`comparison.json` 和 `mantis-report.md` 作为 Actions 工件上传。它还会在 Crabbox 桌面浏览器中渲染每条通道的时间线 HTML,并在 PR 评论中将这些 VNC 截图与确定性的时间线 PNG 一起发布。该 workflow 会从 `openclaw/crabbox` main 构建 Crabbox CLI,以便在下一个 Crabbox 二进制 release 发布前使用当前桌面/browser lease 标志。
|
||||
|
||||
你也可以直接从 PR 评论触发 Status 回应运行:
|
||||
你也可以直接从 PR 评论触发 status-reactions 运行:
|
||||
|
||||
```text
|
||||
@Mantis discord status reactions
|
||||
```
|
||||
|
||||
评论触发器有意保持狭窄。它只会在具有 write、maintain 或 admin 访问权限的用户发布的拉取请求评论上运行,并且只识别 Discord Status 回应请求。默认情况下,它使用已知有问题的基线 ref,并将当前 PR head SHA 作为候选。维护者可以覆盖任一 ref:
|
||||
评论触发器刻意保持窄范围。它只会在拥有 write、maintain 或 admin 访问权限的用户发出的 pull request 评论上运行,并且只识别 Discord status-reaction 请求。默认情况下,它使用已知有问题的基线 ref 和当前 PR head SHA 作为候选。维护者可以覆盖任一 ref:
|
||||
|
||||
```text
|
||||
@Mantis discord status reactions baseline=origin/main candidate=HEAD
|
||||
@ -115,45 +147,45 @@ ClawSweeper 命令示例:
|
||||
@clawsweeper verify e2e discord
|
||||
```
|
||||
|
||||
第一个命令是显式且聚焦场景的。第二个命令稍后可以根据标签、已更改文件和 ClawSweeper 评审发现,将 PR 或 issue 映射到推荐的 Mantis 场景。
|
||||
第一个命令是显式且聚焦场景的。第二个之后可以从标签、变更文件和 ClawSweeper review 发现,将 PR 或 issue 映射到推荐的 Mantis 场景。
|
||||
|
||||
## 运行生命周期
|
||||
|
||||
1. 获取凭证。
|
||||
2. 分配或复用 VM。
|
||||
3. 当场景需要 UI 证据时,准备桌面/浏览器配置文件。
|
||||
4. 为基线 ref 准备干净检出。
|
||||
3. 当场景需要 UI 证据时,准备桌面/browser profile。
|
||||
4. 为基线 ref 准备干净 checkout。
|
||||
5. 安装依赖,并只构建场景需要的内容。
|
||||
6. 使用隔离状态目录启动一个子 OpenClaw Gateway 网关。
|
||||
7. 配置实时传输协议、提供商、模型和浏览器配置文件。
|
||||
6. 使用隔离状态目录启动子 OpenClaw Gateway 网关。
|
||||
7. 配置实时传输协议、提供商、模型和 browser profile。
|
||||
8. 运行场景并捕获基线证据。
|
||||
9. 停止 Gateway 网关并保留日志。
|
||||
10. 在同一 VM 中准备候选 ref。
|
||||
11. 运行相同场景并捕获候选证据。
|
||||
12. 比较判定器结果和视觉证据。
|
||||
12. 对比判定器结果和视觉证据。
|
||||
13. 写入 Markdown、JSON、日志、截图和可选 trace 工件。
|
||||
14. 上传 GitHub Actions 工件。
|
||||
15. 发布简洁的 PR 或 Discord Status 消息。
|
||||
15. 发布简洁 PR 或 Discord Status 消息。
|
||||
|
||||
场景应能够以两种不同方式失败:
|
||||
场景应该能够以两种不同方式失败:
|
||||
|
||||
- **Bug 已复现**:基线以预期方式失败。
|
||||
- **Harness 失败**:在 bug 判定器具有意义之前,环境设置、凭证、Discord API、浏览器或提供商失败。
|
||||
- **Harness 失败**:环境设置、凭证、Discord API、浏览器或提供商在 bug 判定器有意义之前失败。
|
||||
|
||||
最终报告必须区分这些情况,避免维护者将不稳定环境与产品行为混淆。
|
||||
最终报告必须区分这些情况,这样维护者就不会把不稳定环境与产品行为混淆。
|
||||
|
||||
## Discord MVP
|
||||
|
||||
第一个场景应针对公会频道中的 Discord Status 回应,其中源回复投递模式为 `message_tool_only`。
|
||||
第一个场景应以源回复投递模式为 `message_tool_only` 的服务器渠道中的 Discord Status reaction 为目标。
|
||||
|
||||
它是一个好的 Mantis 种子,原因如下:
|
||||
它适合作为 Mantis 种子场景的原因:
|
||||
|
||||
- 它在 Discord 中以触发消息上的回应形式可见。
|
||||
- 它通过 Discord 消息回应状态提供强 REST 判定器。
|
||||
- 它会覆盖真实 OpenClaw Gateway 网关、Discord 机器人凭证、消息分派、源回复投递模式、Status 回应状态和模型回合生命周期。
|
||||
- 它足够狭窄,可以让首个实现保持可靠。
|
||||
- 它在 Discord 中以触发消息上的 reaction 可见。
|
||||
- 它通过 Discord 消息 reaction 状态具备强 REST 判定器。
|
||||
- 它会覆盖真实 OpenClaw Gateway 网关、Discord bot 凭证、消息分发、源回复投递模式、Status reaction 状态和模型 turn 生命周期。
|
||||
- 它足够窄,可以让首个实现保持诚实。
|
||||
|
||||
预期场景形式:
|
||||
预期场景形态:
|
||||
|
||||
```yaml
|
||||
id: discord-status-reactions-tool-only
|
||||
@ -184,9 +216,9 @@ evidence:
|
||||
screenshotMessageRow: true
|
||||
```
|
||||
|
||||
基线证据应显示 queued 确认回应,但在 tool-only 模式中没有生命周期转换。候选证据应显示当 `messages.statusReactions.enabled` 显式为 true 时运行的生命周期 Status 回应。
|
||||
基线证据应显示 queued 确认 reaction,但在 tool-only 模式下没有生命周期转换。候选证据应显示当 `messages.statusReactions.enabled` 显式为 true 时,生命周期 Status reaction 会运行。
|
||||
|
||||
可执行的首个切片是选择启用的 Discord 实时 QA 场景:
|
||||
可执行的第一个切片是 opt-in Discord 实时 QA 场景:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa discord \
|
||||
@ -198,23 +230,24 @@ pnpm openclaw qa discord \
|
||||
--output-dir .artifacts/qa-e2e/mantis/discord-status-reactions-candidate
|
||||
```
|
||||
|
||||
它会使用始终开启的公会处理、`visibleReplies: "message_tool"`、`ackReaction: "👀"` 和显式 Status 回应来配置 SUT。判定器会轮询真实 Discord 触发消息,并期望观察到的序列为 `👀 -> 🤔 -> 👍`。工件包括 `discord-qa-reaction-timelines.json`、`discord-status-reactions-tool-only-timeline.html` 和 `discord-status-reactions-tool-only-timeline.png`。
|
||||
它会将 SUT 配置为始终开启 guild 处理、`visibleReplies:
|
||||
"message_tool"`、`ackReaction: "👀"`,以及显式状态 reaction。预言机会轮询真实的 Discord 触发消息,并期望观察到序列 `👀 -> 🤔 -> 👍`。工件包括 `discord-qa-reaction-timelines.json`、`discord-status-reactions-tool-only-timeline.html` 和 `discord-status-reactions-tool-only-timeline.png`。
|
||||
|
||||
## 现有 QA 组件
|
||||
|
||||
Mantis 应基于现有私有 QA 栈构建,而不是从零开始:
|
||||
|
||||
- `pnpm openclaw qa discord` 已经使用 driver 和 SUT 机器人运行一个实时 Discord 通道。
|
||||
- 实时传输协议运行器已经在 `.artifacts/qa-e2e/` 下写入报告和观测消息工件。
|
||||
- Convex 凭证 lease 已经为共享实时传输协议凭证提供独占访问。
|
||||
- 浏览器控制服务已经支持截图、快照、无头托管配置文件和远程 CDP 配置文件。
|
||||
- QA Lab 已经有用于传输协议形态测试的调试器 UI 和总线。
|
||||
- `pnpm openclaw qa discord` 已经运行带有驱动和 SUT bot 的实时 Discord 通道。
|
||||
- 实时传输运行器已经会在 `.artifacts/qa-e2e/` 下写入报告和观察到的消息工件。
|
||||
- Convex 凭证租约已经提供对共享实时传输凭证的独占访问。
|
||||
- 浏览器控制服务已经支持截图、快照、无头托管 profile 和远程 CDP profile。
|
||||
- QA Lab 已经有用于传输形态测试的调试器 UI 和总线。
|
||||
|
||||
第一个 Mantis 实现可以是在这些组件之上的薄 before/after 运行器,再加上一层视觉证据。
|
||||
第一个 Mantis 实现可以是这些组件之上的一个轻量 before/after 运行器,再加上一层视觉证据。
|
||||
|
||||
## 证据模型
|
||||
|
||||
每次运行都会写入稳定的工件目录:
|
||||
每次运行都会写入一个稳定的工件目录:
|
||||
|
||||
```text
|
||||
.artifacts/qa-e2e/mantis/<run-id>/
|
||||
@ -234,65 +267,65 @@ Mantis 应基于现有私有 QA 栈构建,而不是从零开始:
|
||||
run.log
|
||||
```
|
||||
|
||||
`mantis-summary.json` 应是机器可读的事实来源。Markdown 报告用于 PR 评论和人工评审。
|
||||
`mantis-summary.json` 应该是机器可读的事实来源。Markdown 报告用于 PR 评论和人工审查。
|
||||
|
||||
摘要必须包括:
|
||||
摘要必须包含:
|
||||
|
||||
- 测试过的 ref 和 SHA
|
||||
- 传输协议和场景 id
|
||||
- 机器提供商和机器 id 或 lease id
|
||||
- 不含密钥值的凭证来源
|
||||
- 基线结果
|
||||
- 候选结果
|
||||
- bug 是否已在基线上复现
|
||||
- 候选是否修复了它
|
||||
- 已测试的 ref 和 SHA
|
||||
- 传输和场景 id
|
||||
- 机器提供商以及机器 id 或租约 id
|
||||
- 不含 secret 值的凭证来源
|
||||
- baseline 结果
|
||||
- candidate 结果
|
||||
- bug 是否在 baseline 上复现
|
||||
- candidate 是否修复了它
|
||||
- 工件路径
|
||||
- 已清理的设置或清理问题
|
||||
- 已脱敏的设置或清理问题
|
||||
|
||||
截图是证据,不是密钥。它们仍需要遵守脱敏纪律:可能会出现私有频道名称、用户名或消息内容。对于公开 PR,在脱敏方案更完善之前,优先使用 GitHub Actions 工件链接,而不是内联图片。
|
||||
截图是证据,不是 secret。它们仍然需要遵守脱敏纪律:私有 channel 名称、用户名或消息内容可能会出现。对于公开 PR,在脱敏方案更完善之前,优先使用 GitHub Actions 工件链接,而不是内联图片。
|
||||
|
||||
## 浏览器和 VNC
|
||||
|
||||
浏览器通道有两种模式:
|
||||
|
||||
- **无头自动化**:CI 的默认模式。Chrome 启用 CDP 运行,并由 Playwright 或 OpenClaw 浏览器控制捕获截图。
|
||||
- **无头自动化**:CI 默认模式。Chrome 会启用 CDP,Playwright 或 OpenClaw 浏览器控制会捕获截图。
|
||||
- **VNC 救援**:当登录、MFA、Discord 反自动化或视觉调试需要人工介入时,在同一 VM 上启用。
|
||||
|
||||
Discord 观察者浏览器配置文件应足够持久,避免每次运行都要登录,但要与个人浏览器状态隔离。配置文件属于 Mantis 机器池,而不是开发者笔记本电脑。
|
||||
Discord 观察者浏览器 profile 应该足够持久,避免每次运行都登录,但要与个人浏览器状态隔离。profile 属于 Mantis 机器池,而不是开发者笔记本。
|
||||
|
||||
当 Mantis 卡住时,它会发布一条 Discord 状态消息,其中包含:
|
||||
|
||||
- 运行 ID
|
||||
- 场景 ID
|
||||
- 运行 id
|
||||
- 场景 id
|
||||
- 机器提供商
|
||||
- 构件目录
|
||||
- 工件目录
|
||||
- VNC 或 noVNC 连接说明(如果可用)
|
||||
- 简短阻塞原因文本
|
||||
- 简短阻塞说明
|
||||
|
||||
首次私有部署可以先把这些消息发布到现有操作员渠道,之后再迁移到专用 Mantis 渠道。
|
||||
第一个私有部署可以将这些消息发布到现有 operator channel,之后再迁移到专用 Mantis channel。
|
||||
|
||||
## 机器
|
||||
|
||||
Mantis 的首个远程实现应优先通过 Crabbox 使用 AWS。Crabbox 为我们提供预热机器、租约跟踪、水合、日志、结果和清理。如果 AWS 容量太慢或不可用,请在同一机器接口后添加 Hetzner 提供商。
|
||||
Mantis 的第一个远程实现应优先通过 Crabbox 使用 AWS。Crabbox 为我们提供预热机器、租约跟踪、hydration、日志、结果和清理。如果 AWS 容量太慢或不可用,则在同一个机器接口后面添加 Hetzner 提供商。
|
||||
|
||||
最低 VM 要求:
|
||||
|
||||
- Linux,并安装支持桌面的 Chrome 或 Chromium
|
||||
- CDP 访问权限,用于浏览器自动化
|
||||
- VNC 或 noVNC,用于救援
|
||||
- 用于浏览器自动化的 CDP 访问
|
||||
- 用于救援的 VNC 或 noVNC
|
||||
- Node 22 和 pnpm
|
||||
- OpenClaw 检出和依赖缓存
|
||||
- OpenClaw checkout 和依赖缓存
|
||||
- 使用 Playwright 时的 Playwright Chromium 浏览器缓存
|
||||
- 足够的 CPU 和内存,用于一个 OpenClaw Gateway 网关、一个浏览器和一次模型运行
|
||||
- 可出站访问 Discord、GitHub、模型提供商和凭证代理
|
||||
- 足够运行一个 OpenClaw Gateway 网关、一个浏览器和一次模型运行的 CPU 和内存
|
||||
- 能够出站访问 Discord、GitHub、模型提供商和凭证代理
|
||||
|
||||
VM 不应在预期凭证或浏览器配置文件存储之外保留长期有效的原始密钥。
|
||||
VM 不应在预期的凭证或浏览器 profile 存储之外保留长期原始 secret。
|
||||
|
||||
## 密钥
|
||||
## Secret
|
||||
|
||||
远程运行的密钥存放在 GitHub 组织或仓库密钥中,本地运行的密钥存放在由本地操作员控制的密钥文件中。
|
||||
远程运行的 secret 存在 GitHub 组织或仓库 secret 中,本地运行的 secret 存在由本地 operator 控制的 secret 文件中。
|
||||
|
||||
推荐的密钥名称:
|
||||
推荐的 secret 名称:
|
||||
|
||||
- `OPENCLAW_QA_DISCORD_MANTIS_BOT_TOKEN`
|
||||
- `OPENCLAW_QA_DISCORD_DRIVER_BOT_TOKEN`
|
||||
@ -300,34 +333,34 @@ VM 不应在预期凭证或浏览器配置文件存储之外保留长期有效
|
||||
- `OPENCLAW_QA_DISCORD_GUILD_ID`
|
||||
- `OPENCLAW_QA_DISCORD_CHANNEL_ID`
|
||||
- `OPENCLAW_QA_DISCORD_NOTIFY_CHANNEL_ID`
|
||||
- `OPENCLAW_QA_REDACT_PUBLIC_METADATA=1`,用于公开 GitHub 构件上传
|
||||
- `OPENCLAW_QA_REDACT_PUBLIC_METADATA=1`,用于公开 GitHub 工件上传
|
||||
- `OPENCLAW_QA_CONVEX_SITE_URL`
|
||||
- `OPENCLAW_QA_CONVEX_SECRET_CI`
|
||||
- `OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR`
|
||||
- `OPENCLAW_QA_MANTIS_CRABBOX_COORDINATOR_TOKEN`
|
||||
|
||||
长期来看,Convex 凭证池应继续作为实时传输凭证的常规来源。GitHub 密钥用于引导代理和回退通道。Discord 状态反应工作流会把 Mantis Crabbox 密钥映射回 Crabbox CLI 预期的 `CRABBOX_COORDINATOR` 和 `CRABBOX_COORDINATOR_TOKEN` 环境变量。纯 `CRABBOX_*` GitHub 密钥名称仍会作为兼容性回退被接受。
|
||||
长期来看,Convex 凭证池应继续作为实时传输凭证的常规来源。GitHub secret 用于引导代理和 fallback 通道。Discord 状态 reaction 工作流会将 Mantis Crabbox secret 映射回 Crabbox CLI 期望的 `CRABBOX_COORDINATOR` 和 `CRABBOX_COORDINATOR_TOKEN` 环境变量。普通的 `CRABBOX_*` GitHub secret 名称仍会作为兼容 fallback 被接受。
|
||||
|
||||
Mantis 运行器绝不能打印:
|
||||
|
||||
- Discord 机器人令牌
|
||||
- Discord bot token
|
||||
- 提供商 API key
|
||||
- 浏览器 Cookie
|
||||
- 认证配置文件内容
|
||||
- 浏览器 cookie
|
||||
- auth profile 内容
|
||||
- VNC 密码
|
||||
- 原始凭证载荷
|
||||
- 原始凭证 payload
|
||||
|
||||
公开构件上传还应遮盖 Discord 目标元数据,例如机器人、服务器、频道和消息 ID。GitHub 烟测工作流因此启用了 `OPENCLAW_QA_REDACT_PUBLIC_METADATA=1`。
|
||||
公开工件上传还应脱敏 Discord 目标元数据,例如 bot、guild、channel 和 message id。GitHub smoke 工作流因此启用了 `OPENCLAW_QA_REDACT_PUBLIC_METADATA=1`。
|
||||
|
||||
如果令牌被意外粘贴到 issue、PR、聊天或日志中,请在新密钥存储完成后轮换该令牌。
|
||||
如果 token 被意外粘贴到 issue、PR、聊天或日志中,请在存储新的 secret 后轮换它。
|
||||
|
||||
## GitHub 构件和 PR 评论
|
||||
## GitHub 工件和 PR 评论
|
||||
|
||||
Mantis 工作流应将完整证据包作为短期 Actions 构件上传。当工作流针对 bug 报告或修复 PR 运行时,还应将已遮盖的 PNG 截图发布到 `qa-artifacts` 分支,并在对应 bug 或修复 PR 上更新插入一条评论,内联展示修复前/修复后截图。不要只把主要证明发布在通用 QA 自动化 PR 上。原始日志、观察到的消息和其他体积较大的证据保留在 Actions 构件中。
|
||||
Mantis 工作流应将完整证据包作为短期 Actions 工件上传。当工作流针对 bug 报告或修复 PR 运行时,还应将脱敏后的 PNG 截图发布到 `qa-artifacts` 分支,并在对应 bug 或修复 PR 上 upsert 一条包含内联 before/after 截图的评论。不要只把主要证明发布到通用 QA 自动化 PR。原始日志、观察到的消息和其他大型证据保留在 Actions 工件中。
|
||||
|
||||
生产工作流应使用 Mantis GitHub App 发布这些评论,而不是使用 `github-actions[bot]`。将应用 ID 和私钥作为 `MANTIS_GITHUB_APP_ID` 与 `MANTIS_GITHUB_APP_PRIVATE_KEY` GitHub Actions 密钥存储。工作流使用隐藏标记作为更新插入键;当令牌可以编辑评论时更新该评论;当较早的机器人所有标记无法编辑时,创建一条新的 Mantis 所有评论。
|
||||
生产工作流应使用 Mantis GitHub App 发布这些评论,而不是使用 `github-actions[bot]`。将 app id 和私钥作为 `MANTIS_GITHUB_APP_ID` 和 `MANTIS_GITHUB_APP_PRIVATE_KEY` GitHub Actions secret 存储。工作流使用隐藏标记作为 upsert key,当 token 可以编辑时更新该评论;当较旧的 bot 所有标记无法编辑时,创建一条新的 Mantis 所有评论。
|
||||
|
||||
PR 评论应简短且视觉化:
|
||||
PR 评论应简短且可视化:
|
||||
|
||||
```md
|
||||
Mantis Discord Status Reactions QA
|
||||
@ -347,60 +380,60 @@ candidate showed the expected queued -> thinking -> done sequence.
|
||||
| <inline screenshot> | <inline screenshot> |
|
||||
```
|
||||
|
||||
当运行失败是因为 harness 失败时,评论必须说明这一点,而不是暗示候选修复失败。
|
||||
当运行因为 harness 失败而失败时,评论必须明确说明这一点,而不是暗示 candidate 失败。
|
||||
|
||||
## 私有部署说明
|
||||
|
||||
私有部署可能已经有一个 Mantis Discord 应用。如果该应用具备正确的机器人权限并且可以安全轮换,请复用该应用,而不是再创建一个应用。
|
||||
私有部署可能已经有一个 Mantis Discord application。如果该 application 拥有正确的 bot 权限并且可以安全轮换,请复用它,而不是创建另一个 app。
|
||||
|
||||
通过密钥或部署配置设置初始操作员通知渠道。它可以先指向现有维护者或运维渠道,等专用 Mantis 渠道存在后再迁移过去。
|
||||
通过 secret 或部署配置设置初始 operator 通知 channel。它可以先指向现有 maintainer 或 operations channel,等专用 Mantis channel 存在后再迁移过去。
|
||||
|
||||
不要把服务器 ID、频道 ID、机器人令牌、浏览器 Cookie 或 VNC 密码放入本文档。请将它们存放在 GitHub 密钥、凭证代理或操作员的本地密钥存储中。
|
||||
不要把 guild id、channel id、bot token、浏览器 cookie 或 VNC 密码放进本文档。将它们存储在 GitHub secret、凭证代理或 operator 的本地 secret 存储中。
|
||||
|
||||
## 添加场景
|
||||
|
||||
Mantis 场景应声明:
|
||||
|
||||
- ID 和标题
|
||||
- 传输协议
|
||||
- id 和标题
|
||||
- 传输
|
||||
- 所需凭证
|
||||
- 基线引用策略
|
||||
- 候选引用策略
|
||||
- baseline ref 策略
|
||||
- candidate ref 策略
|
||||
- OpenClaw 配置补丁
|
||||
- 设置步骤
|
||||
- 刺激输入
|
||||
- 预期基线判定器
|
||||
- 预期候选判定器
|
||||
- 刺激
|
||||
- 预期 baseline 预言机
|
||||
- 预期 candidate 预言机
|
||||
- 视觉捕获目标
|
||||
- 超时预算
|
||||
- 清理步骤
|
||||
|
||||
场景应优先使用小型、带类型的判定器:
|
||||
场景应优先使用小型、类型化的预言机:
|
||||
|
||||
- 用于反应 bug 的 Discord 反应状态
|
||||
- 用于串线 bug 的 Discord 消息引用
|
||||
- 用于 Slack bug 的 Slack 线程 ts 和反应 API 状态
|
||||
- 用于电子邮件 bug 的电子邮件消息 ID 和标头
|
||||
- 当 UI 是唯一可靠可观察对象时使用浏览器截图
|
||||
- reaction bug 使用 Discord reaction 状态
|
||||
- threading bug 使用 Discord 消息引用
|
||||
- Slack bug 使用 Slack thread ts 和 reaction API 状态
|
||||
- email bug 使用 email message id 和 header
|
||||
- 当 UI 是唯一可靠可观测对象时使用浏览器截图
|
||||
|
||||
视觉检查应是附加的。如果平台 API 可以证明 bug,请使用该 API 作为通过/失败判定器,并保留截图以增强人工信心。
|
||||
视觉检查应是附加的。如果平台 API 可以证明 bug,请将 API 用作通过/失败预言机,并保留截图用于增强人工信心。
|
||||
|
||||
## 提供商扩展
|
||||
|
||||
在 Discord 之后,同一运行器可以添加:
|
||||
Discord 之后,同一个运行器可以添加:
|
||||
|
||||
- Slack:反应、线程、应用提及、模态框、文件上传。
|
||||
- 电子邮件:Gmail 认证,以及在连接器不足时使用 `gog` 进行消息串线。
|
||||
- WhatsApp:二维码登录、重新识别、消息送达、媒体、反应。
|
||||
- Telegram:群组提及门控、命令、反应(如可用)。
|
||||
- Matrix:加密房间、线程或回复关系、重启恢复。
|
||||
- Slack:reaction、thread、app mention、modal、文件上传。
|
||||
- Email:在 connector 不足时,使用 `gog` 进行 Gmail auth 和消息 threading。
|
||||
- WhatsApp:二维码登录、重新识别、消息投递、媒体、reaction。
|
||||
- Telegram:群组 mention gating、command、可用时的 reaction。
|
||||
- Matrix:加密房间、thread 或 reply relation、重启恢复。
|
||||
|
||||
每种传输协议都应有一个低成本烟测场景,以及一个或多个 bug 类场景。昂贵的视觉场景应保持为选择性启用。
|
||||
每种传输都应有一个低成本 smoke 场景,以及一个或多个 bug 类别场景。昂贵的视觉场景应保持 opt-in。
|
||||
|
||||
## 待解决问题
|
||||
## 未决问题
|
||||
|
||||
- 复用现有 Mantis 机器人时,哪个 Discord 机器人应作为驱动,哪个应作为 SUT?
|
||||
- 第一阶段中,观察者浏览器登录应使用真人 Discord 账号、测试账号,还是仅使用机器人可读的 REST 证据?
|
||||
- GitHub 应为 PR 保留 Mantis 构件多久?
|
||||
- ClawSweeper 什么时候应自动推荐 Mantis,而不是等待维护者命令?
|
||||
- 面向公开 PR 上传之前,截图是否应被遮盖或裁剪?
|
||||
- 复用现有 Mantis bot 时,哪个 Discord bot 应该作为 driver,哪个应该作为 SUT?
|
||||
- 第一阶段,观察者浏览器登录应使用人类 Discord 账户、测试账户,还是只使用 bot 可读的 REST 证据?
|
||||
- GitHub 应为 PR 保留 Mantis 工件多长时间?
|
||||
- ClawSweeper 应在什么时候自动推荐 Mantis,而不是等待 maintainer 命令?
|
||||
- 公开 PR 上传前,截图是否应该脱敏或裁剪?
|
||||
|
||||
@ -1,61 +1,61 @@
|
||||
---
|
||||
read_when:
|
||||
- 了解 QA 栈如何协同工作
|
||||
- 扩展 qa-lab、qa-channel 或传输协议适配器
|
||||
- 添加由仓库支持的 QA 场景
|
||||
- 围绕 Gateway 网关仪表板构建更高真实度的 QA 自动化
|
||||
summary: QA 栈概览:qa-lab、qa-channel、由仓库支撑的场景、实时传输通道、传输适配器和报告。
|
||||
- 扩展 qa-lab、qa-channel 或传输适配器
|
||||
- 添加基于仓库的 QA 场景
|
||||
- 围绕 Gateway 网关仪表盘构建更高真实度的 QA 自动化
|
||||
summary: QA stack 概览:qa-lab、qa-channel、由仓库支持的场景、实时传输通道、传输适配器和报告。
|
||||
title: QA overview
|
||||
x-i18n:
|
||||
generated_at: "2026-05-04T00:35:07Z"
|
||||
generated_at: "2026-05-04T02:52:01Z"
|
||||
model: gpt-5.5
|
||||
provider: openai
|
||||
source_hash: 0b376767b967a51cc8a45ca5ce420f78067b52e6368d2abe921ffed533f6f9ba
|
||||
source_hash: 067f5aa0831724659ae36d548ef2e7bd28b40aad9cef45f325a01a2748003b29
|
||||
source_path: concepts/qa-e2e-automation.md
|
||||
workflow: 16
|
||||
---
|
||||
|
||||
私有 QA 栈旨在以比单个单元测试更接近真实、符合渠道形态的方式来演练 OpenClaw。
|
||||
私有 QA 栈旨在以比单个单元测试更贴近真实、类似渠道形态的方式来测试 OpenClaw。
|
||||
|
||||
当前组成部分:
|
||||
|
||||
- `extensions/qa-channel`:合成消息渠道,覆盖私信、渠道、线程、回应、编辑和删除表面。
|
||||
- `extensions/qa-lab`:调试器 UI 和 QA 总线,用于观察对话记录、注入入站消息,并导出 Markdown 报告。
|
||||
- `extensions/qa-matrix`、未来的运行器插件:实时传输协议适配器,用于在子 QA Gateway 网关内驱动真实渠道。
|
||||
- `qa/`:由仓库支持的启动任务和基线 QA 场景种子资产。
|
||||
- [Mantis](/zh-CN/concepts/mantis):针对需要真实传输协议、浏览器截图、VM 状态和 PR 证据的 bug,进行修复前后实时验证。
|
||||
- `extensions/qa-channel`:合成消息渠道,包含私信、渠道、线程、反应、编辑和删除界面。
|
||||
- `extensions/qa-lab`:调试器 UI 和 QA 总线,用于观察转录记录、注入入站消息,并导出 Markdown 报告。
|
||||
- `extensions/qa-matrix`、未来的运行器插件:实时传输适配器,用于在子 QA Gateway 网关内驱动真实渠道。
|
||||
- `qa/`:由仓库托管的种子资源,用于启动任务和基线 QA 场景。
|
||||
- [Mantis](/zh-CN/concepts/mantis):针对需要真实传输、浏览器截图、VM 状态和 PR 证据的 bug,进行修复前后实时验证。
|
||||
|
||||
## 命令界面
|
||||
|
||||
每个 QA 流程都在 `pnpm openclaw qa <subcommand>` 下运行。许多命令有 `pnpm qa:*` 脚本别名;两种形式都受支持。
|
||||
每个 QA 流程都在 `pnpm openclaw qa <subcommand>` 下运行。许多流程都有 `pnpm qa:*` 脚本别名;两种形式都受支持。
|
||||
|
||||
| 命令 | 用途 |
|
||||
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `qa run` | 内置 QA 自检;写入 Markdown 报告。 |
|
||||
| `qa suite` | 针对 QA Gateway 网关通道运行由仓库支持的场景。别名:`pnpm openclaw qa suite --runner multipass`,用于一次性 Linux VM。 |
|
||||
| `qa coverage` | 打印 Markdown 场景覆盖清单(`--json` 用于机器输出)。 |
|
||||
| `qa parity-report` | 比较两个 `qa-suite-summary.json` 文件,并写入智能体一致性报告。 |
|
||||
| `qa character-eval` | 跨多个实时模型运行角色 QA 场景,并生成评审报告。参见[报告](#reporting)。 |
|
||||
| `qa manual` | 针对所选提供商/模型通道运行一次性提示。 |
|
||||
| `qa ui` | 启动 QA 调试器 UI 和本地 QA 总线(别名:`pnpm qa:lab:ui`)。 |
|
||||
| `qa docker-build-image` | 构建预烘焙的 QA Docker 镜像。 |
|
||||
| `qa docker-scaffold` | 为 QA 仪表板 + Gateway 网关通道写入 docker-compose 脚手架。 |
|
||||
| `qa up` | 构建 QA 站点,启动 Docker 支持的栈,打印 URL(别名:`pnpm qa:lab:up`;`:fast` 变体会添加 `--use-prebuilt-image --bind-ui-dist --skip-ui-build`)。 |
|
||||
| `qa aimock` | 仅启动 AIMock provider 服务器。 |
|
||||
| `qa mock-openai` | 仅启动具备场景感知的 `mock-openai` provider 服务器。 |
|
||||
| `qa credentials doctor` / `add` / `list` / `remove` | 管理共享的 Convex 凭证池。 |
|
||||
| `qa matrix` | 针对一次性 Tuwunel homeserver 的实时传输协议通道。参见 [Matrix QA](/zh-CN/concepts/qa-matrix)。 |
|
||||
| `qa telegram` | 针对真实私有 Telegram 群组的实时传输协议通道。 |
|
||||
| `qa discord` | 针对真实私有 Discord guild 渠道的实时传输协议通道。 |
|
||||
| `qa slack` | 针对真实私有 Slack 渠道的实时传输协议通道。 |
|
||||
| `qa mantis` | 面向实时传输协议 bug 的修复前后验证运行器,包含 Discord 状态回应证据和 Crabbox 桌面/浏览器冒烟测试。参见 [Mantis](/zh-CN/concepts/mantis)。 |
|
||||
| 命令 | 用途 |
|
||||
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `qa run` | 内置 QA 自检;写入 Markdown 报告。 |
|
||||
| `qa suite` | 针对 QA Gateway 网关运行通道运行仓库托管的场景。别名:`pnpm openclaw qa suite --runner multipass`,用于一次性 Linux VM。 |
|
||||
| `qa coverage` | 打印 Markdown 场景覆盖清单(使用 `--json` 输出机器可读内容)。 |
|
||||
| `qa parity-report` | 比较两个 `qa-suite-summary.json` 文件并写入智能体一致性报告。 |
|
||||
| `qa character-eval` | 在多个实时模型上运行角色 QA 场景,并生成带评审的报告。参见[报告](#reporting)。 |
|
||||
| `qa manual` | 针对所选提供商/模型运行通道运行一次性提示。 |
|
||||
| `qa ui` | 启动 QA 调试器 UI 和本地 QA 总线(别名:`pnpm qa:lab:ui`)。 |
|
||||
| `qa docker-build-image` | 构建预制 QA Docker 镜像。 |
|
||||
| `qa docker-scaffold` | 写入 QA 仪表板 + Gateway 网关运行通道的 docker-compose 脚手架。 |
|
||||
| `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 matrix` | 针对一次性 Tuwunel homeserver 的实时传输运行通道。参见 [Matrix QA](/zh-CN/concepts/qa-matrix)。 |
|
||||
| `qa telegram` | 针对真实私有 Telegram 群组的实时传输运行通道。 |
|
||||
| `qa discord` | 针对真实私有 Discord guild 渠道的实时传输运行通道。 |
|
||||
| `qa slack` | 针对真实私有 Slack 渠道的实时传输运行通道。 |
|
||||
| `qa mantis` | 面向实时传输 bug 的修复前后验证运行器,包含 Discord 状态反应证据、Crabbox 桌面/浏览器冒烟测试,以及 Slack-in-VNC 冒烟测试。参见 [Mantis](/zh-CN/concepts/mantis)。 |
|
||||
|
||||
## 操作者流程
|
||||
## 操作员流程
|
||||
|
||||
当前 QA 操作者流程是一个双栏 QA 站点:
|
||||
当前 QA 操作员流程是一个双面板 QA 站点:
|
||||
|
||||
- 左侧:带有智能体的 Gateway 网关仪表板(Control UI)。
|
||||
- 右侧:QA Lab,显示类似 Slack 的对话记录和场景计划。
|
||||
- 右侧:QA Lab,显示类似 Slack 的转录记录和场景计划。
|
||||
|
||||
运行方式:
|
||||
|
||||
@ -63,9 +63,9 @@ x-i18n:
|
||||
pnpm qa:lab:up
|
||||
```
|
||||
|
||||
这会构建 QA 站点,启动 Docker 支持的 Gateway 网关通道,并暴露 QA Lab 页面,操作者或自动化循环可以在此给智能体分配 QA 任务、观察真实渠道行为,并记录哪些内容有效、失败或仍被阻塞。
|
||||
该命令会构建 QA 站点,启动 Docker 支撑的 Gateway 网关运行通道,并公开 QA Lab 页面,操作员或自动化循环可以在其中给智能体下发 QA 任务、观察真实渠道行为,并记录哪些内容有效、失败或仍被阻塞。
|
||||
|
||||
若要在不每次都重建 Docker 镜像的情况下更快迭代 QA Lab UI,请使用绑定挂载的 QA Lab bundle 启动栈:
|
||||
若要更快地迭代 QA Lab UI,而无需每次重建 Docker 镜像,请使用绑定挂载的 QA Lab 包启动栈:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa docker-build-image
|
||||
@ -74,27 +74,27 @@ 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 资产哈希变化时,浏览器会自动重新加载。
|
||||
`qa:lab:up:fast` 会让 Docker 服务使用预制镜像,并将 `extensions/qa-lab/web/dist` 绑定挂载到 `qa-lab` 容器中。`qa:lab:watch` 会在变更时重建该包,并且浏览器会在 QA Lab 资源哈希变更时自动重新加载。
|
||||
|
||||
若要进行本地 OpenTelemetry 跟踪冒烟测试,请运行:
|
||||
如需进行本地 OpenTelemetry 跟踪冒烟测试,请运行:
|
||||
|
||||
```bash
|
||||
pnpm qa:otel:smoke
|
||||
```
|
||||
|
||||
该脚本会启动本地 OTLP/HTTP 跟踪接收器,在启用 `diagnostics-otel` 插件的情况下运行 `otel-trace-smoke` QA 场景,然后解码导出的 protobuf spans,并断言发布关键形态:必须存在 `openclaw.run`、`openclaw.harness.run`、`openclaw.model.call`、`openclaw.context.assembled` 和 `openclaw.message.delivery`;成功轮次中的模型调用不得导出 `StreamAbandoned`;原始诊断 ID 和 `openclaw.content.*` 属性必须保留在跟踪之外。它会在 QA suite 产物旁边写入 `otel-smoke-summary.json`。
|
||||
该脚本会启动本地 OTLP/HTTP 跟踪接收器,在启用 `diagnostics-otel` 插件的情况下运行 `otel-trace-smoke` QA 场景,然后解码导出的 protobuf span,并断言发布关键形态:必须存在 `openclaw.run`、`openclaw.harness.run`、`openclaw.model.call`、`openclaw.context.assembled` 和 `openclaw.message.delivery`;成功轮次中的模型调用不得导出 `StreamAbandoned`;原始诊断 ID 和 `openclaw.content.*` 属性必须保留在跟踪之外。它会在 QA suite 产物旁写入 `otel-smoke-summary.json`。
|
||||
|
||||
可观测性 QA 仅限源码 checkout。npm tarball 会有意省略 QA Lab,因此包 Docker 发布通道不会运行 `qa` 命令。变更诊断插桩时,请从已构建的源码 checkout 运行 `pnpm qa:otel:smoke`。
|
||||
可观测性 QA 仅保留在源码检出中。npm tarball 会有意省略 QA Lab,因此包 Docker 发布运行通道不会运行 `qa` 命令。更改诊断插桩时,请从已构建的源码检出运行 `pnpm qa:otel:smoke`。
|
||||
|
||||
若要运行真实传输协议 Matrix 冒烟通道,请运行:
|
||||
对于真实传输的 Matrix 冒烟测试运行通道,请运行:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa matrix --profile fast --fail-fast
|
||||
```
|
||||
|
||||
该通道的完整 CLI 参考、profile/场景目录、环境变量和产物布局见 [Matrix QA](/zh-CN/concepts/qa-matrix)。简要来说:它会在 Docker 中预配一次性 Tuwunel homeserver,注册临时 driver/SUT/observer 用户,在限定到该传输协议的子 QA Gateway 网关中运行真实 Matrix 插件(不使用 `qa-channel`),然后在 `.artifacts/qa-e2e/matrix-<timestamp>/` 下写入 Markdown 报告、JSON 摘要、observed-events 产物和合并输出日志。
|
||||
此运行通道的完整 CLI 参考、profile/场景目录、环境变量和产物布局位于 [Matrix QA](/zh-CN/concepts/qa-matrix)。概览:它会在 Docker 中预配一次性 Tuwunel homeserver,注册临时 driver/SUT/observer 用户,在限定到该传输的子 QA Gateway 网关内运行真实 Matrix 插件(无 `qa-channel`),然后在 `.artifacts/qa-e2e/matrix-<timestamp>/` 下写入 Markdown 报告、JSON 摘要、observed-events 产物和合并输出日志。
|
||||
|
||||
对于真实传输协议的 Telegram、Discord 和 Slack 冒烟通道:
|
||||
对于真实传输的 Telegram、Discord 和 Slack 冒烟测试运行通道:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa telegram
|
||||
@ -102,62 +102,73 @@ pnpm openclaw qa discord
|
||||
pnpm openclaw qa slack
|
||||
```
|
||||
|
||||
它们面向已有的真实渠道,并使用两个 bot(driver + SUT)。所需环境变量、场景列表、输出产物和 Convex 凭证池记录在下方的 [Telegram、Discord 和 Slack QA 参考](#telegram-discord-and-slack-qa-reference)中。
|
||||
它们面向一个预先存在的真实渠道,使用两个机器人(driver + SUT)。所需环境变量、场景列表、输出产物和 Convex 凭据池记录在下方的 [Telegram、Discord 和 Slack QA 参考](#telegram-discord-and-slack-qa-reference)中。
|
||||
|
||||
使用池化实时凭证前,请运行:
|
||||
如需运行带 VNC 救援的完整 Slack 桌面 VM,请运行:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa mantis slack-desktop-smoke \
|
||||
--gateway-setup \
|
||||
--scenario slack-canary \
|
||||
--keep-lease
|
||||
```
|
||||
|
||||
该命令会租用一台 Crabbox 桌面/浏览器机器,在 VM 内运行 Slack 实时运行通道,在 VNC 浏览器中打开 Slack Web,捕获桌面,并将 `slack-qa/` 以及 `slack-desktop-smoke.png` 复制回 Mantis 产物目录。通过 VNC 手动登录 Slack Web 后,可复用 `--lease-id <cbx_...>`。使用 `--gateway-setup` 时,Mantis 会在 VM 内保留一个持久的 OpenClaw Slack Gateway 网关,在端口 `38973` 上运行;若不使用该选项,命令会运行普通的 bot-to-bot Slack QA 运行通道,并在产物捕获后退出。
|
||||
|
||||
使用池化实时凭据之前,请运行:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa credentials doctor
|
||||
```
|
||||
|
||||
Doctor 会检查 Convex broker 环境、验证 endpoint 设置,并在存在维护者密钥时验证 admin/list 可达性。它只报告密钥的已设置/缺失状态。
|
||||
Doctor 会检查 Convex broker 环境,验证端点设置,并在维护者密钥存在时验证 admin/list 可达性。它只报告密钥的已设置/缺失状态。
|
||||
|
||||
## 实时传输协议覆盖范围
|
||||
## 实时传输覆盖范围
|
||||
|
||||
实时传输协议通道共享一个契约,而不是各自发明自己的场景列表形态。`qa-channel` 是广泛的合成产品行为 suite,不属于实时传输协议覆盖矩阵。
|
||||
实时传输运行通道共享同一个契约,而不是各自发明自己的场景列表形态。`qa-channel` 是覆盖面广的合成产品行为 suite,并不是实时传输覆盖矩阵的一部分。
|
||||
|
||||
| 通道 | Canary | 提及门控 | Bot 到 bot | Allowlist 阻断 | 顶层回复 | 重启恢复 | 线程跟进 | 线程隔离 | 回应观察 | 帮助命令 | 原生命令注册 |
|
||||
| -------- | ------ | -------- | ---------- | --------------- | -------- | -------- | -------- | -------- | -------- | -------- | ------------ |
|
||||
| Matrix | x | x | x | x | x | x | x | x | x | | |
|
||||
| Telegram | x | x | x | | | | | | | x | |
|
||||
| Discord | x | x | x | | | | | | | | x |
|
||||
| Slack | x | x | x | | | | | | | | |
|
||||
| 运行通道 | 金丝雀 | 提及门控 | Bot-to-bot | 允许列表阻止 | 顶层回复 | 重启恢复 | 线程跟进 | 线程隔离 | 反应观察 | 帮助命令 | 原生命令注册 |
|
||||
| -------- | ------ | -------- | ---------- | ------------ | -------- | -------- | -------- | -------- | -------- | -------- | ------------ |
|
||||
| Matrix | x | x | x | x | x | x | x | x | x | | |
|
||||
| Telegram | x | x | x | | | | | | | x | |
|
||||
| Discord | x | x | x | | | | | | | | x |
|
||||
| Slack | x | x | x | | | | | | | | |
|
||||
|
||||
这会将 `qa-channel` 保持为广泛的产品行为 suite,同时让 Matrix、Telegram 和未来的实时传输协议共享一个明确的传输协议契约检查清单。
|
||||
这会让 `qa-channel` 保持为覆盖面广的产品行为 suite,同时让 Matrix、Telegram 和未来的实时传输共享一份明确的传输契约检查清单。
|
||||
|
||||
若要运行一个不把 Docker 带入 QA 路径的一次性 Linux VM 通道,请运行:
|
||||
如需运行不把 Docker 带入 QA 路径的一次性 Linux VM 运行通道,请运行:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline
|
||||
```
|
||||
|
||||
这会启动一个全新的 Multipass guest,安装依赖,在 guest 内构建 OpenClaw,运行 `qa suite`,然后把常规 QA 报告和摘要复制回主机上的 `.artifacts/qa-e2e/...`。
|
||||
这会启动一个新的 Multipass 虚拟机,安装依赖,在虚拟机内构建 OpenClaw,运行 `qa suite`,然后把常规 QA 报告和摘要复制回主机上的 `.artifacts/qa-e2e/...`。
|
||||
它复用与主机上 `qa suite` 相同的场景选择行为。
|
||||
默认情况下,主机和 Multipass suite 运行会通过隔离的 Gateway 网关 worker 并行执行多个所选场景。`qa-channel` 默认并发数为 4,并受所选场景数量限制。使用 `--concurrency <count>` 调整 worker 数量,或使用 `--concurrency 1` 进行串行执行。
|
||||
任一场景失败时,该命令会以非零状态退出。当你想要产物但不想要失败退出码时,请使用 `--allow-failures`。
|
||||
实时运行会转发对 guest 实用的受支持 QA 认证输入:基于环境的 provider key、QA 实时 provider 配置路径,以及存在时的 `CODEX_HOME`。请将 `--output-dir` 保持在仓库根目录下,这样 guest 才能通过挂载的工作区写回。
|
||||
主机和 Multipass suite 运行默认会使用隔离的 Gateway 网关工作进程并行执行多个已选场景。`qa-channel` 默认并发数为 4,并受所选场景数量限制。使用 `--concurrency <count>` 调整工作进程数量,或使用 `--concurrency 1` 进行串行执行。
|
||||
当任何场景失败时,该命令会以非零状态退出。如果你想要产物但不想产生失败退出码,请使用 `--allow-failures`。
|
||||
实时运行会转发对虚拟机而言可行的受支持 QA 认证输入:基于环境变量的提供商密钥、QA 实时提供商配置路径,以及存在时的 `CODEX_HOME`。请将 `--output-dir` 保持在仓库根目录下,以便虚拟机可以通过挂载的工作区写回。
|
||||
|
||||
## Telegram、Discord 和 Slack QA 参考
|
||||
|
||||
Matrix 有一个[专用页面](/zh-CN/concepts/qa-matrix),因为它场景数量较多,并且需要 Docker 支持的 homeserver 预配。Telegram、Discord 和 Slack 更小,每个只有少量场景,没有 profile 系统,并且面向已有真实渠道,因此它们的参考放在这里。
|
||||
Matrix 有一个[专用页面](/zh-CN/concepts/qa-matrix),因为它的场景数量较多,并且需要基于 Docker 的 homeserver 配置。Telegram、Discord 和 Slack 规模较小——每个只有少量场景,没有配置档案系统,面向预先存在的真实渠道——因此它们的参考内容放在这里。
|
||||
|
||||
### 共享 CLI 标志
|
||||
|
||||
这些通道通过 `extensions/qa-lab/src/live-transports/shared/live-transport-cli.ts` 注册,并接受相同的标志:
|
||||
|
||||
| 标志 | 默认值 | 描述 |
|
||||
| 标志 | 默认值 | 描述 |
|
||||
| ------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
||||
| `--scenario <id>` | — | 仅运行此场景。可重复指定。 |
|
||||
| `--output-dir <path>` | `<repo>/.artifacts/qa-e2e/{telegram,discord,slack}-<timestamp>` | 写入报告、摘要、观测到的消息和输出日志的位置。相对路径会基于 `--repo-root` 解析。 |
|
||||
| `--repo-root <path>` | `process.cwd()` | 从中性 cwd 调用时的仓库根目录。 |
|
||||
| `--sut-account <id>` | `sut` | QA Gateway 网关配置中的临时账户 id。 |
|
||||
| `--provider-mode <mode>` | `live-frontier` | `mock-openai` 或 `live-frontier`(旧版 `live-openai` 仍然可用)。 |
|
||||
| `--model <ref>` / `--alt-model <ref>` | provider 默认值 | 主模型和备用模型引用。 |
|
||||
| `--fast` | 关闭 | provider 支持时使用快速模式。 |
|
||||
| `--credential-source <env\|convex>` | `env` | 参见 [Convex 凭证池](#convex-credential-pool)。 |
|
||||
| `--credential-role <maintainer\|ci>` | CI 中为 `ci`,否则为 `maintainer` | 使用 `--credential-source convex` 时采用的角色。 |
|
||||
| `--scenario <id>` | — | 仅运行此场景。可重复。 |
|
||||
| `--output-dir <path>` | `<repo>/.artifacts/qa-e2e/{telegram,discord,slack}-<timestamp>` | 写入报告、摘要、观察到的消息和输出日志的位置。相对路径会相对于 `--repo-root` 解析。 |
|
||||
| `--repo-root <path>` | `process.cwd()` | 从中立 cwd 调用时的仓库根目录。 |
|
||||
| `--sut-account <id>` | `sut` | QA Gateway 网关配置内的临时账号 id。 |
|
||||
| `--provider-mode <mode>` | `live-frontier` | `mock-openai` 或 `live-frontier`(旧版 `live-openai` 仍然可用)。 |
|
||||
| `--model <ref>` / `--alt-model <ref>` | 提供商默认值 | 主模型/备用模型引用。 |
|
||||
| `--fast` | 关闭 | 在受支持位置启用提供商快速模式。 |
|
||||
| `--credential-source <env\|convex>` | `env` | 参见 [Convex 凭证池](#convex-credential-pool)。 |
|
||||
| `--credential-role <maintainer\|ci>` | CI 中为 `ci`,否则为 `maintainer` | 使用 `--credential-source convex` 时使用的角色。 |
|
||||
|
||||
任何场景失败时,每个测试通道都会以非零状态退出。`--allow-failures` 会写入产物,但不会设置失败退出码。
|
||||
每个通道在任何场景失败时都会以非零状态退出。`--allow-failures` 会写入产物,但不会设置失败退出码。
|
||||
|
||||
### Telegram QA
|
||||
|
||||
@ -165,9 +176,9 @@ Matrix 有一个[专用页面](/zh-CN/concepts/qa-matrix),因为它场景数
|
||||
pnpm openclaw qa telegram
|
||||
```
|
||||
|
||||
目标是一个真实的私有 Telegram 群组,其中包含两个不同的机器人(驱动程序 + SUT)。SUT 机器人必须拥有 Telegram 用户名;当两个机器人都在 `@BotFather` 中启用 **Bot-to-Bot Communication Mode** 时,机器人到机器人的观测效果最佳。
|
||||
目标是一个真实的私有 Telegram 群组,使用两个不同的 bot(driver + SUT)。SUT bot 必须拥有 Telegram 用户名;当两个 bot 都在 `@BotFather` 中启用 **Bot-to-Bot Communication Mode** 时,bot 到 bot 的观察效果最佳。
|
||||
|
||||
当 `--credential-source env` 时所需的环境变量:
|
||||
当 `--credential-source env` 时需要的环境变量:
|
||||
|
||||
- `OPENCLAW_QA_TELEGRAM_GROUP_ID` — 数字聊天 id(字符串)。
|
||||
- `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN`
|
||||
@ -175,7 +186,7 @@ pnpm openclaw qa telegram
|
||||
|
||||
可选:
|
||||
|
||||
- `OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1` 会在观测消息产物中保留消息正文(默认会脱敏)。
|
||||
- `OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1` 会在观察消息产物中保留消息正文(默认会编辑隐藏)。
|
||||
|
||||
场景(`extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts:44`):
|
||||
|
||||
@ -191,8 +202,8 @@ pnpm openclaw qa telegram
|
||||
输出产物:
|
||||
|
||||
- `telegram-qa-report.md`
|
||||
- `telegram-qa-summary.json` — 包含从 canary 开始的每条回复 RTT(驱动程序发送 → 观测到 SUT 回复)。
|
||||
- `telegram-qa-observed-messages.json` — 除非设置 `OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1`,否则正文会被脱敏。
|
||||
- `telegram-qa-summary.json` — 从 canary 开始包含每条回复的 RTT(driver 发送 → 观察到 SUT 回复)。
|
||||
- `telegram-qa-observed-messages.json` — 除非设置 `OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1`,否则正文会被编辑隐藏。
|
||||
|
||||
### Discord QA
|
||||
|
||||
@ -200,28 +211,28 @@ pnpm openclaw qa telegram
|
||||
pnpm openclaw qa discord
|
||||
```
|
||||
|
||||
目标是一个真实的私有 Discord guild 渠道,其中包含两个机器人:由 harness 控制的驱动机器人,以及由子 OpenClaw Gateway 网关通过内置 Discord 插件启动的 SUT 机器人。它会验证渠道提及处理、SUT 机器人是否已向 Discord 注册原生 `/help` 命令,以及需要选择加入的 Mantis 证据场景。
|
||||
目标是一个真实的私有 Discord guild 渠道,使用两个 bot:一个由 harness 控制的 driver bot,以及一个由子 OpenClaw Gateway 网关通过内置 Discord 插件启动的 SUT bot。验证渠道提及处理、SUT bot 已向 Discord 注册原生 `/help` 命令,以及选择加入的 Mantis 证据场景。
|
||||
|
||||
当 `--credential-source env` 时所需的环境变量:
|
||||
当 `--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 机器人用户 id(否则该测试通道会快速失败)。
|
||||
- `OPENCLAW_QA_DISCORD_SUT_APPLICATION_ID` — 必须与 Discord 返回的 SUT bot 用户 id 匹配(否则该通道会快速失败)。
|
||||
|
||||
可选:
|
||||
|
||||
- `OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1` 会在观测消息产物中保留消息正文。
|
||||
- `OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1` 会在观察消息产物中保留消息正文。
|
||||
|
||||
场景(`extensions/qa-lab/src/live-transports/discord/discord-live.runtime.ts:36`):
|
||||
|
||||
- `discord-canary`
|
||||
- `discord-mention-gating`
|
||||
- `discord-native-help-command-registration`
|
||||
- `discord-status-reactions-tool-only` — 选择加入的 Mantis 场景。它会单独运行,因为它会将 SUT 切换为始终开启、仅工具驱动的 guild 回复,并设置 `messages.statusReactions.enabled=true`,然后捕获 REST 反应时间线以及 HTML/PNG 可视产物。
|
||||
- `discord-status-reactions-tool-only` — 选择加入的 Mantis 场景。它会单独运行,因为它会将 SUT 切换为始终开启、仅工具的 guild 回复,并设置 `messages.statusReactions.enabled=true`,然后捕获 REST reaction 时间线以及 HTML/PNG 可视产物。
|
||||
|
||||
显式运行 Mantis status-reaction 场景:
|
||||
显式运行 Mantis 状态 reaction 场景:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa discord \
|
||||
@ -236,8 +247,8 @@ pnpm openclaw qa discord \
|
||||
|
||||
- `discord-qa-report.md`
|
||||
- `discord-qa-summary.json`
|
||||
- `discord-qa-observed-messages.json` — 除非设置 `OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1`,否则正文会被脱敏。
|
||||
- 运行 status-reaction 场景时会生成 `discord-qa-reaction-timelines.json` 和 `discord-status-reactions-tool-only-timeline.png`。
|
||||
- `discord-qa-observed-messages.json` — 除非设置 `OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1`,否则正文会被编辑隐藏。
|
||||
- 运行状态 reaction 场景时会生成 `discord-qa-reaction-timelines.json` 和 `discord-status-reactions-tool-only-timeline.png`。
|
||||
|
||||
### Slack QA
|
||||
|
||||
@ -245,9 +256,9 @@ pnpm openclaw qa discord \
|
||||
pnpm openclaw qa slack
|
||||
```
|
||||
|
||||
目标是一个真实的私有 Slack 渠道,其中包含两个不同的机器人:由 harness 控制的驱动机器人,以及由子 OpenClaw Gateway 网关通过内置 Slack 插件启动的 SUT 机器人。
|
||||
目标是一个真实的私有 Slack 渠道,使用两个不同的 bot:一个由 harness 控制的 driver bot,以及一个由子 OpenClaw Gateway 网关通过内置 Slack 插件启动的 SUT bot。
|
||||
|
||||
当 `--credential-source env` 时所需的环境变量:
|
||||
当 `--credential-source env` 时需要的环境变量:
|
||||
|
||||
- `OPENCLAW_QA_SLACK_CHANNEL_ID`
|
||||
- `OPENCLAW_QA_SLACK_DRIVER_BOT_TOKEN`
|
||||
@ -256,7 +267,7 @@ pnpm openclaw qa slack
|
||||
|
||||
可选:
|
||||
|
||||
- `OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1` 会在观测消息产物中保留消息正文。
|
||||
- `OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1` 会在观察消息产物中保留消息正文。
|
||||
|
||||
场景(`extensions/qa-lab/src/live-transports/slack/slack-live.runtime.ts:39`):
|
||||
|
||||
@ -267,18 +278,18 @@ pnpm openclaw qa slack
|
||||
|
||||
- `slack-qa-report.md`
|
||||
- `slack-qa-summary.json`
|
||||
- `slack-qa-observed-messages.json` — 除非设置 `OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1`,否则正文会被脱敏。
|
||||
- `slack-qa-observed-messages.json` — 除非设置 `OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1`,否则正文会被编辑隐藏。
|
||||
|
||||
### Convex 凭证池
|
||||
|
||||
Telegram、Discord 和 Slack 测试通道可以从共享 Convex 池租用凭证,而不是读取上面的环境变量。传入 `--credential-source convex`(或设置 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`);QA Lab 会获取一个独占租约,在运行期间发送 Heartbeat,并在关闭时释放它。池类型为 `"telegram"`、`"discord"` 和 `"slack"`。
|
||||
Telegram、Discord 和 Slack 通道可以从共享 Convex 池租用凭证,而不是读取上面的环境变量。传入 `--credential-source convex`(或设置 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`);QA Lab 会获取独占租约,在运行期间对其发送 Heartbeat,并在关闭时释放它。池类型为 `"telegram"`、`"discord"` 和 `"slack"`。
|
||||
|
||||
broker 在 `admin/add` 上验证的载荷形状:
|
||||
broker 会在 `admin/add` 上校验的 payload 形状:
|
||||
|
||||
- Telegram(`kind: "telegram"`):`{ groupId: string, driverToken: string, sutToken: string }` — `groupId` 必须是数字聊天 id 字符串。
|
||||
- Discord(`kind: "discord"`):`{ guildId: string, channelId: string, driverBotToken: string, sutBotToken: string, sutApplicationId: string }`。
|
||||
|
||||
操作环境变量和 Convex broker 端点契约位于 [测试 → 通过 Convex 共享 Telegram 凭证](/zh-CN/help/testing#shared-telegram-credentials-via-convex-v1)(该小节名称早于 Discord 支持;两种类型的 broker 语义相同)。
|
||||
操作环境变量和 Convex broker 端点契约位于[测试 → 通过 Convex 共享 Telegram 凭证](/zh-CN/help/testing#shared-telegram-credentials-via-convex-v1)(该章节名称早于 Discord 支持;broker 语义对两种类型都相同)。
|
||||
|
||||
## 仓库支持的种子
|
||||
|
||||
@ -287,22 +298,22 @@ broker 在 `admin/add` 上验证的载荷形状:
|
||||
- `qa/scenarios/index.md`
|
||||
- `qa/scenarios/<theme>/*.md`
|
||||
|
||||
这些内容有意放在 git 中,因此 QA 计划对人工和智能体都可见。
|
||||
这些内容有意放在 git 中,这样 QA 计划对人类和智能体都可见。
|
||||
|
||||
`qa-lab` 应保持为通用 Markdown 运行器。每个场景 Markdown 文件都是一次测试运行的事实来源,并应定义:
|
||||
`qa-lab` 应保持为通用 markdown runner。每个场景 markdown 文件都是一次测试运行的事实来源,并应定义:
|
||||
|
||||
- 场景元数据
|
||||
- 可选的类别、能力、测试通道和风险元数据
|
||||
- 可选的类别、能力、通道和风险元数据
|
||||
- 文档和代码引用
|
||||
- 可选的插件要求
|
||||
- 可选的 Gateway 网关配置补丁
|
||||
- 可执行的 `qa-flow`
|
||||
|
||||
支撑 `qa-flow` 的可复用运行时表面可以保持通用且跨领域。例如,Markdown 场景可以组合传输侧 helper 和浏览器侧 helper,后者通过 Gateway 网关 `browser.request` 接缝驱动嵌入式 Control UI,而无需添加特殊场景运行器。
|
||||
支持 `qa-flow` 的可复用运行时表面允许保持通用且跨领域。例如,markdown 场景可以组合传输侧 helper 和浏览器侧 helper,后者通过 Gateway 网关 `browser.request` 接缝驱动嵌入式 Control UI,而无需添加特殊情况 runner。
|
||||
|
||||
场景文件应按产品能力分组,而不是按源码树文件夹分组。文件移动时保持场景 ID 稳定;使用 `docsRefs` 和 `codeRefs` 提供实现可追溯性。
|
||||
场景文件应按产品能力而不是源码树文件夹分组。文件移动时请保持场景 ID 稳定;使用 `docsRefs` 和 `codeRefs` 进行实现可追溯。
|
||||
|
||||
基线列表应保持足够宽,以覆盖:
|
||||
基线列表应保持足够广,以覆盖:
|
||||
|
||||
- 私信和渠道聊天
|
||||
- 线程行为
|
||||
@ -310,79 +321,79 @@ broker 在 `admin/add` 上验证的载荷形状:
|
||||
- cron 回调
|
||||
- 记忆召回
|
||||
- 模型切换
|
||||
- 子智能体交接
|
||||
- subagent handoff
|
||||
- 仓库读取和文档读取
|
||||
- 一个小型构建任务,例如 Lobster Invaders
|
||||
|
||||
## Provider mock 测试通道
|
||||
## 提供商 mock 通道
|
||||
|
||||
`qa suite` 有两个本地 provider mock 测试通道:
|
||||
`qa suite` 有两个本地提供商 mock 通道:
|
||||
|
||||
- `mock-openai` 是具备场景感知能力的 OpenClaw mock。它仍然是仓库支持的 QA 和 parity gate 的默认确定性 mock 测试通道。
|
||||
- `aimock` 会启动一个由 AIMock 支持的 provider 服务器,用于实验性协议、fixture、record/replay 和混沌覆盖。它是增量能力,不会取代 `mock-openai` 场景分发器。
|
||||
- `mock-openai` 是可感知场景的 OpenClaw mock。它仍然是仓库支持 QA 和 parity gate 的默认确定性 mock 通道。
|
||||
- `aimock` 会启动一个 AIMock 支持的提供商服务器,用于实验性协议、fixture、record/replay 和 chaos 覆盖。它是增量能力,不会替代 `mock-openai` 场景分派器。
|
||||
|
||||
Provider 测试通道实现位于 `extensions/qa-lab/src/providers/` 下。每个 provider 都拥有自己的默认值、本地服务器启动、Gateway 网关模型配置、auth-profile 暂存需求,以及 live/mock 能力标志。共享 suite 和 Gateway 网关代码应通过 provider 注册表路由,而不是按 provider 名称分支。
|
||||
提供商通道实现位于 `extensions/qa-lab/src/providers/` 下。每个提供商拥有自己的默认值、本地服务器启动、Gateway 网关模型配置、认证档案 staging 需求,以及实时/mock 能力标志。共享 suite 和 Gateway 网关代码应通过提供商注册表路由,而不是基于提供商名称分支。
|
||||
|
||||
## 传输适配器
|
||||
|
||||
`qa-lab` 为 Markdown QA 场景拥有一个通用传输接缝。`qa-channel` 是该接缝上的第一个适配器,但设计目标更广:未来真实或合成的渠道都应接入同一个 suite 运行器,而不是添加特定传输的 QA 运行器。
|
||||
`qa-lab` 拥有面向 markdown QA 场景的通用传输接缝。`qa-channel` 是该接缝上的第一个适配器,但设计目标更广:未来的真实或合成渠道应接入同一个 suite runner,而不是添加特定传输的 QA runner。
|
||||
|
||||
在架构层面,拆分如下:
|
||||
在架构层面,拆分为:
|
||||
|
||||
- `qa-lab` 拥有通用场景执行、worker 并发、产物写入和报告。
|
||||
- 传输适配器拥有 Gateway 网关配置、就绪性、入站和出站观测、传输操作以及规范化传输状态。
|
||||
- `qa/scenarios/` 下的 Markdown 场景文件定义测试运行;`qa-lab` 提供执行它们的可复用运行时表面。
|
||||
- `qa-lab` 拥有通用场景执行、工作进程并发、产物写入和报告。
|
||||
- 传输适配器拥有 Gateway 网关配置、就绪状态、入站和出站观察、传输操作,以及规范化的传输状态。
|
||||
- `qa/scenarios/` 下的 markdown 场景文件定义测试运行;`qa-lab` 提供执行它们的可复用运行时表面。
|
||||
|
||||
### 添加渠道
|
||||
|
||||
向 Markdown QA 系统添加渠道只需要两件事:
|
||||
向 markdown QA 系统添加渠道只需要两件事:
|
||||
|
||||
1. 该渠道的传输适配器。
|
||||
2. 覆盖该渠道契约的场景包。
|
||||
|
||||
当共享的 `qa-lab` 宿主可以拥有流程时,不要添加新的顶层 QA 命令根。
|
||||
当共享 `qa-lab` 主机可以拥有流程时,不要添加新的顶层 QA 命令根。
|
||||
|
||||
`qa-lab` 拥有共享宿主机制:
|
||||
`qa-lab` 拥有共享主机机制:
|
||||
|
||||
- `openclaw qa` 命令根
|
||||
- suite 启动和拆卸
|
||||
- 套件启动和清理
|
||||
- worker 并发
|
||||
- 产物写入
|
||||
- artifact 写入
|
||||
- 报告生成
|
||||
- 场景执行
|
||||
- 旧版 `qa-channel` 场景的兼容别名
|
||||
- 旧版 `qa-channel` 场景的兼容性别名
|
||||
|
||||
运行器插件拥有传输契约:
|
||||
运行器插件拥有传输协议契约:
|
||||
|
||||
- 如何将 `openclaw qa <runner>` 挂载到共享 `qa` 根之下
|
||||
- 如何为该传输配置 Gateway 网关
|
||||
- 如何检查就绪性
|
||||
- `openclaw qa <runner>` 如何挂载到共享 `qa` 根下
|
||||
- 如何为该传输协议配置 Gateway 网关
|
||||
- 如何检查就绪状态
|
||||
- 如何注入入站事件
|
||||
- 如何观测出站消息
|
||||
- 如何暴露转录和规范化传输状态
|
||||
- 如何执行传输支持的操作
|
||||
- 如何处理特定于传输的重置或清理
|
||||
- 如何观察出站消息
|
||||
- 如何暴露 transcript 和规范化后的传输协议状态
|
||||
- 如何执行由传输协议支持的操作
|
||||
- 如何处理传输协议专属的重置或清理
|
||||
|
||||
新渠道的最低采用门槛:
|
||||
|
||||
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 和运行器执行应保留在单独的入口点之后。
|
||||
5. 在主题化的 `qa/scenarios/` 目录下编写或改编 markdown 场景。
|
||||
6. 为新场景使用通用场景辅助函数。
|
||||
7. 除非仓库正在进行有意迁移,否则保持现有兼容别名可用。
|
||||
1. 保持 `qa-lab` 作为共享 `qa` 根的所有者。
|
||||
2. 在共享 `qa-lab` 主机 seam 上实现传输协议运行器。
|
||||
3. 将传输协议专属机制保留在运行器插件或渠道 harness 内。
|
||||
4. 将运行器挂载为 `openclaw qa <runner>`,而不是注册竞争性的根命令。运行器插件应在 `openclaw.plugin.json` 中声明 `qaRunners`,并从 `runtime-api.ts` 导出匹配的 `qaRunnerCliRegistrations` 数组。保持 `runtime-api.ts` 轻量;延迟 CLI 和运行器执行应保留在单独入口点之后。
|
||||
5. 在主题化的 `qa/scenarios/` 目录下编写或改编 Markdown 场景。
|
||||
6. 对新场景使用通用场景 helper。
|
||||
7. 除非仓库正在进行有意的迁移,否则保持现有兼容性别名可用。
|
||||
|
||||
决策规则很严格:
|
||||
决策规则是严格的:
|
||||
|
||||
- 如果行为可以在 `qa-lab` 中表达一次,就把它放在 `qa-lab` 中。
|
||||
- 如果行为依赖于某一个渠道传输,就把它保留在该运行器插件或插件 harness 中。
|
||||
- 如果某个场景需要一项可被多个渠道使用的新能力,请添加通用辅助函数,而不是在 `suite.ts` 中添加渠道特定分支。
|
||||
- 如果某个行为只对一种传输有意义,请保持场景为传输特定,并在场景契约中明确说明。
|
||||
- 如果行为可以在 `qa-lab` 中只表达一次,就把它放在 `qa-lab` 中。
|
||||
- 如果行为依赖某一个渠道传输协议,就把它保留在该运行器插件或插件 harness 中。
|
||||
- 如果某个场景需要一个多个渠道都能使用的新能力,就添加通用 helper,而不是在 `suite.ts` 中添加渠道专属分支。
|
||||
- 如果某个行为只对一种传输协议有意义,就保持该场景为传输协议专属,并在场景契约中明确说明。
|
||||
|
||||
### 场景辅助函数名称
|
||||
### 场景 helper 名称
|
||||
|
||||
新场景首选的通用辅助函数:
|
||||
新场景首选的通用 helper:
|
||||
|
||||
- `waitForTransportReady`
|
||||
- `waitForChannelReady`
|
||||
@ -397,7 +408,7 @@ Provider 测试通道实现位于 `extensions/qa-lab/src/providers/` 下。每
|
||||
- `formatTransportTranscript`
|
||||
- `resetTransport`
|
||||
|
||||
兼容别名仍可用于现有场景 — `waitForQaChannelReady`、`waitForOutboundMessage`、`waitForNoOutbound`、`formatConversationTranscript`、`resetBus` — 但新场景编写应使用通用名称。这些别名的存在是为了避免一次性迁移,而不是作为未来的模型。
|
||||
现有场景仍可使用兼容性别名:`waitForQaChannelReady`、`waitForOutboundMessage`、`waitForNoOutbound`、`formatConversationTranscript`、`resetBus`,但新场景编写应使用通用名称。这些别名存在是为了避免一次性迁移,而不是未来的模型。
|
||||
|
||||
## 报告
|
||||
|
||||
@ -406,12 +417,12 @@ Provider 测试通道实现位于 `extensions/qa-lab/src/providers/` 下。每
|
||||
|
||||
- 哪些有效
|
||||
- 哪些失败
|
||||
- 哪些仍然受阻
|
||||
- 哪些仍被阻塞
|
||||
- 哪些后续场景值得添加
|
||||
|
||||
要查看可用场景清单 — 在评估后续工作规模或接入新传输时很有用 — 运行 `pnpm openclaw qa coverage`(添加 `--json` 可获得机器可读输出)。
|
||||
如需查看可用场景清单(在评估后续工作规模或接入新传输协议时很有用),运行 `pnpm openclaw qa coverage`(添加 `--json` 可获得机器可读输出)。
|
||||
|
||||
对于角色和风格检查,请在多个实时模型引用上运行同一场景,并编写经过评判的 Markdown 报告:
|
||||
对于角色和风格检查,请跨多个实时模型 refs 运行同一场景,并编写一个经过评判的 Markdown 报告:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa character-eval \
|
||||
@ -430,16 +441,16 @@ pnpm openclaw qa character-eval \
|
||||
--judge-concurrency 16
|
||||
```
|
||||
|
||||
该命令会运行本地 QA gateway 子进程,而不是 Docker。角色评估场景应通过 `SOUL.md` 设置 persona,然后运行普通用户轮次,例如聊天、工作区帮助和小型文件任务。不应告知候选模型它正在被评估。该命令会保留每份完整转录,记录基本运行统计信息,然后以快速模式请求评判模型,并在支持的情况下使用 `xhigh` 推理,根据自然度、气质和幽默感对运行进行排名。比较提供商时使用 `--blind-judge-models`:评判提示仍会获得每份转录和运行状态,但候选引用会替换为中性标签,例如 `candidate-01`;报告会在解析后将排名映射回真实引用。
|
||||
候选运行默认使用 `high` thinking,GPT-5.5 使用 `medium`,支持它的较旧 OpenAI 评估引用使用 `xhigh`。使用 `--model provider/model,thinking=<level>` 内联覆盖特定候选。`--thinking <level>` 仍会设置全局回退,较旧的 `--model-thinking <provider/model=level>` 形式会保留以兼容。
|
||||
OpenAI 候选引用默认使用快速模式,以便在提供商支持时使用优先处理。单个候选或评判需要覆盖时,内联添加 `,fast`、`,no-fast` 或 `,fast=false`。仅当你想强制所有候选模型开启快速模式时,才传入 `--fast`。候选和评判持续时间会记录在报告中用于基准分析,但评判提示会明确说明不要按速度排名。
|
||||
候选和评判模型运行默认并发数均为 16。当提供商限制或本地 gateway 压力导致运行噪声过大时,降低 `--concurrency` 或 `--judge-concurrency`。
|
||||
该命令运行本地 QA Gateway 网关子进程,而不是 Docker。角色评估场景应通过 `SOUL.md` 设置 persona,然后运行普通用户轮次,例如聊天、工作区帮助和小型文件任务。不应告知候选模型它正在被评估。该命令会保留每个完整 transcript,记录基础运行统计,然后以 fast mode 请求评审模型,并在受支持时使用 `xhigh` reasoning,按自然度、氛围和幽默感对运行结果排序。比较提供商时使用 `--blind-judge-models`:评审提示仍会获得每个 transcript 和运行状态,但候选 refs 会被替换为中性标签,例如 `candidate-01`;报告在解析后会将排名映射回真实 refs。
|
||||
候选运行默认使用 `high` thinking;GPT-5.5 使用 `medium`,支持该级别的旧版 OpenAI 评估 refs 使用 `xhigh`。使用 `--model provider/model,thinking=<level>` 内联覆盖特定候选。`--thinking <level>` 仍会设置全局 fallback,旧版 `--model-thinking <provider/model=level>` 形式保留用于兼容。
|
||||
OpenAI 候选 refs 默认使用 fast mode,以便在提供商支持时使用 priority processing。当单个候选或评审需要覆盖时,内联添加 `,fast`、`,no-fast` 或 `,fast=false`。仅当你想为每个候选模型强制开启 fast mode 时,才传递 `--fast`。候选和评审耗时会记录在报告中以供基准分析,但评审提示会明确说明不要按速度排序。
|
||||
候选和评审模型运行都默认并发数为 16。当提供商限制或本地 Gateway 网关压力导致运行过于嘈杂时,降低 `--concurrency` 或 `--judge-concurrency`。
|
||||
未传入候选 `--model` 时,角色评估默认使用 `openai/gpt-5.5`、`openai/gpt-5.2`、`openai/gpt-5`、`anthropic/claude-opus-4-6`、`anthropic/claude-sonnet-4-6`、`zai/glm-5.1`、`moonshot/kimi-k2.5` 和 `google/gemini-3.1-pro-preview`。
|
||||
未传入 `--judge-model` 时,评判默认使用 `openai/gpt-5.5,thinking=xhigh,fast` 和 `anthropic/claude-opus-4-6,thinking=high`。
|
||||
未传入 `--judge-model` 时,评审默认使用 `openai/gpt-5.5,thinking=xhigh,fast` 和 `anthropic/claude-opus-4-6,thinking=high`。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [Matrix QA](/zh-CN/concepts/qa-matrix)
|
||||
- [QA channel](/zh-CN/channels/qa-channel)
|
||||
- [QA Channel](/zh-CN/channels/qa-channel)
|
||||
- [测试](/zh-CN/help/testing)
|
||||
- [仪表板](/zh-CN/web/dashboard)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user