跳转至

扩展 QA 技术栈

基于仓库的种子数据

种子资产位于 qa/ 中:

  • qa/scenarios/index.yaml
  • qa/scenarios/<theme>/*.yaml

涉及身份敏感的频道变更使用隔离的 channel-participant-identity-inspection QA Channel 流程。它驱动一个真实的临时 Gateway 和 mock provider,然后使用操作员所用的同一套 openclaw audit --run ... --explain JSON 及人工界面来检查被准入的运行。该流程包括由生命周期管理的重启,以及对被拒绝的 pre-run 入口进行行数检查。

这些内容有意放在 git 中,以便 QA 计划对人和 agent 都可见。

qa-lab 仍然是一个通用的 YAML 场景运行器。每个场景 YAML 文件是单次测试运行的唯一事实来源,应定义:

  • 顶层 title
  • scenario 元数据
  • scenario 中可选的 category、capability、lane 和 risk 元数据
  • scenario 中的文档和代码引用
  • scenario 中可选的插件要求
  • scenario 中可选的 gateway 配置补丁
  • 对于 flow 场景,提供可执行的顶层 flow;对于 Vitest 和 Playwright 场景,提供 scenario.execution.kind / scenario.execution.path

支撑 flow 的可复用运行时层面保持通用且具有横切性。例如,YAML 场景可以将传输侧助手与浏览器侧助手结合,通过 Gateway 的 browser.request 接缝驱动内嵌的 Control UI,而无需添加特例 runner。

场景文件应按产品能力分组,而不是按源代码树目录分组。文件移动时应保持场景 ID 稳定;使用 docsRefs 和 codeRefs 实现实现可追溯性。

基线列表应保持足够广泛,以覆盖:

  • DM 和频道聊天
  • 线程行为
  • 消息操作生命周期
  • cron 回调
  • 记忆召回
  • 模型切换
  • subagent 交接
  • 仓库读取和文档读取
  • 一个小型构建任务,例如 Lobster Invaders

Provider 模拟通道

qa suite 有两条本地 provider 模拟通道:

  • mock-openai 是感知场景的 OpenClaw mock。它仍然是基于仓库的 QA 和一致性门禁的默认确定性 mock 通道。
  • aimock 启动一个由 AIMock 支撑的 provider 服务器,用于实验性协议、fixture、录制/回放和混沌覆盖。它是增量式的,不会取代 mock-openai 场景调度器。

感知场景的 mock 会单独响应 Activity recap 请求,而不与 agent 回合混在一起。Recap 将对话文本作为数据引用,因此它们不会触发场景工具,也不会进入由 /debug/requests 返回的场景请求证据。

对于 IPv6 回环服务器,运行 pnpm openclaw qa mock-openai --host ::1。打印出的 URL 包含方括号,例如 http://[::1]:<port>;配置客户端时请使用该 URL。QA Lab 也会在其监听和对外公布的 URL 中用方括号括起 IPv6 主机。请将裸地址传给 --host。

Provider 通道的实现位于 extensions/qa-lab/src/providers/ 下。每个 provider 自行管理其默认值、本地服务器启动、gateway 模型配置、auth-profile 暂存需求,以及 live/mock 能力标志。共享的 suite 和 gateway 代码通过 provider 注册表进行路由,而不是按 provider 名称分支。

传输适配器

qa-lab 为 YAML QA 场景提供一个通用的传输接缝。qa-channel 是默认的合成实现。crabline 会启动独立的本地 provider 服务器,并让 OpenClaw 的正常 channel 插件面向这些 provider 形态的 REST 和流式边界运行;它不使用 Crabline 的 fixture 级本地 mock provider。live 保留给真实的 provider 凭据和外部渠道。

在架构层面,职责划分如下:

  • qa-lab 负责通用场景执行、worker 并发、artifact 写入和报告生成。
  • 传输适配器负责 gateway 配置、就绪性、入站和出站观察、传输操作,以及规范化传输状态。
  • qa/scenarios/ 下的 YAML 场景文件定义测试运行;qa-lab 提供执行这些文件的可复用运行时层面。

适配器关闭与失败钩子

可选的 QA runner 钩子遵循由宿主控制的单一 teardown 顺序:

  1. cleanup() 停止新的 fixture 操作,同时保留凭据权威性以及对未完成写入的所有权。最终回执所需的观察者可以保持活动直到 Gateway 关闭。已绑定的传输请求本身不受影响;场景截止时间不会了结已经派发的请求。
  2. 宿主停止 Gateway 并确认进程已关闭。
  3. captureBeforeGatewayCleanup() 在临时 Gateway 状态被移除之前,对最终的原生回执进行快照。成功的捕获在每次 Gateway 生命周期内运行一次。抛出的错误会保留运行时证据并使 teardown 失败;但不会阻止停止后的 fixture 清理。
  4. cleanupAfterGatewayStop() 了结未完成的写入和所拥有的 fixture 清理,然后释放凭据租约。如果 Gateway 关闭未得到确认,宿主将不调用此钩子。应报告失败,而不是声称清理成功。

省略的钩子不执行任何适配器特定工作;正常的宿主 teardown 仍会运行。错误会在各个清理阶段中累积。对于未知的远程写入结果,应保持明确,而不是推断所有权或重放写入。

可选的 whenUnhealthy promise 会resolve(而不是 reject)一个终止错误。宿主会中止正在进行的 flow 准入;适配器在清理期间仍负责了结。省略该钩子的适配器保留其显式健康检查和场景截止时间。

添加频道

向 YAML QA 系统添加一个频道,需要该频道的实现,以及一个覆盖频道契约的场景包。为了 smoke CI 覆盖,请添加匹配的 Crabline 本地 provider 服务器,并通过 crabline 驱动暴露它。

当共享的 qa-lab 宿主能够负责该流程时,不要添加新的顶层 QA 命令根。

qa-lab 负责共享宿主机制:

  • openclaw qa 命令根
  • suite 启动与 teardown
  • worker 并发
  • artifact 写入
  • 报告生成
  • 场景执行
  • 旧版 qa-channel 场景的兼容别名

Runner 插件负责传输契约:

  • 如何在共享的 qa 根下挂载 openclaw qa <runner>
  • 如何为该传输配置 Gateway
  • 如何检查就绪状态
  • 如何注入入站事件
  • 如何观察出站消息
  • 如何暴露转录和规范化传输状态
  • 如何执行由传输支撑的操作
  • Gateway 运行时需要哪些受信任模块预加载
  • 如何处理特定传输的重置或清理

新渠道的最低采用门槛:

  1. 保持 qa-lab 作为共享 qa 根的拥有者。
  2. 在共享的 qa-lab 宿主接缝上实现传输 Runner。
  3. 将特定传输的机制保留在 Runner 插件或渠道测试框架中。
  4. 将 Runner 挂载为 openclaw qa <runner>,而不是注册一个竞争性的根命令。Runner 插件应在 openclaw.plugin.json 中声明 qaRunners,并从轻量级的 qa-runner-api.ts 接口导出匹配的 qaRunnerCliRegistrations 数组。使用随附 runtime-api.ts 契约的已安装插件在作者迁移期间将继续获得支持,直至 2026-10-01。将 Runner 执行保留在惰性入口点之后。可选的 adapterFactory 可将传输暴露给共享场景,而不改变命令现有的场景目录。同一渠道的分区是串行的,除非工厂声明每个实例都拥有隔离的凭据或一次性服务器、Gateway 状态以及产物路径。由模块支撑的流程场景还要求 adapterFactory.supportsModuleFlows: true;这些工厂必须返回实现 prepareFlow 的适配器。
  5. 在按主题划分的 qa/scenarios/ 目录下创建或适配 YAML 场景。
  6. 对新场景使用通用场景辅助函数。
  7. 除非仓库正在进行有意迁移,否则保持现有兼容性别名可用。

决策规则严格如下:

  • 如果行为可以在 qa-lab 中一次性表达,就将其放入 qa-lab。
  • 如果行为依赖于某个渠道传输,就将其保留在该 Runner 插件或插件测试框架中。
  • 如果某个场景需要一个多个渠道都可使用的新能力,请添加通用辅助函数,而不是在 suite.ts 中添加渠道特定分支。
  • 如果某个行为仅对一个传输有意义,请保持场景为传输特定,并在场景契约中明确说明。

场景辅助函数名称

新场景推荐的通用辅助函数:

  • waitForTransportReady
  • waitForChannelReady
  • injectInboundMessage
  • injectOutboundMessage
  • waitForOutboundMessage
  • waitForNoTransportOutbound
  • getTransportSnapshot
  • readTransportMessage
  • readTransportTranscript
  • formatTransportTranscript
  • resetTransport

兼容性别名对现有场景仍然可用 - waitForQaChannelReady、waitForNoOutbound、formatConversationTranscript 和 resetBus - 但新场景编写应使用通用名称。对于出站检查,请使用规范的 waitForOutboundMessage,而不是添加传输特定或渠道特定的出站等待别名。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw