From 8368406b5dcd0df01e82b4cdfadf69c341f61a25 Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Fri, 1 May 2026 03:03:15 +0000 Subject: [PATCH] chore(i18n): refresh zh-CN translations --- docs/zh-CN/channels/groups.md | 143 ++--- docs/zh-CN/ci.md | 320 ++++++------ docs/zh-CN/gateway/config-channels.md | 284 +++++----- docs/zh-CN/help/testing.md | 716 +++++++++++++------------- docs/zh-CN/reference/RELEASING.md | 341 ++++++------ docs/zh-CN/reference/test.md | 98 ++-- 6 files changed, 966 insertions(+), 936 deletions(-) diff --git a/docs/zh-CN/channels/groups.md b/docs/zh-CN/channels/groups.md index c2b10f0b9..250143c70 100644 --- a/docs/zh-CN/channels/groups.md +++ b/docs/zh-CN/channels/groups.md @@ -2,33 +2,33 @@ read_when: - 更改群聊行为或提及门控 sidebarTitle: Groups -summary: 各平台上的群聊行为(Discord/iMessage/Matrix/Microsoft Teams/Signal/Slack/Telegram/WhatsApp/Zalo) +summary: 各界面的群聊行为(Discord/iMessage/Matrix/Microsoft Teams/Signal/Slack/Telegram/WhatsApp/Zalo) title: 群组 x-i18n: - generated_at: "2026-04-30T14:57:26Z" + generated_at: "2026-05-01T02:59:51Z" model: gpt-5.5 provider: openai - source_hash: ed9cba03cf4546a20d473e8095a54858530869b27f8934f2680e8dbe987dbf5e + source_hash: a8580f98ab03c89770688102da776627d8ce18b7bd34c4a687009fd4aabb6213 source_path: channels/groups.md workflow: 16 --- -OpenClaw 会在各个平台上一致处理群聊:Discord、iMessage、Matrix、Microsoft Teams、Signal、Slack、Telegram、WhatsApp、Zalo。 +OpenClaw 在各个表面上对群聊的处理保持一致:Discord、iMessage、Matrix、Microsoft Teams、Signal、Slack、Telegram、WhatsApp、Zalo。 -## 初学者简介(2 分钟) +## 新手介绍(2 分钟) -OpenClaw “存在于”你自己的消息账号中。没有单独的 WhatsApp bot 用户。如果**你**在某个群组中,OpenClaw 就能看到该群组并在那里回复。 +OpenClaw “运行”在你自己的消息账号上。没有单独的 WhatsApp bot 用户。如果**你**在某个群组中,OpenClaw 就能看到该群组并在那里回复。 默认行为: - 群组受限制(`groupPolicy: "allowlist"`)。 -- 除非你明确禁用提及门控,否则回复需要提及。 -- 群组/渠道中的普通最终回复默认是私有的。可见的房间输出使用 `message` 工具。 +- 回复需要提及,除非你明确禁用提及门控。 +- 群组/渠道中的常规最终回复默认是私密的。可见的房间输出使用 `message` 工具。 换句话说:允许列表中的发送者可以通过提及 OpenClaw 来触发它。 -**太长不看** +**概要** - **私信访问**由 `*.allowFrom` 控制。 - **群组访问**由 `*.groupPolicy` + 允许列表(`*.groups`、`*.groupAllowFrom`)控制。 @@ -48,15 +48,18 @@ otherwise -> reply ## 可见回复 对于群组/渠道房间,OpenClaw 默认使用 `messages.groupChat.visibleReplies: "message_tool"`。 -这意味着智能体仍会处理该轮次,并且可以更新记忆/会话状态,但它的普通最终答案不会自动发回房间。要可见地发言,智能体会使用 `message(action=send)`。 +这意味着智能体仍会处理这一轮,并且可以更新记忆/会话状态,但它的常规最终答案不会自动发回房间。要可见地发言,智能体使用 `message(action=send)`。 -对于直接聊天和任何其他来源轮次,使用 `messages.visibleReplies: "message_tool"` 可在全局应用相同的仅工具可见回复行为。`messages.groupChat.visibleReplies` 仍然是针对群组/渠道房间的更具体覆盖项。 +如果在当前工具策略下消息工具不可用,OpenClaw 会回退到自动可见回复,而不是静默抑制响应。 +`openclaw doctor` 会警告这种不匹配。 -这取代了旧模式:强制模型在大多数潜伏模式轮次中回答 `NO_REPLY`。在仅工具模式中,不产生任何可见输出只意味着不调用消息工具。 +对于直接聊天和任何其他来源轮次,使用 `messages.visibleReplies: "message_tool"` 可在全局应用相同的仅工具可见回复行为。`messages.groupChat.visibleReplies` 仍然是针对群组/渠道房间更具体的覆盖项。 -当智能体在仅工具模式中工作时,仍会发送输入状态提示。对于这些轮次,默认群组输入状态模式会从 “message” 升级为 “instant”,因为在智能体决定是否调用消息工具之前,可能永远不会有普通的助手消息文本。显式配置的输入状态模式仍然优先生效。 +这取代了旧模式:强制模型在大多数潜伏模式轮次中回答 `NO_REPLY`。在仅工具模式下,不产生可见内容只是意味着不调用消息工具。 -要恢复群组/渠道房间的旧版自动最终回复: +智能体在仅工具模式下工作时,仍会发送正在输入指示。对于这些轮次,默认群组输入模式会从 “message” 升级为 “instant”,因为在智能体决定是否调用消息工具之前,可能永远不会有常规助手消息文本。显式的输入模式配置仍然优先。 + +要为群组/渠道房间恢复旧版自动最终回复: ```json5 { @@ -68,9 +71,9 @@ otherwise -> reply } ``` -文件保存后,Gateway 网关会热重载 `messages` 配置。只有在部署中禁用了文件监听或配置重载时才需要重启。 +保存文件后,Gateway 网关会热重载 `messages` 配置。仅当部署中禁用了文件监听或配置重载时才需要重启。 -要要求每个来源聊天的可见输出都通过消息工具: +要要求每个来源聊天的可见输出都通过消息工具发送: ```json5 { @@ -80,16 +83,16 @@ otherwise -> reply } ``` -原生斜杠命令(Discord、Telegram 以及其他支持原生命令的平台)会绕过 `visibleReplies: "message_tool"`,并始终可见地回复,以便渠道原生命令 UI 获得预期响应。这仅适用于已验证的原生命令轮次;文本输入的 `/...` 命令和普通聊天轮次仍遵循配置的群组默认值。 +原生命令(Discord、Telegram 以及其他支持原生命令的表面)会绕过 `visibleReplies: "message_tool"`,并始终可见地回复,这样渠道原生命令 UI 才能获得预期的响应。这仅适用于已验证的原生命令轮次;以文本输入的 `/...` 命令和普通聊天轮次仍遵循配置的群组默认值。 -## 上下文可见性和允许列表 +## 上下文可见性与允许列表 群组安全涉及两种不同的控制: -- **触发授权**:谁可以触发智能体(`groupPolicy`、`groups`、`groupAllowFrom`、渠道专用允许列表)。 -- **上下文可见性**:哪些补充上下文会注入到模型中(回复文本、引用、线程历史、转发元数据)。 +- **触发授权**:谁可以触发智能体(`groupPolicy`、`groups`、`groupAllowFrom`、渠道特定允许列表)。 +- **上下文可见性**:哪些补充上下文会注入模型(回复文本、引用、线程历史、转发元数据)。 -默认情况下,OpenClaw 优先考虑正常聊天行为,并尽量按接收原样保留上下文。这意味着允许列表主要决定谁可以触发操作,而不是作为每段引用或历史片段的通用脱敏边界。 +默认情况下,OpenClaw 优先保持正常聊天行为,并让上下文大体按接收原样保留。这意味着允许列表主要决定谁可以触发操作,而不是每个引用或历史片段的通用脱敏边界。 @@ -98,11 +101,11 @@ otherwise -> reply - - `contextVisibility: "all"`(默认)保持当前按接收原样的行为。 + - `contextVisibility: "all"`(默认)保留当前按接收原样的行为。 - `contextVisibility: "allowlist"` 将补充上下文过滤为允许列表中的发送者。 - - `contextVisibility: "allowlist_quote"` 是 `allowlist` 加上一个显式的引用/回复例外。 + - `contextVisibility: "allowlist_quote"` 是 `allowlist` 加上一个显式引用/回复例外。 - 在这个加固模型跨渠道一致实现之前,预期不同平台会存在差异。 + 在此加固模型跨渠道一致实现之前,预期不同表面会存在差异。 @@ -111,39 +114,39 @@ otherwise -> reply 如果你想要…… -| 目标 | 要设置的内容 | +| 目标 | 需要设置什么 | | -------------------------------------------- | ---------------------------------------------------------- | | 允许所有群组,但只在 @提及时回复 | `groups: { "*": { requireMention: true } }` | | 禁用所有群组回复 | `groupPolicy: "disabled"` | -| 仅允许特定群组 | `groups: { "": { ... } }`(没有 `"*"` 键) | -| 只有你可以在群组中触发 | `groupPolicy: "allowlist"`、`groupAllowFrom: ["+1555..."]` | +| 仅特定群组 | `groups: { "": { ... } }`(没有 `"*"` 键) | +| 只有你可以在群组中触发 | `groupPolicy: "allowlist"`, `groupAllowFrom: ["+1555..."]` | ## 会话键 - 群组会话使用 `agent:::group:` 会话键(房间/渠道使用 `agent:::channel:`)。 -- Telegram 论坛话题会向群组 ID 添加 `:topic:`,因此每个话题都有自己的会话。 -- 直接聊天使用主会话(如果已配置,也可以按发送者使用单独会话)。 +- Telegram 论坛主题会向群组 ID 添加 `:topic:`,因此每个主题都有自己的会话。 +- 直接聊天使用主会话(如果已配置,则使用按发送者的会话)。 - 群组会话会跳过 Heartbeat。 -## 模式:个人私信 + 公开群组(单智能体) +## 模式:个人私信 + 公开群组(单个智能体) -可以。如果你的“个人”流量是**私信**,而“公开”流量是**群组**,这会很好用。 +可以,这很适合你的“个人”流量是**私信**、你的“公开”流量是**群组**的情况。 -原因:在单智能体模式下,私信通常会落入**主**会话键(`agent:main:main`),而群组始终使用**非主**会话键(`agent:main::group:`)。如果你启用了 `mode: "non-main"` 的沙箱隔离,这些群组会话会在配置的沙箱后端中运行,而你的主私信会话仍留在主机上。如果你没有选择后端,Docker 是默认后端。 +原因:在单智能体模式下,私信通常会落到**主**会话键(`agent:main:main`)中,而群组始终使用**非主**会话键(`agent:main::group:`)。如果你启用 `mode: "non-main"` 的沙箱隔离,这些群组会话会在配置的沙箱后端中运行,而你的主私信会话仍保留在主机上。如果你没有选择后端,Docker 是默认后端。 -这会给你一个智能体“大脑”(共享工作区 + 记忆),但有两种执行姿态: +这为你提供一个智能体“大脑”(共享工作区 + 记忆),但有两种执行姿态: - **私信**:完整工具(主机) - **群组**:沙箱 + 受限工具 -如果你需要真正分离的工作区/角色(“个人”和“公开”绝不能混用),请使用第二个智能体 + 绑定。参见[多智能体路由](/zh-CN/concepts/multi-agent)。 +如果你需要真正独立的工作区/人格(“个人”和“公开”绝不能混合),请使用第二个智能体 + 绑定。参见[多智能体路由](/zh-CN/concepts/multi-agent)。 - + ```json5 { agents: { @@ -168,7 +171,7 @@ otherwise -> reply ``` - 想让“群组只能看到文件夹 X”,而不是“不能访问主机”?保留 `workspaceAccess: "none"`,并只将允许列表中的路径挂载到沙箱中: + 想要“群组只能看到文件夹 X”,而不是“无主机访问”?保留 `workspaceAccess: "none"`,并只将允许列表中的路径挂载到沙箱: ```json5 { @@ -196,7 +199,7 @@ otherwise -> reply 相关: - 配置键和默认值:[Gateway 网关配置](/zh-CN/gateway/config-agents#agentsdefaultssandbox) -- 调试工具被阻止的原因:[沙箱 vs 工具策略 vs 提权](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated) +- 调试工具为什么被阻止:[沙箱 vs 工具策略 vs 提权](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated) - 绑定挂载详情:[沙箱隔离](/zh-CN/gateway/sandboxing#custom-bind-mounts) ## 显示标签 @@ -260,30 +263,30 @@ otherwise -> reply | `"allowlist"` | 只允许匹配已配置允许列表的群组/房间。 | - - - `groupPolicy` 与提及门控(需要 @提及)是分开的。 + + - `groupPolicy` 独立于提及门控(后者要求 @提及)。 - WhatsApp/Telegram/Signal/iMessage/Microsoft Teams/Zalo:使用 `groupAllowFrom`(回退:显式 `allowFrom`)。 - Signal:`groupAllowFrom` 可以匹配入站 Signal 群组 ID 或发送者电话/UUID。 - - 私信配对审批(`*-allowFrom` 存储条目)仅适用于私信访问;群组发送者授权仍显式使用群组允许列表。 + - 私信配对批准(`*-allowFrom` 存储条目)仅适用于私信访问;群组发送者授权仍显式保留在群组允许列表中。 - Discord:允许列表使用 `channels.discord.guilds..channels`。 - Slack:允许列表使用 `channels.slack.channels`。 - - Matrix:允许列表使用 `channels.matrix.groups`。优先使用房间 ID 或别名;已加入房间的名称查找是尽力而为,未解析的名称会在运行时被忽略。使用 `channels.matrix.groupAllowFrom` 限制发送者;也支持按房间配置的 `users` 允许列表。 + - Matrix:允许列表使用 `channels.matrix.groups`。优先使用房间 ID 或别名;已加入房间的名称查找是尽力而为的,未解析的名称会在运行时被忽略。使用 `channels.matrix.groupAllowFrom` 限制发送者;也支持按房间的 `users` 允许列表。 - 群组私信单独控制(`channels.discord.dm.*`、`channels.slack.dm.*`)。 - Telegram 允许列表可以匹配用户 ID(`"123456789"`、`"telegram:123456789"`、`"tg:123456789"`)或用户名(`"@alice"` 或 `"alice"`);前缀不区分大小写。 - - 默认值为 `groupPolicy: "allowlist"`;如果你的群组允许列表为空,群组消息会被阻止。 - - 运行时安全:当提供商块完全缺失(不存在 `channels.`)时,群组策略会回退到故障关闭模式(通常是 `allowlist`),而不是继承 `channels.defaults.groupPolicy`。 + - 默认值是 `groupPolicy: "allowlist"`;如果你的群组允许列表为空,群组消息会被阻止。 + - 运行时安全:当提供商块完全缺失(`channels.` 不存在)时,群组策略会回退到失败关闭模式(通常是 `allowlist`),而不是继承 `channels.defaults.groupPolicy`。 -快速心智模型(群组消息的评估顺序): +群组消息的快速心智模型(评估顺序): `groupPolicy`(open/disabled/allowlist)。 - 群组允许列表(`*.groups`、`*.groupAllowFrom`、渠道专用允许列表)。 + 群组允许列表(`*.groups`、`*.groupAllowFrom`、特定渠道允许列表)。 提及门控(`requireMention`、`/activation`)。 @@ -292,9 +295,9 @@ otherwise -> reply ## 提及门控(默认) -除非按群组覆盖,否则群组消息需要提及。默认值按子系统位于 `*.groups."*"` 下。 +群组消息需要提及,除非按群组覆盖。默认值位于每个子系统的 `*.groups."*"` 下。 -回复机器人消息在渠道支持回复元数据时会计为隐式提及。引用机器人消息在暴露引用元数据的渠道上也可计为隐式提及。当前内置案例包括 Telegram、WhatsApp、Slack、Discord、Microsoft Teams 和 ZaloUser。 +当渠道支持回复元数据时,回复机器人消息会被视为隐式提及。在暴露引用元数据的渠道上,引用机器人消息也可以被视为隐式提及。当前内置情况包括 Telegram、WhatsApp、Slack、Discord、Microsoft Teams 和 ZaloUser。 ```json5 { @@ -334,15 +337,15 @@ otherwise -> reply - - `mentionPatterns` 是大小写不敏感的安全正则表达式模式;无效模式和不安全的嵌套重复形式会被忽略。 - - 提供显式提及的界面仍会通过;模式是一种回退机制。 - - 按智能体覆盖:`agents.list[].groupChat.mentionPatterns`(当多个智能体共享同一个群组时很有用)。 - - 只有在可以进行提及检测时,才会强制执行提及门控(配置了原生提及或 `mentionPatterns`)。 - - 将某个群组或发送者加入允许列表不会禁用提及门控;当所有消息都应触发时,请将该群组的 `requireMention` 设置为 `false`。 - - 群聊提示词上下文会在每轮携带解析后的静默回复指令;工作区文件不应重复 `NO_REPLY` 机制。 - - 允许静默回复的群组会将干净的空模型轮次或仅推理的模型轮次视为静默,等同于 `NO_REPLY`。只有在明确允许直接静默回复时,直接聊天才会执行相同行为;否则空回复仍会保留为失败的智能体轮次。 + - `mentionPatterns` 是不区分大小写的安全正则表达式模式;无效模式和不安全的嵌套重复形式会被忽略。 + - 提供显式提及的表面仍会通过;模式是一种回退机制。 + - 按智能体覆盖:`agents.list[].groupChat.mentionPatterns`(当多个智能体共享一个群组时很有用)。 + - 只有在可以检测提及时,才会强制执行提及门控(已配置原生提及或 `mentionPatterns`)。 + - 将群组或发送者加入允许列表不会禁用提及门控;当所有消息都应触发时,请将该群组的 `requireMention` 设为 `false`。 + - 群聊提示上下文会在每轮携带已解析的静默回复指令;工作区文件不应重复 `NO_REPLY` 机制。 + - 允许静默回复的群组会将干净的空模型轮次或仅推理模型轮次视为静默,等同于 `NO_REPLY`。只有在明确允许直接静默回复时,直接聊天才会执行相同处理;否则空回复仍会被视为失败的智能体轮次。 - Discord 默认值位于 `channels.discord.guilds."*"`(可按服务器/渠道覆盖)。 - - 群组历史上下文在各渠道中以统一方式包装,并且是**仅待处理**的(因提及门控而跳过的消息);使用 `messages.groupChat.historyLimit` 设置全局默认值,使用 `channels..historyLimit`(或 `channels..accounts.*.historyLimit`)进行覆盖。设置为 `0` 可禁用。 + - 群组历史上下文在各渠道中统一包装,并且**仅限待处理**(因提及门控而跳过的消息);使用 `messages.groupChat.historyLimit` 设置全局默认值,并使用 `channels..historyLimit`(或 `channels..accounts.*.historyLimit`)进行覆盖。设为 `0` 可禁用。 @@ -354,19 +357,19 @@ otherwise -> reply - `tools`:允许/拒绝整个群组的工具。 - `toolsBySender`:群组内按发送者覆盖。使用显式键前缀:`id:`、`e164:`、`username:`、`name:` 和 `"*"` 通配符。旧版无前缀键仍被接受,并且仅按 `id:` 匹配。 -解析顺序(最具体的优先): +解析顺序(最具体者优先): 群组/渠道 `toolsBySender` 匹配。 - + 群组/渠道 `tools`。 默认(`"*"`)`toolsBySender` 匹配。 - + 默认(`"*"`)`tools`。 @@ -392,15 +395,15 @@ otherwise -> reply ``` -群组/渠道工具限制会在全局/智能体工具策略之外额外应用(拒绝仍然优先)。某些渠道对房间/渠道使用不同的嵌套结构(例如 Discord `guilds.*.channels.*`、Slack `channels.*`、Microsoft Teams `teams.*.channels.*`)。 +群组/渠道工具限制会叠加到全局/智能体工具策略之上(拒绝仍然优先)。某些渠道对房间/渠道使用不同的嵌套结构(例如 Discord `guilds.*.channels.*`、Slack `channels.*`、Microsoft Teams `teams.*.channels.*`)。 ## 群组允许列表 -配置 `channels.whatsapp.groups`、`channels.telegram.groups` 或 `channels.imessage.groups` 时,这些键会作为群组允许列表。使用 `"*"` 可允许所有群组,同时仍设置默认提及行为。 +配置 `channels.whatsapp.groups`、`channels.telegram.groups` 或 `channels.imessage.groups` 时,键会作为群组允许列表。使用 `"*"` 可允许所有群组,同时仍设置默认提及行为。 -常见混淆:私信配对批准并不等同于群组授权。对于支持私信配对的渠道,配对存储只会解锁私信。群组命令仍需要来自配置允许列表(如 `groupAllowFrom`)的显式群组发送者授权,或该渠道记录的配置回退。 +常见混淆:私信配对批准不同于群组授权。对于支持私信配对的渠道,配对存储只会解锁私信。群组命令仍需要来自配置允许列表的显式群组发送者授权,例如 `groupAllowFrom` 或该渠道记录的配置回退。 常见意图(复制/粘贴): @@ -460,7 +463,7 @@ otherwise -> reply - `/activation mention` - `/activation always` -所有者由 `channels.whatsapp.allowFrom` 确定(未设置时使用机器人的自有 E.164)。将命令作为独立消息发送。其他界面目前会忽略 `/activation`。 +所有者由 `channels.whatsapp.allowFrom` 确定(未设置时使用机器人的自身 E.164)。将命令作为独立消息发送。其他表面目前会忽略 `/activation`。 ## 上下文字段 @@ -470,27 +473,27 @@ otherwise -> reply - `GroupSubject`(如果已知) - `GroupMembers`(如果已知) - `WasMentioned`(提及门控结果) -- Telegram 论坛主题还包含 `MessageThreadId` 和 `IsForum`。 +- Telegram 论坛话题还包括 `MessageThreadId` 和 `IsForum`。 渠道特定说明: -- BlueBubbles 可以选择在填充 `GroupMembers` 之前,从本地通讯录数据库补充未命名的 macOS 群组参与者。此功能默认关闭,并且仅在正常群组门控通过后运行。 +- BlueBubbles 可以在填充 `GroupMembers` 之前,从本地通讯录数据库可选地补充未命名的 macOS 群组参与者信息。此功能默认关闭,并且只在正常群组门控通过后运行。 -智能体系统提示词会在新群组会话的第一轮包含群组介绍。它会提醒模型像人类一样回复,避免 Markdown 表格,尽量减少空行并遵循正常聊天间距,并避免输入字面量 `\n` 序列。来自渠道的群组名称和参与者标签会渲染为围栏包裹的不受信任元数据,而不是内联系统指令。 +智能体系统提示会在新群组会话的第一轮包含群组介绍。它提醒模型像真人一样回复,避免使用 Markdown 表格,尽量减少空行并遵循正常聊天间距,且避免输入字面量 `\n` 序列。来自渠道的群组名称和参与者标签会以围栏形式呈现为不受信任的元数据,而不是内联系统指令。 ## iMessage 细节 -- 路由或加入允许列表时,优先使用 `chat_id:`。 +- 路由或加入允许列表时优先使用 `chat_id:`。 - 列出聊天:`imsg chats --limit 20`。 -- 群组回复始终回到同一个 `chat_id`。 +- 群组回复始终返回同一个 `chat_id`。 -## WhatsApp 系统提示词 +## WhatsApp 系统提示 -请参阅 [WhatsApp](/zh-CN/channels/whatsapp#system-prompts),了解规范的 WhatsApp 系统提示词规则,包括群组和直接提示词解析、通配符行为以及账号覆盖语义。 +请参阅 [WhatsApp](/zh-CN/channels/whatsapp#system-prompts),了解规范的 WhatsApp 系统提示规则,包括群组和直接提示解析、通配符行为以及账号覆盖语义。 ## WhatsApp 细节 -请参阅[群组消息](/zh-CN/channels/group-messages),了解 WhatsApp 专属行为(历史注入、提及处理细节)。 +请参阅 [群组消息](/zh-CN/channels/group-messages),了解仅限 WhatsApp 的行为(历史注入、提及处理细节)。 ## 相关 diff --git a/docs/zh-CN/ci.md b/docs/zh-CN/ci.md index 8075b8c4c..da39162eb 100644 --- a/docs/zh-CN/ci.md +++ b/docs/zh-CN/ci.md @@ -1,75 +1,75 @@ --- read_when: - - 你需要了解某个 CI 作业为什么运行或未运行 - - 你正在调试一个失败的 GitHub Actions 检查 - - 你正在协调一次发布验证运行或重新运行 -summary: CI 作业图、范围门禁、发布总括项和本地命令等价项 + - 你需要了解 CI 作业为什么运行或未运行 + - 你正在调试一项失败的 GitHub Actions 检查 + - 你正在协调发布验证的一次运行或重新运行 +summary: CI 作业图、范围门控、发布总括和本地命令等价项 title: CI 流水线 x-i18n: - generated_at: "2026-05-01T02:24:10Z" + generated_at: "2026-05-01T03:00:03Z" model: gpt-5.5 provider: openai - source_hash: 0c2ee36f96ccf86d4adb739f5f7efb82c05f733e7693571ce391269d2538fec7 + source_hash: aea06f9f336f9a478a284473b5c5f38730b87837b1acb0390161bf2c455f6c41 source_path: ci.md workflow: 16 --- -OpenClaw CI 会在每次推送到 `main` 以及每个拉取请求时运行。`preflight` 作业会分类差异,并在只有无关区域发生变化时关闭昂贵的执行通道。手动 `workflow_dispatch` 运行会有意绕过智能作用域划分,并为候选版本和广泛验证展开完整图。Android 通道通过 `include_android` 保持可选启用。仅发布用的插件覆盖率位于单独的 [`Plugin Prerelease`](#plugin-prerelease) 工作流中,并且只会从 [`Full Release Validation`](#full-release-validation) 或显式手动分发运行。 +OpenClaw CI 会在每次推送到 `main` 以及每个拉取请求时运行。`preflight` 作业会分类差异,并在只有无关区域发生变更时关闭高成本通道。手动 `workflow_dispatch` 运行会有意绕过智能作用域划分,并为发布候选版本和广泛验证展开完整图。Android 通道通过 `include_android` 保持选择性启用。仅发布使用的插件覆盖位于单独的 [`插件预发布`](#plugin-prerelease) 工作流中,并且只会从 [`完整发布验证`](#full-release-validation) 或显式手动触发运行。 ## 流水线概览 -| 作业 | 用途 | 运行时机 | +| 作业 | 目的 | 运行时机 | | -------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------- | -| `preflight` | 检测仅文档变更、变更作用域、变更插件,并构建 CI 清单 | 始终在非草稿推送和 PR 上运行 | -| `security-scm-fast` | 通过 `zizmor` 进行私钥检测和工作流审计 | 始终在非草稿推送和 PR 上运行 | -| `security-dependency-audit` | 针对 npm 公告进行无依赖的生产锁文件审计 | 始终在非草稿推送和 PR 上运行 | -| `security-fast` | 快速安全作业所需的聚合项 | 始终在非草稿推送和 PR 上运行 | -| `check-dependencies` | 生产 Knip 仅依赖检查,加上未使用文件允许列表防护 | Node 相关变更 | -| `build-artifacts` | 构建 `dist/`、Control UI、构建产物检查,以及可复用的下游产物 | Node 相关变更 | -| `checks-fast-core` | 快速 Linux 正确性通道,例如内置/插件契约/协议检查 | Node 相关变更 | -| `checks-fast-contracts-channels` | 分片的渠道契约检查,并提供稳定的聚合检查结果 | Node 相关变更 | -| `checks-node-core-test` | Core Node 测试分片,不包括渠道、内置、契约和插件通道 | Node 相关变更 | -| `check` | 分片的主要本地门禁等价项:生产类型、lint、防护、测试类型和严格冒烟 | Node 相关变更 | -| `check-additional` | 架构、边界、插件表面防护、包边界和 Gateway 网关 watch 分片 | Node 相关变更 | -| `build-smoke` | 已构建 CLI 冒烟测试和启动内存冒烟 | Node 相关变更 | -| `checks` | 构建产物渠道测试的验证器 | Node 相关变更 | -| `checks-node-compat-node22` | Node 22 兼容性构建和冒烟通道 | 用于发布的手动 CI 分发 | -| `check-docs` | 文档格式、lint 和断链检查 | 文档变更 | -| `skills-python` | 面向 Python 支撑的 Skills 的 Ruff + pytest | Python Skill 相关变更 | -| `checks-windows` | Windows 专用进程/路径测试,加上共享运行时导入说明符回归 | Windows 相关变更 | -| `macos-node` | 使用共享构建产物的 macOS TypeScript 测试通道 | macOS 相关变更 | -| `macos-swift` | macOS 应用的 Swift lint、构建和测试 | macOS 相关变更 | -| `android` | 两种 flavor 的 Android 单元测试,加上一次调试 APK 构建 | Android 相关变更 | -| `test-performance-agent` | 受信任活动后的每日 Codex 慢测试优化 | 主 CI 成功或手动分发 | +| `preflight` | 检测仅文档变更、变更作用域、变更插件,并构建 CI 清单 | 始终在非草稿推送和 PR 上运行 | +| `security-scm-fast` | 通过 `zizmor` 检测私钥并审计工作流 | 始终在非草稿推送和 PR 上运行 | +| `security-dependency-audit` | 针对 npm 公告执行不依赖外部依赖的生产 lockfile 审计 | 始终在非草稿推送和 PR 上运行 | +| `security-fast` | 快速安全作业的必需聚合 | 始终在非草稿推送和 PR 上运行 | +| `check-dependencies` | 仅依赖项的生产 Knip 检查,加上未使用文件允许列表保护 | Node 相关变更 | +| `build-artifacts` | 构建 `dist/`、Control UI、构建产物检查以及可复用的下游产物 | Node 相关变更 | +| `checks-fast-core` | 快速 Linux 正确性通道,例如内置插件、插件契约和协议检查 | Node 相关变更 | +| `checks-fast-contracts-channels` | 分片渠道契约检查,并提供稳定的聚合检查结果 | Node 相关变更 | +| `checks-node-core-test` | 核心 Node 测试分片,不包括渠道、内置、契约和插件通道 | Node 相关变更 | +| `check` | 分片主本地门禁等价项:生产类型、lint、保护、测试类型和严格 smoke | Node 相关变更 | +| `check-additional` | 架构、边界、插件表面保护、包边界和 gateway-watch 分片 | Node 相关变更 | +| `build-smoke` | 已构建 CLI smoke 测试和启动内存 smoke | Node 相关变更 | +| `checks` | 构建产物渠道测试的验证器 | Node 相关变更 | +| `checks-node-compat-node22` | Node 22 兼容性构建和 smoke 通道 | 发布的手动 CI 触发 | +| `check-docs` | 文档格式化、lint 和断链检查 | 文档变更 | +| `skills-python` | 针对 Python 支持的 Skills 执行 Ruff + pytest | Python Skills 相关变更 | +| `checks-windows` | Windows 特定的进程/路径测试,以及共享运行时导入说明符回归测试 | Windows 相关变更 | +| `macos-node` | 使用共享构建产物的 macOS TypeScript 测试通道 | macOS 相关变更 | +| `macos-swift` | macOS 应用的 Swift lint、构建和测试 | macOS 相关变更 | +| `android` | 两种 flavor 的 Android 单元测试,以及一次 debug APK 构建 | Android 相关变更 | +| `test-performance-agent` | 可信活动后每日进行的 Codex 慢测试优化 | 主 CI 成功或手动触发 | ## 快速失败顺序 -1. `preflight` 决定哪些通道实际存在。`docs-scope` 和 `changed-scope` 逻辑是此作业中的步骤,而不是独立作业。 -2. `security-scm-fast`、`security-dependency-audit`、`security-fast`、`check`、`check-additional`、`check-docs` 和 `skills-python` 会快速失败,而不等待更重的产物和平台矩阵作业。 -3. `build-artifacts` 会与快速 Linux 通道重叠运行,以便共享构建就绪后下游消费者可以立即开始。 +1. `preflight` 决定哪些通道实际存在。`docs-scope` 和 `changed-scope` 逻辑是此作业内的步骤,不是独立作业。 +2. `security-scm-fast`、`security-dependency-audit`、`security-fast`、`check`、`check-additional`、`check-docs` 和 `skills-python` 会快速失败,不等待更重的产物和平台矩阵作业。 +3. `build-artifacts` 会与快速 Linux 通道重叠运行,使下游消费者可以在共享构建就绪后立即开始。 4. 更重的平台和运行时通道随后展开:`checks-fast-core`、`checks-fast-contracts-channels`、`checks-node-core-test`、`checks`、`checks-windows`、`macos-node`、`macos-swift` 和 `android`。 -当较新的推送落在同一个 PR 或 `main` ref 上时,GitHub 可能会将被取代的作业标记为 `cancelled`。除非同一 ref 的最新运行也失败,否则将其视为 CI 噪声。聚合分片检查使用 `!cancelled() && always()`,因此它们仍会报告正常的分片失败,但不会在整个工作流已经被取代后继续排队。自动 CI 并发键带有版本号(`CI-v7-*`),因此 GitHub 侧旧队列组中的僵尸项无法无限阻塞新的 main 运行。手动完整套件运行使用 `CI-manual-v1-*`,并且不会取消正在进行的运行。 +当同一个 PR 或 `main` ref 上有更新推送落地时,GitHub 可能会将被取代的作业标记为 `cancelled`。除非同一 ref 的最新运行也失败,否则将其视为 CI 噪声。聚合分片检查使用 `!cancelled() && always()`,因此它们仍会报告正常的分片失败,但不会在整个工作流已经被取代后继续排队。自动 CI 并发键带有版本号(`CI-v7-*`),因此 GitHub 端旧队列组中的僵尸运行无法无限期阻塞新的 main 运行。手动完整套件运行使用 `CI-manual-v1-*`,并且不会取消正在进行的运行。 -## 作用域和路由 +## 作用域与路由 -作用域逻辑位于 `scripts/ci-changed-scope.mjs`,并由 `src/scripts/ci-changed-scope.test.ts` 中的单元测试覆盖。手动分发会跳过变更作用域检测,并让 preflight 清单表现得像每个有作用域的区域都发生了变化。 +作用域逻辑位于 `scripts/ci-changed-scope.mjs`,并由 `src/scripts/ci-changed-scope.test.ts` 中的单元测试覆盖。手动触发会跳过变更作用域检测,并让 preflight 清单表现得像每个有作用域的区域都发生了变更。 -- **CI 工作流编辑**会验证 Node CI 图和工作流 linting,但不会单独强制 Windows、Android 或 macOS 原生构建;这些平台通道仍限定为平台源代码变更。 -- **仅 CI 路由编辑、选定的低成本核心测试 fixture 编辑,以及窄范围插件契约 helper/测试路由编辑**使用快速的仅 Node 清单路径:`preflight`、security,以及单个 `checks-fast-core` 任务。当变更仅限于该快速任务直接覆盖的路由或 helper 表面时,此路径会跳过构建产物、Node 22 兼容性、渠道契约、完整核心分片、内置插件分片和额外防护矩阵。 -- **Windows Node 检查**限定于 Windows 专用进程/路径包装器、npm/pnpm/UI 运行器 helper、包管理器配置,以及执行该通道的 CI 工作流表面;无关源代码、插件、安装冒烟和仅测试变更仍停留在 Linux Node 通道上。 +- **CI 工作流编辑**会验证 Node CI 图和工作流 lint,但本身不会强制运行 Windows、Android 或 macOS 原生构建;这些平台通道仍然限定于平台源代码变更。 +- **仅 CI 路由编辑、选定的低成本核心测试 fixture 编辑,以及窄范围插件契约 helper/测试路由编辑**使用快速的仅 Node 清单路径:`preflight`、security,以及一个 `checks-fast-core` 任务。当变更仅限于该快速任务直接覆盖的路由或 helper 表面时,该路径会跳过构建产物、Node 22 兼容性、渠道契约、完整核心分片、内置插件分片和额外保护矩阵。 +- **Windows Node 检查**限定于 Windows 特定的进程/路径 wrapper、npm/pnpm/UI runner helper、包管理器配置,以及执行该通道的 CI 工作流表面;无关源代码、插件、install-smoke 和仅测试变更仍留在 Linux Node 通道上。 -最慢的 Node 测试族会被拆分或平衡,使每个作业保持较小规模且不过度预留运行器:渠道契约作为三个加权分片运行,小型核心单元通道会配对,auto-reply 作为四个均衡 worker 运行(reply 子树拆分为 agent-runner、dispatch 和 commands/state-routing 分片),agentic gateway/插件配置则分散到现有的仅源代码 agentic Node 作业中,而不是等待构建产物。广泛的浏览器、QA、媒体和杂项插件测试使用其专用 Vitest 配置,而不是共享插件兜底项。include-pattern 分片使用 CI 分片名称记录计时条目,因此 `.artifacts/vitest-shard-timings.json` 可以区分整个配置和过滤后的分片。`check-additional` 将包边界编译/canary 工作保持在一起,并将运行时拓扑架构与 Gateway 网关 watch 覆盖分离;边界防护分片会在一个作业内并发运行其小型独立防护。Gateway 网关 watch、渠道测试和核心支持边界分片会在 `dist/` 和 `dist-runtime/` 已经构建完成后,在 `build-artifacts` 内并发运行。 +最慢的 Node 测试族会被拆分或均衡,使每个作业保持较小规模且不过度预留 runner:渠道契约作为三个加权分片运行,小型核心单元通道会配对运行,auto-reply 作为四个均衡 worker 运行(reply 子树拆分为 agent-runner、dispatch 和 commands/state-routing 分片),而 agentic gateway/plugin 配置分布在现有仅源代码的 agentic Node 作业中,而不是等待构建产物。宽泛的浏览器、QA、媒体和杂项插件测试使用其专用 Vitest 配置,而不是共享插件 catch-all。include-pattern 分片会使用 CI 分片名称记录计时条目,因此 `.artifacts/vitest-shard-timings.json` 可以区分整个配置和过滤后的分片。`check-additional` 将包边界编译/canary 工作放在一起,并将运行时拓扑架构与 gateway watch 覆盖分开;边界保护分片会在一个作业内并发运行其小型独立保护。Gateway watch、渠道测试和核心 support-boundary 分片会在 `dist/` 和 `dist-runtime/` 已构建完成后,在 `build-artifacts` 内并发运行。 -Android CI 会同时运行 `testPlayDebugUnitTest` 和 `testThirdPartyDebugUnitTest`,然后构建 Play 调试 APK。第三方 flavor 没有单独的源码集或清单;其单元测试通道仍会使用 SMS/call-log BuildConfig 标志编译该 flavor,同时避免在每次 Android 相关推送中重复执行调试 APK 打包作业。 +Android CI 会同时运行 `testPlayDebugUnitTest` 和 `testThirdPartyDebugUnitTest`,然后构建 Play debug APK。third-party flavor 没有单独的 source set 或 manifest;它的单元测试通道仍会使用 SMS/call-log BuildConfig 标志编译该 flavor,同时避免在每个 Android 相关推送上重复执行 debug APK 打包作业。 -`check-dependencies` 分片运行 `pnpm deadcode:dependencies`(生产 Knip 仅依赖检查,固定到最新 Knip 版本,并为 `dlx` 安装禁用 pnpm 的最低发布时间限制)和 `pnpm deadcode:unused-files`,后者会将 Knip 的生产未使用文件发现结果与 `scripts/deadcode-unused-files.allowlist.mjs` 进行比较。当 PR 新增未经审查的未使用文件或留下过期的允许列表条目时,未使用文件防护会失败,同时保留 Knip 无法静态解析的有意动态插件、生成内容、构建、实时测试和包桥接表面。 +`check-dependencies` 分片运行 `pnpm deadcode:dependencies`(一个仅依赖项的生产 Knip 检查,固定到最新 Knip 版本,并在 `dlx` 安装时禁用 pnpm 的最小发布时间限制)和 `pnpm deadcode:unused-files`,后者会将 Knip 的生产未使用文件发现与 `scripts/deadcode-unused-files.allowlist.mjs` 进行比较。当 PR 添加新的未经审查未使用文件或留下过期允许列表条目时,未使用文件保护会失败,同时保留 Knip 无法静态解析的有意动态插件、生成内容、构建内容、实时测试以及包桥接表面。 -## 手动分发 +## 手动触发 -手动 CI 分发运行与普通 CI 相同的作业图,但会强制开启每个非 Android 作用域通道:Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建冒烟、文档检查、Python Skills、Windows、macOS 和 Control UI i18n。独立手动 CI 分发只有在 `include_android=true` 时才运行 Android;完整发布总控通过传递 `include_android=true` 启用 Android。插件预发布静态检查、仅发布用的 `agentic-plugins` 分片、完整插件批量扫描以及插件预发布 Docker 通道都不包含在 CI 中。Docker 预发布套件只在 `Full Release Validation` 以启用 release-validation 门禁的方式分发单独的 `Plugin Prerelease` 工作流时运行。 +手动 CI 触发会运行与普通 CI 相同的作业图,但强制启用每个非 Android 作用域通道:Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建 smoke、文档检查、Python Skills、Windows、macOS 和 Control UI i18n。独立手动 CI 触发只有在 `include_android=true` 时才会运行 Android;完整发布总控通过传入 `include_android=true` 启用 Android。插件预发布静态检查、仅发布的 `agentic-plugins` 分片、完整插件批量 sweep,以及插件预发布 Docker 通道都排除在 CI 之外。Docker 预发布套件只会在 `完整发布验证` 以启用 release-validation 门禁的方式触发单独的 `插件预发布` 工作流时运行。 -手动运行使用唯一并发组,因此候选版本完整套件不会被同一 ref 上的另一个推送或 PR 运行取消。可选的 `target_ref` 输入允许受信任调用方针对分支、标签或完整提交 SHA 运行该图,同时使用所选分发 ref 中的工作流文件。 +手动运行使用唯一的并发组,因此发布候选完整套件不会被同一 ref 上的另一次推送或 PR 运行取消。可选的 `target_ref` 输入允许可信调用方针对某个分支、标签或完整提交 SHA 运行该图,同时使用所选触发 ref 中的工作流文件。 ```bash gh workflow run ci.yml --ref release/YYYY.M.D @@ -77,19 +77,19 @@ gh workflow run ci.yml --ref main -f target_ref= -f include_andro gh workflow run full-release-validation.yml --ref main -f ref= ``` -## 运行器 +## Runner | 运行器 | 作业 | | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `ubuntu-24.04` | `preflight`、快速安全作业和聚合作业(`security-scm-fast`、`security-dependency-audit`、`security-fast`)、快速协议/契约/内置检查、分片渠道契约检查、除 lint 以外的 `check` 分片、`check-additional` 分片和聚合作业、Node 测试聚合验证器、文档检查、Python Skills、workflow-sanity、labeler、auto-response;install-smoke 预检也使用 GitHub 托管的 Ubuntu,这样 Blacksmith 矩阵可以更早排队 | +| `ubuntu-24.04` | `preflight`、快速安全作业和聚合项(`security-scm-fast`、`security-dependency-audit`、`security-fast`)、快速协议/契约/内置检查、分片渠道契约检查、除 lint 之外的 `check` 分片、`check-additional` 分片和聚合项、Node 测试聚合验证器、文档检查、Python Skills、workflow-sanity、labeler、auto-response;install-smoke 预检也使用 GitHub 托管的 Ubuntu,因此 Blacksmith 矩阵可以更早排队 | | `blacksmith-4vcpu-ubuntu-2404` | `CodeQL Critical Quality`、较低权重的插件分片、`checks-fast-core`、`checks-node-compat-node22`、`check-prod-types` 和 `check-test-types` | | `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`、build-smoke、Linux Node 测试分片、内置插件测试分片、`android` | -| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`(对 CPU 足够敏感,8 vCPU 的成本高于节省的时间);install-smoke Docker 构建(32-vCPU 排队时间成本高于节省的时间) | +| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`(对 CPU 足够敏感,8 vCPU 增加的成本超过节省的时间);install-smoke Docker 构建(32-vCPU 队列时间的成本超过节省的时间) | | `blacksmith-16vcpu-windows-2025` | `checks-windows` | -| `blacksmith-6vcpu-macos-latest` | `openclaw/openclaw` 上的 `macos-node`;分叉仓库回退到 `macos-latest` | -| `blacksmith-12vcpu-macos-latest` | `openclaw/openclaw` 上的 `macos-swift`;分叉仓库回退到 `macos-latest` | +| `blacksmith-6vcpu-macos-latest` | `openclaw/openclaw` 上的 `macos-node`;fork 回退到 `macos-latest` | +| `blacksmith-12vcpu-macos-latest` | `openclaw/openclaw` 上的 `macos-swift`;fork 回退到 `macos-latest` | -## 本地等效命令 +## 本地等价命令 ```bash pnpm changed:lanes # inspect the local changed-lane classifier for origin/main...HEAD @@ -117,27 +117,27 @@ pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifac ## 完整发布验证 -`Full Release Validation` 是“发布前运行所有内容”的手动总控工作流。它接受分支、标签或完整提交 SHA,使用该目标调度手动 `CI` 工作流,调度 `Plugin Prerelease` 以提供仅发布所需的插件/软件包/静态/Docker 证明,并调度 `OpenClaw Release Checks` 以执行安装冒烟、软件包验收、Docker 发布路径套件、live/E2E、OpenWebUI、QA Lab parity、Matrix 和 Telegram 通道。当提供已发布的软件包规格时,它还可以运行发布后的 `NPM Telegram Beta E2E` 工作流。 +`Full Release Validation` 是“发布前运行所有内容”的手动总控工作流。它接受分支、标签或完整提交 SHA,使用该目标分派手动 `CI` 工作流,分派 `Plugin Prerelease` 以进行仅发布所需的插件/包/静态/Docker 验证,并分派 `OpenClaw Release Checks` 以运行安装冒烟、包验收、Docker 发布路径套件、live/E2E、OpenWebUI、QA Lab parity、Matrix 和 Telegram 通道。提供已发布包规格时,它还可以运行发布后的 `NPM Telegram Beta E2E` 工作流。 -参见[完整发布验证](/zh-CN/reference/full-release-validation),了解阶段矩阵、精确的工作流作业名称、配置差异、构件和聚焦重跑句柄。 +有关阶段矩阵、精确工作流作业名称、配置文件差异、构件和聚焦重跑句柄,请参阅[完整发布验证](/zh-CN/reference/full-release-validation)。 -`release_profile` 控制传入发布检查的 live/提供商覆盖范围。手动发布工作流默认使用 `stable`;仅在你明确需要宽泛的建议性提供商/媒体矩阵时才使用 `full`。 +`release_profile` 控制传递到发布检查的 live/提供商覆盖范围。手动发布工作流默认使用 `stable`;仅在你有意需要广泛的 advisory 提供商/媒体矩阵时才使用 `full`。 - `minimum` 保留最快的 OpenAI/核心发布关键通道。 - `stable` 添加稳定的提供商/后端集合。 -- `full` 运行宽泛的建议性提供商/媒体矩阵。 +- `full` 运行广泛的 advisory 提供商/媒体矩阵。 -总控会记录已调度的子运行 ID,最终的 `Verify full validation` 作业会重新检查当前子运行结论,并为每个子运行追加最慢作业表。如果某个子工作流重跑后变绿,只需重跑父验证器作业来刷新总控结果和耗时摘要。 +总控工作流会记录已分派的子运行 ID,最终的 `Verify full validation` 作业会重新检查当前子运行结论,并为每个子运行追加最慢作业表。如果子工作流重跑后变绿,只需重跑父验证器作业即可刷新总控结果和耗时摘要。 -对于恢复,`Full Release Validation` 和 `OpenClaw Release Checks` 都接受 `rerun_group`。发布候选版使用 `all`,仅普通完整 CI 子项使用 `ci`,仅插件预发布子项使用 `plugin-prerelease`,每个发布子项使用 `release-checks`,或在总控上使用更窄的组:`install-smoke`、`cross-os`、`live-e2e`、`package`、`qa`、`qa-parity`、`qa-live` 或 `npm-telegram`。这样在聚焦修复后,失败的发布盒子重跑可以保持有界。 +恢复时,`Full Release Validation` 和 `OpenClaw Release Checks` 都接受 `rerun_group`。对发布候选使用 `all`,仅普通完整 CI 子工作流使用 `ci`,仅插件预发布子工作流使用 `plugin-prerelease`,所有发布子工作流使用 `release-checks`,或者在总控中使用更窄的组:`install-smoke`、`cross-os`、`live-e2e`、`package`、`qa`、`qa-parity`、`qa-live` 或 `npm-telegram`。这样,在聚焦修复后可以将失败发布箱的重跑范围保持受限。 -`OpenClaw Release Checks` 使用受信任的工作流 ref,将所选 ref 一次性解析为 `release-package-under-test` tarball,然后将该构件传给 live/E2E 发布路径 Docker 工作流和软件包验收分片。这会让各发布盒子使用一致的软件包字节,并避免在多个子作业中重新打包同一个候选项。 +`OpenClaw Release Checks` 使用受信任的工作流 ref,将选定 ref 一次解析为 `release-package-under-test` tarball,然后把该构件传递给 live/E2E 发布路径 Docker 工作流和包验收分片。这样可以让发布箱之间的包字节保持一致,并避免在多个子作业中重新打包同一个候选版本。 -针对 `ref=main` 和 `rerun_group=all` 的重复 `Full Release Validation` 运行会取代较旧的总控。父监视器在父项被取消时,会取消它已经调度的任何子工作流,因此较新的 main 验证不会排在陈旧的两小时发布检查运行后面。发布分支/标签验证和聚焦重跑组保持 `cancel-in-progress: false`。 +`ref=main` 且 `rerun_group=all` 的重复 `Full Release Validation` 运行会取代较旧的总控运行。父监视器在父运行被取消时,会取消它已分派的任何子工作流,因此较新的 main 验证不会排在一个过期的两小时发布检查运行之后。发布分支/标签验证和聚焦重跑组保持 `cancel-in-progress: false`。 ## Live 和 E2E 分片 -发布 live/E2E 子项保留宽泛的原生 `pnpm test:live` 覆盖范围,但它通过 `scripts/test-live-shard.mjs` 以命名分片运行,而不是一个串行作业: +发布 live/E2E 子工作流保留广泛的原生 `pnpm test:live` 覆盖范围,但它通过 `scripts/test-live-shard.mjs` 作为具名分片运行,而不是作为一个串行作业运行: - `native-live-src-agents` - `native-live-src-gateway-core` @@ -151,33 +151,33 @@ pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifac - `native-live-extensions-xai` - 拆分的媒体音频/视频分片和提供商过滤的音乐分片 -这样在保持相同文件覆盖范围的同时,也让缓慢的 live 提供商失败更容易重跑和诊断。聚合的 `native-live-extensions-o-z`、`native-live-extensions-media` 和 `native-live-extensions-media-music` 分片名称仍可用于手动一次性重跑。 +这会保持相同的文件覆盖范围,同时让缓慢的 live 提供商失败更容易重跑和诊断。聚合 `native-live-extensions-o-z`、`native-live-extensions-media` 和 `native-live-extensions-media-music` 分片名称仍然可用于手动一次性重跑。 -原生 live 媒体分片在 `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04` 中运行,该镜像由 `Live Media Runner Image` 工作流构建。该镜像预装 `ffmpeg` 和 `ffprobe`;媒体作业只会在设置前验证这些二进制文件。将 Docker 支持的 live 套件保留在普通 Blacksmith 运行器上,容器作业不是启动嵌套 Docker 测试的合适位置。 +原生 live 媒体分片在 `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04` 中运行,该镜像由 `Live Media Runner Image` 工作流构建。该镜像预装了 `ffmpeg` 和 `ffprobe`;媒体作业只会在设置前验证二进制文件。将 Docker 支持的 live 套件保留在普通 Blacksmith 运行器上,容器作业不适合启动嵌套 Docker 测试。 -Docker 支持的 live 模型/后端分片会为每个所选提交使用单独的共享 `ghcr.io/openclaw/openclaw-live-test:` 镜像。live 发布工作流会构建并推送该镜像一次,然后 Docker live 模型、按提供商分片的 Gateway 网关、CLI 后端、ACP bind 和 Codex harness 分片会使用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 运行。Gateway 网关 Docker 分片携带显式的脚本级 `timeout` 上限,低于工作流作业超时,因此卡住的容器或清理路径会快速失败,而不是消耗整个发布检查预算。如果这些分片独立重建完整源码 Docker 目标,则说明发布运行配置错误,并会在重复镜像构建上浪费实际时间。 +Docker 支持的 live 模型/后端分片会为每个选定提交使用单独的共享 `ghcr.io/openclaw/openclaw-live-test:` 镜像。live 发布工作流只构建并推送该镜像一次,然后 Docker live 模型、按提供商分片的 Gateway 网关、CLI 后端、ACP bind 和 Codex harness 分片会使用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 运行。Gateway 网关 Docker 分片带有显式脚本级 `timeout` 上限,低于工作流作业超时,因此卡住的容器或清理路径会快速失败,而不是消耗整个发布检查预算。如果这些分片独立重建完整源 Docker 目标,则表示发布运行配置错误,并会把挂钟时间浪费在重复镜像构建上。 -## 软件包验收 +## 包验收 -当问题是“这个可安装的 OpenClaw 软件包作为产品是否可用?”时,使用 `Package Acceptance`。它不同于普通 CI:普通 CI 验证源码树,而软件包验收通过用户安装或更新后会执行的同一套 Docker E2E harness 来验证单个 tarball。 +当问题是“这个可安装的 OpenClaw 包作为产品是否可用?”时,使用 `Package Acceptance`。它不同于普通 CI:普通 CI 验证源代码树,而包验收会通过用户在安装或更新后执行的同一个 Docker E2E harness 来验证单个 tarball。 ### 作业 -1. `resolve_package` 会检出 `workflow_ref`,解析一个包候选项,写入 `.artifacts/docker-e2e-package/openclaw-current.tgz`,写入 `.artifacts/docker-e2e-package/package-candidate.json`,将两者作为 `package-under-test` 工件上传,并在 GitHub 步骤摘要中打印来源、工作流 ref、包 ref、版本、SHA-256 和 profile。 -2. `docker_acceptance` 会以 `ref=workflow_ref` 和 `package_artifact_name=package-under-test` 调用 `openclaw-live-and-e2e-checks-reusable.yml`。可复用工作流会下载该工件,验证 tarball 清单,在需要时准备 package-digest Docker 镜像,并针对该包运行选定的 Docker lane,而不是打包工作流检出内容。当某个 profile 选择了多个目标 `docker_lanes` 时,可复用工作流会先准备一次包和共享镜像,然后将这些 lane 扇出为并行的目标 Docker 作业,并使用唯一工件。 -3. `package_telegram` 可选调用 `NPM Telegram Beta E2E`。当 `telegram_mode` 不是 `none` 时它会运行;如果包验收已解析出一个包,它会安装同一个 `package-under-test` 工件;独立的 Telegram 分发仍可安装已发布的 npm spec。 -4. 如果包解析、Docker 验收或可选 Telegram lane 失败,`summary` 会使工作流失败。 +1. `resolve_package` 检出 `workflow_ref`,解析一个包候选项,写入 `.artifacts/docker-e2e-package/openclaw-current.tgz`,写入 `.artifacts/docker-e2e-package/package-candidate.json`,将两者都作为 `package-under-test` 工件上传,并在 GitHub 步骤摘要中打印源、工作流 ref、包 ref、版本、SHA-256 和配置档。 +2. `docker_acceptance` 使用 `ref=workflow_ref` 和 `package_artifact_name=package-under-test` 调用 `openclaw-live-and-e2e-checks-reusable.yml`。可复用工作流会下载该工件,验证 tarball 清单,在需要时准备 package-digest Docker 镜像,并针对该包运行所选 Docker lane,而不是打包工作流检出的内容。当某个配置档选择多个定向 `docker_lanes` 时,可复用工作流会准备一次包和共享镜像,然后将这些 lane 扇出为并行的定向 Docker 作业,并使用唯一工件。 +3. `package_telegram` 可选调用 `NPM Telegram Beta E2E`。当 `telegram_mode` 不是 `none` 时运行;如果 Package Acceptance 解析出了 `package-under-test` 工件,它会安装同一个工件;独立 Telegram 调度仍可安装已发布的 npm 规格。 +4. 如果包解析、Docker acceptance 或可选 Telegram lane 失败,`summary` 会使工作流失败。 -### 候选来源 +### 候选源 -- `source=npm` 仅接受 `openclaw@beta`、`openclaw@latest`,或精确的 OpenClaw 发布版本,例如 `openclaw@2026.4.27-beta.2`。将它用于已发布 beta/稳定版验收。 -- `source=ref` 会打包受信任的 `package_ref` 分支、标签或完整 commit SHA。解析器会获取 OpenClaw 分支/标签,验证所选 commit 可从仓库分支历史或发布标签到达,在分离 worktree 中安装依赖,并用 `scripts/package-openclaw-for-docker.mjs` 打包。 -- `source=url` 会下载 HTTPS `.tgz`;必须提供 `package_sha256`。 -- `source=artifact` 会从 `artifact_run_id` 和 `artifact_name` 下载一个 `.tgz`;`package_sha256` 是可选的,但对于外部共享的工件应提供。 +- `source=npm` 只接受 `openclaw@beta`、`openclaw@latest`,或精确的 OpenClaw 发布版本,例如 `openclaw@2026.4.27-beta.2`。将其用于已发布 beta/稳定版验收。 +- `source=ref` 会打包受信任的 `package_ref` 分支、标签或完整提交 SHA。解析器会获取 OpenClaw 分支/标签,验证所选提交可从仓库分支历史或发布标签到达,在分离 worktree 中安装依赖,并使用 `scripts/package-openclaw-for-docker.mjs` 打包。 +- `source=url` 下载一个 HTTPS `.tgz`;`package_sha256` 为必填。 +- `source=artifact` 从 `artifact_run_id` 和 `artifact_name` 下载一个 `.tgz`;`package_sha256` 可选,但对于外部共享工件应提供。 -请将 `workflow_ref` 和 `package_ref` 分开。`workflow_ref` 是运行测试的受信任工作流/harness 代码。`package_ref` 是在 `source=ref` 时被打包的源 commit。这样,当前测试 harness 就能验证较旧的受信任源 commit,而无需运行旧的工作流逻辑。 +保持 `workflow_ref` 和 `package_ref` 分离。`workflow_ref` 是运行测试的受信任工作流/测试框架代码。`package_ref` 是 `source=ref` 时被打包的源提交。这让当前测试框架可以验证较早的受信任源提交,而无需运行旧工作流逻辑。 -### 套件 profile +### 套件配置档 - `smoke` — `npm-onboard-channel-agent`、`gateway-network`、`config-reload` - `package` — `npm-onboard-channel-agent`、`doctor-switch`、`update-channel-switch`、`upgrade-survivor`、`published-upgrade-survivor`、`bundled-channel-deps-compat`、`plugins-offline`、`plugin-update` @@ -185,21 +185,21 @@ Docker 支持的 live 模型/后端分片会为每个所选提交使用单独的 - `full` — 带 OpenWebUI 的完整 Docker 发布路径分块 - `custom` — 精确的 `docker_lanes`;当 `suite_profile=custom` 时必填 -`package` profile 使用离线插件覆盖,因此已发布包验证不会被实时 ClawHub 可用性阻塞。可选 Telegram lane 会在 `NPM Telegram Beta E2E` 中复用 `package-under-test` 工件,同时为独立分发保留已发布 npm spec 路径。 +`package` 配置档使用离线插件覆盖,因此已发布包验证不会受实时 ClawHub 可用性约束。可选 Telegram lane 在 `NPM Telegram Beta E2E` 中复用 `package-under-test` 工件,并为独立调度保留已发布 npm 规格路径。 -发布检查会以 `source=ref`、`package_ref=`、`workflow_ref=`、`suite_profile=custom`、`docker_lanes='bundled-channel-deps-compat plugins-offline'` 和 `telegram_mode=mock-openai` 调用包验收。发布路径 Docker 分块会覆盖重叠的包/更新/插件 lane;包验收则针对同一个已解析包 tarball 保留原生工件的内置渠道兼容、离线插件和 Telegram 证明。跨 OS 发布检查仍会覆盖特定于 OS 的新手引导、安装器和平台行为;包/更新产品验证应从包验收开始。Windows 打包版和安装器全新 lane 还会验证已安装包可以从原始 Windows 绝对路径导入 browser-control override。OpenAI 跨 OS 智能体回合 smoke 在设置时默认使用 `OPENCLAW_CROSS_OS_OPENAI_MODEL`,否则使用 `openai/gpt-5.4-mini`,因此安装和 Gateway 网关证明保持快速且确定。 +发布检查使用 `source=ref`、`package_ref=`、`workflow_ref=`、`suite_profile=custom`、`docker_lanes='bundled-channel-deps-compat plugins-offline'` 和 `telegram_mode=mock-openai` 调用 Package Acceptance。发布路径 Docker 分块覆盖重叠的 package/update/plugin lane;Package Acceptance 保留基于同一已解析包 tarball 的工件原生内置渠道兼容性、离线插件和 Telegram 验证。跨 OS 发布检查仍覆盖特定 OS 的新手引导、安装器和平台行为;package/update 产品验证应从 Package Acceptance 开始。`published-upgrade-survivor` Docker lane 每次运行验证一个已发布包基线。在 Package Acceptance 中,已解析的 `package-under-test` tarball 始终是候选项,而 `published_upgrade_survivor_baseline` 选择已发布基线,默认值为 `openclaw@latest`;失败 lane 的重跑命令会保留该基线。本地运行可以将 `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC` 设置为精确包,例如 `openclaw@2026.4.15`。已发布 lane 使用预置的 `openclaw config set` 命令配方配置基线,然后在 `summary.json` 中记录配方步骤。更广泛的旧版本覆盖应按精确的 `published_upgrade_survivor_baseline` 值对 Package Acceptance 分片。Windows 打包和安装器全新 lane 还会验证已安装包可以从原始绝对 Windows 路径导入 browser-control 覆盖。OpenAI 跨 OS agent-turn smoke 在设置时默认使用 `OPENCLAW_CROSS_OS_OPENAI_MODEL`,否则使用 `openai/gpt-5.4-mini`,因此安装和 Gateway 网关验证保持快速且确定性。 ### 旧版兼容窗口 -包验收为已发布包提供有界的旧版兼容窗口。直到 `2026.4.25` 的包(包括 `2026.4.25-beta.*`)可以使用兼容路径: +Package Acceptance 对已发布包有有界的旧版兼容窗口。到 `2026.4.25` 为止的包,包括 `2026.4.25-beta.*`,可以使用兼容路径: -- `dist/postinstall-inventory.json` 中的已知私有 QA 条目可能指向 tarball 省略的文件; -- 当包未暴露 `gateway install --wrapper` 标志时,`doctor-switch` 可以跳过该持久化子用例; -- `update-channel-switch` 可以从 tarball 派生的 fake git fixture 中剪除缺失的 `pnpm.patchedDependencies`,并可以记录缺失的持久化 `update.channel`; -- 插件 smoke 可以读取旧版安装记录位置,或接受缺少 marketplace 安装记录持久化; -- `plugin-update` 可以允许配置元数据迁移,同时仍要求安装记录和不重新安装行为保持不变。 +- `dist/postinstall-inventory.json` 中已知的私有 QA 条目可以指向 tarball 省略的文件; +- 当包未暴露 `gateway install --wrapper` 标志时,`doctor-switch` 可以跳过 `gateway install --wrapper` 持久化子用例; +- `update-channel-switch` 可以从 tarball 派生的假 git fixture 中裁剪缺失的 `pnpm.patchedDependencies`,并可记录缺失的持久化 `update.channel`; +- 插件 smoke 可以读取旧版安装记录位置,或接受缺失的 marketplace 安装记录持久化; +- `plugin-update` 可以允许配置元数据迁移,同时仍要求安装记录和无重新安装行为保持不变。 -已发布的 `2026.4.26` 包也可能对已发货的本地构建元数据 stamp 文件发出警告。后续包必须满足现代契约;相同条件会失败,而不是警告或跳过。 +已发布的 `2026.4.26` 包也可以对已经发布的本地构建元数据标记文件发出警告。后续包必须满足现代契约;相同条件会失败,而不是警告或跳过。 ### 示例 @@ -242,111 +242,111 @@ gh workflow run package-acceptance.yml \ -f docker_lanes='install-e2e plugin-update' ``` -调试失败的包验收运行时,先查看 `resolve_package` 摘要,以确认包来源、版本和 SHA-256。然后检查 `docker_acceptance` 子运行及其 Docker 工件:`.artifacts/docker-tests/**/summary.json`、`failures.json`、lane 日志、阶段计时和重运行命令。优先重运行失败的包 profile 或精确 Docker lane,而不是重运行完整发布验证。 +调试失败的包验收运行时,先查看 `resolve_package` 摘要,以确认包源、版本和 SHA-256。然后检查 `docker_acceptance` 子运行及其 Docker 工件:`.artifacts/docker-tests/**/summary.json`、`failures.json`、lane 日志、阶段耗时和重跑命令。优先重跑失败的包配置档或精确的 Docker lane,而不是重跑完整发布验证。 ## 安装 smoke -独立的 `Install Smoke` 工作流会通过自己的 `preflight` 作业复用同一个范围脚本。它将 smoke 覆盖拆分为 `run_fast_install_smoke` 和 `run_full_install_smoke`。 +单独的 `Install Smoke` 工作流通过自己的 `preflight` 作业复用同一个范围脚本。它将 smoke 覆盖拆分为 `run_fast_install_smoke` 和 `run_full_install_smoke`。 -- **快速路径**会在拉取请求触及 Docker/包表面、内置插件包/manifest 变更,或 Docker smoke 作业会执行的核心插件/渠道/Gateway 网关/插件 SDK 表面时运行。仅源码的内置插件变更、仅测试编辑和仅文档编辑不会预留 Docker worker。快速路径会构建一次根 Dockerfile 镜像,检查 CLI,运行智能体删除共享工作区 CLI smoke,运行容器 `gateway-network` e2e,验证内置扩展构建参数,并在 240 秒聚合命令超时下运行有界的内置插件 Docker profile(每个场景的 Docker 运行单独设置上限)。 -- **完整路径**会为夜间定时运行、手动分发、workflow-call 发布检查,以及确实触及安装器/包/Docker 表面的拉取请求保留 QR 包安装和安装器 Docker/更新覆盖。在完整模式下,install-smoke 会准备或复用一个目标 SHA 的 GHCR 根 Dockerfile smoke 镜像,然后将 QR 包安装、根 Dockerfile/Gateway 网关 smoke、安装器/更新 smoke,以及快速内置插件 Docker E2E 作为独立作业运行,这样安装器工作不会排在根镜像 smoke 之后等待。 +- **快速路径**会在 pull request 触及 Docker/包表面、内置插件包/manifest 变更,或 Docker smoke 作业会覆盖的核心插件/渠道/Gateway 网关/插件 SDK 表面时运行。仅源代码的内置插件变更、仅测试编辑和仅文档编辑不会占用 Docker worker。快速路径会构建一次根 Dockerfile 镜像,检查 CLI,运行 agents delete shared-workspace CLI smoke,运行容器 gateway-network e2e,验证内置扩展构建参数,并在 240 秒聚合命令超时内运行有界的 bundled-plugin Docker 配置档(每个场景的 Docker 运行分别设置上限)。 +- **完整路径**保留 QR 包安装以及安装器 Docker/update 覆盖,用于夜间计划运行、手动调度、workflow-call 发布检查,以及真正触及安装器/包/Docker 表面的 pull request。在完整模式下,install-smoke 会准备或复用一个目标 SHA 的 GHCR 根 Dockerfile smoke 镜像,然后将 QR 包安装、根 Dockerfile/Gateway 网关 smoke、安装器/update smoke,以及快速 bundled-plugin Docker E2E 作为独立作业运行,使安装器工作无需等待根镜像 smoke。 -`main` 推送(包括 merge commit)不会强制走完整路径;当变更范围逻辑会在推送上请求完整覆盖时,工作流会保留快速 Docker smoke,并把完整安装 smoke 留给夜间或发布验证。 +`main` 推送(包括合并提交)不会强制完整路径;当变更范围逻辑会在推送上请求完整覆盖时,工作流会保留快速 Docker smoke,并将完整 install smoke 留给夜间或发布验证。 -较慢的 Bun 全局安装 image-provider smoke 由 `run_bun_global_install_smoke` 单独门控。它会在夜间计划和发布检查工作流中运行,手动 `Install Smoke` 分发可以选择启用它,但拉取请求和 `main` 推送不会运行。QR 和安装器 Docker 测试保留各自以安装为重点的 Dockerfile。 +较慢的 Bun 全局安装 image-provider smoke 由 `run_bun_global_install_smoke` 单独控制。它会在夜间计划和发布检查工作流中运行,手动 `Install Smoke` 调度也可以选择启用它,但 pull request 和 `main` 推送不会运行。QR 和安装器 Docker 测试保留各自专注于安装的 Dockerfile。 ## 本地 Docker E2E `pnpm test:docker:all` 会预构建一个共享 live-test 镜像,将 OpenClaw 打包一次为 npm tarball,并构建两个共享的 `scripts/e2e/Dockerfile` 镜像: -- 一个裸 Node/Git runner,用于安装器/更新/插件依赖 lane; -- 一个功能镜像,将同一个 tarball 安装到 `/app`,用于常规功能 lane。 +- 用于安装器/update/plugin-dependency lane 的裸 Node/Git runner; +- 将同一个 tarball 安装到 `/app`、用于正常功能 lane 的功能镜像。 -Docker lane 定义位于 `scripts/lib/docker-e2e-scenarios.mjs`,planner 逻辑位于 `scripts/lib/docker-e2e-plan.mjs`,runner 只执行所选 plan。调度器会通过 `OPENCLAW_DOCKER_E2E_BARE_IMAGE` 和 `OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE` 为每个 lane 选择镜像,然后以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 运行 lane。 +Docker lane 定义位于 `scripts/lib/docker-e2e-scenarios.mjs`,规划器逻辑位于 `scripts/lib/docker-e2e-plan.mjs`,runner 只执行所选计划。调度器使用 `OPENCLAW_DOCKER_E2E_BARE_IMAGE` 和 `OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE` 为每个 lane 选择镜像,然后使用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 运行 lane。 -### 可调参数 +### 可调项 | 变量 | 默认值 | 用途 | | -------------------------------------- | ------- | --------------------------------------------------------------------------------------------- | -| `OPENCLAW_DOCKER_ALL_PARALLELISM` | 10 | 普通 lane 的主池 slot 数。 | -| `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM` | 10 | 对提供商敏感的 tail-pool slot 数。 | +| `OPENCLAW_DOCKER_ALL_PARALLELISM` | 10 | 普通 lane 的主池槽位数。 | +| `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM` | 10 | 对提供商敏感的尾池槽位数。 | | `OPENCLAW_DOCKER_ALL_LIVE_LIMIT` | 9 | 并发 live lane 上限,避免提供商限流。 | | `OPENCLAW_DOCKER_ALL_NPM_LIMIT` | 10 | 并发 npm install lane 上限。 | | `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT` | 7 | 并发多服务 lane 上限。 | -| `OPENCLAW_DOCKER_ALL_START_STAGGER_MS` | 2000 | lane 启动之间的错峰时间,以避免 Docker daemon 创建风暴;设为 `0` 表示不做错峰。 | +| `OPENCLAW_DOCKER_ALL_START_STAGGER_MS` | 2000 | lane 启动之间的错峰时间,用于避免 Docker daemon create 风暴;设为 `0` 表示不交错。 | | `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS` | 7200000 | 每个 lane 的兜底超时(120 分钟);选定的 live/tail lane 使用更严格的上限。 | -| `OPENCLAW_DOCKER_ALL_DRY_RUN` | unset | `1` 会打印调度器 plan,而不运行 lane。 | -| `OPENCLAW_DOCKER_ALL_LANES` | unset | 逗号分隔的精确 lane 列表;跳过清理 smoke,以便智能体复现一个失败 lane。 | +| `OPENCLAW_DOCKER_ALL_DRY_RUN` | 未设置 | `1` 会打印调度器计划而不运行 lane。 | +| `OPENCLAW_DOCKER_ALL_LANES` | 未设置 | 逗号分隔的精确 lane 列表;跳过 cleanup smoke,以便智能体复现一个失败 lane。 | -重于其有效上限的 lane 仍可从空池启动,然后独占运行直到释放容量。本地聚合会预检查 Docker,移除陈旧的 OpenClaw E2E 容器,输出活跃 lane Status,持久化 lane 计时以进行最长优先排序,并且默认在首次失败后停止调度新的池化 lane。 +重于其有效上限的泳道仍可从空池启动,然后独占运行直到释放容量。本地聚合会预检 Docker,移除陈旧的 OpenClaw E2E 容器,输出活跃泳道 Status,持久化泳道耗时以便按最长优先排序,并且默认在首次失败后停止调度新的池化泳道。 -### 可复用 live/E2E 工作流 +### 可复用的 live/E2E 工作流 -可复用的 live/E2E 工作流会询问 `scripts/test-docker-all.mjs --plan-json` 需要哪些包、镜像类型、live 镜像、lane 和凭据覆盖范围。随后 `scripts/docker-e2e.mjs` 会把该计划转换为 GitHub 输出和摘要。它会通过 `scripts/package-openclaw-for-docker.mjs` 打包 OpenClaw,下载当前运行的包构件,或从 `package_artifact_run_id` 下载包构件;验证 tarball 清单;在计划需要包安装 lane 时,通过 Blacksmith 的 Docker 层缓存构建并推送带有包摘要标签的 bare/functional GHCR Docker E2E 镜像;并复用提供的 `docker_e2e_bare_image`/`docker_e2e_functional_image` 输入或已有的包摘要镜像,而不是重新构建。Docker 镜像拉取会按每次尝试 180 秒的有界超时重试,因此卡住的 registry/cache 流会快速重试,而不是消耗 CI 关键路径的大部分时间。 +可复用的 live/E2E 工作流会询问 `scripts/test-docker-all.mjs --plan-json` 需要哪些包、镜像类型、live 镜像、泳道和凭证覆盖范围。随后 `scripts/docker-e2e.mjs` 将该计划转换为 GitHub 输出和摘要。它要么通过 `scripts/package-openclaw-for-docker.mjs` 打包 OpenClaw,要么下载当前运行的包构件,要么从 `package_artifact_run_id` 下载包构件;校验 tarball 清单;在计划需要已安装包的泳道时,通过 Blacksmith 的 Docker 层缓存构建并推送带有包摘要标签的 bare/functional GHCR Docker E2E 镜像;并且复用提供的 `docker_e2e_bare_image`/`docker_e2e_functional_image` 输入或现有包摘要镜像,而不是重新构建。Docker 镜像拉取会在每次尝试设置有界的 180 秒超时后重试,因此卡住的 registry/cache 流会快速重试,而不是消耗大部分 CI 关键路径时间。 ### 发布路径分块 -发布 Docker 覆盖范围会运行更小的分块作业,并设置 `OPENCLAW_SKIP_DOCKER_BUILD=1`,因此每个分块只拉取它需要的镜像类型,并通过同一个加权调度器执行多个 lane: +发布 Docker 覆盖使用较小的分块任务运行,并设置 `OPENCLAW_SKIP_DOCKER_BUILD=1`,这样每个分块只拉取自己需要的镜像类型,并通过同一个加权调度器执行多个泳道: - `OPENCLAW_DOCKER_ALL_PROFILE=release-path` - `OPENCLAW_DOCKER_ALL_CHUNK=core | package-update-openai | package-update-anthropic | package-update-core | plugins-runtime-plugins | plugins-runtime-services | plugins-runtime-install-a..h | bundled-channels` -当前发布 Docker 分块包括 `core`、`package-update-openai`、`package-update-anthropic`、`package-update-core`、`plugins-runtime-plugins`、`plugins-runtime-services`、从 `plugins-runtime-install-a` 到 `plugins-runtime-install-h`、`bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-discord`、`bundled-channels-update-b` 和 `bundled-channels-contracts`。聚合的 `bundled-channels` 分块仍可用于手动一次性重新运行,`plugins-runtime-core`、`plugins-runtime` 和 `plugins-integrations` 也仍作为聚合的插件/运行时别名。`install-e2e` lane 别名仍是两个提供商安装器 lane 的聚合手动重新运行别名。`bundled-channels` 分块运行拆分后的 `bundled-channel-*` 和 `bundled-channel-update-*` lane,而不是串行的全合一 `bundled-channel-deps` lane。 +当前发布 Docker 分块包括 `core`、`package-update-openai`、`package-update-anthropic`、`package-update-core`、`plugins-runtime-plugins`、`plugins-runtime-services`、从 `plugins-runtime-install-a` 到 `plugins-runtime-install-h`、`bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-discord`、`bundled-channels-update-b` 和 `bundled-channels-contracts`。聚合的 `bundled-channels` 分块仍可用于手动一次性重跑,而 `plugins-runtime-core`、`plugins-runtime` 和 `plugins-integrations` 仍保留为聚合插件/运行时别名。`install-e2e` 泳道别名仍是两个提供商安装器泳道的聚合手动重跑别名。`bundled-channels` 分块运行拆分后的 `bundled-channel-*` 和 `bundled-channel-update-*` 泳道,而不是串行的一体化 `bundled-channel-deps` 泳道。 -当完整发布路径覆盖范围请求 OpenWebUI 时,OpenWebUI 会并入 `plugins-runtime-services`,并且只为仅 OpenWebUI 的调度保留独立的 `openwebui` 分块。内置渠道更新 lane 会针对临时 npm 网络失败重试一次。 +当完整发布路径覆盖请求 OpenWebUI 时,OpenWebUI 会并入 `plugins-runtime-services`,并且仅在只调度 OpenWebUI 时保留独立的 `openwebui` 分块。内置渠道更新泳道会针对临时 npm 网络故障重试一次。 -每个分块都会上传 `.artifacts/docker-tests/`,其中包含 lane 日志、计时、`summary.json`、`failures.json`、阶段计时、调度器计划 JSON、慢 lane 表以及每个 lane 的重新运行命令。工作流 `docker_lanes` 输入会针对准备好的镜像运行所选 lane,而不是运行分块作业,这会把失败 lane 调试限定在一个有针对性的 Docker 作业内,并为该次运行准备、下载或复用包构件;如果所选 lane 是 live Docker lane,则有针对性的作业会为该次重新运行在本地构建 live-test 镜像。生成的每个 lane GitHub 重新运行命令会在这些值存在时包含 `package_artifact_run_id`、`package_artifact_name` 和准备好的镜像输入,因此失败的 lane 可以复用失败运行中的确切包和镜像。 +每个分块都会上传 `.artifacts/docker-tests/`,其中包含泳道日志、耗时、`summary.json`、`failures.json`、阶段耗时、调度器计划 JSON、慢泳道表,以及每个泳道的重跑命令。工作流 `docker_lanes` 输入会针对已准备的镜像运行选定泳道,而不是运行分块任务,这会把失败泳道的调试限制在一个有针对性的 Docker 任务内,并为该次运行准备、下载或复用包构件;如果选定泳道是 live Docker 泳道,目标任务会在本地为该次重跑构建 live-test 镜像。生成的每泳道 GitHub 重跑命令会在这些值存在时包含 `package_artifact_run_id`、`package_artifact_name` 和已准备的镜像输入,因此失败泳道可以复用失败运行中的确切包和镜像。 ```bash -pnpm test:docker:rerun # download Docker artifacts and print combined/per-lane targeted rerun commands -pnpm test:docker:timings # slow-lane and phase critical-path summaries +pnpm test:docker:rerun # 下载 Docker 构件并打印组合/每泳道定向重跑命令 +pnpm test:docker:timings # 慢泳道和阶段关键路径摘要 ``` -定时 live/E2E 工作流每天运行完整的发布路径 Docker 套件。 +计划任务 live/E2E 工作流每天运行完整的发布路径 Docker 套件。 ## 插件预发布 -`Plugin Prerelease` 是成本更高的产品/包覆盖范围,因此它是一个独立工作流,由 `Full Release Validation` 或显式操作员调度。普通拉取请求、`main` 推送和独立手动 CI 调度不会开启该套件。它会在八个插件工作器之间均衡内置插件测试;这些插件分片作业一次最多运行两个插件配置组,每组一个 Vitest 工作器,并使用更大的 Node 堆,因此导入负载较重的插件批次不会创建额外的 CI 作业。仅发布 Docker 预发布路径会把有针对性的 Docker lane 分成小组批处理,以避免为一到三分钟的作业保留数十个运行器。 +`Plugin Prerelease` 是成本更高的产品/包覆盖,因此它是一个单独的工作流,由 `Full Release Validation` 或显式操作员调度。普通拉取请求、`main` 推送和独立手动 CI 调度都会关闭该套件。它会把内置插件测试均衡分配到八个扩展工作器;这些扩展分片任务每次最多运行两个插件配置组,每组使用一个 Vitest 工作器和更大的 Node 堆,因此导入密集型插件批次不会创建额外的 CI 任务。仅发布使用的 Docker 预发布路径会以小组批处理目标 Docker 泳道,避免为一到三分钟的任务预留几十个运行器。 ## QA 实验室 -QA 实验室在主智能范围化工作流之外有专用 CI lane。 +QA 实验室在主智能作用域工作流之外有专用 CI 泳道。 -- `Parity gate` 工作流会在匹配的 PR 更改和手动调度时运行;它构建私有 QA 运行时,并比较 mock GPT-5.5 和 Opus 4.6 agentic 包。 -- `QA-Lab - All Lanes` 工作流会在 `main` 上每晚运行,也会在手动调度时运行;它会把 mock parity gate、live Matrix lane,以及 live Telegram 和 Discord lane 作为并行作业展开。Live 作业使用 `qa-live-shared` 环境,Telegram/Discord 使用 Convex 租约。 +- `Parity gate` 工作流会在匹配的 PR 变更和手动调度时运行;它会构建私有 QA 运行时,并比较模拟 GPT-5.5 和 Opus 4.6 的 agentic 包。 +- `QA-Lab - All Lanes` 工作流会每晚在 `main` 上运行,也可手动调度;它会把模拟 parity gate、live Matrix 泳道,以及 live Telegram 和 Discord 泳道扇出为并行任务。Live 任务使用 `qa-live-shared` 环境,Telegram/Discord 使用 Convex 租约。 -发布检查会使用确定性的 mock 提供商和 mock 限定模型(`mock-openai/gpt-5.5` 和 `mock-openai/gpt-5.5-alt`)运行 Matrix 和 Telegram live 传输 lane,因此渠道契约会与 live 模型延迟和普通提供商插件启动隔离开。Live 传输 Gateway 网关会禁用记忆搜索,因为 QA parity 会单独覆盖记忆行为;提供商连接性由单独的 live 模型、原生提供商和 Docker 提供商套件覆盖。 +发布检查会使用确定性的模拟提供商和模拟限定模型(`mock-openai/gpt-5.5` 和 `mock-openai/gpt-5.5-alt`)运行 Matrix 和 Telegram live 传输泳道,因此渠道契约会与 live 模型延迟和正常提供商插件启动隔离。live 传输 Gateway 网关会禁用记忆搜索,因为 QA parity 会单独覆盖记忆行为;提供商连通性由单独的 live 模型、原生提供商和 Docker 提供商套件覆盖。 -Matrix 在定时和发布门禁中使用 `--profile fast`,并且只在检出的 CLI 支持时添加 `--fail-fast`。CLI 默认值和手动工作流输入仍为 `all`;手动 `matrix_profile=all` 调度始终会把完整 Matrix 覆盖范围分片为 `transport`、`media`、`e2ee-smoke`、`e2ee-deep` 和 `e2ee-cli` 作业。 +Matrix 对计划任务和发布门禁使用 `--profile fast`,仅在检出的 CLI 支持时添加 `--fail-fast`。CLI 默认值和手动工作流输入仍为 `all`;手动 `matrix_profile=all` 调度始终会把完整 Matrix 覆盖分片为 `transport`、`media`、`e2ee-smoke`、`e2ee-deep` 和 `e2ee-cli` 任务。 -`OpenClaw Release Checks` 也会在发布批准前运行发布关键的 QA 实验室 lane;它的 QA parity gate 会把候选包和基线包作为并行 lane 作业运行,然后把两个构件下载到一个小型报告作业中进行最终 parity 比较。 +`OpenClaw Release Checks` 还会在发布批准前运行发布关键的 QA 实验室泳道;它的 QA parity gate 会把候选包和基线包作为并行泳道任务运行,然后将两个构件都下载到一个小型报告任务中,用于最终 parity 比较。 -不要把 PR 落地路径置于 `Parity gate` 之后,除非更改确实触及 QA 运行时、模型包 parity,或 parity 工作流拥有的表面。对于普通渠道、配置、文档或单元测试修复,请将其视为可选信号,并遵循范围化 CI/检查证据。 +不要把 PR 合入路径放在 `Parity gate` 之后,除非该变更确实触及 QA 运行时、模型包 parity,或 parity 工作流拥有的表面。对于普通渠道、配置、文档或单元测试修复,应将它视为可选信号,并遵循作用域化的 CI/检查证据。 ## CodeQL -`CodeQL` 工作流有意作为狭窄的第一轮安全扫描器,而不是完整仓库扫描。每日、手动和非草稿拉取请求守护运行会扫描 Actions 工作流代码,以及风险最高的 JavaScript/TypeScript 表面,并使用筛选到高/严重 `security-severity` 的高置信度安全查询。 +`CodeQL` 工作流有意作为范围狭窄的第一轮安全扫描器,而不是完整仓库扫描。每日、手动和非草稿拉取请求守护运行会扫描 Actions 工作流代码,以及风险最高的 JavaScript/TypeScript 表面,并使用过滤到高/严重 `security-severity` 的高置信度安全查询。 -拉取请求守护保持轻量:它只会在 `.github/actions`、`.github/codeql`、`.github/workflows`、`packages` 或 `src` 下发生更改时启动,并运行与定时工作流相同的高置信度安全矩阵。Android 和 macOS CodeQL 不属于 PR 默认项。 +拉取请求守护保持轻量:它只会针对 `.github/actions`、`.github/codeql`、`.github/workflows`、`packages` 或 `src` 下的变更启动,并运行与计划任务工作流相同的高置信度安全矩阵。Android 和 macOS CodeQL 不包含在 PR 默认项中。 ### 安全类别 | 类别 | 表面 | | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| `/codeql-security-high/core-auth-secrets` | 认证、密钥、沙箱、cron 和 gateway 基线 | +| `/codeql-security-high/core-auth-secrets` | 凭证、密钥、沙箱、cron 和 Gateway 网关基线 | | `/codeql-security-high/channel-runtime-boundary` | 核心渠道实现契约,以及渠道插件运行时、Gateway 网关、插件 SDK、密钥、审计触点 | -| `/codeql-security-high/network-ssrf-boundary` | 核心 SSRF、IP 解析、网络防护、web-fetch 和插件 SDK SSRF 策略表面 | -| `/codeql-security-high/mcp-process-tool-boundary` | MCP 服务器、进程执行辅助工具、出站投递和智能体工具执行门禁 | +| `/codeql-security-high/network-ssrf-boundary` | 核心 SSRF、IP 解析、网络防护、web-fetch 和插件 SDK SSRF 策略表面 | +| `/codeql-security-high/mcp-process-tool-boundary` | MCP 服务器、进程执行辅助工具、出站投递和 agent 工具执行门禁 | | `/codeql-security-high/plugin-trust-boundary` | 插件安装、加载器、清单、registry、运行时依赖暂存、源码加载和插件 SDK 包契约信任表面 | ### 平台特定安全分片 -- `CodeQL Android Critical Security` — 定时 Android 安全分片。在 workflow sanity 接受的最小 Blacksmith Linux 运行器上为 CodeQL 手动构建 Android 应用。上传到 `/codeql-critical-security/android` 下。 -- `CodeQL macOS Critical Security` — 每周/手动 macOS 安全分片。在 Blacksmith macOS 上为 CodeQL 手动构建 macOS 应用,从上传的 SARIF 中过滤掉依赖构建结果,并上传到 `/codeql-critical-security/macos` 下。它保留在每日默认项之外,因为即使在干净状态下,macOS 构建也会主导运行时间。 +- `CodeQL Android Critical Security` — 计划任务 Android 安全分片。在工作流完整性检查接受的最小 Blacksmith Linux 运行器上,为 CodeQL 手动构建 Android 应用。上传到 `/codeql-critical-security/android` 下。 +- `CodeQL macOS Critical Security` — 每周/手动 macOS 安全分片。在 Blacksmith macOS 上为 CodeQL 手动构建 macOS 应用,从上传的 SARIF 中过滤依赖构建结果,并上传到 `/codeql-critical-security/macos` 下。由于 macOS 构建即使干净也主导运行时,因此保持在每日默认项之外。 ### 关键质量类别 -`CodeQL Critical Quality` 是对应的非安全分片。它只在较小的 Blacksmith Linux 运行器上,对狭窄的高价值表面运行错误严重级别、非安全 JavaScript/TypeScript 质量查询。它的拉取请求守护有意小于定时配置:非草稿 PR 只会为智能体命令/模型/工具执行和回复调度代码、配置 schema/迁移/IO 代码、认证/密钥/沙箱/安全代码、核心渠道和内置渠道插件运行时、gateway 协议/服务器方法、记忆运行时/SDK 胶水、MCP/进程/出站投递、提供商运行时/模型目录、会话诊断/投递队列、插件加载器、插件 SDK/包契约,或插件 SDK 回复运行时更改运行匹配的 `agent-runtime-boundary`、`config-boundary`、`core-auth-secrets`、`channel-runtime-boundary`、`gateway-runtime-boundary`、`memory-runtime-boundary`、`mcp-process-runtime-boundary`、`provider-runtime-boundary`、`session-diagnostics-boundary`、`plugin-boundary`、`plugin-sdk-package-contract` 和 `plugin-sdk-reply-runtime` 分片。CodeQL 配置和质量工作流更改会运行全部十二个 PR 质量分片。 +`CodeQL Critical Quality` 是对应的非安全分片。它只在较小的 Blacksmith Linux 运行器上,对狭窄的高价值表面运行 error-severity、非安全 JavaScript/TypeScript 质量查询。它的拉取请求守护有意比计划任务配置文件更小:非草稿 PR 只会针对 agent 命令/模型/工具执行和回复分发代码、配置 schema/迁移/IO 代码、凭证/密钥/沙箱/安全代码、核心渠道和内置渠道插件运行时、Gateway 网关协议/服务器方法、记忆运行时/SDK 粘合代码、MCP/进程/出站投递、提供商运行时/模型目录、会话诊断/投递队列、插件加载器、插件 SDK/包契约,或插件 SDK 回复运行时变更,运行匹配的 `agent-runtime-boundary`、`config-boundary`、`core-auth-secrets`、`channel-runtime-boundary`、`gateway-runtime-boundary`、`memory-runtime-boundary`、`mcp-process-runtime-boundary`、`provider-runtime-boundary`、`session-diagnostics-boundary`、`plugin-boundary`、`plugin-sdk-package-contract` 和 `plugin-sdk-reply-runtime` 分片。CodeQL 配置和质量工作流变更会运行全部十二个 PR 质量分片。 手动调度接受: @@ -354,40 +354,40 @@ Matrix 在定时和发布门禁中使用 `--profile fast`,并且只在检出 profile=all|agent-runtime-boundary|config-boundary|core-auth-secrets|channel-runtime-boundary|gateway-runtime-boundary|memory-runtime-boundary|mcp-process-runtime-boundary|plugin-boundary|plugin-sdk-package-contract|plugin-sdk-reply-runtime|provider-runtime-boundary|session-diagnostics-boundary ``` -狭窄配置是用于单独运行一个质量分片的教学/迭代钩子。 +这些窄配置文件是用于单独运行一个质量分片的教学/迭代钩子。 -| 类别 | 表面 | -| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `/codeql-critical-quality/core-auth-secrets` | 凭证、密钥、沙箱、cron 和 Gateway 网关安全边界代码 | -| `/codeql-critical-quality/config-boundary` | 配置架构、迁移、规范化和 IO 契约 | -| `/codeql-critical-quality/gateway-runtime-boundary` | Gateway 网关协议架构和服务器方法契约 | -| `/codeql-critical-quality/channel-runtime-boundary` | 核心渠道和内置渠道插件实现契约 | -| `/codeql-critical-quality/agent-runtime-boundary` | 命令执行、模型/提供商分发、自动回复分发和队列,以及 ACP 控制平面运行时契约 | -| `/codeql-critical-quality/mcp-process-runtime-boundary` | MCP 服务器和工具桥接、进程监督辅助工具,以及出站投递契约 | -| `/codeql-critical-quality/memory-runtime-boundary` | 记忆宿主 SDK、记忆运行时门面、记忆插件 SDK 别名、记忆运行时激活粘合代码,以及记忆 Doctor 命令 | -| `/codeql-critical-quality/session-diagnostics-boundary` | 回复队列内部机制、会话投递队列、出站会话绑定/投递辅助工具、诊断事件/日志包表面,以及会话 Doctor CLI 契约 | -| `/codeql-critical-quality/plugin-sdk-reply-runtime` | 插件 SDK 入站回复分发、回复载荷/分块/运行时辅助工具、渠道回复选项、投递队列,以及会话/线程绑定辅助工具 | -| `/codeql-critical-quality/provider-runtime-boundary` | 模型目录规范化、提供商凭证和设备发现、提供商运行时注册、提供商默认值/目录,以及 Web/搜索/抓取/嵌入注册表 | -| `/codeql-critical-quality/ui-control-plane` | 控制 UI 引导、本地持久化、Gateway 网关控制流,以及任务控制平面运行时契约 | -| `/codeql-critical-quality/web-media-runtime-boundary` | 核心 Web 抓取/搜索、媒体 IO、媒体理解、图像生成和媒体生成运行时契约 | -| `/codeql-critical-quality/plugin-boundary` | 加载器、注册表、公共表面和插件 SDK 入口点契约 | -| `/codeql-critical-quality/plugin-sdk-package-contract` | 已发布包侧插件 SDK 源码和插件包契约辅助工具 | +| 类别 | 表面 | +| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `/codeql-critical-quality/core-auth-secrets` | 认证、密钥、沙箱、cron 和 Gateway 网关安全边界代码 | +| `/codeql-critical-quality/config-boundary` | 配置架构、迁移、规范化和 IO 契约 | +| `/codeql-critical-quality/gateway-runtime-boundary` | Gateway 网关协议架构和服务器方法契约 | +| `/codeql-critical-quality/channel-runtime-boundary` | 核心渠道和内置渠道插件实现契约 | +| `/codeql-critical-quality/agent-runtime-boundary` | 命令执行、模型/提供商分派、自动回复分派和队列,以及 ACP 控制平面运行时契约 | +| `/codeql-critical-quality/mcp-process-runtime-boundary` | MCP 服务器和工具桥接、进程监督辅助工具,以及出站投递契约 | +| `/codeql-critical-quality/memory-runtime-boundary` | 记忆宿主 SDK、记忆运行时门面、记忆插件 SDK 别名、记忆运行时激活胶水代码,以及记忆 Doctor 命令 | +| `/codeql-critical-quality/session-diagnostics-boundary` | 回复队列内部机制、会话投递队列、出站会话绑定/投递辅助工具、诊断事件/日志包表面,以及会话 Doctor CLI 契约 | +| `/codeql-critical-quality/plugin-sdk-reply-runtime` | 插件 SDK 入站回复分派、回复载荷/分块/运行时辅助工具、渠道回复选项、投递队列,以及会话/线程绑定辅助工具 | +| `/codeql-critical-quality/provider-runtime-boundary` | 模型目录规范化、提供商认证和设备发现、提供商运行时注册、提供商默认值/目录,以及 Web/搜索/抓取/嵌入注册表 | +| `/codeql-critical-quality/ui-control-plane` | 控制 UI 引导、本地持久化、Gateway 网关控制流,以及任务控制平面运行时契约 | +| `/codeql-critical-quality/web-media-runtime-boundary` | 核心 Web 抓取/搜索、媒体 IO、媒体理解、图像生成,以及媒体生成运行时契约 | +| `/codeql-critical-quality/plugin-boundary` | 加载器、注册表、公开表面和插件 SDK 入口点契约 | +| `/codeql-critical-quality/plugin-sdk-package-contract` | 已发布包侧插件 SDK 源码和插件包契约辅助工具 | -质量与安全保持分离,这样质量发现项可以被调度、度量、禁用或扩展,而不会模糊安全信号。Swift、Python 和内置插件 CodeQL 扩展只应在窄配置文件具备稳定运行时和信号后,作为有范围或分片的后续工作加回。 +质量与安全保持分离,这样质量发现就可以被排期、度量、禁用或扩展,而不会掩盖安全信号。Swift、Python 和内置插件 CodeQL 扩展只应在这些窄配置文件拥有稳定的运行时和信号之后,作为有作用域或分片的后续工作加回。 ## 维护工作流 -### 文档智能体 +### Docs Agent -`Docs Agent` 工作流是一个事件驱动的 Codex 维护通道,用于让现有文档与最近落地的更改保持一致。它没有纯定时计划:`main` 上成功的非机器人 push CI 运行可以触发它,手动分发也可以直接运行它。当 `main` 已经继续推进,或过去一小时内已经创建了另一个未跳过的 Docs Agent 运行时,工作流运行调用会跳过。运行时,它会审查从上一个未跳过的 Docs Agent 源 SHA 到当前 `main` 的提交范围,因此一次每小时运行可以覆盖自上次文档处理以来积累的所有 main 更改。 +`Docs Agent` 工作流是一个事件驱动的 Codex 维护通道,用于让现有文档与最近落地的更改保持一致。它没有纯定时计划:`main` 上一次成功的非 bot 推送 CI 运行可以触发它,手动派发也可以直接运行它。当 `main` 已经继续前进,或者过去一小时内已经创建了另一次未跳过的 Docs Agent 运行时,workflow-run 调用会跳过。运行时,它会审阅从上一个未跳过的 Docs Agent 源 SHA 到当前 `main` 的提交范围,因此一次每小时运行可以覆盖自上次文档处理以来累积的所有 main 更改。 -### 测试性能智能体 +### Test Performance Agent -`Test Performance Agent` 工作流是一个事件驱动的 Codex 维护通道,用于处理慢速测试。它没有纯定时计划:`main` 上成功的非机器人 push CI 运行可以触发它,但如果当天 UTC 已经有另一个工作流运行调用已运行或正在运行,它会跳过。手动分发会绕过该每日活动门禁。该通道会构建全套分组 Vitest 性能报告,让 Codex 只做小型且保持覆盖率的测试性能修复,而不是大范围重构,然后重新运行全套报告,并拒绝会减少通过基线测试数量的更改。如果基线存在失败测试,Codex 只能修复显而易见的失败,并且智能体后的全套报告必须通过后才会提交任何内容。当机器人 push 落地前 `main` 前进时,该通道会 rebase 已验证的补丁,重新运行 `pnpm check:changed`,并重试 push;冲突的过期补丁会被跳过。它使用 GitHub 托管的 Ubuntu,因此 Codex action 可以保持与文档智能体相同的 drop-sudo 安全姿态。 +`Test Performance Agent` 工作流是一个事件驱动的 Codex 维护通道,用于慢测试。它没有纯定时计划:`main` 上一次成功的非 bot 推送 CI 运行可以触发它,但如果当天 UTC 已经有另一个 workflow-run 调用运行过或正在运行,它会跳过。手动派发会绕过这个每日活动门禁。该通道会构建完整套件分组 Vitest 性能报告,让 Codex 只做保留覆盖率的小型测试性能修复,而不是大范围重构,然后重新运行完整套件报告,并拒绝会降低通过基线测试数量的更改。如果基线存在失败测试,Codex 只能修复明显失败,且 agent 之后的完整套件报告必须通过,才会提交任何内容。当 `main` 在 bot 推送落地前前进时,该通道会 rebase 已验证的补丁,重新运行 `pnpm check:changed`,并重试推送;有冲突的过期补丁会被跳过。它使用 GitHub 托管的 Ubuntu,因此 Codex action 可以与 docs agent 保持相同的 drop-sudo 安全姿态。 ### 合并后的重复 PR -`Duplicate PRs After Merge` 工作流是用于落地后重复项清理的手动维护者工作流。它默认 dry-run,并且只有在 `apply=true` 时才会关闭明确列出的 PR。在变更 GitHub 之前,它会验证已落地 PR 已合并,并且每个重复项要么有共享的引用 issue,要么有重叠的变更 hunk。 +`Duplicate PRs After Merge` 工作流是一个手动维护者工作流,用于落地后的重复项清理。它默认 dry-run,只有在 `apply=true` 时才会关闭明确列出的 PR。在修改 GitHub 之前,它会验证已落地 PR 已合并,并验证每个重复 PR 要么共享引用的问题,要么有重叠的变更 hunk。 ```bash gh workflow run duplicate-after-merge.yml \ @@ -398,25 +398,25 @@ gh workflow run duplicate-after-merge.yml \ ## 本地检查门禁和变更路由 -本地变更通道逻辑位于 `scripts/changed-lanes.mjs`,并由 `scripts/check-changed.mjs` 执行。该本地检查门禁对架构边界的要求比宽泛的 CI 平台范围更严格: +本地 changed-lane 逻辑位于 `scripts/changed-lanes.mjs`,并由 `scripts/check-changed.mjs` 执行。该本地检查门禁在架构边界上比宽泛的 CI 平台作用域更严格: -- 核心生产更改运行核心生产和核心测试类型检查,以及核心 lint/guard; -- 仅核心测试更改只运行核心测试类型检查以及核心 lint; -- 插件生产更改运行插件生产和插件测试类型检查,以及插件 lint; -- 仅插件测试更改运行插件测试类型检查以及插件 lint; -- 公共插件 SDK 或插件契约更改会扩展到插件类型检查,因为插件依赖这些核心契约(Vitest 插件扫测仍然是显式测试工作); -- 仅发布元数据的版本 bump 运行有针对性的版本/配置/根依赖检查; -- 未知的根/配置更改会故障安全地进入所有检查通道。 +- 核心生产更改会运行核心生产和核心测试类型检查,以及核心 lint/防护; +- 仅核心测试更改只会运行核心测试类型检查,以及核心 lint; +- 插件生产更改会运行插件生产和插件测试类型检查,以及插件 lint; +- 仅插件测试更改会运行插件测试类型检查,以及插件 lint; +- 公开插件 SDK 或插件契约更改会扩展到插件类型检查,因为插件依赖这些核心契约(Vitest 插件扫测仍然是显式测试工作); +- 仅发布元数据的版本号提升会运行有针对性的版本/配置/根依赖检查; +- 未知的根目录/配置更改会 fail safe 到所有检查通道。 -本地变更测试路由位于 `scripts/test-projects.test-support.mjs`,并且有意比 `check:changed` 更便宜:直接测试编辑会运行自身,源码编辑优先使用显式映射,然后是同级测试和导入图依赖项。共享群组房间投递配置是显式映射之一:对群组可见回复配置、源回复投递模式或消息工具系统提示的更改,会通过核心回复测试以及 Discord 和 Slack 投递回归,因此共享默认值更改会在第一个 PR push 前失败。只有当更改涉及足够广的 harness 范围,导致廉价映射集不再是可信代理时,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 +本地 changed-test 路由位于 `scripts/test-projects.test-support.mjs`,并且刻意比 `check:changed` 更便宜:直接测试编辑会运行自身,源码编辑优先使用显式映射,然后是兄弟测试和导入图依赖项。共享群组房间投递配置是显式映射之一:对群组可见回复配置、源回复投递模式或 message-tool 系统提示词的更改,会经过核心回复测试以及 Discord 和 Slack 投递回归测试,因此共享默认值更改会在第一次 PR 推送前失败。只有当变更影响范围足够覆盖整个 harness,便宜的映射集合不再是可信代理时,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 ## Testbox 验证 -从仓库根目录运行 Testbox,并优先为宽泛证明使用新预热的 box。在把慢速门禁花到一个复用、过期或刚报告异常大同步的 box 上之前,先在该 box 内运行 `pnpm testbox:sanity`。 +从仓库根目录运行 Testbox,并优先为宽泛证明使用一个新预热的 box。在对一个被复用、已过期或刚报告了意外大同步的 box 花费慢门禁之前,先在 box 内运行 `pnpm testbox:sanity`。 -当所需根文件(例如 `pnpm-lock.yaml`)消失,或 `git status --short` 显示至少 200 个已跟踪删除时,完整性检查会快速失败。这通常意味着远程同步状态不是 PR 的可信副本;停止该 box 并预热一个新的,而不是调试产品测试失败。对于有意的大规模删除 PR,请为该次完整性检查设置 `OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1`。 +当 `pnpm-lock.yaml` 等必需根文件消失,或者 `git status --short` 显示至少 200 个已跟踪删除时,完整性检查会快速失败。这通常意味着远程同步状态不是 PR 的可信副本;请停止该 box,并预热一个新的,而不是调试产品测试失败。对于有意的大删除 PR,为那次完整性运行设置 `OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1`。 -`pnpm testbox:run` 还会终止本地 Blacksmith CLI 调用,如果它在同步阶段停留超过五分钟且没有同步后输出。设置 `OPENCLAW_TESTBOX_SYNC_TIMEOUT_MS=0` 可禁用该 guard,或者为异常大的本地 diff 使用更大的毫秒值。 +如果本地 Blacksmith CLI 调用停留在同步阶段超过五分钟且没有同步后输出,`pnpm testbox:run` 也会终止该调用。设置 `OPENCLAW_TESTBOX_SYNC_TIMEOUT_MS=0` 可禁用该防护,或者为异常大的本地 diff 使用更大的毫秒值。 ## 相关 diff --git a/docs/zh-CN/gateway/config-channels.md b/docs/zh-CN/gateway/config-channels.md index a9164b78d..a8b7fb096 100644 --- a/docs/zh-CN/gateway/config-channels.md +++ b/docs/zh-CN/gateway/config-channels.md @@ -1,27 +1,27 @@ --- read_when: - - 配置渠道插件(认证、访问控制、多账号) - - 按渠道的配置键名故障排除 + - 配置渠道插件(身份验证、访问控制、多账户) + - 排查各渠道配置键 - 审计私信策略、群组策略或提及门控 summary: 渠道配置:Slack、Discord、Telegram、WhatsApp、Matrix、iMessage 等的访问控制、配对和各渠道密钥 title: 配置 — 渠道 x-i18n: - generated_at: "2026-04-30T13:59:04Z" + generated_at: "2026-05-01T03:00:03Z" model: gpt-5.5 provider: openai - source_hash: aba14cb43e1fe914cc7c03f41bed1b5915cc6b2ad8e0f1d47f58b7e98c1b3915 + source_hash: ce1571d51e026182d49b935780a986780a90b05afc0acca027b2541b80a1aac2 source_path: gateway/config-channels.md workflow: 16 --- -`channels.*` 下的按渠道配置键。涵盖私信和群组访问、多账号设置、提及门控,以及 Slack、Discord、Telegram、WhatsApp、Matrix、iMessage 和其他内置渠道插件的按渠道键名。 +`channels.*` 下的各渠道配置键。涵盖私信和群组访问、多账号设置、提及门控,以及 Slack、Discord、Telegram、WhatsApp、Matrix、iMessage 和其他内置渠道插件的各渠道键。 -对于智能体、工具、Gateway 网关运行时和其他顶层键,请参阅 +对于智能体、工具、Gateway 网关运行时和其他顶级键,请参阅 [配置参考](/zh-CN/gateway/configuration-reference)。 ## 渠道 -每个渠道会在其配置段存在时自动启动(除非 `enabled: false`)。 +每个渠道会在其配置段存在时自动启动(除非设置了 `enabled: false`)。 ### 私信和群组访问 @@ -31,8 +31,8 @@ x-i18n: | ------------------- | --------------------------------------------------------------- | | `pairing`(默认) | 未知发送者会收到一次性配对码;所有者必须批准 | | `allowlist` | 仅允许 `allowFrom`(或已配对允许存储)中的发送者 | -| `open` | 允许所有传入私信(需要 `allowFrom: ["*"]`) | -| `disabled` | 忽略所有传入私信 | +| `open` | 允许所有入站私信(需要 `allowFrom: ["*"]`) | +| `disabled` | 忽略所有入站私信 | | 群组策略 | 行为 | | --------------------- | ------------------------------------------------------ | @@ -42,13 +42,13 @@ x-i18n: `channels.defaults.groupPolicy` 会在提供商的 `groupPolicy` 未设置时设置默认值。 -配对码会在 1 小时后过期。待处理的私信配对请求上限为**每个渠道 3 个**。 -如果提供商块完全缺失(不存在 `channels.`),运行时群组策略会回退到 `allowlist`(默认拒绝),并在启动时发出警告。 +配对码会在 1 小时后过期。待处理的私信配对请求上限为 **每个渠道 3 个**。 +如果提供商块完全缺失(不存在 `channels.`),运行时群组策略会回退到 `allowlist`(故障关闭),并在启动时发出警告。 ### 渠道模型覆盖 -使用 `channels.modelByChannel` 将特定渠道 ID 固定到某个模型。值接受 `provider/model` 或已配置的模型别名。当会话尚未有模型覆盖时(例如通过 `/model` 设置),会应用该渠道映射。 +使用 `channels.modelByChannel` 将特定渠道 ID 固定到某个模型。值接受 `provider/model` 或已配置的模型别名。当会话尚未有模型覆盖时(例如通过 `/model` 设置),会应用渠道映射。 ```json5 { @@ -89,15 +89,15 @@ x-i18n: } ``` -- `channels.defaults.groupPolicy`:当提供商级别的 `groupPolicy` 未设置时使用的回退群组策略。 -- `channels.defaults.contextVisibility`:所有渠道的默认补充上下文可见性模式。值:`all`(默认,包含所有引用/线程/历史上下文)、`allowlist`(仅包含来自允许列表发送者的上下文)、`allowlist_quote`(与允许列表相同,但保留显式引用/回复上下文)。按渠道覆盖:`channels..contextVisibility`。 -- `channels.defaults.heartbeat.showOk`:在 Heartbeat 输出中包含健康的渠道状态。 -- `channels.defaults.heartbeat.showAlerts`:在 Heartbeat 输出中包含降级/错误状态。 -- `channels.defaults.heartbeat.useIndicator`:渲染紧凑的指示器样式 Heartbeat 输出。 +- `channels.defaults.groupPolicy`:提供商级 `groupPolicy` 未设置时的备用群组策略。 +- `channels.defaults.contextVisibility`:所有渠道的默认补充上下文可见性模式。值:`all`(默认,包含所有引用/话题串/历史上下文)、`allowlist`(仅包含来自允许列表发送者的上下文)、`allowlist_quote`(与允许列表相同,但保留显式引用/回复上下文)。按渠道覆盖:`channels..contextVisibility`。 +- `channels.defaults.heartbeat.showOk`:在 Heartbeat 输出中包含健康的渠道 Status。 +- `channels.defaults.heartbeat.showAlerts`:在 Heartbeat 输出中包含降级/错误 Status。 +- `channels.defaults.heartbeat.useIndicator`:渲染紧凑指示器样式的 Heartbeat 输出。 ### WhatsApp -WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当已存在链接会话时,它会自动启动。 +WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。存在已链接会话时,它会自动启动。 ```json5 { @@ -137,7 +137,7 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当已存 } ``` - + ```json5 { @@ -155,9 +155,9 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当已存 } ``` -- 出站命令默认使用账号 `default`(如果存在);否则使用第一个已配置的账号 ID(排序后)。 -- 可选的 `channels.whatsapp.defaultAccount` 会在其匹配已配置账号 ID 时覆盖该回退默认账号选择。 -- 旧版单账号 Baileys 认证目录会由 `openclaw doctor` 迁移到 `whatsapp/default`。 +- 出站命令默认使用 `default` 账号(如果存在);否则使用第一个已配置账号 ID(排序后)。 +- 可选的 `channels.whatsapp.defaultAccount` 会在匹配已配置账号 ID 时覆盖该备用默认账号选择。 +- 旧版单账号 Baileys 凭证目录会由 `openclaw doctor` 迁移到 `whatsapp/default`。 - 按账号覆盖:`channels.whatsapp.accounts..sendReadReceipts`、`channels.whatsapp.accounts..dmPolicy`、`channels.whatsapp.accounts..allowFrom`。 @@ -217,13 +217,13 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当已存 } ``` -- Bot token:`channels.telegram.botToken` 或 `channels.telegram.tokenFile`(仅限普通文件;会拒绝符号链接),默认账号以 `TELEGRAM_BOT_TOKEN` 作为回退。 -- `apiRoot` 仅是 Telegram Bot API 根地址。使用 `https://api.telegram.org` 或你的自托管/代理根地址,不要使用 `https://api.telegram.org/bot`;`openclaw doctor --fix` 会移除意外尾随的 `/bot` 后缀。 -- 可选的 `channels.telegram.defaultAccount` 会在其匹配已配置账号 ID 时覆盖默认账号选择。 -- 在多账号设置(2 个以上账号 ID)中,设置显式默认值(`channels.telegram.defaultAccount` 或 `channels.telegram.accounts.default`)以避免回退路由;当缺失或无效时,`openclaw doctor` 会发出警告。 +- 机器人令牌:`channels.telegram.botToken` 或 `channels.telegram.tokenFile`(仅常规文件;拒绝符号链接),默认账号以 `TELEGRAM_BOT_TOKEN` 作为备用。 +- `apiRoot` 只是 Telegram Bot API 根地址。使用 `https://api.telegram.org` 或你自托管/代理的根地址,而不是 `https://api.telegram.org/bot`;`openclaw doctor --fix` 会移除意外的尾随 `/bot` 后缀。 +- 可选的 `channels.telegram.defaultAccount` 会在匹配已配置账号 ID 时覆盖默认账号选择。 +- 在多账号设置(2 个以上账号 ID)中,设置显式默认值(`channels.telegram.defaultAccount` 或 `channels.telegram.accounts.default`)以避免备用路由;缺失或无效时,`openclaw doctor` 会发出警告。 - `configWrites: false` 会阻止由 Telegram 发起的配置写入(超级群组 ID 迁移、`/config set|unset`)。 -- 顶层 `bindings[]` 条目使用 `type: "acp"` 为论坛话题配置持久 ACP 绑定(在 `match.peer.id` 中使用规范的 `chatId:topic:topicId`)。字段语义在 [ACP 智能体](/zh-CN/tools/acp-agents#channel-specific-settings) 中共享。 -- Telegram 流式预览使用 `sendMessage` + `editMessageText`(适用于直接聊天和群组聊天)。 +- 带有 `type: "acp"` 的顶级 `bindings[]` 条目会为论坛话题配置持久 ACP 绑定(在 `match.peer.id` 中使用规范的 `chatId:topic:topicId`)。字段语义在 [ACP 智能体](/zh-CN/tools/acp-agents#channel-specific-settings) 中共享。 +- Telegram 流式预览使用 `sendMessage` + `editMessageText`(适用于直接聊天和群聊)。 - 重试策略:参阅[重试策略](/zh-CN/concepts/retry)。 ### Discord @@ -326,34 +326,34 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当已存 } ``` -- Token:`channels.discord.token`,默认账号可回退到 `DISCORD_BOT_TOKEN`。 -- 提供显式 Discord `token` 的直接出站调用会使用该 token 执行调用;账号重试/策略设置仍来自活动运行时快照中选中的账号。 -- 可选的 `channels.discord.defaultAccount` 在匹配已配置账号 ID 时会覆盖默认账号选择。 +- 令牌:`channels.discord.token`,默认账号的备用值为 `DISCORD_BOT_TOKEN`。 +- 提供显式 Discord `token` 的直接出站调用会使用该令牌执行调用;账号重试/策略设置仍来自活动运行时快照中选定的账号。 +- 可选的 `channels.discord.defaultAccount` 在匹配已配置账号 ID 时,会覆盖默认账号选择。 - 使用 `user:`(私信)或 `channel:`(服务器频道)作为投递目标;裸数字 ID 会被拒绝。 -- 服务器 slug 为小写,并将空格替换为 `-`;频道键使用 slug 化后的名称(不含 `#`)。优先使用服务器 ID。 -- 默认会忽略机器人发出的消息。`allowBots: true` 会启用它们;使用 `allowBots: "mentions"` 仅接受提及该机器人的机器人消息(自己的消息仍会被过滤)。 -- `channels.discord.guilds..ignoreOtherMentions`(以及频道覆盖项)会丢弃提及其他用户或角色但未提及该机器人的消息(不包括 @everyone/@here)。 -- `maxLinesPerMessage`(默认 17)即使在 2000 个字符以内,也会拆分行数过多的消息。 -- `channels.discord.threadBindings` 控制 Discord 话题串绑定路由: - - `enabled`:Discord 对话题串绑定会话功能(`/focus`、`/unfocus`、`/agents`、`/session idle`、`/session max-age`,以及绑定投递/路由)的覆盖值 - - `idleHours`:Discord 对按小时计的不活动自动取消聚焦的覆盖值(`0` 表示禁用) - - `maxAgeHours`:Discord 对按小时计的硬性最大时长的覆盖值(`0` 表示禁用) - - `spawnSubagentSessions`:用于 `sessions_spawn({ thread: true })` 自动创建/绑定话题串的选择启用开关 -- 带有 `type: "acp"` 的顶层 `bindings[]` 条目会为渠道和话题串配置持久 ACP 绑定(在 `match.peer.id` 中使用频道/话题串 ID)。字段语义在 [ACP 智能体](/zh-CN/tools/acp-agents#channel-specific-settings) 中共享。 +- 服务器 slug 为小写,并将空格替换为 `-`;频道键使用已 slug 化的名称(不含 `#`)。优先使用服务器 ID。 +- 默认忽略机器人发送的消息。`allowBots: true` 会启用它们;使用 `allowBots: "mentions"` 可仅接受提及该机器人的机器人消息(仍会过滤自己的消息)。 +- `channels.discord.guilds..ignoreOtherMentions`(以及频道覆盖)会丢弃提及其他用户或角色但未提及该机器人的消息(不包括 @everyone/@here)。 +- `maxLinesPerMessage`(默认 17)即使在低于 2000 个字符时,也会拆分过高的消息。 +- `channels.discord.threadBindings` 控制 Discord 线程绑定路由: + - `enabled`:用于线程绑定会话功能(`/focus`、`/unfocus`、`/agents`、`/session idle`、`/session max-age`,以及绑定投递/路由)的 Discord 覆盖项 + - `idleHours`:Discord 的非活动自动取消聚焦覆盖项,单位为小时(`0` 表示禁用) + - `maxAgeHours`:Discord 的硬性最大时长覆盖项,单位为小时(`0` 表示禁用) + - `spawnSubagentSessions`:用于 `sessions_spawn({ thread: true })` 自动创建/绑定线程的选择性开关 +- 顶层 `bindings[]` 条目中带 `type: "acp"` 的配置用于为渠道和线程配置持久 ACP 绑定(在 `match.peer.id` 中使用频道/线程 ID)。字段语义在 [ACP Agents](/zh-CN/tools/acp-agents#channel-specific-settings) 中共享。 - `channels.discord.ui.components.accentColor` 设置 Discord components v2 容器的强调色。 - `channels.discord.voice` 启用 Discord 语音频道对话,以及可选的自动加入 + LLM + TTS 覆盖项。 - `channels.discord.voice.model` 可选择覆盖用于 Discord 语音频道响应的 LLM 模型。 -- `channels.discord.voice.daveEncryption` 和 `channels.discord.voice.decryptionFailureTolerance` 会透传到 `@discordjs/voice` DAVE 选项(默认分别为 `true` 和 `24`)。 -- OpenClaw 还会在反复解密失败后通过离开/重新加入语音会话来尝试语音接收恢复。 -- `channels.discord.streaming` 是规范流模式键。旧版 `streamMode` 和布尔值 `streaming` 会自动迁移。 -- `channels.discord.autoPresence` 将运行时可用性映射到机器人状态(healthy => online、degraded => idle、exhausted => dnd),并允许可选的状态文本覆盖项。 +- `channels.discord.voice.daveEncryption` 和 `channels.discord.voice.decryptionFailureTolerance` 会透传给 `@discordjs/voice` DAVE 选项(默认分别为 `true` 和 `24`)。 +- OpenClaw 还会在反复解密失败后,通过离开/重新加入语音会话来尝试恢复语音接收。 +- `channels.discord.streaming` 是规范的流模式键。旧版 `streamMode` 和布尔型 `streaming` 值会自动迁移。 +- `channels.discord.autoPresence` 将运行时可用性映射到机器人在线状态(healthy => online、degraded => idle、exhausted => dnd),并允许可选的状态文本覆盖。 - `channels.discord.dangerouslyAllowNameMatching` 会重新启用可变名称/标签匹配(破窗兼容模式)。 - `channels.discord.execApprovals`:Discord 原生 exec 审批投递和审批人授权。 - - `enabled`:`true`、`false` 或 `"auto"`(默认)。在自动模式下,当可从 `approvers` 或 `commands.ownerAllowFrom` 解析审批人时,会激活 exec 审批。 - - `approvers`:允许审批 exec 请求的 Discord 用户 ID。省略时回退到 `commands.ownerAllowFrom`。 - - `agentFilter`:可选的智能体 ID allowlist。省略则转发所有智能体的审批。 + - `enabled`:`true`、`false` 或 `"auto"`(默认)。在自动模式下,当可以从 `approvers` 或 `commands.ownerAllowFrom` 解析审批人时,会激活 exec 审批。 + - `approvers`:允许批准 exec 请求的 Discord 用户 ID。省略时回退到 `commands.ownerAllowFrom`。 + - `agentFilter`:可选的智能体 ID 允许列表。省略时转发所有智能体的审批。 - `sessionFilter`:可选的会话键模式(子字符串或正则表达式)。 - - `target`:发送审批提示的位置。`"dm"`(默认)发送到审批人私信,`"channel"` 发送到来源频道,`"both"` 同时发送到两者。当 target 包含 `"channel"` 时,按钮仅可由已解析的审批人使用。 + - `target`:发送审批提示的位置。`"dm"`(默认)发送到审批人私信,`"channel"` 发送到来源频道,`"both"` 同时发送到两者。当目标包含 `"channel"` 时,按钮仅可由已解析的审批人使用。 - `cleanupAfterResolve`:为 `true` 时,在批准、拒绝或超时后删除审批私信。 **反应通知模式:** `off`(无)、`own`(机器人的消息,默认)、`all`(所有消息)、`allowlist`(来自所有消息上的 `guilds..users`)。 @@ -389,9 +389,9 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当已存 - 服务账号 JSON:内联(`serviceAccount`)或基于文件(`serviceAccountFile`)。 - 也支持服务账号 SecretRef(`serviceAccountRef`)。 -- 环境变量回退项:`GOOGLE_CHAT_SERVICE_ACCOUNT` 或 `GOOGLE_CHAT_SERVICE_ACCOUNT_FILE`。 +- 环境备用值:`GOOGLE_CHAT_SERVICE_ACCOUNT` 或 `GOOGLE_CHAT_SERVICE_ACCOUNT_FILE`。 - 使用 `spaces/` 或 `users/` 作为投递目标。 -- `channels.googlechat.dangerouslyAllowNameMatching` 会重新启用可变电子邮件主体匹配(破窗兼容模式)。 +- `channels.googlechat.dangerouslyAllowNameMatching` 会重新启用可变邮箱主体匹配(破窗兼容模式)。 ### Slack @@ -463,35 +463,35 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当已存 } ``` -- **Socket 模式**需要同时提供 `botToken` 和 `appToken`(默认账号环境变量回退项为 `SLACK_BOT_TOKEN` + `SLACK_APP_TOKEN`)。 -- **HTTP 模式**需要 `botToken` 加 `signingSecret`(位于根级或每个账号中)。 -- `socketMode` 会将 Slack SDK Socket Mode 传输调优透传到公共 Bolt 接收器 API。仅在调查 ping/pong 超时或陈旧 websocket 行为时使用。 +- **Socket 模式**需要同时提供 `botToken` 和 `appToken`(默认账号环境备用值为 `SLACK_BOT_TOKEN` + `SLACK_APP_TOKEN`)。 +- **HTTP 模式**需要 `botToken` 以及 `signingSecret`(位于根级别或每个账号中)。 +- `socketMode` 会将 Slack SDK Socket Mode 传输调优透传给公开的 Bolt receiver API。仅在调查 ping/pong 超时或陈旧 websocket 行为时使用它。 - `botToken`、`appToken`、`signingSecret` 和 `userToken` 接受明文字符串或 SecretRef 对象。 -- Slack 账号快照会暴露每个凭证的来源/状态字段,例如 `botTokenSource`、`botTokenStatus`、`appTokenStatus`,以及在 HTTP 模式下的 `signingSecretStatus`。`configured_unavailable` 表示账号已通过 SecretRef 配置,但当前命令/运行时路径无法解析 secret 值。 -- `configWrites: false` 会阻止 Slack 发起的配置写入。 -- 可选的 `channels.slack.defaultAccount` 在匹配已配置账号 ID 时会覆盖默认账号选择。 -- `channels.slack.streaming.mode` 是规范 Slack 流模式键。`channels.slack.streaming.nativeTransport` 控制 Slack 的原生流式传输。旧版 `streamMode`、布尔值 `streaming` 和 `nativeStreaming` 会自动迁移。 +- Slack 账号快照会公开每个凭证的来源/状态字段,例如 `botTokenSource`、`botTokenStatus`、`appTokenStatus`,以及在 HTTP 模式下的 `signingSecretStatus`。`configured_unavailable` 表示账号通过 SecretRef 配置,但当前命令/运行时路径无法解析密钥值。 +- `configWrites: false` 会阻止由 Slack 发起的配置写入。 +- 可选的 `channels.slack.defaultAccount` 在匹配已配置账号 ID 时,会覆盖默认账号选择。 +- `channels.slack.streaming.mode` 是规范的 Slack 流模式键。`channels.slack.streaming.nativeTransport` 控制 Slack 的原生流式传输。旧版 `streamMode`、布尔型 `streaming` 和 `nativeStreaming` 值会自动迁移。 - 使用 `user:`(私信)或 `channel:` 作为投递目标。 **反应通知模式:** `off`、`own`(默认)、`all`、`allowlist`(来自 `reactionAllowlist`)。 -**话题串会话隔离:** `thread.historyScope` 是按话题串(默认)或跨频道共享。`thread.inheritParent` 会将父频道转录复制到新话题串。 +**线程会话隔离:** `thread.historyScope` 是按线程(默认)或跨频道共享。`thread.inheritParent` 会将父频道转录复制到新线程。 -- Slack 原生流式传输加上 Slack assistant 风格的“正在输入...”话题串状态需要一个回复话题串目标。顶层私信默认保持在话题串之外,因此会使用 `typingReaction` 或正常投递,而不是话题串风格预览。 -- `typingReaction` 会在回复运行期间向传入 Slack 消息添加临时反应,然后在完成时移除。使用 Slack emoji 短代码,例如 `"hourglass_flowing_sand"`。 +- Slack 原生流式传输以及 Slack 助手风格的 “is typing...” 线程状态需要回复线程目标。顶层私信默认保持非线程状态,因此它们会使用 `typingReaction` 或普通投递,而不是线程风格预览。 +- `typingReaction` 会在回复运行期间向入站 Slack 消息添加临时反应,并在完成时移除它。使用 Slack emoji 短代码,例如 `"hourglass_flowing_sand"`。 - `channels.slack.execApprovals`:Slack 原生 exec 审批投递和审批人授权。架构与 Discord 相同:`enabled`(`true`/`false`/`"auto"`)、`approvers`(Slack 用户 ID)、`agentFilter`、`sessionFilter` 和 `target`(`"dm"`、`"channel"` 或 `"both"`)。 -| 操作组 | 默认 | 备注 | -| ------------ | ------ | ---------------- | +| 操作组 | 默认值 | 备注 | +| ------------ | ------- | ---------------------- | | reactions | 已启用 | 反应 + 列出反应 | -| messages | 已启用 | 读取/发送/编辑/删除 | -| pins | 已启用 | 置顶/取消置顶/列出 | -| memberInfo | 已启用 | 成员信息 | -| emojiList | 已启用 | 自定义 emoji 列表 | +| messages | 已启用 | 读取/发送/编辑/删除 | +| pins | 已启用 | 置顶/取消置顶/列出 | +| memberInfo | 已启用 | 成员信息 | +| emojiList | 已启用 | 自定义 emoji 列表 | ### Mattermost -在当前 OpenClaw 版本中,Mattermost 作为内置插件发布。较旧或自定义构建可以使用 `openclaw plugins install @openclaw/mattermost` 安装当前 npm 包;如果 npm 报告 OpenClaw 拥有的包已弃用,请使用内置插件或本地 checkout,直到发布更新的 npm 包。 +Mattermost 在当前 OpenClaw 版本中作为内置插件发布。较旧版本或自定义构建可以使用 `openclaw plugins install @openclaw/mattermost` 安装当前 npm 包;如果 npm 报告 OpenClaw 拥有的包已弃用,请使用内置插件或本地检出,直到发布更新的 npm 包。 ```json5 { @@ -525,14 +525,14 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当已存 启用 Mattermost 原生命令时: -- `commands.callbackPath` 必须是路径(例如 `/api/channels/mattermost/command`),不能是完整 URL。 -- `commands.callbackUrl` 必须解析到 OpenClaw Gateway 网关端点,并且 Mattermost 服务器可以访问。 -- 原生斜杠回调使用 Mattermost 在斜杠命令注册期间返回的每命令 token 进行身份验证。如果注册失败或没有命令被激活,OpenClaw 会以 `Unauthorized: invalid command token.` 拒绝回调。 -- 对于私有/tailnet/内部回调主机,Mattermost 可能需要 `ServiceSettings.AllowedUntrustedInternalConnections` 包含该回调主机/域名。使用主机/域名值,而不是完整 URL。 -- `channels.mattermost.configWrites`:允许或拒绝 Mattermost 发起的配置写入。 +- `commands.callbackPath` 必须是路径(例如 `/api/channels/mattermost/command`),而不是完整 URL。 +- `commands.callbackUrl` 必须解析为 OpenClaw Gateway 网关端点,并且可由 Mattermost 服务器访问。 +- 原生 slash 回调使用 Mattermost 在 slash 命令注册期间返回的每命令令牌进行认证。如果注册失败或没有激活命令,OpenClaw 会以 `Unauthorized: invalid command token.` 拒绝回调。 +- 对于私有/tailnet/内部回调主机,Mattermost 可能要求 `ServiceSettings.AllowedUntrustedInternalConnections` 包含回调主机/域名。使用主机/域名值,而不是完整 URL。 +- `channels.mattermost.configWrites`:允许或拒绝由 Mattermost 发起的配置写入。 - `channels.mattermost.requireMention`:在频道中回复前要求 `@mention`。 - `channels.mattermost.groups..requireMention`:按频道的提及门控覆盖项(`"*"` 表示默认值)。 -- 可选的 `channels.mattermost.defaultAccount` 在匹配已配置账号 ID 时会覆盖默认账号选择。 +- 可选的 `channels.mattermost.defaultAccount` 在匹配已配置账号 ID 时,会覆盖默认账号选择。 ### Signal @@ -553,11 +553,11 @@ WhatsApp 通过 Gateway 网关的 Web 渠道(Baileys Web)运行。当已存 } ``` -**回应通知模式:**`off`、`own`(默认)、`all`、`allowlist`(来自 `reactionAllowlist`)。 +**响应通知模式:** `off`、`own`(默认)、`all`、`allowlist`(来自 `reactionAllowlist`)。 -- `channels.signal.account`:将渠道启动固定到特定的 Signal 账号身份。 +- `channels.signal.account`:将渠道启动固定到特定 Signal 账户身份。 - `channels.signal.configWrites`:允许或拒绝由 Signal 发起的配置写入。 -- 可选的 `channels.signal.defaultAccount` 会在匹配已配置账号 ID 时覆盖默认账号选择。 +- 可选的 `channels.signal.defaultAccount` 会在匹配已配置账户 ID 时覆盖默认账户选择。 ### BlueBubbles @@ -577,13 +577,13 @@ BlueBubbles 是推荐的 iMessage 路径(由插件支持,在 `channels.blueb ``` - 此处涵盖的核心键路径:`channels.bluebubbles`、`channels.bluebubbles.dmPolicy`。 -- 可选的 `channels.bluebubbles.defaultAccount` 会在匹配已配置账号 ID 时覆盖默认账号选择。 -- 带有 `type: "acp"` 的顶层 `bindings[]` 条目可以将 BlueBubbles 对话绑定到持久 ACP 会话。在 `match.peer.id` 中使用 BlueBubbles handle 或目标字符串(`chat_id:*`、`chat_guid:*`、`chat_identifier:*`)。共享字段语义:[ACP Agents](/zh-CN/tools/acp-agents#channel-specific-settings)。 -- 完整的 BlueBubbles 渠道配置记录在 [BlueBubbles](/zh-CN/channels/bluebubbles) 中。 +- 可选的 `channels.bluebubbles.defaultAccount` 会在匹配已配置账户 ID 时覆盖默认账户选择。 +- 顶层 `bindings[]` 条目如果带有 `type: "acp"`,可将 BlueBubbles 对话绑定到持久 ACP 会话。在 `match.peer.id` 中使用 BlueBubbles 句柄或目标字符串(`chat_id:*`、`chat_guid:*`、`chat_identifier:*`)。共享字段语义:[ACP 智能体](/zh-CN/tools/acp-agents#channel-specific-settings)。 +- 完整的 BlueBubbles 渠道配置记录在 [BlueBubbles](/zh-CN/channels/bluebubbles)。 ### iMessage -OpenClaw 会生成 `imsg rpc`(通过 stdio 的 JSON-RPC)。不需要守护进程或端口。 +OpenClaw 会启动 `imsg rpc`(通过 stdio 运行的 JSON-RPC)。不需要守护进程或端口。 ```json5 { @@ -607,15 +607,15 @@ OpenClaw 会生成 `imsg rpc`(通过 stdio 的 JSON-RPC)。不需要守护 } ``` -- 可选的 `channels.imessage.defaultAccount` 会在匹配已配置账号 ID 时覆盖默认账号选择。 +- 可选的 `channels.imessage.defaultAccount` 会在匹配已配置账户 ID 时覆盖默认账户选择。 -- 需要对 Messages 数据库授予完全磁盘访问权限。 +- 需要对 Messages DB 授予完整磁盘访问权限。 - 优先使用 `chat_id:` 目标。使用 `imsg chats --limit 20` 列出聊天。 -- `cliPath` 可以指向 SSH 包装器;设置 `remoteHost`(`host` 或 `user@host`)用于通过 SCP 获取附件。 -- `attachmentRoots` 和 `remoteAttachmentRoots` 会限制入站附件路径(默认:`/Users/*/Library/Messages/Attachments`)。 -- SCP 使用严格的主机密钥检查,因此请确保中继主机密钥已存在于 `~/.ssh/known_hosts` 中。 +- `cliPath` 可以指向 SSH 包装器;设置 `remoteHost`(`host` 或 `user@host`)以通过 SCP 获取附件。 +- `attachmentRoots` 和 `remoteAttachmentRoots` 会限制传入附件路径(默认:`/Users/*/Library/Messages/Attachments`)。 +- SCP 使用严格主机密钥检查,因此请确保中继主机密钥已存在于 `~/.ssh/known_hosts` 中。 - `channels.imessage.configWrites`:允许或拒绝由 iMessage 发起的配置写入。 -- 带有 `type: "acp"` 的顶层 `bindings[]` 条目可以将 iMessage 对话绑定到持久 ACP 会话。在 `match.peer.id` 中使用规范化 handle 或显式聊天目标(`chat_id:*`、`chat_guid:*`、`chat_identifier:*`)。共享字段语义:[ACP Agents](/zh-CN/tools/acp-agents#channel-specific-settings)。 +- 顶层 `bindings[]` 条目如果带有 `type: "acp"`,可将 iMessage 对话绑定到持久 ACP 会话。在 `match.peer.id` 中使用规范化句柄或显式聊天目标(`chat_id:*`、`chat_guid:*`、`chat_identifier:*`)。共享字段语义:[ACP 智能体](/zh-CN/tools/acp-agents#channel-specific-settings)。 @@ -658,21 +658,21 @@ Matrix 由插件支持,并在 `channels.matrix` 下配置。 } ``` -- Token 认证使用 `accessToken`;密码认证使用 `userId` + `password`。 -- `channels.matrix.proxy` 会通过显式 HTTP(S) 代理路由 Matrix HTTP 流量。命名账号可以通过 `channels.matrix.accounts..proxy` 覆盖它。 -- `channels.matrix.network.dangerouslyAllowPrivateNetwork` 允许私有/内部 homeserver。`proxy` 和这个网络选择加入是独立控制项。 -- `channels.matrix.defaultAccount` 在多账号设置中选择首选账号。 -- `channels.matrix.autoJoin` 默认为 `off`,因此邀请的房间和新的私信式邀请会被忽略,直到你设置带有 `autoJoinAllowlist` 的 `autoJoin: "allowlist"` 或 `autoJoin: "always"`。 -- `channels.matrix.execApprovals`:Matrix 原生 exec 批准投递和批准者授权。 - - `enabled`:`true`、`false` 或 `"auto"`(默认)。在自动模式下,当可以从 `approvers` 或 `commands.ownerAllowFrom` 解析批准者时,exec 批准会激活。 +- 令牌认证使用 `accessToken`;密码认证使用 `userId` + `password`。 +- `channels.matrix.proxy` 会通过显式 HTTP(S) 代理路由 Matrix HTTP 流量。具名账户可以用 `channels.matrix.accounts..proxy` 覆盖它。 +- `channels.matrix.network.dangerouslyAllowPrivateNetwork` 允许私有/内部 homeserver。`proxy` 和此网络选择加入是相互独立的控制项。 +- `channels.matrix.defaultAccount` 会在多账户设置中选择首选账户。 +- `channels.matrix.autoJoin` 默认为 `off`,因此受邀房间和新的私信风格邀请会被忽略,直到你设置带 `autoJoinAllowlist` 的 `autoJoin: "allowlist"` 或 `autoJoin: "always"`。 +- `channels.matrix.execApprovals`:Matrix 原生 exec 审批投递和审批者授权。 + - `enabled`:`true`、`false` 或 `"auto"`(默认)。在自动模式下,当可从 `approvers` 或 `commands.ownerAllowFrom` 解析审批者时,exec 审批会激活。 - `approvers`:允许批准 exec 请求的 Matrix 用户 ID(例如 `@owner:example.org`)。 - - `agentFilter`:可选的智能体 ID 允许列表。省略则转发所有智能体的批准。 + - `agentFilter`:可选的智能体 ID 允许列表。省略则转发所有智能体的审批。 - `sessionFilter`:可选的会话键模式(子字符串或正则表达式)。 - - `target`:发送批准提示的位置。`"dm"`(默认)、`"channel"`(来源房间)或 `"both"`。 - - 按账号覆盖:`channels.matrix.accounts..execApprovals`。 -- `channels.matrix.dm.sessionScope` 控制 Matrix 私信如何分组到会话中:`per-user`(默认)按路由后的对端共享,而 `per-room` 会隔离每个私信房间。 + - `target`:发送审批提示的位置。`"dm"`(默认)、`"channel"`(来源房间)或 `"both"`。 + - 按账户覆盖:`channels.matrix.accounts..execApprovals`。 +- `channels.matrix.dm.sessionScope` 控制 Matrix 私信如何分组为会话:`per-user`(默认)按路由后的对等方共享,而 `per-room` 会隔离每个私信房间。 - Matrix Status 探测和实时目录查找使用与运行时流量相同的代理策略。 -- 完整的 Matrix 配置、目标规则和设置示例记录在 [Matrix](/zh-CN/channels/matrix) 中。 +- 完整的 Matrix 配置、目标规则和设置示例记录在 [Matrix](/zh-CN/channels/matrix)。 ### Microsoft Teams @@ -692,7 +692,7 @@ Microsoft Teams 由插件支持,并在 `channels.msteams` 下配置。 ``` - 此处涵盖的核心键路径:`channels.msteams`、`channels.msteams.configWrites`。 -- 完整的 Teams 配置(凭证、webhook、私信/群组策略、按团队/按渠道覆盖)记录在 [Microsoft Teams](/zh-CN/channels/msteams) 中。 +- 完整的 Teams 配置(凭据、webhook、私信/群组策略、按团队/按频道覆盖)记录在 [Microsoft Teams](/zh-CN/channels/msteams)。 ### IRC @@ -718,12 +718,12 @@ IRC 由插件支持,并在 `channels.irc` 下配置。 ``` - 此处涵盖的核心键路径:`channels.irc`、`channels.irc.dmPolicy`、`channels.irc.configWrites`、`channels.irc.nickserv.*`。 -- 可选的 `channels.irc.defaultAccount` 会在匹配已配置账号 ID 时覆盖默认账号选择。 -- 完整的 IRC 渠道配置(host/port/TLS/channels/允许列表/提及门控)记录在 [IRC](/zh-CN/channels/irc) 中。 +- 可选的 `channels.irc.defaultAccount` 会在匹配已配置账户 ID 时覆盖默认账户选择。 +- 完整的 IRC 渠道配置(主机/端口/TLS/频道/允许列表/提及门控)记录在 [IRC](/zh-CN/channels/irc)。 -### 多账号(所有渠道) +### 多账户(所有渠道) -每个渠道运行多个账号(每个账号都有自己的 `accountId`): +每个渠道运行多个账户(每个账户都有自己的 `accountId`): ```json5 { @@ -744,32 +744,34 @@ IRC 由插件支持,并在 `channels.irc` 下配置。 } ``` -- 当省略 `accountId` 时会使用 `default`(CLI + 路由)。 -- 环境变量 token 只应用于**默认**账号。 -- 基础渠道设置会应用于所有账号,除非按账号覆盖。 -- 使用 `bindings[].match.accountId` 将每个账号路由到不同的智能体。 -- 如果你仍在使用单账号顶层渠道配置时,通过 `openclaw channels add`(或渠道新手引导)添加非默认账号,OpenClaw 会先将账号作用域的顶层单账号值提升到渠道账号映射中,以便原始账号继续工作。大多数渠道会把它们移入 `channels..accounts.default`;Matrix 则可以保留现有匹配的命名/默认目标。 -- 现有的仅渠道绑定(没有 `accountId`)会继续匹配默认账号;账号作用域绑定仍然是可选的。 -- `openclaw doctor --fix` 也会通过将账号作用域的顶层单账号值移动到为该渠道选择的提升账号中来修复混合形态。大多数渠道使用 `accounts.default`;Matrix 则可以保留现有匹配的命名/默认目标。 +- 省略 `accountId` 时会使用 `default`(CLI + 路由)。 +- 环境变量令牌只应用于**默认**账户。 +- 基础渠道设置会应用于所有账户,除非按账户覆盖。 +- 使用 `bindings[].match.accountId` 将每个账户路由到不同的智能体。 +- 如果你在仍使用单账户顶层渠道配置时,通过 `openclaw channels add`(或渠道新手引导)添加非默认账户,OpenClaw 会先将账户范围的顶层单账户值提升到渠道账户映射中,让原始账户继续工作。大多数渠道会将它们移动到 `channels..accounts.default`;Matrix 可以改为保留现有的匹配具名/默认目标。 +- 现有仅渠道绑定(没有 `accountId`)会继续匹配默认账户;账户范围绑定仍然是可选的。 +- `openclaw doctor --fix` 也会通过将账户范围的顶层单账户值移动到为该渠道选择的提升账户来修复混合形态。大多数渠道使用 `accounts.default`;Matrix 可以改为保留现有的匹配具名/默认目标。 ### 其他插件渠道 -许多插件渠道配置为 `channels.`,并记录在各自专用的渠道页面中(例如 Feishu、Matrix、LINE、Nostr、Zalo、Nextcloud Talk、Synology Chat 和 Twitch)。 -查看完整渠道索引:[Channels](/zh-CN/channels)。 +许多插件渠道配置为 `channels.`,并记录在其专用渠道页面中(例如 Feishu、Matrix、LINE、Nostr、Zalo、Nextcloud Talk、Synology Chat 和 Twitch)。 +查看完整渠道索引:[渠道](/zh-CN/channels)。 ### 群聊提及门控 -群组消息默认**需要提及**(元数据提及或安全的正则表达式模式)。适用于 WhatsApp、Telegram、Discord、Google Chat 和 iMessage 群聊。 +群组消息默认**需要提及**(元数据提及或安全正则表达式模式)。适用于 WhatsApp、Telegram、Discord、Google Chat 和 iMessage 群聊。 -可见回复由单独的设置控制。群组/渠道房间默认为 `messages.groupChat.visibleReplies: "message_tool"`:OpenClaw 仍会处理该轮次,但普通最终回复会保持私密,可见的房间输出需要 `message(action=send)`。只有当你想要旧版行为,即普通回复会发布回房间时,才设置为 `"automatic"`。若要把相同的仅工具可见回复行为也应用到直接聊天,请设置 `messages.visibleReplies: "message_tool"`。 +可见回复单独控制。群组/频道房间默认为 `messages.groupChat.visibleReplies: "message_tool"`:OpenClaw 仍会处理该轮次,但普通最终回复保持私密,可见房间输出需要 `message(action=send)`。仅当你想要旧行为,也就是普通回复会发布回房间时,才设置为 `"automatic"`。如果也要对直接聊天应用相同的仅工具可见回复行为,请设置 `messages.visibleReplies: "message_tool"`。 -保存文件后,Gateway 网关会热重载 `messages` 配置。只有在部署中禁用文件监听或配置重载时才需要重启。 +如果消息工具在当前工具策略下不可用,OpenClaw 会回退到自动可见回复,而不是静默抑制响应。`openclaw doctor` 会对此不匹配发出警告。 + +Gateway 网关会在文件保存后热重载 `messages` 配置。仅当部署中禁用文件监听或配置重载时才需要重启。 **提及类型:** -- **元数据提及**:原生平台 @-mentions。在 WhatsApp 自聊模式中会被忽略。 +- **元数据提及**:原生平台 @ 提及。在 WhatsApp 自聊模式中会被忽略。 - **文本模式**:`agents.list[].groupChat.mentionPatterns` 中的安全正则表达式模式。无效模式和不安全的嵌套重复会被忽略。 -- 只有在可以检测时(原生提及或至少一个模式),才会执行提及门控。 +- 仅在可以检测时(原生提及或至少一个模式)强制执行提及门控。 ```json5 { @@ -786,9 +788,9 @@ IRC 由插件支持,并在 `channels.irc` 下配置。 } ``` -`messages.groupChat.historyLimit` 设置全局默认值。渠道可以通过 `channels..historyLimit`(或按账号)覆盖。设置为 `0` 可禁用。 +`messages.groupChat.historyLimit` 设置全局默认值。渠道可以用 `channels..historyLimit`(或按账户)覆盖。设置为 `0` 可禁用。 -`messages.visibleReplies` 是全局来源轮次默认值;`messages.groupChat.visibleReplies` 会为群组/渠道来源轮次覆盖它。渠道允许列表和提及门控仍然决定是否处理某个轮次。 +`messages.visibleReplies` 是全局来源轮次默认值;`messages.groupChat.visibleReplies` 会为群组/频道来源轮次覆盖它。渠道允许列表和提及门控仍会决定是否处理某个轮次。 #### 私信历史限制 @@ -811,7 +813,7 @@ IRC 由插件支持,并在 `channels.irc` 下配置。 #### 自聊模式 -在 `allowFrom` 中包含你自己的号码以启用自聊模式(忽略原生 @-mentions,只响应文本模式): +在 `allowFrom` 中包含你自己的号码以启用自聊模式(忽略原生 @ 提及,只响应文本模式): ```json5 { @@ -861,28 +863,28 @@ IRC 由插件支持,并在 `channels.irc` 下配置。 -- 此代码块用于配置命令界面。当前的内置 + 捆绑命令目录见 [Slash Commands](/zh-CN/tools/slash-commands)。 -- 本页是**配置键参考**,不是完整命令目录。由渠道/插件拥有的命令,例如 QQ Bot `/bot-ping` `/bot-help` `/bot-logs`、LINE `/card`、设备配对 `/pair`、记忆 `/dreaming`、手机控制 `/phone` 和 Talk `/voice`,记录在其渠道/插件页面以及 [Slash Commands](/zh-CN/tools/slash-commands) 中。 -- 文本命令必须是带有前导 `/` 的**独立**消息。 -- `native: "auto"` 会为 Discord/Telegram 启用原生命令,并让 Slack 保持关闭。 -- `nativeSkills: "auto"` 会为 Discord/Telegram 启用原生 Skills 命令,并让 Slack 保持关闭。 -- 按渠道覆盖:`channels.discord.commands.native`(布尔值或 `"auto"`)。`false` 会清除先前注册的命令。 +- 此块配置命令入口。当前内置 + 捆绑命令目录见[斜杠命令](/zh-CN/tools/slash-commands)。 +- 本页面是**配置键参考**,不是完整命令目录。渠道/插件拥有的命令,例如 QQ Bot `/bot-ping` `/bot-help` `/bot-logs`、LINE `/card`、设备配对 `/pair`、记忆 `/dreaming`、手机控制 `/phone` 和 Talk `/voice`,记录在各自的渠道/插件页面以及[斜杠命令](/zh-CN/tools/slash-commands)中。 +- 文本命令必须是以 `/` 开头的**独立**消息。 +- `native: "auto"` 会为 Discord/Telegram 启用原生命令,Slack 保持关闭。 +- `nativeSkills: "auto"` 会为 Discord/Telegram 启用原生 Skills 命令,Slack 保持关闭。 +- 按渠道覆盖:`channels.discord.commands.native`(布尔值或 `"auto"`)。`false` 会清除此前注册的命令。 - 使用 `channels..commands.nativeSkills` 按渠道覆盖原生 Skills 注册。 -- `channels.telegram.customCommands` 会添加额外的 Telegram 机器人菜单条目。 -- `bash: true` 会为主机 shell 启用 `! `。需要 `tools.elevated.enabled`,且发送者位于 `tools.elevated.allowFrom.` 中。 -- `config: true` 启用 `/config`(读取/写入 `openclaw.json`)。对于 Gateway 网关 `chat.send` 客户端,持久化的 `/config set|unset` 写入还需要 `operator.admin`;只读的 `/config show` 仍可供普通写入范围的 operator 客户端使用。 -- `mcp: true` 会为 `mcp.servers` 下由 OpenClaw 管理的 MCP 服务器配置启用 `/mcp`。 -- `plugins: true` 启用 `/plugins`,用于插件发现、安装以及启用/禁用控制。 -- `channels..configWrites` 按渠道控制配置变更(默认:true)。 -- 对于多账号渠道,`channels..accounts..configWrites` 也会控制针对该账号的写入(例如 `/allowlist --config --account ` 或 `/config set channels..accounts....`)。 -- `restart: false` 会禁用 `/restart` 和 Gateway 网关重启工具操作。默认:`true`。 -- `ownerAllowFrom` 是仅限所有者命令/工具的显式所有者允许列表。它与 `allowFrom` 分开。 -- `ownerDisplay: "hash"` 会在系统提示中哈希所有者 ID。设置 `ownerDisplaySecret` 以控制哈希。 -- `allowFrom` 按 provider 配置。设置后,它是**唯一**授权来源(渠道允许列表/配对和 `useAccessGroups` 会被忽略)。 +- `channels.telegram.customCommands` 会添加额外的 Telegram 机器人菜单项。 +- `bash: true` 为宿主 shell 启用 `! `。需要 `tools.elevated.enabled`,且发送者在 `tools.elevated.allowFrom.` 中。 +- `config: true` 启用 `/config`(读取/写入 `openclaw.json`)。对于 Gateway 网关 `chat.send` 客户端,持久化 `/config set|unset` 写入还需要 `operator.admin`;只读 `/config show` 仍可供普通写作用域的操作方客户端使用。 +- `mcp: true` 为 `mcp.servers` 下由 OpenClaw 管理的 MCP 服务器配置启用 `/mcp`。 +- `plugins: true` 为插件发现、安装以及启用/禁用控制启用 `/plugins`。 +- `channels..configWrites` 按渠道限制配置变更(默认:true)。 +- 对于多账号渠道,`channels..accounts..configWrites` 也会限制针对该账号的写入(例如 `/allowlist --config --account ` 或 `/config set channels..accounts....`)。 +- `restart: false` 会禁用 `/restart` 和 Gateway 网关重启工具操作。默认值:`true`。 +- `ownerAllowFrom` 是仅限所有者命令/工具的显式所有者允许列表。它独立于 `allowFrom`。 +- `ownerDisplay: "hash"` 会在系统提示词中对所有者 ID 做哈希处理。设置 `ownerDisplaySecret` 可控制哈希。 +- `allowFrom` 按提供商设置。设置后,它是**唯一**授权来源(渠道允许列表/配对和 `useAccessGroups` 会被忽略)。 - 当未设置 `allowFrom` 时,`useAccessGroups: false` 允许命令绕过访问组策略。 - 命令文档映射: - - 内置 + 捆绑目录:[Slash Commands](/zh-CN/tools/slash-commands) - - 渠道特定命令界面:[渠道](/zh-CN/channels) + - 内置 + 捆绑目录:[斜杠命令](/zh-CN/tools/slash-commands) + - 渠道特定命令入口:[渠道](/zh-CN/channels) - QQ Bot 命令:[QQ Bot](/zh-CN/channels/qqbot) - 配对命令:[配对](/zh-CN/channels/pairing) - LINE 卡片命令:[LINE](/zh-CN/channels/line) @@ -892,7 +894,7 @@ IRC 由插件支持,并在 `channels.irc` 下配置。 --- -## 相关内容 +## 相关 - [配置参考](/zh-CN/gateway/configuration-reference) — 顶层键 - [配置 — 智能体](/zh-CN/gateway/config-agents) diff --git a/docs/zh-CN/help/testing.md b/docs/zh-CN/help/testing.md index 71099d001..65f8cb6e7 100644 --- a/docs/zh-CN/help/testing.md +++ b/docs/zh-CN/help/testing.md @@ -3,182 +3,163 @@ read_when: - 在本地或 CI 中运行测试 - 为模型/提供商缺陷添加回归测试 - 调试 Gateway 网关 + 智能体行为 -summary: 测试工具包:单元/e2e/live 套件、Docker 运行器,以及每项测试覆盖的内容 +summary: 测试工具包:unit/e2e/live 测试套件、Docker 运行器,以及每项测试覆盖的内容 title: 测试 x-i18n: - generated_at: "2026-04-30T23:44:08Z" + generated_at: "2026-05-01T03:00:03Z" model: gpt-5.5 provider: openai - source_hash: f663a4476a59e4ccc2a6ea5b43eb0079534945eac37374bec891d6cccb1e941c + source_hash: 3c28e45c483169f528483f7a27265d89c34f3865eb56b51407639b566e117162 source_path: help/testing.md workflow: 16 --- -OpenClaw 有三个 Vitest 测试套件(单元/集成、E2E、实测)和一小组 Docker 运行器。本文是“我们如何测试”指南: +OpenClaw 有三个 Vitest 测试套件(单元/集成、e2e、live)和少量 Docker 运行器。本文档是一份“我们如何测试”的指南: -- 每个套件覆盖什么(以及它刻意 _不_ 覆盖什么)。 -- 常见工作流应运行哪些命令(本地、推送前、调试)。 -- 实测测试如何发现凭证并选择模型/提供商。 -- 如何为真实世界的模型/提供商问题添加回归测试。 +- 每个测试套件覆盖什么(以及它刻意_不_覆盖什么)。 +- 常见工作流(本地、推送前、调试)应运行哪些命令。 +- live 测试如何发现凭证并选择模型/提供商。 +- 如何为真实世界中的模型/提供商问题添加回归测试。 -**QA 栈(qa-lab、qa-channel、实测传输通道)**单独记录在: +**QA 技术栈(qa-lab、qa-channel、live 传输通道)**单独记录在文档中: - [QA overview](/zh-CN/concepts/qa-e2e-automation) — 架构、命令界面、场景编写。 -- [Matrix QA](/zh-CN/concepts/qa-matrix) — `pnpm openclaw qa matrix` 的参考。 -- [QA channel](/zh-CN/channels/qa-channel) — 仓库支持场景使用的合成传输插件。 +- [Matrix QA](/zh-CN/concepts/qa-matrix) — `pnpm openclaw qa matrix` 参考。 +- [QA channel](/zh-CN/channels/qa-channel) — 由仓库支持的场景使用的合成传输插件。 -本页覆盖常规测试套件和 Docker/Parallels 运行器的运行方式。下面的 QA 专用运行器部分([QA 专用运行器](#qa-specific-runners))列出了具体的 `qa` 调用,并指回上面的参考文档。 +本页介绍常规测试套件以及 Docker/Parallels 运行器。下面的 QA 专用运行器章节([QA 专用运行器](#qa-specific-runners))列出了具体的 `qa` 调用,并指回上面的参考资料。 ## 快速开始 大多数时候: -- 完整门禁(推送前预期运行):`pnpm build && pnpm check && pnpm check:test-types && pnpm test` -- 在资源充裕的机器上更快地运行本地完整套件:`pnpm test:max` +- 完整门禁(推送前预期执行):`pnpm build && pnpm check && pnpm check:test-types && pnpm test` +- 在资源充足的机器上更快运行本地完整测试套件:`pnpm test:max` - 直接 Vitest 监听循环:`pnpm test:watch` -- 直接按文件定位现在也会路由插件/渠道路径:`pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` -- 当你在迭代单个失败时,优先先运行有针对性的命令。 +- 直接文件定位现在也会路由插件/渠道路径:`pnpm test 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` +- E2E 测试套件:`pnpm test:e2e` 调试真实提供商/模型时(需要真实凭证): -- 实测套件(模型 + Gateway 网关工具/图像探针):`pnpm test:live` -- 静默定位一个实测文件:`pnpm test:live -- src/agents/models.profiles.live.test.ts` -- Docker 实测模型扫描:`pnpm test:docker:live-models` - - 每个选中的模型现在会运行一个文本轮次,以及一个小型文件读取风格探针。 - 元数据声明支持 `image` 输入的模型还会运行一个小型图像轮次。 +- Live 测试套件(模型 + Gateway 网关工具/图片探测):`pnpm test:live` +- 静默定位一个 live 文件:`pnpm test:live -- src/agents/models.profiles.live.test.ts` +- Docker live 模型扫描:`pnpm test:docker:live-models` + - 每个选中的模型现在会运行一个文本轮次,再加一个小型文件读取风格探测。 + 元数据声明支持 `image` 输入的模型也会运行一个很小的图片轮次。 在隔离提供商失败时,可用 `OPENCLAW_LIVE_MODEL_FILE_PROBE=0` 或 - `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0` 禁用额外探针。 + `OPENCLAW_LIVE_MODEL_IMAGE_PROBE=0` 禁用额外探测。 - CI 覆盖:每日 `OpenClaw Scheduled Live And E2E Checks` 和手动 - `OpenClaw Release Checks` 都会调用可复用的实测/E2E 工作流,并设置 - `include_live_suites: true`,其中包含按提供商分片的独立 Docker 实测模型 - 矩阵任务。 + `OpenClaw Release Checks` 都会调用可复用的 live/E2E 工作流,并设置 + `include_live_suites: true`,其中包括按提供商分片的独立 Docker live 模型 + matrix 作业。 - 对于聚焦的 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` 和它的 + 以及 `.github/workflows/openclaw-live-and-e2e-checks-reusable.yml` 及其 定时/发布调用方。 - 原生 Codex 绑定聊天冒烟测试:`pnpm test:docker:live-codex-bind` - - 针对 Codex 应用服务器路径运行 Docker 实测通道,使用 `/codex bind` 绑定一个合成 - Slack 私信,执行 `/codex fast` 和 - `/codex permissions`,然后验证普通回复和图像附件会通过原生插件绑定路由,而不是 ACP。 -- Codex 应用服务器 harness 冒烟测试:`pnpm test:docker:live-codex-harness` - - 通过插件拥有的 Codex 应用服务器 harness 运行 Gateway 网关 agent 轮次, - 验证 `/codex status` 和 `/codex models`,并默认执行图像、 - cron MCP、子 agent 和 Guardian 探针。在隔离其他 Codex - 应用服务器失败时,可用 - `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0` 禁用子 agent 探针。要进行聚焦的子 agent 检查,请禁用其他探针: + - 针对 Codex app-server 路径运行 Docker live 通道,绑定一个带 `/codex bind` + 的合成 Slack 私信,执行 `/codex fast` 和 + `/codex permissions`,然后验证普通回复和图片附件通过原生插件绑定而不是 ACP 路由。 +- Codex app-server harness 冒烟测试:`pnpm test:docker:live-codex-harness` + - 通过插件拥有的 Codex app-server harness 运行 Gateway 网关智能体轮次, + 验证 `/codex status` 和 `/codex models`,默认执行图片、 + cron MCP、子智能体和 Guardian 探测。在隔离其他 Codex + app-server 失败时,可用 `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0` + 禁用子智能体探测。若要进行聚焦的子智能体检查,请禁用其他探测: `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`,否则它会在子 agent 探针之后退出。 + `OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_ONLY=0`,否则它会在子智能体探测后退出。 - Crestodian 救援命令冒烟测试:`pnpm test:live:crestodian-rescue-channel` - - 可选的双保险检查,用于消息渠道救援命令界面。它会执行 `/crestodian status`,排队一个持久模型 - 变更,回复 `/crestodian yes`,并验证审计/配置写入路径。 + - 针对消息渠道救援命令界面的选择性双重保险检查。 + 它会执行 `/crestodian status`,排队一个持久模型变更, + 回复 `/crestodian yes`,并验证审计/配置写入路径。 - Crestodian 规划器 Docker 冒烟测试:`pnpm test:docker:crestodian-planner` - - 在无配置容器中运行 Crestodian,`PATH` 上放置一个假的 Claude CLI, - 并验证模糊规划器回退会转化为一次经审计的类型化配置写入。 + - 在无配置容器中运行 Crestodian,在 `PATH` 上放置假的 Claude CLI, + 并验证模糊规划器回退会转换为经过审计的类型化配置写入。 - Crestodian 首次运行 Docker 冒烟测试:`pnpm test:docker:crestodian-first-run` - 从空的 OpenClaw 状态目录开始,将裸 `openclaw` 路由到 - Crestodian,应用设置/模型/agent/Discord 插件 + SecretRef 写入, - 验证配置,并验证审计条目。同一 Ring 0 设置路径也在 QA Lab 中由 + Crestodian,应用设置/模型/智能体/Discord 插件 + SecretRef 写入, + 验证配置,并验证审计条目。同一 Ring 0 设置路径也由 QA Lab 中的 `pnpm openclaw qa suite --scenario crestodian-ring-zero-setup` 覆盖。 - Moonshot/Kimi 成本冒烟测试:设置 `MOONSHOT_API_KEY` 后,运行 - `openclaw models list --provider moonshot --json`,然后针对 + `openclaw models list --provider moonshot --json`,然后对 `moonshot/kimi-k2.6` 运行一个隔离的 `openclaw agent --local --session-id live-kimi-cost --message 'Reply exactly: KIMI_LIVE_OK' --thinking off --json`。 - 验证 JSON 报告 Moonshot/K2.6,并且助手转录存储了规范化的 `usage.cost`。 + 验证 JSON 报告 Moonshot/K2.6,并且助手 transcript 存储了归一化的 `usage.cost`。 -当你只需要一个失败用例时,优先通过下面描述的允许列表环境变量缩小实测测试范围。 +当你只需要一个失败用例时,优先通过下文描述的 allowlist 环境变量缩小 live 测试范围。 ## QA 专用运行器 -当你需要 QA-lab 真实度时,这些命令位于主测试套件旁边: +当你需要 QA-lab 真实度时,这些命令与主测试套件并列使用: -CI 在专用工作流中运行 QA Lab。`Parity gate` 会在匹配的 PR 上运行,也可通过手动触发使用模拟提供商运行。`QA-Lab - All Lanes` 每晚在 -`main` 上运行,也可通过手动触发运行,并将模拟一致性门禁、实测 Matrix 通道、 -Convex 管理的实测 Telegram 通道,以及 Convex 管理的实测 Discord 通道作为 -并行任务。定时 QA 和发布检查会显式传递 Matrix `--profile fast`, -而 Matrix CLI 和手动工作流输入默认仍为 -`all`;手动触发可将 `all` 分片为 `transport`、`media`、`e2ee-smoke`、 -`e2ee-deep` 和 `e2ee-cli` 任务。`OpenClaw Release Checks` 会在发布批准前运行一致性检查,以及快速 Matrix 和 Telegram 通道,并使用 -`mock-openai/gpt-5.5` 执行发布传输检查,使其保持确定性并避免常规提供商插件启动。这些实测传输 Gateway 网关会禁用记忆搜索;记忆行为仍由 QA 一致性套件覆盖。 +CI 在专用工作流中运行 QA Lab。`Parity gate` 会在匹配的 PR 上运行,也可通过手动调度配合 mock 提供商运行。`QA-Lab - All Lanes` 每晚在 `main` 上运行,也可通过手动调度运行,其中 mock parity gate、live Matrix 通道、Convex 管理的 live Telegram 通道和 Convex 管理的 live Discord 通道作为并行作业执行。定时 QA 和发布检查会显式传递 Matrix `--profile fast`,而 Matrix CLI 和手动工作流输入的默认值仍为 `all`;手动调度可以将 `all` 分片为 `transport`、`media`、`e2ee-smoke`、`e2ee-deep` 和 `e2ee-cli` 作业。`OpenClaw Release Checks` 会在发布批准前运行 parity 以及 fast Matrix 和 Telegram 通道,并使用 `mock-openai/gpt-5.5` 进行发布传输检查,使其保持确定性并避免普通提供商插件启动。这些 live 传输 Gateway 网关会禁用记忆搜索;记忆行为仍由 QA parity 测试套件覆盖。 -完整发布实测媒体分片使用 +完整发布 live 媒体分片使用 `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04`,其中已经包含 -`ffmpeg` 和 `ffprobe`。Docker 实测模型/后端分片使用共享的 -`ghcr.io/openclaw/openclaw-live-test:` 镜像,该镜像会为每个选中 -提交构建一次,然后使用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 拉取它,而不是在每个分片内部重建。 +`ffmpeg` 和 `ffprobe`。Docker live 模型/后端分片使用共享的 +`ghcr.io/openclaw/openclaw-live-test:` 镜像,该镜像会为每个选中提交构建一次,然后用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 拉取它,而不是在每个分片内重新构建。 - `pnpm openclaw qa suite` - - 直接在主机上运行仓库支持的 QA 场景。 - - 默认使用隔离的 Gateway 网关 worker 并行运行多个选中的场景。`qa-channel` 默认并发为 4(受 - 选中场景数量限制)。使用 `--concurrency ` 调整 worker - 数量,或使用 `--concurrency 1` 运行较旧的串行通道。 - - 任何场景失败时以非零状态退出。当你想要产物但不想要失败退出码时,使用 `--allow-failures`。 + - 直接在主机上运行由仓库支持的 QA 场景。 + - 默认使用隔离的 Gateway 网关 worker 并行运行多个选中的场景。 + `qa-channel` 默认并发为 4(受选中场景数量限制)。使用 `--concurrency ` 调整 worker + 数量,或使用 `--concurrency 1` 进入较旧的串行通道。 + - 任一场景失败时以非零状态退出。当你想要产物但不想要失败退出码时,使用 `--allow-failures`。 - 支持提供商模式 `live-frontier`、`mock-openai` 和 `aimock`。 - `aimock` 会启动一个本地 AIMock 支持的提供商服务器,用于实验性 - 固件和协议模拟覆盖,而不会替代具备场景感知能力的 - `mock-openai` 通道。 + `aimock` 会启动一个由本地 AIMock 支持的提供商服务器,用于实验性 fixture 和协议 mock 覆盖,而不会替代具备场景感知的 `mock-openai` 通道。 - `pnpm test:gateway:cpu-scenarios` - - 运行 Gateway 网关启动基准,加上一小组模拟 QA Lab 场景包 + - 运行 Gateway 网关启动基准,加上一小组 mock QA Lab 场景包 (`channel-chat-baseline`、`memory-failure-fallback`、 `gateway-restart-inflight-run`),并在 `.artifacts/gateway-cpu-scenarios/` - 下写入组合 CPU 观测摘要。 - - 默认只标记持续的高 CPU 观测(`--cpu-core-warn` - 加 `--hot-wall-warn-ms`),因此短暂启动峰值会记录为指标,而不会看起来像持续数分钟的 Gateway 网关占满回归。 - - 使用构建好的 `dist` 产物;当检出目录尚无新鲜运行时输出时,请先运行构建。 + 下写入组合 CPU 观察摘要。 + - 默认只标记持续的高 CPU 观察(`--cpu-core-warn` + 加 `--hot-wall-warn-ms`),因此短暂启动突增会被记录为指标,而不会看起来像持续数分钟的 Gateway 网关占满回归。 + - 使用已构建的 `dist` 产物;当 checkout 中尚无新的运行时输出时,请先运行构建。 - `pnpm openclaw qa suite --runner multipass` - - 在一次性 Multipass Linux VM 内运行同一 QA 套件。 + - 在一次性 Multipass Linux VM 中运行同一个 QA 测试套件。 - 保持与主机上 `qa suite` 相同的场景选择行为。 - 复用与 `qa suite` 相同的提供商/模型选择标志。 - - 实测运行会转发适合客户机的受支持 QA 认证输入: - 基于环境变量的提供商密钥、QA 实测提供商配置路径,以及存在时的 `CODEX_HOME`。 - - 输出目录必须保留在仓库根目录下,以便客户机可通过挂载的工作区写回。 - - 在 `.artifacts/qa-e2e/...` 下写入正常 QA 报告 + 摘要以及 Multipass 日志。 + - Live 运行会转发对 guest 实用的受支持 QA 认证输入: + 基于环境变量的提供商 key、QA live 提供商配置路径,以及存在时的 `CODEX_HOME`。 + - 输出目录必须保留在仓库根目录下,以便 guest 能通过挂载的工作区写回。 + - 在 `.artifacts/qa-e2e/...` 下写入常规 QA 报告 + 摘要,以及 Multipass 日志。 - `pnpm qa:lab:up` - 启动 Docker 支持的 QA 站点,用于操作员风格的 QA 工作。 - `pnpm test:docker:npm-onboard-channel-agent` - - 从当前检出构建 npm tarball,在 Docker 中全局安装,运行非交互式 OpenAI API 密钥新手引导, - 默认配置 Telegram,验证启用插件会按需安装运行时依赖, - 运行 Doctor,并针对模拟 OpenAI 端点运行一次本地 agent 轮次。 - - 使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 可用 Discord 运行同一打包安装通道。 + - 从当前 checkout 构建 npm tarball,在 Docker 中全局安装它,运行非交互式 OpenAI API key 新手引导,默认配置 Telegram,验证启用插件会按需安装运行时依赖,运行 Doctor,并对 mock OpenAI 端点运行一个本地智能体轮次。 + - 使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 通过 Discord 运行同一 packaged-install 通道。 - `pnpm test:docker:session-runtime-context` - - 为嵌入式运行时上下文转录运行一个确定性的构建应用 Docker 冒烟测试。它验证隐藏的 OpenClaw 运行时上下文会作为 - 非显示自定义消息持久化,而不是泄漏到可见用户轮次中, - 然后播种一个受影响的损坏会话 JSONL,并验证 - `openclaw doctor --fix` 会将其重写到当前分支且生成备份。 + - 针对嵌入式运行时上下文 transcript 运行确定性的已构建应用 Docker 冒烟测试。它会验证隐藏的 OpenClaw 运行时上下文被持久化为非显示自定义消息,而不是泄漏到可见用户轮次中,然后播种一个受影响的损坏会话 JSONL,并验证 + `openclaw doctor --fix` 会用备份将其重写到活跃分支。 - `pnpm test:docker:npm-telegram-live` - - 在 Docker 中安装 OpenClaw 包候选,运行已安装包的新手引导, - 通过已安装的 CLI 配置 Telegram,然后复用实测 Telegram QA 通道,并将该已安装包作为被测系统 Gateway 网关。 + - 在 Docker 中安装 OpenClaw 包候选版本,运行已安装包的新手引导,通过已安装 CLI 配置 Telegram,然后复用 live Telegram QA 通道,并将该已安装包作为被测 SUT Gateway 网关。 - 默认值为 `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@beta`;设置 `OPENCLAW_NPM_TELEGRAM_PACKAGE_TGZ=/path/to/openclaw-current.tgz` 或 - `OPENCLAW_CURRENT_PACKAGE_TGZ`,即可测试解析后的本地 tarball,而不是从注册表安装。 - - 使用与 `pnpm openclaw qa telegram` 相同的 Telegram 环境凭证或 Convex 凭证源。对于 CI/发布自动化,请设置 - `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex`,以及 - `OPENCLAW_QA_CONVEX_SITE_URL` 和角色密钥。如果 - `OPENCLAW_QA_CONVEX_SITE_URL` 和一个 Convex 角色密钥存在于 CI 中, + `OPENCLAW_CURRENT_PACKAGE_TGZ` 可测试已解析的本地 tarball,而不是从 registry 安装。 + - 使用与 `pnpm openclaw qa telegram` 相同的 Telegram 环境凭证或 Convex 凭证来源。对于 CI/发布自动化,设置 + `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex`,再加上 + `OPENCLAW_QA_CONVEX_SITE_URL` 和角色密钥。如果 CI 中存在 + `OPENCLAW_QA_CONVEX_SITE_URL` 和 Convex 角色密钥, Docker 包装器会自动选择 Convex。 - - `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintainer` 仅为此通道覆盖共享的 + - `OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci|maintainer` 仅针对该通道覆盖共享的 `OPENCLAW_QA_CREDENTIAL_ROLE`。 - GitHub Actions 将此通道公开为手动维护者工作流 `NPM Telegram Beta E2E`。它不会在合并时运行。该工作流使用 `qa-live-shared` 环境和 Convex CI 凭证租约。 -- GitHub Actions 还公开了 `Package Acceptance`,用于针对一个候选包进行旁路运行的产品证明。 - 它接受受信任的 ref、已发布的 npm 规格、 - HTTPS tarball URL 加 SHA-256,或来自另一运行的 tarball 产物, - 将规范化的 `openclaw-current.tgz` 作为 `package-under-test` 上传,然后使用冒烟、包、产品、完整或自定义 - 通道配置文件运行现有 Docker E2E 调度器。设置 `telegram_mode=mock-openai` 或 `live-frontier` 可针对同一个 - `package-under-test` 产物运行 Telegram QA 工作流。 +- GitHub Actions 还公开 `Package Acceptance`,用于针对一个候选包进行旁路产品证明。它接受可信 ref、已发布 npm spec、HTTPS tarball URL 加 SHA-256,或来自另一次运行的 tarball 产物,将归一化的 `openclaw-current.tgz` 作为 `package-under-test` 上传,然后使用 smoke、package、product、full 或自定义通道 profile 运行现有 Docker E2E 调度器。设置 `telegram_mode=mock-openai` 或 `live-frontier`,可让 Telegram QA 工作流针对同一个 `package-under-test` 产物运行。 - 最新 beta 产品证明: ```bash @@ -199,7 +180,7 @@ gh workflow run package-acceptance.yml --ref main \ -f suite_profile=package ``` -- 构件证明会从另一个 Actions 运行下载 tarball 构件: +- 工件证明会从另一个 Actions 运行下载 tarball 工件: ```bash gh workflow run package-acceptance.yml --ref main \ @@ -211,43 +192,43 @@ gh workflow run package-acceptance.yml --ref main \ - `pnpm test:docker:bundled-channel-deps` - 在 Docker 中打包并安装当前 OpenClaw 构建,启动已配置 OpenAI 的 Gateway 网关,然后通过配置编辑启用内置渠道/插件。 - - 验证设置发现会保持未配置的插件运行时依赖缺失,第一个已配置的 Gateway 网关或 doctor 运行会按需安装每个内置插件的运行时依赖,并且第二次重启不会重新安装已经激活的依赖。 - - 还会安装一个已知的较旧 npm 基线,在运行 `openclaw update --tag ` 之前启用 Telegram,并验证候选版本的更新后 doctor 会修复内置渠道运行时依赖,而不需要 harness 侧 postinstall 修复。 + - 验证设置发现会让未配置的插件运行时依赖保持缺失状态,首次配置后的 Gateway 网关或 doctor 运行会按需安装每个内置插件的运行时依赖,并且第二次重启不会重新安装已经激活的依赖。 + - 还会安装一个已知的较旧 npm 基线,在运行 `openclaw update --tag ` 前启用 Telegram,并验证候选版本的更新后 doctor 会修复内置渠道运行时依赖,而不需要 harness 侧的 postinstall 修复。 - `pnpm test:parallels:npm-update` - - 在 Parallels 客户机上运行原生打包安装更新 smoke。每个选定平台会先安装请求的基线包,然后在同一个客户机中运行已安装的 `openclaw update` 命令,并验证已安装版本、更新 Status、Gateway 网关就绪状态,以及一次本地智能体轮次。 - - 在迭代单个客户机时使用 `--platform macos`、`--platform windows` 或 `--platform linux`。使用 `--json` 获取摘要构件路径和各泳道 Status。 - - OpenAI 泳道默认使用 `openai/gpt-5.5` 作为实时智能体轮次证明。若要有意验证另一个 OpenAI 模型,请传入 `--model ` 或设置 `OPENCLAW_PARALLELS_OPENAI_MODEL`。 - - 用宿主机超时包装较长的本地运行,避免 Parallels 传输卡顿耗尽剩余测试窗口: + - 跨 Parallels guest 运行原生打包安装更新 smoke。每个选中的平台会先安装请求的基线包,然后在同一 guest 中运行已安装的 `openclaw update` 命令,并验证已安装版本、更新 Status、Gateway 网关就绪状态以及一次本地智能体回合。 + - 在迭代单个 guest 时使用 `--platform macos`、`--platform windows` 或 `--platform linux`。使用 `--json` 获取摘要工件路径和每条 lane 的 Status。 + - OpenAI lane 默认使用 `openai/gpt-5.5` 作为实时智能体回合证明。若要有意验证另一个 OpenAI 模型,请传入 `--model ` 或设置 `OPENCLAW_PARALLELS_OPENAI_MODEL`。 + - 用主机 timeout 包裹较长的本地运行,避免 Parallels 传输停滞耗尽剩余测试窗口: ```bash timeout --foreground 150m pnpm test:parallels:npm-update -- --json timeout --foreground 90m pnpm test:parallels:npm-update -- --platform windows --json ``` - - 脚本会在 `/tmp/openclaw-parallels-npm-update.*` 下写入嵌套泳道日志。先检查 `windows-update.log`、`macos-update.log` 或 `linux-update.log`,再判断外层包装器是否卡住。 - - Windows 更新在冷启动客户机上可能会花 10 到 15 分钟进行更新后 doctor/运行时依赖修复;只要嵌套 npm debug 日志仍在推进,这仍属正常。 - - 不要将这个聚合包装器与单独的 Parallels macOS、Windows 或 Linux smoke 泳道并行运行。它们共享 VM 状态,可能在快照恢复、包服务或客户机 Gateway 网关状态上发生冲突。 - - 更新后证明会运行常规内置插件表面,因为即使智能体轮次本身只检查简单文本响应,语音、图像生成和媒体理解等能力外观也是通过内置运行时 API 加载的。 + - 该脚本会把嵌套 lane 日志写入 `/tmp/openclaw-parallels-npm-update.*` 下。先检查 `windows-update.log`、`macos-update.log` 或 `linux-update.log`,再判断外层 wrapper 是否卡住。 + - Windows 更新在冷 guest 上可能会花 10 到 15 分钟执行更新后 doctor/运行时依赖修复;只要嵌套的 npm debug 日志仍在推进,这仍然是正常的。 + - 不要将这个聚合 wrapper 与单独的 Parallels macOS、Windows 或 Linux smoke lane 并行运行。它们共享虚拟机状态,可能在快照恢复、包服务或 guest Gateway 网关状态上发生冲突。 + - 更新后证明会运行常规内置插件表面,因为语音、图像生成和媒体理解等 capability facade 会通过内置运行时 API 加载,即使智能体回合本身只检查简单文本响应。 - `pnpm openclaw qa aimock` - 仅启动本地 AIMock 提供商服务器,用于直接协议 smoke 测试。 - `pnpm openclaw qa matrix` - - 针对一次性 Docker 支持的 Tuwunel homeserver 运行 Matrix 实时 QA 泳道。仅限源码检出;打包安装不会随附 `qa-lab`。 - - 完整 CLI、profile/scenario 目录、环境变量和构件布局:[Matrix QA](/zh-CN/concepts/qa-matrix)。 + - 针对一次性 Docker 后端 Tuwunel homeserver 运行 Matrix 实时 QA lane。仅适用于源代码 checkout;打包安装不会发布 `qa-lab`。 + - 完整 CLI、profile/scenario catalog、环境变量和工件布局:[Matrix QA](/zh-CN/concepts/qa-matrix)。 - `pnpm openclaw qa telegram` - - 使用来自环境变量的驱动和 SUT 机器人 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` 以使用共享池化凭证。默认使用环境变量模式,或设置 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` 选择加入池化租约。 - - 任一场景失败时会以非零状态退出。若你希望获取构件但不产生失败退出码,请使用 `--allow-failures`。 - - 需要两个不同的机器人位于同一个私有群组中,且 SUT 机器人公开 Telegram 用户名。 - - 为了稳定观察机器人之间的通信,请在 `@BotFather` 中为两个机器人启用 Bot-to-Bot Communication Mode,并确保驱动机器人可以观察群组机器人流量。 - - 在 `.artifacts/qa-e2e/...` 下写入 Telegram QA 报告、摘要和 observed-messages 构件。回复场景包含从驱动发送请求到观察到 SUT 回复之间的 RTT。 + - 使用来自环境的 driver 和 SUT bot token,针对真实私有群组运行 Telegram 实时 QA lane。 + - 需要 `OPENCLAW_QA_TELEGRAM_GROUP_ID`、`OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN` 和 `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`。群组 id 必须是数字形式的 Telegram chat id。 + - 支持 `--credential-source convex` 以使用共享池化凭证。默认使用 env 模式,或设置 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex` 以选择使用池化租约。 + - 当任何场景失败时会以非零状态退出。当你想要工件但不想要失败退出码时,使用 `--allow-failures`。 + - 需要同一私有群组中的两个不同 bot,且 SUT bot 需要公开一个 Telegram username。 + - 为获得稳定的 bot 到 bot 观测,请在 `@BotFather` 中为两个 bot 启用 Bot-to-Bot Communication Mode,并确保 driver bot 可以观测群组 bot 流量。 + - 在 `.artifacts/qa-e2e/...` 下写入 Telegram QA 报告、摘要和 observed-messages 工件。回复场景包含从 driver 发送请求到观测到 SUT 回复的 RTT。 -实时传输泳道共享一套标准契约,因此新传输不会漂移;各泳道覆盖矩阵位于 [QA overview → 实时传输覆盖范围](/zh-CN/concepts/qa-e2e-automation#live-transport-coverage)。`qa-channel` 是宽泛的合成套件,不属于该矩阵。 +实时传输 lane 共享一套标准契约,因此新的传输不会偏离;每条 lane 的覆盖矩阵位于 [QA overview → 实时传输覆盖](/zh-CN/concepts/qa-e2e-automation#live-transport-coverage)。`qa-channel` 是广泛的合成套件,不属于该矩阵。 ### 通过 Convex 共享 Telegram 凭证(v1) -当为 `openclaw qa telegram` 启用 `--credential-source convex`(或 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`)时,QA lab 会从 Convex 支持的池中获取独占租约,在泳道运行期间对该租约发送 Heartbeat,并在关闭时释放租约。 +为 `openclaw qa telegram` 启用 `--credential-source convex`(或 `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`)时,QA lab 会从 Convex 后端池获取独占租约,在该 lane 运行期间为该租约发送 Heartbeat,并在关闭时释放租约。 参考 Convex 项目脚手架: @@ -256,12 +237,12 @@ gh workflow run package-acceptance.yml --ref main \ 必需环境变量: - `OPENCLAW_QA_CONVEX_SITE_URL`(例如 `https://your-deployment.convex.site`) -- 所选角色的一个 secret: +- 所选角色的一个密钥: - `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER` 用于 `maintainer` - `OPENCLAW_QA_CONVEX_SECRET_CI` 用于 `ci` - 凭证角色选择: - CLI:`--credential-role maintainer|ci` - - 环境变量默认值:`OPENCLAW_QA_CREDENTIAL_ROLE`(在 CI 中默认为 `ci`,否则为 `maintainer`) + - Env 默认值:`OPENCLAW_QA_CREDENTIAL_ROLE`(在 CI 中默认是 `ci`,否则默认是 `maintainer`) 可选环境变量: @@ -271,13 +252,13 @@ gh workflow run package-acceptance.yml --ref main \ - `OPENCLAW_QA_CREDENTIAL_HTTP_TIMEOUT_MS`(默认 `15000`) - `OPENCLAW_QA_CONVEX_ENDPOINT_PREFIX`(默认 `/qa-credentials/v1`) - `OPENCLAW_QA_CREDENTIAL_OWNER_ID`(可选 trace id) -- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` 允许用于仅本地开发的 loopback `http://` Convex URL。 +- `OPENCLAW_QA_ALLOW_INSECURE_HTTP=1` 允许 local-only 开发使用 loopback `http://` Convex URL。 -`OPENCLAW_QA_CONVEX_SITE_URL` 在正常运行中应使用 `https://`。 +正常运行中,`OPENCLAW_QA_CONVEX_SITE_URL` 应使用 `https://`。 -维护者管理命令(池添加/移除/列出)明确要求 `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`。 +维护者管理命令(pool add/remove/list)明确需要 `OPENCLAW_QA_CONVEX_SECRET_MAINTAINER`。 -维护者 CLI 辅助命令: +面向维护者的 CLI helper: ```bash pnpm openclaw qa credentials doctor @@ -286,9 +267,9 @@ pnpm openclaw qa credentials list --kind telegram pnpm openclaw qa credentials remove --credential-id ``` -在实时运行前使用 `doctor` 检查 Convex site URL、broker secrets、endpoint prefix、HTTP timeout 和 admin/list 可达性,同时不会打印 secret 值。在脚本和 CI 工具中使用 `--json` 获取机器可读输出。 +在实时运行前使用 `doctor` 检查 Convex site URL、broker secret、endpoint prefix、HTTP timeout 和 admin/list 可达性,且不会打印 secret 值。在脚本和 CI 工具中使用 `--json` 获取机器可读输出。 -默认端点契约(`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`): +默认 endpoint 契约(`OPENCLAW_QA_CONVEX_SITE_URL` + `/qa-credentials/v1`): - `POST /acquire` - 请求:`{ kind, ownerId, actorRole, leaseTtlMs, heartbeatIntervalMs }` @@ -315,92 +296,118 @@ Telegram kind 的 payload 形状: - `{ groupId: string, driverToken: string, sutToken: string }` - `groupId` 必须是数字形式的 Telegram chat id 字符串。 -- `admin/add` 会为 `kind: "telegram"` 验证此形状,并拒绝格式错误的 payload。 +- `admin/add` 会针对 `kind: "telegram"` 验证该形状,并拒绝格式错误的 payload。 -### 向 QA 添加渠道 +### 向 QA 添加一个渠道 -新渠道适配器的架构和场景辅助名称位于 [QA overview → 添加渠道](/zh-CN/concepts/qa-e2e-automation#adding-a-channel)。最低要求:在共享 `qa-lab` host seam 上实现传输运行器,在插件清单中声明 `qaRunners`,挂载为 `openclaw qa `,并在 `qa/scenarios/` 下编写场景。 +新渠道 adapter 的架构和场景 helper 名称位于 [QA overview → 添加一个渠道](/zh-CN/concepts/qa-e2e-automation#adding-a-channel)。最低要求:在共享 `qa-lab` host seam 上实现 transport runner,在插件 manifest 中声明 `qaRunners`,挂载为 `openclaw qa `,并在 `qa/scenarios/` 下编写场景。 -## 测试套件(何处运行什么) +## 测试套件(在哪里运行什么) -可以将这些套件理解为“逐步提高真实性”(同时也提高不稳定性/成本): +可以把这些套件理解为“逐步提高真实性”(同时也增加 flakiness/成本): ### 单元 / 集成(默认) - 命令:`pnpm test` -- 配置:非定向运行使用 `vitest.full-*.config.ts` 分片集,并且可能将多项目分片展开为按项目配置以进行并行调度 -- 文件:`src/**/*.test.ts`、`packages/**/*.test.ts` 和 `test/**/*.test.ts` 下的核心/单元清单;UI 单元测试在专用 `unit-ui` 分片中运行 +- 配置:非定向运行使用 `vitest.full-*.config.ts` shard 集合,并且可能会将多项目 shard 展开为按项目划分的配置,以便并行调度 +- 文件:`src/**/*.test.ts`、`packages/**/*.test.ts` 和 `test/**/*.test.ts` 下的 core/unit inventory;UI 单元测试在专用 `unit-ui` shard 中运行 - 范围: - 纯单元测试 - - 进程内集成测试(Gateway 网关认证、路由、工具调用、解析、配置) - - 已知 bug 的确定性回归测试 -- 期望: + - 进程内集成测试(Gateway 网关 auth、routing、tooling、parsing、配置) + - 已知 bug 的确定性回归 +- 预期: - 在 CI 中运行 - - 不需要真实密钥 + - 不需要真实 key - 应该快速且稳定 - - 解析器和公共表面加载器测试必须使用生成的微型插件 fixture 证明宽泛的 `api.js` 和 `runtime-api.js` fallback 行为,而不是使用真实内置插件源码 API。真实插件 API 加载属于插件拥有的契约/集成套件。 + - Resolver 和公共表面 loader 测试必须使用生成的微型插件 fixture 来证明宽泛 `api.js` 和 `runtime-api.js` fallback 行为,而不是使用真实内置插件源 API。真实插件 API 加载属于插件自有的契约/集成套件。 - - 非定向的 `pnpm test` 会运行十二个较小的分片配置(`core-unit-fast`、`core-unit-src`、`core-unit-security`、`core-unit-ui`、`core-unit-support`、`core-support-boundary`、`core-contracts`、`core-bundled`、`core-runtime`、`agentic`、`auto-reply`、`extensions`),而不是一个巨大的原生根项目进程。这会降低繁忙机器上的峰值 RSS,并避免 auto-reply/插件工作让无关测试套件得不到资源。 + - 无目标的 `pnpm test` 会运行十二个更小的分片配置(`core-unit-fast`、`core-unit-src`、`core-unit-security`、`core-unit-ui`、`core-unit-support`、`core-support-boundary`、`core-contracts`、`core-bundled`、`core-runtime`、`agentic`、`auto-reply`、`extensions`),而不是一个巨大的原生根项目进程。这样可以降低高负载机器上的峰值 RSS,并避免 auto-reply/extension 工作饿死无关套件。 - `pnpm test --watch` 仍使用原生根 `vitest.config.ts` 项目图,因为多分片 watch 循环并不实用。 - - `pnpm test`、`pnpm test:watch` 和 `pnpm test:perf:imports` 会先通过作用域 lane 路由显式文件/目录目标,因此 `pnpm test extensions/discord/src/monitor/message-handler.preflight.test.ts` 可以避免支付完整根项目启动成本。 - - `pnpm test:changed` 默认会把变更的 git 路径展开为低成本的作用域 lane:直接测试编辑、同级 `*.test.ts` 文件、显式源码映射,以及本地导入图依赖项。Config/设置/包编辑不会广泛运行测试,除非你显式使用 `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 `。仅发布元数据的版本递增会运行定向版本/配置/根依赖检查,并带有一个 guard,用于拒绝顶层 version 字段以外的 package 变更。 - - Live Docker ACP harness 编辑会运行聚焦检查:live Docker 认证脚本的 shell 语法检查,以及 live Docker 调度器 dry-run。只有当 diff 限定在 `scripts["test:docker:live-*"]` 时,才会包含 `package.json` 变更;依赖、导出、版本和其他 package 表面编辑仍使用更广泛的 guard。 - - 来自 agents、commands、plugins、auto-reply helpers、`plugin-sdk` 和类似纯工具区域的轻导入单元测试会路由到 `unit-fast` lane,该 lane 会跳过 `test/setup-openclaw-runtime.ts`;有状态/运行时较重的文件仍保留在现有 lane 上。 - - 选定的 `plugin-sdk` 和 `commands` helper 源文件也会将 changed-mode 运行映射到这些轻量 lane 中的显式同级测试,因此 helper 编辑可以避免为该目录重新运行完整重型套件。 - - `auto-reply` 有专用 bucket,分别覆盖顶层 core helpers、顶层 `reply.*` 集成测试,以及 `src/auto-reply/reply/**` 子树。CI 会进一步将 reply 子树拆分为 agent-runner、dispatch 和 commands/state-routing 分片,避免一个导入较重的 bucket 占用完整 Node 尾部时间。 - - 常规 PR/main CI 会有意跳过插件批量扫描和仅发布用的 `agentic-plugins` 分片。完整发布验证会为发布候选触发单独的 `Plugin Prerelease` 子工作流,覆盖这些插件/扩展较重的套件。 + - `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` 文件、显式源文件映射,以及本地导入图依赖方。配置/设置/package 编辑不会广泛运行测试,除非你显式使用 `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,然后运行匹配的类型检查、lint 和防护命令。它不会运行 Vitest 测试;如需测试证明,请调用 `pnpm test:changed` 或显式 `pnpm test `。仅发布元数据的版本提升会运行有针对性的版本/config/root-dependency 检查,并带有一个防护,用于拒绝顶层 version 字段以外的 package 变更。 + - 实时 Docker ACP harness 编辑会运行聚焦检查:实时 Docker 认证脚本的 shell 语法检查,以及实时 Docker 调度器 dry-run。只有当 diff 限于 `scripts["test:docker:live-*"]` 时才会包含 `package.json` 变更;dependency、export、version 和其他 package 表面编辑仍使用更广泛的防护。 + - 来自 agents、commands、plugins、auto-reply helpers、`plugin-sdk` 以及类似纯工具区域的轻导入单元测试会路由到 `unit-fast` lane,该 lane 会跳过 `test/setup-openclaw-runtime.ts`;有状态/运行时较重的文件仍留在现有 lane 上。 + - 选定的 `plugin-sdk` 和 `commands` helper 源文件也会把 changed-mode 运行映射到这些轻量 lane 中的显式同级测试,因此 helper 编辑可以避免为该目录重新运行完整重型套件。 + - `auto-reply` 为顶层 core helpers、顶层 `reply.*` 集成测试,以及 `src/auto-reply/reply/**` 子树设置了专用 bucket。CI 还会进一步把 reply 子树拆分为 agent-runner、dispatch 和 commands/state-routing 分片,避免一个导入较重的 bucket 独占完整 Node 尾部。 + - 常规 PR/main CI 会有意跳过 extension 批量扫测和仅发布使用的 `agentic-plugins` 分片。完整 Release Validation 会为候选发布版本上的这些 plugin/extension 重型套件调度单独的 `Plugin Prerelease` 子工作流。 - + - - 当你更改 message-tool 发现输入或 compaction 运行时上下文时,请保留两层覆盖。 - - 为纯路由与规范化边界添加聚焦的 helper 回归测试。 + - 当你变更 message-tool 发现输入或压缩运行时上下文时, + 请保持两个层级的覆盖率。 + - 为纯路由和规范化边界添加聚焦的 helper 回归测试。 - 保持嵌入式运行器集成套件健康: `src/agents/pi-embedded-runner/compact.hooks.test.ts`、 `src/agents/pi-embedded-runner/run.overflow-compaction.test.ts` 和 `src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts`。 - - 这些套件会验证作用域 id 和 compaction 行为仍通过真实的 `run.ts` / `compact.ts` 路径流动;仅 helper 测试不足以替代这些集成路径。 + - 这些套件会验证限定范围的 ID 和压缩行为仍然流经真实的 + `run.ts` / `compact.ts` 路径;仅 helper 测试不足以替代这些集成路径。 - 基础 Vitest 配置默认使用 `threads`。 - - 共享 Vitest 配置固定 `isolate: false`,并在根项目、e2e 和 live 配置中使用非隔离运行器。 - - 根 UI lane 保留其 `jsdom` 设置和优化器,但同样运行在共享非隔离运行器上。 - - 每个 `pnpm test` 分片都会从共享 Vitest 配置继承相同的 `threads` + `isolate: false` 默认值。 - - `scripts/run-vitest.mjs` 默认会为 Vitest 子 Node 进程添加 `--no-maglev`,以减少大型本地运行期间的 V8 编译抖动。设置 `OPENCLAW_VITEST_ENABLE_MAGLEV=1` 可与原生 V8 行为对比。 + - 共享 Vitest 配置固定 `isolate: false`,并在根项目、e2e 和 live 配置中使用 + 非隔离运行器。 + - 根 UI lane 保留其 `jsdom` 设置和优化器,但也运行在共享的非隔离运行器上。 + - 每个 `pnpm test` 分片都会从共享 Vitest 配置继承相同的 `threads` + `isolate: false` + 默认值。 + - `scripts/run-vitest.mjs` 默认会为 Vitest 子 Node + 进程添加 `--no-maglev`,以减少大型本地运行期间的 V8 编译抖动。 + 设置 `OPENCLAW_VITEST_ENABLE_MAGLEV=1` 可与原生 V8 + 行为对比。 - - `pnpm changed:lanes` 会显示一个 diff 触发了哪些架构 lane。 - - pre-commit hook 仅做格式化。它会重新暂存格式化后的文件,不运行 lint、typecheck 或测试。 - - 当你在交接或 push 前需要智能本地检查门禁时,请显式运行 `pnpm check:changed`。 - - `pnpm test:changed` 默认通过低成本作用域 lane 路由。仅当 agent 判定 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`;如果你想为直接 profiling 使用一个显式缓存位置,请设置 `OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/abs/path`。 + - `pnpm changed:lanes` 会显示 diff 触发了哪些架构 lane。 + - pre-commit hook 仅做格式化。它会重新暂存已格式化文件, + 不会运行 lint、类型检查或测试。 + - 当你需要智能本地检查门禁时,在交接或 push 前显式运行 `pnpm check:changed`。 + - `pnpm test:changed` 默认通过低成本的限定范围 lane 路由。仅当智能体 + 判定 harness、config、package 或 contract 编辑确实需要更广泛的 + 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`。 - - `pnpm test:perf:imports` 会启用 Vitest 导入时长报告以及导入拆解输出。 - - `pnpm test:perf:imports:changed` 将相同的 profiling 视图限定到自 `origin/main` 以来变更的文件。 - - 分片计时数据会写入 `.artifacts/vitest-shard-timings.json`。整配置运行使用配置路径作为键;include-pattern CI 分片会追加分片名称,以便单独跟踪经过过滤的分片。 - - 当某个热门测试仍将大部分时间花在启动导入上时,请把重型依赖放在窄范围本地 `*.runtime.ts` 边界后面,并直接 mock 该边界,而不是为了通过 `vi.mock(...)` 传递它们而深度导入运行时 helpers。 - - `pnpm test:perf:changed:bench -- --ref ` 会将路由后的 `test:changed` 与该已提交 diff 的原生根项目路径进行比较,并打印 wall time 和 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 profiles。 + - `pnpm test:perf:imports` 会启用 Vitest 导入耗时报告以及导入拆分输出。 + - `pnpm test:perf:imports:changed` 会把同一分析视图限定到 + 自 `origin/main` 以来变更的文件。 + - 分片计时数据会写入 `.artifacts/vitest-shard-timings.json`。 + 整配置运行使用配置路径作为键;include-pattern CI + 分片会附加分片名称,以便单独跟踪经过过滤的分片。 + - 当某个热点测试仍然把大部分时间花在启动导入上时, + 请把重型依赖放在窄的本地 `*.runtime.ts` seam 后面,并直接 + mock 该 seam,而不是仅为通过 `vi.mock(...)` 传递它们而深度导入运行时 helper。 + - `pnpm test:perf:changed:bench -- --ref ` 会将路由后的 + `test:changed` 与该已提交 diff 的原生根项目路径进行比较,并打印墙钟时间和 macOS 最大 RSS。 + - `pnpm test:perf:changed:bench -- --worktree` 会通过把已变更文件列表路由到 + `scripts/test-projects.mjs` 和根 Vitest 配置,来基准测试当前 + 脏工作树。 + - `pnpm test:perf:profile:main` 会为 + Vitest/Vite 启动和 transform 开销写入主线程 CPU profile。 + - `pnpm test:perf:profile:runner` 会在禁用文件并行的情况下,为 + 单元套件写入 runner CPU+heap profile。 @@ -408,141 +415,142 @@ Telegram kind 的 payload 形状: ### 稳定性(Gateway 网关) - 命令:`pnpm test:stability:gateway` -- 配置:`vitest.gateway.config.ts`,强制为一个 worker +- 配置:`vitest.gateway.config.ts`,强制使用一个 worker - 范围: - - 默认启动一个启用 diagnostics 的真实 loopback Gateway 网关 - - 通过 diagnostic event path 驱动合成的 Gateway 网关 message、memory 和 large-payload churn + - 默认启动一个启用诊断的真实 loopback Gateway 网关 + - 通过诊断事件路径驱动合成 gateway 消息、记忆和大 payload 抖动 - 通过 Gateway 网关 WS RPC 查询 `diagnostics.stability` - - 覆盖诊断稳定性 bundle 持久化 helpers - - 断言 recorder 保持有界、合成 RSS 样本保持低于压力预算,并且每会话队列深度回落到零 -- 预期: - - CI 安全且无须密钥 - - 用于稳定性回归跟进的窄 lane,不是完整 Gateway 网关套件的替代品 + - 覆盖诊断稳定性 bundle 持久化 helper + - 断言 recorder 保持有界,合成 RSS 样本保持在压力预算内,并且每会话队列深度会排空回零 +- 期望: + - CI 安全且无需 key + - 用于稳定性回归跟进的窄 lane,而不是完整 Gateway 网关套件的替代品 -### E2E(Gateway 网关冒烟测试) +### E2E(Gateway 网关冒烟) - 命令:`pnpm test:e2e` - 配置:`vitest.e2e.config.ts` -- 文件:`src/**/*.e2e.test.ts`、`test/**/*.e2e.test.ts`,以及 `extensions/` 下的内置插件 E2E 测试 +- 文件:`src/**/*.e2e.test.ts`、`test/**/*.e2e.test.ts`,以及 `extensions/` 下的 bundled-plugin E2E 测试 - 运行时默认值: - - 使用 Vitest `threads` 与 `isolate: false`,与仓库其余部分一致。 - - 使用自适应 workers(CI:最多 2 个,本地:默认 1 个)。 - - 默认以静默模式运行,以减少控制台 I/O 开销。 + - 使用 Vitest `threads` 和 `isolate: false`,与仓库其余部分匹配。 + - 使用自适应 worker(CI:最多 2 个,本地:默认 1 个)。 + - 默认以静默模式运行,以降低控制台 I/O 开销。 - 有用的覆盖项: - - `OPENCLAW_E2E_WORKERS=` 强制 worker 数量(上限为 16)。 - - `OPENCLAW_E2E_VERBOSE=1` 重新启用详细控制台输出。 + - `OPENCLAW_E2E_WORKERS=` 用于强制 worker 数量(上限为 16)。 + - `OPENCLAW_E2E_VERBOSE=1` 用于重新启用详细控制台输出。 - 范围: - - 多实例 Gateway 网关端到端行为 - - WebSocket/HTTP 表面、节点配对和更重的网络处理 -- 预期: - - 在 CI 中运行(当 pipeline 启用时) - - 不需要真实密钥 - - 比单元测试有更多移动部件(可能更慢) + - 多实例 gateway 端到端行为 + - WebSocket/HTTP 表面、node 配对和更重型的网络 +- 期望: + - 在 CI 中运行(当 pipeline 中启用时) + - 不需要真实 key + - 比单元测试包含更多活动部件(可能更慢) -### E2E:OpenShell 后端冒烟测试 +### E2E:OpenShell 后端冒烟 - 命令:`pnpm test:e2e:openshell` - 文件:`extensions/openshell/src/backend.e2e.test.ts` - 范围: - - 通过 Docker 在主机上启动隔离的 OpenShell Gateway 网关 + - 通过 Docker 在主机上启动一个隔离的 OpenShell gateway - 从临时本地 Dockerfile 创建一个沙箱 - - 通过真实的 `sandbox ssh-config` + SSH exec 测试 OpenClaw 的 OpenShell 后端 - - 通过沙箱 fs bridge 验证远端规范文件系统行为 -- 预期: - - 仅 opt-in;不属于默认 `pnpm test:e2e` 运行的一部分 - - 需要本地 `openshell` CLI 和正常工作的 Docker daemon - - 使用隔离的 `HOME` / `XDG_CONFIG_HOME`,然后销毁测试 Gateway 网关和沙箱 + - 通过真实的 `sandbox ssh-config` + SSH exec 演练 OpenClaw 的 OpenShell 后端 + - 通过沙箱 fs bridge 验证远程 canonical 文件系统行为 +- 期望: + - 仅选择加入;不属于默认 `pnpm test:e2e` 运行 + - 需要本地 `openshell` CLI 以及可工作的 Docker daemon + - 使用隔离的 `HOME` / `XDG_CONFIG_HOME`,然后销毁测试 gateway 和沙箱 - 有用的覆盖项: - - `OPENCLAW_E2E_OPENSHELL=1` 在手动运行更广泛的 e2e 套件时启用该测试 - - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` 指向非默认 CLI 二进制文件或 wrapper script + - `OPENCLAW_E2E_OPENSHELL=1` 用于手动运行更广泛 e2e 套件时启用该测试 + - `OPENCLAW_E2E_OPENSHELL_COMMAND=/path/to/openshell` 用于指向非默认 CLI 二进制文件或 wrapper script ### Live(真实提供商 + 真实模型) - 命令:`pnpm test:live` - 配置:`vitest.live.config.ts` -- 文件:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下的内置插件 live 测试 +- 文件:`src/**/*.live.test.ts`、`test/**/*.live.test.ts`,以及 `extensions/` 下的 bundled-plugin live tests - 默认值:由 `pnpm test:live` **启用**(设置 `OPENCLAW_LIVE_TEST=1`) - 范围: - - “这个提供商/模型在 _今天_ 使用真实凭证时是否真的可用?” - - 捕获提供商格式变更、tool-calling 特性、认证问题和速率限制行为 -- 预期: - - 按设计不是 CI 稳定的(真实网络、真实提供商策略、配额、中断) - - 会花钱 / 使用速率限制额度 - - 更推荐运行缩窄后的子集,而不是“全部” + - “这个提供商/模型今天是否真的能用真实凭据工作?” + - 捕获提供商格式变更、工具调用细节、认证问题和速率限制行为 +- 期望: + - 设计上不保证 CI 稳定(真实网络、真实提供商策略、配额、故障) + - 会产生成本 / 使用速率限制 + - 优先运行缩窄后的子集,而不是“全部内容” - Live 运行会 source `~/.profile` 以获取缺失的 API key。 -- 默认情况下,live 运行仍会隔离 `HOME`,并将配置/认证材料复制到临时测试 home 中,因此单元 fixtures 无法修改你的真实 `~/.openclaw`。 -- 仅当你有意需要 live 测试使用真实 home 目录时,才设置 `OPENCLAW_LIVE_USE_REAL_HOME=1`。 -- `pnpm test:live` 现在默认使用更安静的模式:它保留 `[live] ...` 进度输出,但会抑制额外的 `~/.profile` 提示,并静音 Gateway 网关 bootstrap 日志/Bonjour chatter。如果你想恢复完整启动日志,请设置 `OPENCLAW_LIVE_TEST_QUIET=0`。 -- API key 轮换(按提供商):使用逗号/分号格式设置 `*_API_KEYS` 或 `*_API_KEY_1`、`*_API_KEY_2`(例如 `OPENAI_API_KEYS`、`ANTHROPIC_API_KEYS`、`GEMINI_API_KEYS`),或通过 `OPENCLAW_LIVE_*_KEY` 设置每次 live 覆盖;测试会在速率限制响应时重试。 +- 默认情况下,live 运行仍会隔离 `HOME`,并把 config/auth 材料复制到临时测试 home 中,因此单元 fixture 无法修改你真实的 `~/.openclaw`。 +- 仅当你有意需要 live tests 使用你的真实 home 目录时,才设置 `OPENCLAW_LIVE_USE_REAL_HOME=1`。 +- `pnpm test:live` 现在默认使用更安静的模式:它保留 `[live] ...` 进度输出,但会抑制额外的 `~/.profile` notice,并静音 gateway bootstrap 日志/Bonjour chatter。如果你想恢复完整启动日志,请设置 `OPENCLAW_LIVE_TEST_QUIET=0`。 +- API key 轮换(提供商特定):设置带逗号/分号格式的 `*_API_KEYS`,或 `*_API_KEY_1`、`*_API_KEY_2`(例如 `OPENAI_API_KEYS`、`ANTHROPIC_API_KEYS`、`GEMINI_API_KEYS`),也可通过 `OPENCLAW_LIVE_*_KEY` 设置每个 live 覆盖项;测试会在速率限制响应时重试。 - 进度/heartbeat 输出: - - Live 套件现在会向 stderr 发送进度行,因此即使 Vitest 控制台捕获处于安静状态,长时间提供商调用也会显示为活跃。 - - `vitest.live.config.ts` 会禁用 Vitest 控制台拦截,因此提供商/Gateway 网关进度行会在 live 运行期间立即流式输出。 + - Live 套件现在会向 stderr 发送进度行,因此即使 Vitest 控制台捕获处于安静状态,长时间的提供商调用也能明显显示为活跃。 + - `vitest.live.config.ts` 会禁用 Vitest 控制台拦截,因此提供商/gateway 进度行会在 live 运行期间立即流式输出。 - 使用 `OPENCLAW_LIVE_HEARTBEAT_MS` 调整 direct-model heartbeat。 - - 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 Gateway 网关/probe heartbeat。 + - 使用 `OPENCLAW_LIVE_GATEWAY_HEARTBEAT_MS` 调整 gateway/probe heartbeat。 ## 我应该运行哪个套件? -使用此决策表: +使用这个决策表: -- 编辑逻辑/测试:运行 `pnpm test`(如果你改动很多,也运行 `pnpm test:coverage`) -- 涉及 Gateway 网关网络 / WS 协议 / 配对:添加 `pnpm test:e2e` -- 调试“我的机器人宕机了”/ 提供商特定失败 / 工具调用:运行收窄范围的 `pnpm test:live` +- 编辑逻辑/测试:运行 `pnpm test`(如果你改动较多,也运行 `pnpm test:coverage`) +- 触碰 Gateway 网关网络 / WS 协议 / 配对:添加 `pnpm test:e2e` +- 调试“我的 bot 挂了”/ 提供商特定失败 / 工具调用:运行范围收窄的 `pnpm test:live` -## 真实(触网)测试 +## 实时(涉及网络)测试 -关于真实模型矩阵、CLI 后端冒烟测试、ACP 冒烟测试、Codex 应用服务器 -harness,以及所有媒体提供商真实测试(Deepgram、BytePlus、ComfyUI、图像、 -音乐、视频、媒体 harness)——再加上真实运行的凭证处理——请参阅 -[测试——真实套件](/zh-CN/help/testing-live)。 +对于实时模型矩阵、CLI 后端冒烟测试、ACP 冒烟测试、Codex 应用服务器 +harness,以及所有媒体提供商实时测试(Deepgram、BytePlus、ComfyUI、图像、 +音乐、视频、媒体 harness)——以及实时运行的凭证处理——请参阅 +[测试 — 实时套件](/zh-CN/help/testing-live)。 -## Docker 运行器(可选的“可在 Linux 中工作”检查) +## Docker 运行器(可选的“在 Linux 中可用”检查) -这些 Docker 运行器分成两类: +这些 Docker 运行器分为两类: -- 真实模型运行器:`test:docker:live-models` 和 `test:docker:live-gateway` 只会在仓库 Docker 镜像内运行各自匹配 profile-key 的真实文件(`src/agents/models.profiles.live.test.ts` 和 `src/gateway/gateway-models.profiles.live.test.ts`),并挂载你的本地配置目录和工作区(如果已挂载,还会 source `~/.profile`)。匹配的本地入口点是 `test:live:models-profiles` 和 `test:live:gateway-profiles`。 -- Docker 真实运行器默认使用较小的冒烟上限,让完整 Docker 扫描保持可行: - `test:docker:live-models` 默认使用 `OPENCLAW_LIVE_MAX_MODELS=12`,而 +- 实时模型运行器:`test:docker:live-models` 和 `test:docker:live-gateway` 只会在仓库 Docker 镜像中运行与其匹配的 profile-key 实时文件(`src/agents/models.profiles.live.test.ts` 和 `src/gateway/gateway-models.profiles.live.test.ts`),并挂载你的本地配置目录和工作区(如果已挂载,也会加载 `~/.profile`)。匹配的本地入口点是 `test:live:models-profiles` 和 `test:live:gateway-profiles`。 +- Docker 实时运行器默认使用较小的冒烟上限,因此完整 Docker 扫描仍然可行: + `test:docker:live-models` 默认使用 `OPENCLAW_LIVE_MAX_MODELS=12`,并且 `test:docker:live-gateway` 默认使用 `OPENCLAW_LIVE_GATEWAY_SMOKE=1`、 `OPENCLAW_LIVE_GATEWAY_MAX_MODELS=8`、 `OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=45000`,以及 - `OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`。当你明确需要更大的详尽扫描时,可以覆盖这些环境变量。 -- `test:docker:all` 会先通过 `test:docker:live-build` 构建一次真实 Docker 镜像,通过 `scripts/package-openclaw-for-docker.mjs` 将 OpenClaw 打包一次为 npm tarball,然后构建/复用两个 `scripts/e2e/Dockerfile` 镜像。基础镜像只是用于安装/更新/插件依赖通道的 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=10` 和 `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`;仅在 Docker 主机有更多余量时,才调优 `OPENCLAW_DOCKER_ALL_WEIGHT_LIMIT` 或 `OPENCLAW_DOCKER_ALL_DOCKER_LIMIT`。运行器默认执行 Docker 预检,移除陈旧的 OpenClaw E2E 容器,每 30 秒打印一次状态,将成功通道耗时存储到 `.artifacts/docker-tests/lane-timings.json`,并在后续运行中使用这些耗时优先启动更长的通道。使用 `OPENCLAW_DOCKER_ALL_DRY_RUN=1` 可打印加权通道清单而不构建或运行 Docker,或使用 `node scripts/test-docker-all.mjs --plan-json` 打印所选通道、包/镜像需求和凭证的 CI 计划。 -- `Package Acceptance` 是 GitHub 原生的包门禁,用于验证“这个可安装 tarball 作为产品能否正常工作?”它会从 `source=npm`、`source=ref`、`source=url` 或 `source=artifact` 解析一个候选包,将其作为 `package-under-test` 上传,然后针对该精确 tarball 运行可复用的 Docker E2E 通道,而不是重新打包所选 ref。`workflow_ref` 选择受信任的 workflow/harness 脚本,而 `package_ref` 在 `source=ref` 时选择要打包的源提交/分支/标签;这让当前验收逻辑能够验证较旧的受信任提交。配置档按覆盖范围排序:`smoke` 是快速安装/渠道/智能体加 Gateway 网关/配置,`package` 是包/更新/插件契约加无密钥 upgrade-survivor fixture、已发布基线升级幸存者通道,以及多数 Parallels 包/更新覆盖的默认原生替代项,`product` 添加 MCP 渠道、cron/subagent 清理、OpenAI web search 和 OpenWebUI,`full` 使用 OpenWebUI 运行发布路径 Docker 分块。发布验证会运行自定义包增量(`bundled-channel-deps-compat plugins-offline`)以及 Telegram 包 QA,因为发布路径 Docker 分块已经覆盖重叠的包/更新/插件通道。从制品生成的定向 GitHub Docker 重跑命令会在可用时包含先前的包制品和已准备镜像输入,这样失败通道就能避免重建包和镜像。 -- 构建和发布检查会在 tsdown 之后运行 `scripts/check-cli-bootstrap-imports.mjs`。该守卫会从 `dist/entry.js` 和 `dist/cli/run-main.js` 遍历静态构建图,并在命令分派前的启动导入了 Commander、提示 UI、undici 或日志等包依赖时失败;它还会让打包的 Gateway 网关运行分块保持在预算内,并拒绝已知冷启动 Gateway 网关路径的静态导入。打包后的 CLI 冒烟测试还覆盖根帮助、新手引导帮助、Doctor 帮助、Status、配置 schema 和一个模型列表命令。 -- Package Acceptance 旧版兼容性上限为 `2026.4.25`(包括 `2026.4.25-beta.*`)。在该截止版本之前,harness 只容忍已发布包的元数据缺口:省略的私有 QA 清单条目、缺失的 `gateway install --wrapper`、tarball 派生 git fixture 中缺失的补丁文件、缺失的持久化 `update.channel`、旧版插件安装记录位置、缺失的 marketplace 安装记录持久化,以及 `plugins update` 期间的配置元数据迁移。对于 `2026.4.25` 之后的包,这些路径都是严格失败。 -- 容器冒烟运行器:`test:docker:openwebui`、`test:docker:onboard`、`test:docker:npm-onboard-channel-agent`、`test:docker:update-channel-switch`、`test:docker:upgrade-survivor`、`test:docker:published-upgrade-survivor`、`test:docker:session-runtime-context`、`test:docker:agents-delete-shared-workspace`、`test:docker:gateway-network`、`test:docker:browser-cdp-snapshot`、`test:docker:mcp-channels`、`test:docker:pi-bundle-mcp-tools`、`test:docker:cron-mcp-cleanup`、`test:docker:plugins`、`test:docker:plugin-update` 和 `test:docker:config-reload` 会启动一个或多个真实容器,并验证更高层级的集成路径。 + `OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=90000`。当你明确想要更大的穷尽式扫描时, + 覆盖这些环境变量。 +- `test:docker:all` 通过 `test:docker:live-build` 构建一次实时 Docker 镜像,通过 `scripts/package-openclaw-for-docker.mjs` 将 OpenClaw 打包一次为 npm tarball,然后构建/复用两个 `scripts/e2e/Dockerfile` 镜像。基础镜像只是用于安装/更新/插件依赖 lane 的 Node/Git 运行器;这些 lane 会挂载预构建的 tarball。功能镜像会将同一个 tarball 安装到 `/app`,用于已构建应用的功能 lane。Docker lane 定义位于 `scripts/lib/docker-e2e-scenarios.mjs`;规划器逻辑位于 `scripts/lib/docker-e2e-plan.mjs`;`scripts/test-docker-all.mjs` 执行选定计划。聚合运行器使用加权本地调度器:`OPENCLAW_DOCKER_ALL_PARALLELISM` 控制进程槽位,而资源上限会避免重型实时、npm 安装和多服务 lane 同时全部启动。如果单个 lane 比当前上限更重,调度器仍可在池为空时启动它,然后让它独占运行,直到容量再次可用。默认值为 10 个槽位、`OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`、`OPENCLAW_DOCKER_ALL_NPM_LIMIT=10` 和 `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`;只有当 Docker 主机有更多余量时,才调整 `OPENCLAW_DOCKER_ALL_WEIGHT_LIMIT` 或 `OPENCLAW_DOCKER_ALL_DOCKER_LIMIT`。运行器默认执行 Docker 预检,移除陈旧的 OpenClaw E2E 容器,每 30 秒打印一次状态,将成功 lane 的耗时存储在 `.artifacts/docker-tests/lane-timings.json`,并在后续运行中使用这些耗时来优先启动较长的 lane。使用 `OPENCLAW_DOCKER_ALL_DRY_RUN=1` 可以打印加权 lane 清单,而不构建或运行 Docker;或使用 `node scripts/test-docker-all.mjs --plan-json` 打印所选 lane、包/镜像需求和凭证的 CI 计划。 +- `Package Acceptance` 是 GitHub 原生的包门禁,用于回答“这个可安装的 tarball 作为产品是否可用?”它会从 `source=npm`、`source=ref`、`source=url` 或 `source=artifact` 解析一个候选包,将其上传为 `package-under-test`,然后针对这个精确的 tarball 运行可复用的 Docker E2E lane,而不是重新打包所选 ref。`workflow_ref` 选择可信的 workflow/harness 脚本,而 `package_ref` 在 `source=ref` 时选择要打包的源提交/分支/标签;这使当前验收逻辑可以验证较旧的可信提交。Profile 按覆盖范围排序:`smoke` 是快速安装/渠道/智能体加 Gateway 网关/配置,`package` 是包/更新/插件契约加无密钥升级存活夹具、已发布基线升级存活 lane,以及大多数 Parallels 包/更新覆盖的默认原生替代项,`product` 添加 MCP 渠道、cron/子智能体清理、OpenAI web 搜索和 OpenWebUI,`full` 使用 OpenWebUI 运行发布路径 Docker 分块。对于 `published-upgrade-survivor`,Package Acceptance 始终使用 `package-under-test` 作为候选包,并使用 `published_upgrade_survivor_baseline` 作为已发布基线,默认值为 `openclaw@latest`;通过分派多次带有精确基线值的运行来分片更广覆盖。已发布 lane 使用内置的 `openclaw config set` 命令配方配置其基线,然后在 lane 摘要中记录配方步骤。发布验证运行自定义包增量(`bundled-channel-deps-compat plugins-offline`)加 Telegram 包 QA,因为发布路径 Docker 分块已经覆盖重叠的包/更新/插件 lane。从工件生成的定向 GitHub Docker 重跑命令包含先前的包工件、预准备镜像输入,以及可用时的已发布升级存活基线,因此失败的 lane 可以避免重新构建包和镜像。 +- 构建和发布检查会在 tsdown 之后运行 `scripts/check-cli-bootstrap-imports.mjs`。该防护会从 `dist/entry.js` 和 `dist/cli/run-main.js` 遍历静态构建图,如果命令分派前的启动阶段导入了 Commander、prompt UI、undici 或日志等包依赖,就会失败;它还会将打包的 Gateway 网关运行分块保持在预算内,并拒绝对已知冷启动 Gateway 网关路径的静态导入。打包后的 CLI 冒烟测试还覆盖根帮助、新手引导帮助、Doctor 帮助、Status、配置 schema,以及模型列表命令。 +- Package Acceptance 旧版兼容性上限为 `2026.4.25`(包括 `2026.4.25-beta.*`)。在该截止版本之前,harness 只容忍已发布包的元数据缺口:省略的私有 QA 清单条目、缺失的 `gateway install --wrapper`、tarball 派生 git 夹具中缺失的补丁文件、缺失的持久化 `update.channel`、旧版插件安装记录位置、缺失的 marketplace 安装记录持久化,以及 `plugins update` 期间的配置元数据迁移。对于 `2026.4.25` 之后的包,这些路径都是严格失败。 +- 容器冒烟运行器:`test:docker:openwebui`、`test:docker:onboard`、`test:docker:npm-onboard-channel-agent`、`test:docker:update-channel-switch`、`test:docker:upgrade-survivor`、`test:docker:published-upgrade-survivor`、`test:docker:session-runtime-context`、`test:docker:agents-delete-shared-workspace`、`test:docker:gateway-network`、`test:docker:browser-cdp-snapshot`、`test:docker:mcp-channels`、`test:docker:pi-bundle-mcp-tools`、`test:docker:cron-mcp-cleanup`、`test:docker:plugins`、`test:docker:plugin-update` 和 `test:docker:config-reload` 会启动一个或多个真实容器,并验证更高层的集成路径。 -真实模型 Docker 运行器还只会 bind-mount 所需的 CLI 认证 home(如果运行未收窄,则挂载所有受支持的 home),然后在运行前把它们复制到容器 home 中,这样外部 CLI OAuth 就能刷新令牌,而不会修改主机认证存储: +实时模型 Docker 运行器还只会绑定挂载所需的 CLI 认证 home(或在运行未收窄时挂载所有受支持的 home),然后在运行前将它们复制到容器 home 中,使外部 CLI OAuth 可以刷新令牌而不改变主机认证存储: - 直接模型:`pnpm test:docker:live-models`(脚本:`scripts/test-live-models-docker.sh`) -- ACP 绑定冒烟测试:`pnpm test:docker:live-acp-bind`(脚本:`scripts/test-live-acp-bind-docker.sh`;默认覆盖 Claude、Codex 和 Gemini,并通过 `pnpm test:docker:live-acp-bind:droid` 和 `pnpm test:docker:live-acp-bind:opencode` 严格覆盖 Droid/OpenCode) -- CLI 后端冒烟测试:`pnpm test:docker:live-cli-backend`(脚本:`scripts/test-live-cli-backend-docker.sh`) -- Codex app-server harness 冒烟测试:`pnpm test:docker:live-codex-harness`(脚本:`scripts/test-live-codex-harness-docker.sh`) +- ACP 绑定冒烟:`pnpm test:docker:live-acp-bind`(脚本:`scripts/test-live-acp-bind-docker.sh`;默认覆盖 Claude、Codex 和 Gemini,并通过 `pnpm test:docker:live-acp-bind:droid` 和 `pnpm test:docker:live-acp-bind:opencode` 严格覆盖 Droid/OpenCode) +- CLI 后端冒烟:`pnpm test:docker:live-cli-backend`(脚本:`scripts/test-live-cli-backend-docker.sh`) +- Codex 应用服务器 harness 冒烟:`pnpm test:docker:live-codex-harness`(脚本:`scripts/test-live-codex-harness-docker.sh`) - Gateway 网关 + 开发智能体:`pnpm test:docker:live-gateway`(脚本:`scripts/test-live-gateway-models-docker.sh`) -- 可观测性冒烟测试:`pnpm qa:otel:smoke` 是私有 QA 源码检出通道。它有意不属于包 Docker 发布通道,因为 npm tarball 会省略 QA 实验室。 -- Open WebUI 实时冒烟测试:`pnpm test:docker:openwebui`(脚本:`scripts/e2e/openwebui-docker.sh`) +- 可观测性冒烟:`pnpm qa:otel:smoke` 是私有 QA 源码检出通道。它有意不属于包 Docker 发布通道,因为 npm tarball 省略了 QA Lab。 +- Open WebUI 实时冒烟:`pnpm test:docker:openwebui`(脚本:`scripts/e2e/openwebui-docker.sh`) - 新手引导向导(TTY,完整脚手架):`pnpm test:docker:onboard`(脚本:`scripts/e2e/onboard-docker.sh`) -- npm tarball 新手引导/渠道/智能体冒烟测试:`pnpm test:docker:npm-onboard-channel-agent` 会在 Docker 中全局安装打包后的 OpenClaw tarball,通过 env-ref 新手引导配置 OpenAI,并默认配置 Telegram,验证 Doctor 是否修复已激活插件运行时依赖,然后运行一次模拟的 OpenAI 智能体轮次。可用 `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,用 `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` 跳过主机重建,或用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 切换渠道。 -- 更新渠道切换冒烟测试:`pnpm test:docker:update-channel-switch` 会在 Docker 中全局安装打包后的 OpenClaw tarball,从包 `stable` 切换到 git `dev`,验证持久化渠道和插件更新后工作正常,然后切回包 `stable` 并检查更新 Status。 -- 升级存活冒烟测试:`pnpm test:docker:upgrade-survivor` 会把打包后的 OpenClaw tarball 安装到带有脏旧用户夹具的环境上,该夹具包含智能体、渠道配置、插件 allowlist、过期的插件运行时依赖状态,以及既有工作区/会话文件。它会在没有实时提供商或渠道密钥的情况下运行包更新和非交互式 Doctor,然后启动一个 loopback Gateway 网关,并检查配置/状态保留以及启动/Status 预算。 -- 已发布版本升级存活冒烟测试:`pnpm test:docker:published-upgrade-survivor` 默认把 `openclaw@latest` 安装到同一个脏旧用户夹具上,将该已发布安装更新到候选 tarball,运行非交互式 Doctor,然后启动一个 loopback Gateway 网关,并检查相同的配置/状态保留以及启动/Status 预算。可用 `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC` 覆盖基线。 -- 会话运行时上下文冒烟测试:`pnpm test:docker:session-runtime-context` 验证隐藏运行时上下文转录持久化,以及 Doctor 对受影响的重复 prompt-rewrite 分支的修复。 -- Bun 全局安装冒烟测试:`bash scripts/e2e/bun-global-install-smoke.sh` 会打包当前树,在隔离 home 中用 `bun install -g` 安装它,并验证 `openclaw infer image providers --json` 返回内置图像提供商而不是挂起。可用 `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,用 `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0` 跳过主机构建,或用 `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local` 从已构建的 Docker 镜像复制 `dist/`。 -- 安装器 Docker 冒烟测试:`bash scripts/test-install-sh-docker.sh` 会在其 root、update 和 direct-npm 容器之间共享一个 npm 缓存。更新冒烟测试默认使用 npm `latest` 作为升级到候选 tarball 之前的 stable 基线。本地可用 `OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22` 覆盖,或在 GitHub 上用 Install Smoke 工作流的 `update_baseline_version` 输入覆盖。非 root 安装器检查会保留隔离的 npm 缓存,避免 root 拥有的缓存条目掩盖用户本地安装行为。设置 `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache` 可在本地重跑时复用 root/update/direct-npm 缓存。 -- Install Smoke CI 会用 `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1` 跳过重复的 direct-npm 全局更新;需要覆盖直接 `npm install -g` 时,在本地运行脚本且不要设置该环境变量。 -- 智能体删除共享工作区 CLI 冒烟测试:`pnpm test:docker:agents-delete-shared-workspace`(脚本:`scripts/e2e/agents-delete-shared-workspace-docker.sh`)默认构建根 Dockerfile 镜像,在隔离容器 home 中为两个智能体播种一个工作区,运行 `agents delete --json`,并验证 JSON 有效以及保留工作区行为。可用 `OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE=openclaw-dockerfile-smoke:local OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD=1` 复用 install-smoke 镜像。 +- Npm tarball 新手引导/渠道/智能体冒烟:`pnpm test:docker:npm-onboard-channel-agent` 会在 Docker 中全局安装打包后的 OpenClaw tarball,通过 env-ref 新手引导配置 OpenAI 并默认配置 Telegram,验证 Doctor 修复已激活插件的运行时依赖,并运行一次模拟的 OpenAI 智能体轮次。使用 `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,使用 `OPENCLAW_NPM_ONBOARD_HOST_BUILD=0` 跳过主机重建,或使用 `OPENCLAW_NPM_ONBOARD_CHANNEL=discord` 切换渠道。 +- 更新渠道切换冒烟:`pnpm test:docker:update-channel-switch` 会在 Docker 中全局安装打包后的 OpenClaw tarball,从包 `stable` 切换到 git `dev`,验证持久化的渠道和插件更新后工作正常,然后切回包 `stable` 并检查更新 Status。 +- 升级幸存者冒烟:`pnpm test:docker:upgrade-survivor` 会在一个包含智能体、渠道配置、插件允许列表、陈旧插件运行时依赖状态以及现有工作区/会话文件的脏旧用户 fixture 上安装打包后的 OpenClaw tarball。它在没有实时提供商或渠道密钥的情况下运行包更新和非交互式 Doctor,然后启动一个 loopback Gateway 网关,并检查配置/状态保留以及启动/Status 预算。 +- 已发布升级幸存者冒烟:`pnpm test:docker:published-upgrade-survivor` 默认安装 `openclaw@latest`,播种真实的现有用户文件,用内置命令配方配置该基线,验证生成的配置,将该已发布安装更新到候选 tarball,运行非交互式 Doctor,写入 `.artifacts/upgrade-survivor/summary.json`,然后启动一个 loopback Gateway 网关,并检查已配置意图、状态保留、启动和 Status 预算。使用 `OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC` 覆盖基线;Package Acceptance 将同一值公开为 `published_upgrade_survivor_baseline`。 +- 会话运行时上下文冒烟:`pnpm test:docker:session-runtime-context` 验证隐藏运行时上下文转录持久化,以及 Doctor 对受影响重复 prompt-rewrite 分支的修复。 +- Bun 全局安装冒烟:`bash scripts/e2e/bun-global-install-smoke.sh` 会打包当前树,在隔离 home 中用 `bun install -g` 安装,并验证 `openclaw infer image providers --json` 返回内置图像提供商而不是挂起。使用 `OPENCLAW_BUN_GLOBAL_SMOKE_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 复用预构建 tarball,使用 `OPENCLAW_BUN_GLOBAL_SMOKE_HOST_BUILD=0` 跳过主机构建,或使用 `OPENCLAW_BUN_GLOBAL_SMOKE_DIST_IMAGE=openclaw-dockerfile-smoke:local` 从已构建的 Docker 镜像复制 `dist/`。 +- 安装器 Docker 冒烟:`bash scripts/test-install-sh-docker.sh` 会在其 root、update 和 direct-npm 容器之间共享一个 npm 缓存。更新冒烟默认以 npm `latest` 作为稳定基线,再升级到候选 tarball。本地使用 `OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE=2026.4.22` 覆盖,或在 GitHub 上使用 Install Smoke 工作流的 `update_baseline_version` 输入覆盖。非 root 安装器检查会保留隔离的 npm 缓存,因此 root 所有的缓存条目不会掩盖用户本地安装行为。设置 `OPENCLAW_INSTALL_SMOKE_NPM_CACHE_DIR=/path/to/cache` 可在本地重跑之间复用 root/update/direct-npm 缓存。 +- Install Smoke CI 使用 `OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL=1` 跳过重复的 direct-npm 全局更新;当需要直接 `npm install -g` 覆盖时,在本地运行脚本且不要设置该环境变量。 +- 智能体删除共享工作区 CLI 冒烟:`pnpm test:docker:agents-delete-shared-workspace`(脚本:`scripts/e2e/agents-delete-shared-workspace-docker.sh`)默认构建根 Dockerfile 镜像,在隔离容器 home 中播种两个智能体和一个工作区,运行 `agents delete --json`,并验证有效 JSON 以及保留工作区行为。使用 `OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_IMAGE=openclaw-dockerfile-smoke:local OPENCLAW_AGENTS_DELETE_SHARED_WORKSPACE_E2E_SKIP_BUILD=1` 复用 install-smoke 镜像。 - Gateway 网关网络(两个容器,WS 认证 + 健康检查):`pnpm test:docker:gateway-network`(脚本:`scripts/e2e/gateway-network-docker.sh`) -- 浏览器 CDP 快照冒烟测试:`pnpm test:docker:browser-cdp-snapshot`(脚本:`scripts/e2e/browser-cdp-snapshot-docker.sh`)构建源码 E2E 镜像和 Chromium 层,用原始 CDP 启动 Chromium,运行 `browser doctor --deep`,并验证 CDP 角色快照覆盖链接 URL、光标提升的可点击项、iframe 引用和 frame 元数据。 -- OpenAI Responses web_search minimal reasoning 回归测试:`pnpm test:docker:openai-web-search-minimal`(脚本:`scripts/e2e/openai-web-search-minimal-docker.sh`)通过 Gateway 网关运行模拟的 OpenAI 服务器,验证 `web_search` 会把 `reasoning.effort` 从 `minimal` 提升到 `low`,然后强制提供商 schema 拒绝,并检查原始详情出现在 Gateway 网关日志中。 -- MCP 渠道桥接(已播种 Gateway 网关 + stdio bridge + 原始 Claude notification-frame 冒烟测试):`pnpm test:docker:mcp-channels`(脚本:`scripts/e2e/mcp-channels-docker.sh`) -- Pi bundle MCP 工具(真实 stdio MCP 服务器 + 嵌入式 Pi 配置文件允许/拒绝冒烟测试):`pnpm test:docker:pi-bundle-mcp-tools`(脚本:`scripts/e2e/pi-bundle-mcp-tools-docker.sh`) -- Cron/subagent MCP 清理(真实 Gateway 网关 + 在隔离 cron 和一次性 subagent 运行后拆除 stdio MCP 子进程):`pnpm test:docker:cron-mcp-cleanup`(脚本:`scripts/e2e/cron-mcp-cleanup-docker.sh`) -- 插件(安装冒烟测试、ClawHub kitchen-sink 安装/卸载、marketplace 更新,以及 Claude-bundle 启用/检查):`pnpm test:docker:plugins`(脚本:`scripts/e2e/plugins-docker.sh`) - 设置 `OPENCLAW_PLUGINS_E2E_CLAWHUB=0` 可跳过 ClawHub 块,或用 `OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC` 和 `OPENCLAW_PLUGINS_E2E_CLAWHUB_ID` 覆盖默认的 kitchen-sink 包/运行时组合。没有 `OPENCLAW_CLAWHUB_URL`/`CLAWHUB_URL` 时,测试会使用 hermetic 本地 ClawHub 夹具服务器。 -- 插件更新未变更冒烟测试:`pnpm test:docker:plugin-update`(脚本:`scripts/e2e/plugin-update-unchanged-docker.sh`) -- 配置 reload 元数据冒烟测试:`pnpm test:docker:config-reload`(脚本:`scripts/e2e/config-reload-source-docker.sh`) -- 内置插件运行时依赖:`pnpm test:docker:bundled-channel-deps` 默认构建一个小型 Docker runner 镜像,在主机上构建并打包 OpenClaw 一次,然后把该 tarball 挂载到每个 Linux 安装场景中。可用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 复用镜像,在一次新的本地构建后用 `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0` 跳过主机重建,或用 `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 指向既有 tarball。完整 Docker 聚合和发布路径的 bundled-channel 分块会先预打包此 tarball 一次,然后把内置渠道检查分片到独立通道中,包括 Telegram、Discord、Slack、Feishu、memory-lancedb 和 ACPX 的独立更新通道。发布分块会把渠道冒烟测试、更新目标以及设置/运行时合约拆分到 `bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-b` 和 `bundled-channels-contracts`;聚合 `bundled-channels` 分块仍可用于手动重跑。发布工作流还会拆分提供商安装器分块和内置插件安装/卸载分块;旧版 `package-update`、`plugins-runtime` 和 `plugins-integrations` 分块仍作为手动重跑的聚合别名保留。直接运行内置通道时,可用 `OPENCLAW_BUNDLED_CHANNELS=telegram,slack` 缩小渠道矩阵,或用 `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx` 缩小更新场景。每个场景的 Docker 运行默认使用 `OPENCLAW_BUNDLED_CHANNEL_DOCKER_RUN_TIMEOUT=900s`;多目标更新场景默认使用 `OPENCLAW_BUNDLED_CHANNEL_UPDATE_DOCKER_RUN_TIMEOUT=2400s`。该通道还会验证 `channels..enabled=false` 和 `plugins.entries..enabled=false` 会抑制 Doctor/运行时依赖修复。 -- 迭代时可通过禁用无关场景来缩小内置插件运行时依赖,例如: +- 浏览器 CDP 快照冒烟:`pnpm test:docker:browser-cdp-snapshot`(脚本:`scripts/e2e/browser-cdp-snapshot-docker.sh`)构建源 E2E 镜像和一个 Chromium 层,使用原始 CDP 启动 Chromium,运行 `browser doctor --deep`,并验证 CDP 角色快照覆盖链接 URL、光标提升的可点击项、iframe 引用和 frame 元数据。 +- OpenAI Responses web_search 最小推理回归:`pnpm test:docker:openai-web-search-minimal`(脚本:`scripts/e2e/openai-web-search-minimal-docker.sh`)通过 Gateway 网关运行模拟的 OpenAI 服务器,验证 `web_search` 将 `reasoning.effort` 从 `minimal` 提升到 `low`,然后强制提供商 schema 拒绝,并检查原始详情出现在 Gateway 网关日志中。 +- MCP 渠道桥接(播种的 Gateway 网关 + stdio 桥接 + 原始 Claude notification-frame 冒烟):`pnpm test:docker:mcp-channels`(脚本:`scripts/e2e/mcp-channels-docker.sh`) +- Pi bundle MCP 工具(真实 stdio MCP 服务器 + 嵌入式 Pi 配置文件允许/拒绝冒烟):`pnpm test:docker:pi-bundle-mcp-tools`(脚本:`scripts/e2e/pi-bundle-mcp-tools-docker.sh`) +- Cron/子智能体 MCP 清理(真实 Gateway 网关 + 在隔离 cron 和一次性子智能体运行后拆除 stdio MCP 子进程):`pnpm test:docker:cron-mcp-cleanup`(脚本:`scripts/e2e/cron-mcp-cleanup-docker.sh`) +- 插件(安装冒烟、ClawHub kitchen-sink 安装/卸载、marketplace 更新,以及 Claude-bundle 启用/检查):`pnpm test:docker:plugins`(脚本:`scripts/e2e/plugins-docker.sh`) + 设置 `OPENCLAW_PLUGINS_E2E_CLAWHUB=0` 跳过 ClawHub 块,或使用 `OPENCLAW_PLUGINS_E2E_CLAWHUB_SPEC` 和 `OPENCLAW_PLUGINS_E2E_CLAWHUB_ID` 覆盖默认的 kitchen-sink 包/运行时组合。没有 `OPENCLAW_CLAWHUB_URL`/`CLAWHUB_URL` 时,测试会使用密闭的本地 ClawHub fixture 服务器。 +- 插件更新未变化冒烟:`pnpm test:docker:plugin-update`(脚本:`scripts/e2e/plugin-update-unchanged-docker.sh`) +- 配置重载元数据冒烟:`pnpm test:docker:config-reload`(脚本:`scripts/e2e/config-reload-source-docker.sh`) +- 内置插件运行时依赖:`pnpm test:docker:bundled-channel-deps` 默认构建一个小型 Docker runner 镜像,在主机上构建并打包一次 OpenClaw,然后把该 tarball 挂载到每个 Linux 安装场景中。使用 `OPENCLAW_SKIP_DOCKER_BUILD=1` 复用镜像,在新的本地构建后使用 `OPENCLAW_BUNDLED_CHANNEL_HOST_BUILD=0` 跳过主机重建,或用 `OPENCLAW_CURRENT_PACKAGE_TGZ=/path/to/openclaw-*.tgz` 指向现有 tarball。完整 Docker 聚合和发布路径的 bundled-channel 分块会预先打包该 tarball 一次,然后将内置渠道检查分片到独立通道,包括 Telegram、Discord、Slack、Feishu、memory-lancedb 和 ACPX 的单独更新通道。发布分块将渠道冒烟、更新目标和设置/运行时契约拆分为 `bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-b` 和 `bundled-channels-contracts`;聚合 `bundled-channels` 分块仍可用于手动重跑。发布工作流还会拆分提供商安装器分块和内置插件安装/卸载分块;旧版 `package-update`、`plugins-runtime` 和 `plugins-integrations` 分块仍作为手动重跑的聚合别名保留。直接运行内置通道时,使用 `OPENCLAW_BUNDLED_CHANNELS=telegram,slack` 缩小渠道矩阵,或使用 `OPENCLAW_BUNDLED_CHANNEL_UPDATE_TARGETS=telegram,acpx` 缩小更新场景。每个场景的 Docker 运行默认使用 `OPENCLAW_BUNDLED_CHANNEL_DOCKER_RUN_TIMEOUT=900s`;多目标更新场景默认使用 `OPENCLAW_BUNDLED_CHANNEL_UPDATE_DOCKER_RUN_TIMEOUT=2400s`。该通道还验证 `channels..enabled=false` 和 `plugins.entries..enabled=false` 会抑制 Doctor/运行时依赖修复。 +- 迭代时可通过禁用无关场景来缩小内置插件运行时依赖范围,例如: `OPENCLAW_BUNDLED_CHANNEL_SCENARIOS=0 OPENCLAW_BUNDLED_CHANNEL_UPDATE_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_ROOT_OWNED_SCENARIO=0 OPENCLAW_BUNDLED_CHANNEL_SETUP_ENTRY_SCENARIO=0 pnpm test:docker:bundled-channel-deps`。 要手动预构建并复用共享功能镜像: @@ -552,114 +560,116 @@ OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local pnpm test:docker: OPENCLAW_DOCKER_E2E_IMAGE=openclaw-docker-e2e-functional:local OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-channels ``` -设置了 `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE` 等套件专用镜像覆盖项时,它们仍然优先。当 `OPENCLAW_SKIP_DOCKER_BUILD=1` 指向远程共享镜像时,如果该镜像尚不在本地,脚本会拉取它。QR 和安装器 Docker 测试会保留自己的 Dockerfile,因为它们验证的是包/安装行为,而不是共享的已构建应用运行时。 +设置了 `OPENCLAW_GATEWAY_NETWORK_E2E_IMAGE` 等套件特定镜像覆盖时,它们仍然优先。当 `OPENCLAW_SKIP_DOCKER_BUILD=1` 指向远程共享镜像时,如果本地尚不存在,脚本会拉取它。QR 和安装器 Docker 测试保留自己的 Dockerfile,因为它们验证的是包/安装行为,而不是共享构建应用运行时。 -实时模型 Docker 运行器还会以只读方式绑定挂载当前检出内容,并将其 -暂存到容器内的临时工作目录。这样能保持运行时镜像精简,同时仍然用你的 -精确本地源代码/配置运行 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 网关实时覆盖范围时,也要传入 +实时模型 Docker runner 还会以只读方式 bind-mount 当前 checkout,并将其 +暂存到容器内的临时 workdir 中。这样可以保持运行时镜像精简,同时仍针对你的精确本地源码/配置运行 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` 代理发送真实聊天请求。 +OpenAI 兼容 HTTP 端点的 +OpenClaw Gateway 网关容器, +再启动一个固定版本的 Open WebUI 容器并连接到该 Gateway 网关,通过 +Open WebUI 登录,验证 `/api/models` 暴露 `openclaw/default`,然后通过 Open WebUI 的 +`/api/chat/completions` 代理发送一个 +真实聊天请求。 首次运行可能明显更慢,因为 Docker 可能需要拉取 -Open WebUI 镜像,而 Open WebUI 也可能需要完成自身的冷启动设置。 -此 lane 需要可用的实时模型密钥,`OPENCLAW_PROFILE_FILE` -(默认是 `~/.profile`)是在 Docker 化运行中提供它的主要方式。 -成功运行会打印一个小型 JSON 载荷,例如 `{ "ok": true, "model": +Open WebUI 镜像,并且 Open WebUI 可能需要完成自己的冷启动设置。 +这个 lane 需要一个可用的实时模型密钥,而 `OPENCLAW_PROFILE_FILE` +(默认 `~/.profile`)是在 Docker 化运行中提供它的主要方式。 +成功运行会打印一个小型 JSON payload,例如 `{ "ok": true, "model": "openclaw/default", ... }`。 -`test:docker:mcp-channels` 刻意设计为确定性的,不需要 -真实的 Telegram、Discord 或 iMessage 账号。它会启动一个带种子的 Gateway 网关 -容器,启动第二个容器来生成 `openclaw mcp serve`,然后 -验证已路由会话发现、转录读取、附件元数据、 -实时事件队列行为、出站发送路由,以及通过真实 stdio MCP bridge 发送的 Claude 风格渠道 + -权限通知。通知检查会直接检查原始 stdio MCP 帧,因此该冒烟测试验证的是 +`test:docker:mcp-channels` 是有意保持确定性的,不需要 +真实的 Telegram、Discord 或 iMessage 账户。它会启动一个带种子的 Gateway 网关 +容器,启动第二个容器来派生 `openclaw mcp serve`,然后 +验证路由后的会话发现、transcript 读取、附件元数据、 +实时事件队列行为、出站发送路由,以及通过真实 stdio MCP bridge 传递的 Claude 风格渠道 + +权限通知。通知检查会直接检查原始 stdio MCP frame,因此该冒烟测试验证的是 bridge 实际发出的内容,而不只是某个特定客户端 SDK 恰好暴露的内容。 `test:docker:pi-bundle-mcp-tools` 是确定性的,不需要实时 -模型密钥。它会构建仓库 Docker 镜像,在容器内启动一个真实 stdio MCP 探测服务器, -通过嵌入式 Pi bundle MCP 运行时物化该服务器, -执行工具,然后验证 `coding` 和 `messaging` 会保留 +模型密钥。它会构建 repo Docker 镜像,在容器内启动真实的 stdio MCP probe server, +通过嵌入的 Pi bundle +MCP 运行时物化该 server,执行该工具,然后验证 `coding` 和 `messaging` 会保留 `bundle-mcp` 工具,而 `minimal` 和 `tools.deny: ["bundle-mcp"]` 会过滤它们。 `test:docker:cron-mcp-cleanup` 是确定性的,不需要实时模型 -密钥。它会启动一个带种子的 Gateway 网关和一个真实 stdio MCP 探测服务器,运行一次 -隔离的 cron turn 和一次 `/subagents spawn` 一次性子 turn,然后验证 -MCP 子进程会在每次运行后退出。 +密钥。它会启动一个带种子的 Gateway 网关和真实的 stdio MCP probe server,运行一个 +隔离的 cron turn 和一个 `/subagents spawn` 一次性 child turn,然后验证 +MCP child process 会在每次运行后退出。 -手动 ACP 自然语言线程冒烟测试(非 CI): +手动 ACP 自然语言 thread 冒烟测试(非 CI): - `bun scripts/dev/discord-acp-plain-language-smoke.ts --channel ...` -- 保留此脚本用于回归/调试工作流。ACP 线程路由验证以后可能还会再次需要它,所以不要删除它。 +- 保留这个脚本用于回归/调试工作流。ACP thread 路由验证以后可能还会需要它,因此不要删除它。 有用的环境变量: - `OPENCLAW_CONFIG_DIR=...`(默认:`~/.openclaw`)挂载到 `/home/node/.openclaw` - `OPENCLAW_WORKSPACE_DIR=...`(默认:`~/.openclaw/workspace`)挂载到 `/home/node/.openclaw/workspace` - `OPENCLAW_PROFILE_FILE=...`(默认:`~/.profile`)挂载到 `/home/node/.profile`,并在运行测试前 source -- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` 用于仅验证从 `OPENCLAW_PROFILE_FILE` source 的环境变量,使用临时配置/工作区目录,且不挂载外部 CLI 认证 -- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...`(默认:`~/.cache/openclaw/docker-cli-tools`)挂载到 `/home/node/.npm-global`,用于 Docker 内缓存 CLI 安装 -- `$HOME` 下的外部 CLI 认证目录/文件会以只读方式挂载到 `/host-auth...` 下,然后在测试开始前复制到 `/home/node/...` +- `OPENCLAW_DOCKER_PROFILE_ENV_ONLY=1` 用于仅验证从 `OPENCLAW_PROFILE_FILE` source 的环境变量,使用临时配置/workspace 目录,且不挂载外部 CLI auth +- `OPENCLAW_DOCKER_CLI_TOOLS_DIR=...`(默认:`~/.cache/openclaw/docker-cli-tools`)挂载到 `/home/node/.npm-global`,用于 Docker 内部缓存 CLI 安装 +- `$HOME` 下的外部 CLI auth 目录/文件会以只读方式挂载到 `/host-auth...` 下,然后在测试开始前复制到 `/home/node/...` - 默认目录:`.minimax` - 默认文件:`~/.codex/auth.json`、`~/.codex/config.toml`、`.claude.json`、`~/.claude/.credentials.json`、`~/.claude/settings.json`、`~/.claude/settings.local.json` - - 缩小范围的提供商运行只会挂载从 `OPENCLAW_LIVE_PROVIDERS` / `OPENCLAW_LIVE_GATEWAY_PROVIDERS` 推断出的所需目录/文件 - - 可用 `OPENCLAW_DOCKER_AUTH_DIRS=all`、`OPENCLAW_DOCKER_AUTH_DIRS=none`,或类似 `OPENCLAW_DOCKER_AUTH_DIRS=.claude,.codex` 的逗号列表手动覆盖 -- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` 用于缩小运行范围 + - 缩窄后的提供商运行只会挂载从 `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` 用于确保凭据来自 profile 存储(而不是环境变量) +- `OPENCLAW_SKIP_DOCKER_BUILD=1` 用于在不需要重新构建的重复运行中复用现有 `openclaw:local-live` 镜像 +- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` 用于确保凭据来自 profile store(而不是 env) - `OPENCLAW_OPENWEBUI_MODEL=...` 用于选择 Gateway 网关为 Open WebUI 冒烟测试暴露的模型 -- `OPENCLAW_OPENWEBUI_PROMPT=...` 用于覆盖 Open WebUI 冒烟测试使用的 nonce 检查提示 -- `OPENWEBUI_IMAGE=...` 用于覆盖固定的 Open WebUI 镜像标签 +- `OPENCLAW_OPENWEBUI_PROMPT=...` 用于覆盖 Open WebUI 冒烟测试使用的 nonce-check prompt +- `OPENWEBUI_IMAGE=...` 用于覆盖固定的 Open WebUI 镜像 tag ## 文档完整性检查 文档编辑后运行文档检查:`pnpm check:docs`。 -当你还需要页内标题检查时,运行完整 Mintlify 锚点验证:`pnpm docs:check-links:anchors`。 +当你也需要页内标题检查时,运行完整的 Mintlify anchor 验证:`pnpm docs:check-links:anchors`。 ## 离线回归(CI 安全) -这些是没有真实提供商的“真实流水线”回归: +这些是不使用真实提供商的“真实 pipeline”回归: -- Gateway 网关工具调用(模拟 OpenAI,真实 Gateway 网关 + Agent loop):`src/gateway/gateway.test.ts`(用例:"runs a mock OpenAI tool call end-to-end via gateway agent loop") -- Gateway 网关向导(WS `wizard.start`/`wizard.next`,写入配置 + 强制认证):`src/gateway/gateway.test.ts`(用例:"runs wizard over ws and writes auth token config") +- Gateway 网关工具调用(mock OpenAI,真实 Gateway 网关 + Agent loop):`src/gateway/gateway.test.ts`(用例:"runs a mock OpenAI tool call end-to-end via gateway agent loop") +- Gateway 网关向导(WS `wizard.start`/`wizard.next`,写入配置并强制 auth):`src/gateway/gateway.test.ts`(用例:"runs wizard over ws and writes auth token config") -## 智能体可靠性评估(Skills) +## 智能体可靠性 eval(Skills) -我们已经有一些 CI 安全测试,它们的行为类似于“智能体可靠性评估”: +我们已经有一些 CI 安全测试,其行为类似“智能体可靠性 eval”: -- 通过真实 Gateway 网关 + Agent loop 进行模拟工具调用(`src/gateway/gateway.test.ts`)。 -- 端到端向导流程,用于验证会话接线和配置效果(`src/gateway/gateway.test.ts`)。 +- 通过真实 Gateway 网关 + Agent loop 进行 mock 工具调用(`src/gateway/gateway.test.ts`)。 +- 验证会话 wiring 和配置效果的端到端向导流程(`src/gateway/gateway.test.ts`)。 -Skills 仍然缺失的内容(见 [Skills](/zh-CN/tools/skills)): +Skills 仍缺少的内容(见 [Skills](/zh-CN/tools/skills)): -- **决策:** 当提示中列出 Skills 时,智能体是否选择正确的 Skills(或避开无关项)? -- **合规:** 智能体是否在使用前读取 `SKILL.md`,并遵循必需步骤/参数? -- **工作流契约:** 多轮场景,用于断言工具顺序、会话历史延续和沙箱边界。 +- **决策:** 当 prompt 中列出 Skills 时,智能体是否会选择正确的 skill(或避开不相关的 skill)? +- **合规性:** 智能体是否会在使用前阅读 `SKILL.md` 并遵循所需步骤/参数? +- **工作流契约:** 断言工具顺序、会话历史 carryover 和沙箱边界的多轮场景。 -未来评估应优先保持确定性: +未来 eval 应优先保持确定性: -- 使用模拟提供商的场景运行器,用于断言工具调用 + 顺序、skill 文件读取和会话接线。 -- 一小组聚焦 Skills 的场景(使用 vs 避开、门控、提示注入)。 -- 仅在 CI 安全套件就位后,再添加可选实时评估(选择加入、由环境变量门控)。 +- 一个使用 mock 提供商的场景 runner,用于断言工具调用 + 顺序、skill 文件读取和会话 wiring。 +- 一小组聚焦 skill 的场景(使用与避开、门控、prompt injection)。 +- 可选实时 eval(opt-in、env-gated)仅在 CI 安全套件就绪后添加。 ## 契约测试(插件和渠道形状) -契约测试会验证每个已注册插件和渠道都符合其 -接口契约。它们会遍历所有发现的插件,并运行一套 -形状和行为断言。默认的 `pnpm test` 单元 lane 会刻意 -跳过这些共享 seam 和冒烟文件;当你触及共享渠道或提供商 surface 时, +契约测试会验证每个已注册的插件和渠道都符合其 +接口契约。它们会遍历所有发现的插件,并运行一组 +形状和行为断言。默认的 `pnpm test` unit lane 会有意 +跳过这些共享接缝和冒烟文件;当你触碰共享渠道或提供商表面时, 请显式运行契约命令。 ### 命令 -- 全部契约:`pnpm test:contracts` +- 所有契约:`pnpm test:contracts` - 仅渠道契约:`pnpm test:contracts:channels` - 仅提供商契约:`pnpm test:contracts:plugins` @@ -667,31 +677,31 @@ Skills 仍然缺失的内容(见 [Skills](/zh-CN/tools/skills)): 位于 `src/channels/plugins/contracts/*.contract.test.ts`: -- **plugin** - 基本插件形状(id、名称、能力) +- **plugin** - 基本插件形状(id、name、capabilities) - **setup** - 设置向导契约 - **session-binding** - 会话绑定行为 -- **outbound-payload** - 消息载荷结构 +- **outbound-payload** - 消息 payload 结构 - **inbound** - 入站消息处理 -- **actions** - 渠道操作处理器 -- **threading** - 线程 ID 处理 -- **directory** - 目录/名册 API +- **actions** - 渠道 action handler +- **threading** - Thread ID 处理 +- **directory** - Directory/roster API - **group-policy** - 群组策略强制执行 ### 提供商 Status 契约 位于 `src/plugins/contracts/*.contract.test.ts`。 -- **status** - 渠道 Status 探测 -- **registry** - 插件注册表形状 +- **status** - 渠道 Status probe +- **registry** - 插件 registry 形状 ### 提供商契约 位于 `src/plugins/contracts/*.contract.test.ts`: -- **auth** - 认证流程契约 -- **auth-choice** - 认证选择/选取 -- **catalog** - 模型目录 API -- **discovery** - 插件发现 +- **auth** - Auth flow 契约 +- **auth-choice** - Auth choice/selection +- **catalog** - 模型 catalog API +- **discovery** - 插件设备发现 - **loader** - 插件加载 - **runtime** - 提供商运行时 - **shape** - 插件形状/接口 @@ -699,24 +709,24 @@ Skills 仍然缺失的内容(见 [Skills](/zh-CN/tools/skills)): ### 何时运行 -- 更改 plugin-sdk 导出或子路径后 +- 更改 plugin-sdk 导出或 subpath 后 - 添加或修改渠道或提供商插件后 -- 重构插件注册或发现后 +- 重构插件注册或设备发现后 -契约测试会在 CI 中运行,且不需要真实 API keys。 +契约测试会在 CI 中运行,并且不需要真实 API key。 ## 添加回归(指南) -当你修复在实时中发现的提供商/模型问题时: +当你修复实时运行中发现的提供商/模型问题时: -- 尽可能添加 CI 安全回归(模拟/stub 提供商,或捕获精确的请求形状转换) -- 如果它本质上只能实时测试(速率限制、认证策略),请保持实时测试范围窄,并通过环境变量选择加入 -- 优先针对能捕获该 bug 的最小层级: - - 提供商请求转换/重放 bug → 直接模型测试 - - Gateway 网关会话/历史/工具流水线 bug → Gateway 网关实时冒烟测试或 CI 安全 Gateway 网关模拟测试 -- SecretRef 遍历护栏: - - `src/secrets/exec-secret-ref-id-parity.test.ts` 会从注册表元数据(`listSecretTargetRegistryEntries()`)为每个 SecretRef 类派生一个抽样目标,然后断言 traversal-segment exec ids 会被拒绝。 - - 如果你在 `src/secrets/target-registry-data.ts` 中添加新的 `includeInPlan` SecretRef 目标家族,请更新该测试中的 `classifyTargetClass`。该测试会刻意在未分类目标 id 上失败,这样新类就不能被静默跳过。 +- 尽可能添加 CI 安全回归(mock/stub 提供商,或捕获精确的 request-shape 转换) +- 如果它本质上只能实时测试(rate limit、auth policy),请保持实时测试范围狭窄,并通过环境变量 opt-in +- 优先定位到能捕获 bug 的最小层级: + - 提供商 request conversion/replay bug → 直接模型测试 + - Gateway 网关会话/history/tool pipeline bug → Gateway 网关实时冒烟测试或 CI 安全 Gateway 网关 mock 测试 +- SecretRef traversal guardrail: + - `src/secrets/exec-secret-ref-id-parity.test.ts` 会从 registry 元数据(`listSecretTargetRegistryEntries()`)为每个 SecretRef class 派生一个采样 target,然后断言 traversal-segment exec id 会被拒绝。 + - 如果你在 `src/secrets/target-registry-data.ts` 中添加新的 `includeInPlan` SecretRef target family,请更新该测试中的 `classifyTargetClass`。该测试会故意在未分类 target id 上失败,确保新 class 不会被静默跳过。 ## 相关 diff --git a/docs/zh-CN/reference/RELEASING.md b/docs/zh-CN/reference/RELEASING.md index ced0c4188..97c62ceef 100644 --- a/docs/zh-CN/reference/RELEASING.md +++ b/docs/zh-CN/reference/RELEASING.md @@ -1,146 +1,147 @@ --- read_when: - - 正在查找公开发布渠道定义 + - 正在查找公共发布渠道定义 - 运行发布验证或软件包验收 - 查找版本命名和发布节奏 -summary: 发布通道、操作员检查清单、验证框、版本命名和节奏 +summary: 发布通道、操作员检查清单、验证环境、版本命名和发布节奏 title: 发布策略 x-i18n: - generated_at: "2026-05-01T02:24:12Z" + generated_at: "2026-05-01T03:00:04Z" model: gpt-5.5 provider: openai - source_hash: bb56568bf860ba9eae47df71c5c1ebefe9eb9ae05ac4706dbb425772ff6cdcaa + source_hash: dfe579099a9580e2d0400cd0b24f26d3fa3ee917899423604ebc13aa2519b4ee source_path: reference/RELEASING.md workflow: 16 --- OpenClaw 有三个公开发布通道: -- stable:带标签的版本,默认发布到 npm `beta`,或在明确请求时发布到 npm `latest` -- beta:预发布标签,发布到 npm `beta` -- dev:`main` 的移动头部 +- 稳定版:带标签的发布版本,默认发布到 npm `beta`,或在明确请求时发布到 npm `latest` +- 测试版:发布到 npm `beta` 的预发布标签 +- 开发版:`main` 的移动最新提交 ## 版本命名 -- 稳定版版本:`YYYY.M.D` +- 稳定版发布版本:`YYYY.M.D` - Git 标签:`vYYYY.M.D` -- 稳定修正版版本:`YYYY.M.D-N` +- 稳定版修正发布版本:`YYYY.M.D-N` - Git 标签:`vYYYY.M.D-N` -- Beta 预发布版本:`YYYY.M.D-beta.N` +- 测试版预发布版本:`YYYY.M.D-beta.N` - Git 标签:`vYYYY.M.D-beta.N` -- 不要给月份或日期补零 -- `latest` 表示当前已推广的稳定版 npm 发布 -- `beta` 表示当前 beta 安装目标 -- 稳定版和稳定修正版默认发布到 npm `beta`;发布操作员可以明确指定 `latest`,或稍后推广已审定的 beta 构建 +- 不要为月份或日期补零 +- `latest` 表示当前已提升的稳定版 npm 发布版本 +- `beta` 表示当前的测试版安装目标 +- 稳定版和稳定版修正发布版本默认发布到 npm `beta`;发布操作者可以明确指定 `latest`,或稍后提升经过验证的测试版构建 - 每个稳定版 OpenClaw 发布都会同时交付 npm 包和 macOS 应用; - beta 发布通常先验证并发布 npm/package 路径,除非明确请求,否则 - mac 应用构建/签名/公证仅保留给稳定版 + 测试版发布通常会先验证并发布 npm/包路径,除非明确请求,否则 + mac 应用构建/签名/公证会保留给稳定版 ## 发布节奏 -- 发布先经过 beta -- 只有在最新 beta 验证通过后才进入稳定版 -- 维护者通常从当前 `main` 创建的 `release/YYYY.M.D` 分支切出发布, +- 发布先进入测试版 +- 只有在最新测试版通过验证后,稳定版才会跟进 +- 维护者通常会从基于当前 `main` 创建的 `release/YYYY.M.D` 分支切出发布, 这样发布验证和修复不会阻塞 `main` 上的新开发 -- 如果 beta 标签已经推送或发布并且需要修复,维护者会切出下一个 - `-beta.N` 标签,而不是删除或重新创建旧 beta 标签 -- 详细发布流程、审批、凭证和恢复说明仅限维护者使用 +- 如果测试版标签已经推送或发布但需要修复,维护者会切出下一个 + `-beta.N` 标签,而不是删除或重新创建旧的测试版标签 +- 详细的发布流程、审批、凭证和恢复说明仅限维护者访问 -## 发布操作员检查清单 +## 发布操作者检查清单 -此检查清单描述发布流程的公开形态。私有凭证、 +此检查清单是发布流程的公开形态。私有凭证、 签名、公证、dist-tag 恢复和紧急回滚细节保留在 -仅限维护者使用的发布运行手册中。 +仅限维护者访问的发布运行手册中。 -1. 从当前 `main` 开始:拉取最新代码,确认目标提交已推送, - 并确认当前 `main` CI 足够绿色,可以从它创建分支。 -2. 使用 `/changelog` 根据真实提交历史重写顶部 `CHANGELOG.md` 章节, - 保持条目面向用户,提交它、推送它,并在创建分支前再次 rebase/pull。 +1. 从当前 `main` 开始:拉取最新内容,确认目标提交已推送, + 并确认当前 `main` CI 足够健康,可以从它创建分支。 +2. 使用 `/changelog` 基于真实提交历史重写顶部 `CHANGELOG.md` 章节, + 保持条目面向用户,提交并推送,然后在创建分支前再次 rebase/pull。 3. 查看 `src/plugins/compat/registry.ts` 和 - `src/commands/doctor/shared/deprecation-compat.ts` 中的发布兼容性记录。只有在升级路径仍被覆盖时才移除过期兼容性, - 或记录为什么有意继续保留。 -4. 从当前 `main` 创建 `release/YYYY.M.D`;不要直接在 `main` 上做常规发布工作。 -5. 为目标标签更新每个必需的版本位置,然后运行本地确定性预检: + `src/commands/doctor/shared/deprecation-compat.ts` 中的发布兼容性记录。仅当升级路径仍被覆盖时才移除已过期的 + 兼容性,或记录为什么有意保留它。 +4. 从当前 `main` 创建 `release/YYYY.M.D`;不要直接在 `main` 上进行常规发布工作。 +5. 为目标标签更新每个必需的版本位置,然后运行 + 本地确定性预检: `pnpm check:test-types`、`pnpm check:architecture`、 `pnpm build && pnpm ui:build` 和 `pnpm release:check`。 -6. 运行 `OpenClaw NPM Release`,并设置 `preflight_only=true`。在标签存在之前, - 允许使用完整的 40 字符发布分支 SHA 进行仅验证预检。 - 保存成功的 `preflight_run_id`。 +6. 使用 `preflight_only=true` 运行 `OpenClaw NPM Release`。在标签存在之前, + 允许使用完整的 40 字符发布分支 SHA 进行仅验证预检。保存成功的 `preflight_run_id`。 7. 使用 `Full Release Validation` 为发布分支、标签或完整提交 SHA 启动所有预发布测试。 - 这是四个大型发布测试箱的唯一手动入口点:Vitest、Docker、QA Lab 和 Package。 -8. 如果验证失败,在发布分支上修复,并重新运行能够证明修复的最小失败文件、通道、工作流作业、包配置、提供商或模型允许列表。 - 只有在变更范围使先前证据过时时,才重新运行完整总入口。 -9. 对于 beta,打标签 `vYYYY.M.D-beta.N`,使用 npm dist-tag `beta` 发布,然后针对已发布的 `openclaw@YYYY.M.D-beta.N` - 或 `openclaw@beta` 包运行发布后包验收。如果已推送或已发布的 beta 需要修复, - 切出下一个 `-beta.N`;不要删除或重写旧 beta。 -10. 对于稳定版,只有在已审定的 beta 或候选发布具备所需验证证据后才继续。 - 稳定版 npm 发布通过 `preflight_run_id` 复用成功的预检工件;稳定版 macOS 发布就绪还要求 - 打包的 `.zip`、`.dmg`、`.dSYM.zip` 和更新后的 - `appcast.xml` 位于 `main` 上。 -11. 发布后,运行 npm 发布后验证器;在需要发布后渠道证明时,可选运行独立的 - 已发布 npm Telegram E2E;按需进行 dist-tag 推广;根据完整匹配的 - `CHANGELOG.md` 章节生成 GitHub release/prerelease 说明;并执行发布公告步骤。 + 这是四个大型发布测试盒的唯一手动入口点:Vitest、Docker、QA Lab 和 Package。 +8. 如果验证失败,在发布分支上修复,并重新运行能够证明修复的最小失败 + 文件、通道、工作流作业、包配置、提供商或模型允许列表。仅当变更表面使 + 先前证据失效时,才重新运行完整总入口。 +9. 对于测试版,标记 `vYYYY.M.D-beta.N`,使用 npm dist-tag `beta` 发布,然后针对已发布的 `openclaw@YYYY.M.D-beta.N` + 或 `openclaw@beta` 包运行发布后包验收。如果已推送或已发布的测试版需要修复, + 切出下一个 `-beta.N`;不要删除或重写旧测试版。 +10. 对于稳定版,仅在经过验证的测试版或发布候选版具备 + 所需验证证据后继续。稳定版 npm 发布会通过 `preflight_run_id` 复用成功的 + 预检工件;稳定版 macOS 发布就绪还需要 `main` 上的打包 `.zip`、`.dmg`、`.dSYM.zip` 和已更新的 + `appcast.xml`。 +11. 发布后,运行 npm 发布后验证器;在需要发布后渠道证明时,运行可选的独立 + 已发布 npm Telegram E2E;在需要时进行 dist-tag 提升;根据完整匹配的 `CHANGELOG.md` 章节生成 GitHub 发布/预发布说明; + 并执行发布公告步骤。 ## 发布预检 -- 在发布预检前运行 `pnpm check:test-types`,确保测试 TypeScript 在更快的本地 `pnpm check` 门禁之外仍被覆盖 -- 在发布预检前运行 `pnpm check:architecture`,确保更广泛的导入循环和架构边界检查在更快的本地门禁之外保持绿色 -- 在 `pnpm release:check` 前运行 `pnpm build && pnpm ui:build`,确保预期的 `dist/*` 发布产物和 Control UI bundle 已存在,可用于 pack 验证步骤 -- 在发布批准前运行手动 `Full Release Validation` 工作流,以便从一个入口点启动所有预发布测试盒。它接受分支、标签或完整提交 SHA,派发手动 `CI`,并派发 `OpenClaw Release Checks`,用于安装烟测、package acceptance、Docker 发布路径套件、live/E2E、OpenWebUI、QA Lab parity、Matrix 和 Telegram lane。只有在包已发布且也应运行发布后 Telegram E2E 时,才提供 `npm_telegram_package_spec`。当私有证据报告应证明验证匹配已发布的 npm 包、但不强制运行 Telegram E2E 时,提供 `evidence_package_spec`。 +- 在发布预检前运行 `pnpm check:test-types`,确保测试 TypeScript 在更快的本地 `pnpm check` 门禁之外也被覆盖 +- 在发布预检前运行 `pnpm check:architecture`,确保更广泛的导入循环和架构边界检查在更快的本地门禁之外也是绿色的 +- 在 `pnpm release:check` 前运行 `pnpm build && pnpm ui:build`,确保打包验证步骤所需的 `dist/*` 发布产物和 Control UI bundle 已存在 +- 在发布批准前运行手动 `Full Release Validation` workflow,从一个入口点启动所有预发布测试盒。它接受分支、标签或完整 commit SHA,分发手动 `CI`,并分发 `OpenClaw Release Checks`,用于安装 smoke、包验收、Docker 发布路径套件、live/E2E、OpenWebUI、QA Lab 对齐性、Matrix 和 Telegram 通道。仅在包已发布且发布后 Telegram E2E 也应运行时提供 `npm_telegram_package_spec`。当私有证据报告应证明验证与已发布 npm 包匹配、但不强制运行 Telegram E2E 时,提供 `evidence_package_spec`。 示例: `gh workflow run full-release-validation.yml --ref main -f ref=release/YYYY.M.D` -- 当你希望在发布工作继续进行时为包候选版本获取旁路证明,请运行手动 `Package Acceptance` 工作流。对 `openclaw@beta`、`openclaw@latest` 或精确发布版本使用 `source=npm`;使用 `source=ref` 通过当前 `workflow_ref` harness 打包受信任的 `package_ref` 分支/标签/SHA;对带有必需 SHA-256 的 HTTPS tarball 使用 `source=url`;或对另一个 GitHub Actions 运行上传的 tarball 使用 `source=artifact`。该工作流会将候选项解析为 `package-under-test`,复用 Docker E2E 发布调度器来针对该 tarball 运行,并可使用 `telegram_mode=mock-openai` 或 `telegram_mode=live-frontier` 针对同一个 tarball 运行 Telegram QA。 - 示例:`gh workflow run package-acceptance.yml --ref main -f workflow_ref=main -f source=npm -f package_spec=openclaw@beta -f suite_profile=product -f telegram_mode=mock-openai` +- 当你希望在发布工作继续进行的同时,为包候选版本获取旁路证明时,运行手动 `Package Acceptance` workflow。对 `openclaw@beta`、`openclaw@latest` 或精确发布版本使用 `source=npm`;使用 `source=ref` 将受信任的 `package_ref` 分支/标签/SHA 与当前 `workflow_ref` harness 打包;对需要 SHA-256 的 HTTPS tarball 使用 `source=url`;或对由另一个 GitHub Actions run 上传的 tarball 使用 `source=artifact`。该 workflow 将候选解析为 `package-under-test`,针对该 tarball 复用 Docker E2E 发布调度器,并且可以用 `telegram_mode=mock-openai` 或 `telegram_mode=live-frontier` 针对同一个 tarball 运行 Telegram QA。当选定的 Docker 通道包含 `published-upgrade-survivor` 时,包产物就是候选版本,而 `published_upgrade_survivor_baseline` 选择已发布基线。 + 示例:`gh workflow run package-acceptance.yml --ref main -f workflow_ref=main -f source=npm -f package_spec=openclaw@beta -f suite_profile=product -f published_upgrade_survivor_baseline=openclaw@2026.4.26 -f telegram_mode=mock-openai` 常用 profile: - - `smoke`:安装/渠道/智能体、Gateway 网关网络和配置重载 lane - - `package`:不含 OpenWebUI 或 live ClawHub 的产物原生 package/update/plugin lane - - `product`:package profile 加 MCP 渠道、cron/subagent 清理、OpenAI web 搜索和 OpenWebUI + - `smoke`:安装/渠道/智能体、Gateway 网关网络和配置重载通道 + - `package`:产物原生的包/更新/插件通道,不包含 OpenWebUI 或 live ClawHub + - `product`:package profile 加上 MCP 渠道、cron/subagent 清理、OpenAI web 搜索和 OpenWebUI - `full`:带 OpenWebUI 的 Docker 发布路径分块 - `custom`:用于聚焦重跑的精确 `docker_lanes` 选择 -- 当你只需要发布候选版本的完整常规 CI 覆盖时,直接运行手动 `CI` 工作流。手动 CI 派发会绕过 changed 作用域,并强制运行 Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建烟测、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n lane。 +- 当你只需要发布候选版本的完整常规 CI 覆盖时,直接运行手动 `CI` workflow。手动 CI 分发会绕过变更范围限定,并强制运行 Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建 smoke、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n 通道。 示例:`gh workflow run ci.yml --ref release/YYYY.M.D` -- 验证发布遥测时运行 `pnpm qa:otel:smoke`。它通过本地 OTLP/HTTP receiver 演练 QA-lab,并验证导出的 trace span 名称、有界属性以及内容/标识符脱敏,而无需 Opik、Langfuse 或其他外部 collector。 -- 每次打标签发布前运行 `pnpm release:check` -- 发布检查现在在单独的手动工作流中运行: +- 在验证发布 telemetry 时运行 `pnpm qa:otel:smoke`。它通过本地 OTLP/HTTP 接收器执行 QA-lab,并验证导出的 trace span 名称、有界属性以及内容/标识符脱敏,无需 Opik、Langfuse 或其他外部 collector。 +- 在每次带标签发布前运行 `pnpm release:check` +- 发布检查现在在单独的手动 workflow 中运行: `OpenClaw Release Checks` -- `OpenClaw Release Checks` 还会在发布批准前运行 QA Lab mock parity 门禁,以及快速 live Matrix profile 和 Telegram QA lane。live lane 使用 `qa-live-shared` 环境;Telegram 也使用 Convex CI 凭证租约。当你希望并行获取完整 Matrix 传输、媒体和 E2EE 清单时,使用 `matrix_profile=all` 和 `matrix_shards=true` 运行手动 `QA-Lab - All Lanes` 工作流。 -- 跨操作系统安装和升级运行时验证是公开 `OpenClaw Release Checks` 和 `Full Release Validation` 的一部分,它们会直接调用可复用工作流 `.github/workflows/openclaw-cross-os-release-checks-reusable.yml` -- 这种拆分是有意的:保持真实 npm 发布路径短小、确定且以产物为中心,同时让较慢的 live 检查留在自己的 lane 中,避免拖慢或阻塞发布 -- 带密钥的发布检查应通过 `Full Release Validation` 派发,或从 `main`/release 工作流 ref 派发,以便工作流逻辑和密钥保持受控 -- `OpenClaw Release Checks` 接受分支、标签或完整提交 SHA,只要解析后的提交可从 OpenClaw 分支或发布标签访问 -- `OpenClaw NPM Release` 的仅验证预检也接受当前完整 40 字符工作流分支提交 SHA,而不要求已推送标签 +- `OpenClaw Release Checks` 还会在发布批准前运行 QA Lab mock 对齐性门禁,以及快速 live Matrix profile 和 Telegram QA 通道。live 通道使用 `qa-live-shared` 环境;Telegram 也使用 Convex CI 凭证租约。当你想并行获取完整 Matrix 传输、媒体和 E2EE inventory 时,使用 `matrix_profile=all` 和 `matrix_shards=true` 运行手动 `QA-Lab - All Lanes` workflow。 +- 跨操作系统安装和升级运行时验证是公开 `OpenClaw Release Checks` 和 `Full Release Validation` 的一部分,它们会直接调用可复用 workflow `.github/workflows/openclaw-cross-os-release-checks-reusable.yml` +- 这种拆分是有意的:让真实 npm 发布路径保持短、确定且聚焦产物,而较慢的 live 检查保留在自己的通道中,避免拖慢或阻塞发布 +- 带 secret 的发布检查应通过 `Full Release Validation` 分发,或从 `main`/release workflow ref 分发,以便 workflow 逻辑和 secret 保持受控 +- `OpenClaw Release Checks` 接受分支、标签或完整 commit SHA,只要解析出的 commit 可从 OpenClaw 分支或发布标签访问 +- `OpenClaw NPM Release` 仅验证预检也接受当前完整 40 字符 workflow 分支 commit SHA,不要求已推送标签 - 该 SHA 路径仅用于验证,不能提升为真实发布 -- 在 SHA 模式下,工作流只会为包元数据检查合成 `v`;真实发布仍需要真实发布标签 -- 两个工作流都将真实发布和提升路径保留在 GitHub-hosted runner 上,而非变更性验证路径可以使用更大的 Blacksmith Linux runner -- 该工作流会使用 `OPENAI_API_KEY` 和 `ANTHROPIC_API_KEY` 工作流密钥运行 `OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cache` -- npm 发布预检不再等待单独的发布检查 lane -- 批准前运行 `RELEASE_TAG=vYYYY.M.D node --import tsx scripts/openclaw-npm-release-check.ts`(或匹配的 beta/correction 标签) -- npm 发布后运行 `node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.D`(或匹配的 beta/correction 版本),以在新的临时 prefix 中验证已发布 registry 安装路径 -- beta 发布后运行 `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@YYYY.M.D-beta.N OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci pnpm test:docker:npm-telegram-live`,使用共享租约 Telegram 凭证池,针对已发布 npm 包验证已安装包的新手引导、Telegram 设置和真实 Telegram E2E。本地维护者的一次性运行可以省略 Convex 变量,并直接传入三个 `OPENCLAW_QA_TELEGRAM_*` 环境凭证。 -- 维护者可以通过手动 `NPM Telegram Beta E2E` 工作流从 GitHub Actions 运行相同的发布后检查。它有意仅支持手动运行,不会在每次合并时运行。 -- 维护者发布自动化现在使用先预检、后提升: - - 真实 npm 发布必须通过成功的 npm `preflight_run_id` - - 真实 npm 发布必须从与成功预检运行相同的 `main` 或 `release/YYYY.M.D` 分支派发 +- 在 SHA 模式下,workflow 只会为包元数据检查合成 `v`;真实发布仍需要真实发布标签 +- 两个 workflow 都将真实发布和推广路径保留在 GitHub-hosted runner 上,而非变更性的验证路径可以使用更大的 Blacksmith Linux runner +- 该 workflow 会使用 `OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cache`,并同时使用 `OPENAI_API_KEY` 和 `ANTHROPIC_API_KEY` workflow secret +- npm 发布预检不再等待单独的发布检查通道 +- 在批准前运行 `RELEASE_TAG=vYYYY.M.D node --import tsx scripts/openclaw-npm-release-check.ts`(或匹配的 beta/修正版标签) +- npm publish 后,运行 `node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.D`(或匹配的 beta/修正版版本),在全新的临时 prefix 中验证已发布 registry 安装路径 +- beta publish 后,运行 `OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@YYYY.M.D-beta.N OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex OPENCLAW_NPM_TELEGRAM_CREDENTIAL_ROLE=ci pnpm test:docker:npm-telegram-live`,使用共享租约 Telegram 凭证池,针对已发布 npm 包验证已安装包的新手引导、Telegram 设置和真实 Telegram E2E。本地维护者一次性运行可以省略 Convex vars,并直接传入三个 `OPENCLAW_QA_TELEGRAM_*` 环境凭证。 +- 维护者可以通过手动 `NPM Telegram Beta E2E` workflow 从 GitHub Actions 运行同一个发布后检查。它有意仅限手动运行,不会在每次合并时运行。 +- 维护者发布自动化现在使用先预检再推广: + - 真实 npm publish 必须通过成功的 npm `preflight_run_id` + - 真实 npm publish 必须从与成功预检 run 相同的 `main` 或 `release/YYYY.M.D` 分支分发 - stable npm 发布默认使用 `beta` - - stable npm 发布可以通过工作流输入显式目标为 `latest` - - 基于 token 的 npm dist-tag 变更现在位于 `openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml` 中以保证安全,因为 `npm dist-tag add` 仍需要 `NPM_TOKEN`,而公开 repo 保持仅 OIDC 发布 - - 公开 `macOS Release` 仅用于验证;当标签只存在于 release 分支但工作流从 `main` 派发时,设置 `public_release_branch=release/YYYY.M.D` - - 真实私有 mac 发布必须通过成功的私有 mac `preflight_run_id` 和 `validate_run_id` - - 真实发布路径会提升已准备好的产物,而不是再次重建它们 -- 对于 `YYYY.M.D-N` 这样的 stable 修正发布,发布后验证器还会检查从 `YYYY.M.D` 到 `YYYY.M.D-N` 的相同临时 prefix 升级路径,确保发布修正不会悄悄把较旧的全局安装留在基础 stable payload 上 -- 除非 tarball 同时包含 `dist/control-ui/index.html` 和非空的 `dist/control-ui/assets/` payload,否则 npm 发布预检会失败关闭,避免再次发布空的浏览器 dashboard -- 发布后验证还会检查已发布 registry 安装是否在根 `dist/*` 布局下包含非空的内置插件运行时依赖。缺失或包含空的内置插件依赖 payload 的发布会让 postpublish 验证器失败,且不能提升到 `latest`。 -- `pnpm test:install:smoke` 还会对候选更新 tarball 强制执行 npm pack `unpackedSize` 预算,因此 installer e2e 会在发布路径前捕获意外的 pack 膨胀 -- 如果发布工作触及 CI 规划、插件时序 manifest 或插件测试矩阵,请在批准前重新生成并审查 `.github/workflows/plugin-prerelease.yml` 中由 planner 拥有的 `plugin-prerelease-extension-shard` 矩阵输出,避免发布说明描述过时的 CI 布局 -- stable macOS 发布就绪性还包括 updater surface: - - GitHub release 最终必须包含打包好的 `.zip`、`.dmg` 和 `.dSYM.zip` - - 发布后,`main` 上的 `appcast.xml` 必须指向新的 stable zip - - 打包后的 app 必须保留非 debug bundle id、非空 Sparkle feed URL,以及不低于该发布版本规范 Sparkle build floor 的 `CFBundleVersion` + - stable npm publish 可以通过 workflow input 显式目标为 `latest` + - 基于 token 的 npm dist-tag 变更现在位于 `openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml`,这是出于安全考虑,因为 `npm dist-tag add` 仍然需要 `NPM_TOKEN`,而公开仓库保持仅 OIDC publish + - 公开 `macOS Release` 仅用于验证;当标签只存在于 release 分支但 workflow 从 `main` 分发时,设置 `public_release_branch=release/YYYY.M.D` + - 真实私有 mac publish 必须通过成功的私有 mac `preflight_run_id` 和 `validate_run_id` + - 真实发布路径会推广准备好的产物,而不是再次重建它们 +- 对于 `YYYY.M.D-N` 这样的 stable 修正发布,发布后 verifier 也会检查同一临时 prefix 从 `YYYY.M.D` 到 `YYYY.M.D-N` 的升级路径,确保发布修正不会静默地让较旧的全局安装停留在基础 stable payload 上 +- npm 发布预检默认失败,除非 tarball 同时包含 `dist/control-ui/index.html` 和非空的 `dist/control-ui/assets/` payload,这样我们就不会再次发布空的浏览器 dashboard +- 发布后验证还会检查已发布 registry 安装在根 `dist/*` 布局下包含非空的内置插件运行时依赖。若某个发布缺少内置插件依赖 payload,或该 payload 为空,则 postpublish verifier 会失败,且无法推广到 `latest`。 +- `pnpm test:install:smoke` 也会对候选更新 tarball 强制执行 npm pack `unpackedSize` 预算,因此 installer e2e 可以在发布 publish 路径前捕获意外的 pack 膨胀 +- 如果发布工作触及 CI 规划、插件 timing manifest 或插件测试矩阵,请在批准前重新生成并审查由 planner 拥有的 `.github/workflows/plugin-prerelease.yml` 中的 `plugin-prerelease-extension-shard` 矩阵输出,确保发布说明不会描述过时的 CI 布局 +- stable macOS 发布就绪性也包括 updater 表面: + - GitHub release 最终必须包含打包后的 `.zip`、`.dmg` 和 `.dSYM.zip` + - publish 后,`main` 上的 `appcast.xml` 必须指向新的 stable zip + - 打包后的应用必须保持非 debug bundle id、非空 Sparkle feed URL,以及对该发布版本而言不低于规范 Sparkle build 下限的 `CFBundleVersion` ## 发布测试盒 -`Full Release Validation` 是操作员从一个入口点启动所有预发布测试的方式。从受信任的 `main` 工作流 ref 运行它,并将发布分支、标签或完整提交 SHA 作为 `ref` 传入: +`Full Release Validation` 是操作员从一个入口点启动所有预发布测试的方式。从受信任的 `main` workflow ref 运行它,并将发布分支、标签或完整 commit SHA 作为 `ref` 传入: ```bash gh workflow run full-release-validation.yml \ @@ -152,18 +153,17 @@ gh workflow run full-release-validation.yml \ -f evidence_package_spec=openclaw@YYYY.M.D-beta.N ``` -该工作流会解析目标 ref,使用 `target_ref=` 派发手动 `CI`,派发 `OpenClaw Release Checks`,并在设置 `npm_telegram_package_spec` 时可选派发独立的发布后 Telegram E2E。随后 `OpenClaw Release Checks` 会扇出安装烟测、跨操作系统发布检查、live/E2E Docker 发布路径覆盖、带 Telegram package QA 的 Package Acceptance、QA Lab parity、live Matrix 和 live Telegram。只有当 `Full Release Validation` 摘要显示 `normal_ci` 和 `release_checks` 成功,并且任何可选的 `npm_telegram` 子项成功或被有意跳过时,完整运行才可接受。最终验证器摘要会为每个子运行包含最慢 job 表,因此发布经理无需下载日志即可查看当前关键路径。 -请参阅 [完整发布验证](/zh-CN/reference/full-release-validation),了解完整阶段矩阵、精确工作流 job 名称、stable 与 full profile 差异、产物以及聚焦重跑句柄。 -子工作流会从运行 `Full Release Validation` 的受信任 ref 派发,通常为 `--ref main`,即使目标 `ref` 指向较旧的 release 分支或标签也是如此。不存在单独的 Full Release Validation workflow-ref 输入;通过选择工作流运行 ref 来选择受信任 harness。 +该 workflow 会解析目标 ref,使用 `target_ref=` 分发手动 `CI`,分发 `OpenClaw Release Checks`,并在设置了 `npm_telegram_package_spec` 时可选地分发独立的发布后 Telegram E2E。随后 `OpenClaw Release Checks` 会分发安装 smoke、跨操作系统发布检查、live/E2E Docker 发布路径覆盖、带 Telegram package QA 的 Package Acceptance、QA Lab 对齐性、live Matrix 和 live Telegram。只有当 `Full Release Validation` 摘要显示 `normal_ci` 和 `release_checks` 成功,且任何可选 `npm_telegram` 子项成功或有意跳过时,完整运行才可接受。最终 verifier 摘要会包含每个子 run 的最慢 job 表,因此发布经理无需下载日志就能看到当前关键路径。 +参见 [完整发布验证](/zh-CN/reference/full-release-validation),了解完整阶段矩阵、精确 workflow job 名称、stable 与 full profile 差异、产物以及聚焦重跑句柄。 +子 workflow 从运行 `Full Release Validation` 的受信任 ref 分发,通常是 `--ref main`,即使目标 `ref` 指向较旧的发布分支或标签。没有单独的 Full Release Validation workflow-ref input;通过选择 workflow run ref 来选择受信任的 harness。 -使用 `release_profile` 选择 live/provider 覆盖宽度: +使用 `release_profile` 选择 live/provider 覆盖范围: - `minimum`:最快的发布关键 OpenAI/core live 和 Docker 路径 -- `stable`:minimum 加用于发布批准的 stable provider/backend 覆盖 -- `full`:stable 加广泛的 advisory provider/media 覆盖 +- `stable`:minimum 加上用于发布批准的 stable provider/backend 覆盖 +- `full`:stable 加上广泛的 advisory provider/media 覆盖 -`OpenClaw Release Checks` 使用受信任的工作流 ref 将目标 ref 一次性解析为 `release-package-under-test`,并在发布路径 Docker 检查和 Package Acceptance 中复用该产物。这让所有面向包的测试盒使用相同字节,并避免重复构建包。 -当 repo/org 变量已设置时,跨操作系统 OpenAI 安装烟测使用 `OPENCLAW_CROSS_OS_OPENAI_MODEL`,否则使用 `openai/gpt-5.4-mini`,因为该 lane 证明的是包安装、新手引导、Gateway 网关启动和一次 live 智能体回合,而不是 benchmark 最慢的默认模型。更广泛的 live provider 矩阵仍然是模型特定覆盖的位置。 +`OpenClaw Release Checks` 使用受信任的工作流引用,将目标引用一次解析为 `release-package-under-test`,并在 release-path Docker 检查和 Package Acceptance 中复用该工件。这会让所有面向包的盒子使用相同字节,并避免重复构建包。跨 OS OpenAI 安装冒烟测试会在设置了仓库/组织变量时使用 `OPENCLAW_CROSS_OS_OPENAI_MODEL`,否则使用 `openai/gpt-5.4-mini`,因为此通道验证的是包安装、新手引导、Gateway 网关启动和一次实时智能体轮次,而不是对最慢的默认模型做基准测试。更广泛的实时提供商矩阵仍然负责模型特定覆盖。 根据发布阶段使用这些变体: @@ -194,22 +194,22 @@ gh workflow run full-release-validation.yml \ -f npm_telegram_provider_mode=mock-openai ``` -不要把完整总括流程作为聚焦修复后的第一次重跑。如果某个检查项失败,请使用失败的子 workflow、作业、Docker lane、包 profile、模型提供商或 QA lane 作为下一次证明。只有当修复改动了共享发布编排,或使先前的全检查项证据过期时,才再次运行完整总括流程。总括流程的最终验证器会重新检查已记录的子 workflow run ID,因此在某个子 workflow 成功重跑后,只需重跑失败的 `Verify full validation` 父作业。 +不要在一次聚焦修复后把完整总控作为首次重跑。如果一个盒子失败,请使用失败的子工作流、作业、Docker 通道、包配置文件、模型提供商或 QA 通道作为下一次证明。只有当修复更改了共享发布编排,或让之前的全盒子证据过期时,才再次运行完整总控。总控的最终验证器会重新检查已记录的子工作流运行 ID,因此在子工作流成功重跑后,只需重跑失败的 `Verify full validation` 父作业。 -对于有界恢复,将 `rerun_group` 传给总括流程。`all` 是真正的发布候选运行,`ci` 只运行普通 CI 子项,`plugin-prerelease` 只运行仅发布用的插件子项,`release-checks` 运行每个发布检查项,更窄的发布分组包括 `install-smoke`、`cross-os`、`live-e2e`、`package`、`qa`、`qa-parity`、`qa-live`,以及在提供独立包 Telegram lane 时的 `npm-telegram`。 +对于有界恢复,将 `rerun_group` 传给总控。`all` 是真正的候选发布运行,`ci` 只运行普通 CI 子项,`plugin-prerelease` 只运行仅发布的插件子项,`release-checks` 运行每个发布盒子,更窄的发布分组包括 `install-smoke`、`cross-os`、`live-e2e`、`package`、`qa`、`qa-parity`、`qa-live`,以及在提供独立包 Telegram 通道时的 `npm-telegram`。 ### Vitest -Vitest 检查项是手动 `CI` 子 workflow。手动 CI 会有意绕过变更范围,并强制对发布候选运行普通测试图:Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建 smoke、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n。 +Vitest 盒子是手动 `CI` 子工作流。手动 CI 会有意绕过变更范围限定,并强制对候选发布运行普通测试图:Linux Node 分片、内置插件分片、渠道契约、Node 22 兼容性、`check`、`check-additional`、构建冒烟、文档检查、Python Skills、Windows、macOS、Android 和 Control UI i18n。 -用这个检查项回答“源代码树是否通过了完整普通测试套件?”它不等同于发布路径的产品验证。需要保留的证据: +用这个盒子回答“源代码树是否通过了完整的普通测试套件?”它不同于 release-path 产品验证。需要保留的证据: -- 显示已派发 `CI` 运行 URL 的 `Full Release Validation` 摘要 -- 精确目标 SHA 上绿色通过的 `CI` 运行 -- 调查回归时 CI 作业中失败或缓慢的分片名称 -- 当某次运行需要性能分析时,保留 `.artifacts/vitest-shard-timings.json` 等 Vitest 计时 artifact +- `Full Release Validation` 摘要,显示已分派的 `CI` 运行 URL +- `CI` 在精确目标 SHA 上为绿色 +- 调查回归时来自 CI 作业的失败或慢速分片名称 +- 运行需要性能分析时的 Vitest 计时工件,例如 `.artifacts/vitest-shard-timings.json` -仅当发布需要确定性的普通 CI,而不需要 Docker、QA Lab、live、跨 OS 或包检查项时,才直接运行手动 CI: +仅当发布需要确定性的普通 CI,但不需要 Docker、QA Lab、实时、跨 OS 或包盒子时,才直接运行手动 CI: ```bash gh workflow run ci.yml --ref main -f target_ref=release/YYYY.M.D @@ -217,50 +217,50 @@ gh workflow run ci.yml --ref main -f target_ref=release/YYYY.M.D ### Docker -Docker 检查项通过 `openclaw-live-and-e2e-checks-reusable.yml` 存在于 `OpenClaw Release Checks` 中,并包含发布模式的 `install-smoke` workflow。它通过打包后的 Docker 环境验证发布候选,而不是只运行源代码级测试。 +Docker 盒子位于 `OpenClaw Release Checks` 中,通过 `openclaw-live-and-e2e-checks-reusable.yml` 以及发布模式的 `install-smoke` 工作流提供。它通过打包后的 Docker 环境验证候选发布,而不只是源代码级测试。 发布 Docker 覆盖包括: -- 启用慢速 Bun 全局安装 smoke 的完整 install smoke -- 按目标 SHA 准备/复用根 Dockerfile smoke 镜像,并将 QR、root/Gateway 网关 和 installer/Bun smoke 作业作为独立 install-smoke 分片运行 -- 仓库 E2E lane -- 发布路径 Docker 分块:`core`、`package-update-openai`、`package-update-anthropic`、`package-update-core`、`plugins-runtime-plugins`、`plugins-runtime-services`、`plugins-runtime-install-a`、`plugins-runtime-install-b`、`plugins-runtime-install-c`、`plugins-runtime-install-d`、`plugins-runtime-install-e`、`plugins-runtime-install-f`、`plugins-runtime-install-g`、`plugins-runtime-install-h`、`bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-discord`、`bundled-channels-update-b` 和 `bundled-channels-contracts` -- 请求时,在 `plugins-runtime-services` 分块中覆盖 OpenWebUI -- 将内置渠道依赖 lane 拆分到 channel-smoke、update-target 和 setup/runtime contract 分块,而不是一个大型内置渠道作业 -- 拆分内置插件安装/卸载 lane,从 `bundled-plugin-install-uninstall-0` 到 `bundled-plugin-install-uninstall-23` -- 当发布检查包含 live 套件时,覆盖 live/E2E 提供商套件和 Docker live 模型 +- 启用慢速 Bun 全局安装冒烟的完整安装冒烟 +- 按目标 SHA 准备/复用根 Dockerfile 冒烟镜像,并将 QR、root/gateway 和 installer/Bun 冒烟作业作为独立 install-smoke 分片运行 +- 仓库 E2E 通道 +- release-path Docker 分块:`core`、`package-update-openai`、`package-update-anthropic`、`package-update-core`、`plugins-runtime-plugins`、`plugins-runtime-services`、`plugins-runtime-install-a`、`plugins-runtime-install-b`、`plugins-runtime-install-c`、`plugins-runtime-install-d`、`plugins-runtime-install-e`、`plugins-runtime-install-f`、`plugins-runtime-install-g`、`plugins-runtime-install-h`、`bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-discord`、`bundled-channels-update-b` 和 `bundled-channels-contracts` +- 按请求在 `plugins-runtime-services` 分块内提供 OpenWebUI 覆盖 +- 将内置渠道依赖通道拆分到 channel-smoke、update-target 和 setup/runtime contract 分块,而不是一个大型 bundled-channel 作业 +- 拆分内置插件安装/卸载通道 `bundled-plugin-install-uninstall-0` 到 `bundled-plugin-install-uninstall-23` +- 当发布检查包含实时套件时,包含 live/E2E 提供商套件和 Docker 实时模型覆盖 -重跑前先使用 Docker artifact。发布路径调度器会上传 `.artifacts/docker-tests/`,其中包含 lane 日志、`summary.json`、`failures.json`、阶段计时、调度器计划 JSON 和重跑命令。对于聚焦恢复,请在可复用 live/E2E workflow 上使用 `docker_lanes=`,而不是重跑所有发布分块。生成的重跑命令会在可用时包含先前的 `package_artifact_run_id` 和已准备的 Docker 镜像输入,因此失败 lane 可以复用同一个 tarball 和 GHCR 镜像。 +重跑前先使用 Docker 工件。release-path 调度器会上传 `.artifacts/docker-tests/`,其中包含通道日志、`summary.json`、`failures.json`、阶段计时、调度器计划 JSON 和重跑命令。对于聚焦恢复,在可复用 live/E2E 工作流上使用 `docker_lanes=`,而不是重跑所有发布分块。生成的重跑命令会在可用时包含之前的 `package_artifact_run_id` 和已准备的 Docker 镜像输入,因此失败通道可以复用相同 tarball 和 GHCR 镜像。 ### QA Lab -QA Lab 检查项也是 `OpenClaw Release Checks` 的一部分。它是智能体行为和渠道级发布门禁,独立于 Vitest 和 Docker 包机制。 +QA Lab 盒子也是 `OpenClaw Release Checks` 的一部分。它是智能体行为和渠道级发布门禁,独立于 Vitest 和 Docker 包机制。 发布 QA Lab 覆盖包括: -- mock parity gate,使用 agentic parity pack 将 OpenAI 候选 lane 与 Opus 4.6 baseline 进行比较 -- 使用 `qa-live-shared` 环境的快速 live Matrix QA profile -- 使用 Convex CI 凭证租约的 live Telegram QA lane -- 当发布遥测需要明确本地证明时运行 `pnpm qa:otel:smoke` +- 使用智能体 parity 包对比 OpenAI 候选通道与 Opus 4.6 基线的 mock parity gate +- 使用 `qa-live-shared` 环境的快速实时 Matrix QA 配置文件 +- 使用 Convex CI 凭证租约的实时 Telegram QA 通道 +- 发布遥测需要显式本地证明时的 `pnpm qa:otel:smoke` -用这个检查项回答“发布在 QA 场景和 live 渠道流程中的行为是否正确?”批准发布时,请保留 parity、Matrix 和 Telegram lane 的 artifact URL。完整 Matrix 覆盖仍可作为手动分片 QA-Lab 运行使用,而不是默认的发布关键 lane。 +用这个盒子回答“发布在 QA 场景和实时渠道流程中是否行为正确?”批准发布时保留 parity、Matrix 和 Telegram 通道的工件 URL。完整 Matrix 覆盖仍可作为手动分片 QA-Lab 运行使用,而不是默认的发布关键通道。 ### 包 -Package 检查项是可安装产品门禁。它由 `Package Acceptance` 和解析器 `scripts/resolve-openclaw-package-candidate.mjs` 支撑。解析器会将候选归一化为 Docker E2E 使用的 `package-under-test` tarball,验证包清单,记录包版本和 SHA-256,并将 workflow harness ref 与包源 ref 分开。 +包盒子是可安装产品门禁。它由 `Package Acceptance` 和解析器 `scripts/resolve-openclaw-package-candidate.mjs` 支撑。解析器会将候选项规范化为供 Docker E2E 使用的 `package-under-test` tarball,验证包清单,记录包版本和 SHA-256,并将工作流 harness 引用与包源引用分开。 支持的候选来源: -- `source=npm`:`openclaw@beta`、`openclaw@latest` 或精确的 OpenClaw 发布版本 -- `source=ref`:使用选定的 `workflow_ref` harness 打包受信任的 `package_ref` 分支、标签或完整提交 SHA +- `source=npm`:`openclaw@beta`、`openclaw@latest`,或精确的 OpenClaw 发布版本 +- `source=ref`:使用所选 `workflow_ref` harness 打包受信任的 `package_ref` 分支、标签或完整提交 SHA - `source=url`:下载 HTTPS `.tgz`,并要求提供 `package_sha256` - `source=artifact`:复用另一个 GitHub Actions 运行上传的 `.tgz` -`OpenClaw Release Checks` 使用 `source=ref`、`package_ref=`、`suite_profile=custom`、`docker_lanes=bundled-channel-deps-compat plugins-offline` 和 `telegram_mode=mock-openai` 运行 Package Acceptance。发布路径 Docker 分块会覆盖重叠的安装、更新和插件更新 lane;Package Acceptance 会针对同一个已解析 tarball 保留 artifact 原生的内置渠道兼容性、离线插件 fixture 和 Telegram 包 QA。它是 GitHub 原生替代方案,用于替代过去大多数需要 Parallels 的包/更新覆盖。跨 OS 发布检查对于 OS 特定的新手引导、安装器和平台行为仍然重要,但包/更新产品验证应优先使用 Package Acceptance。 +`OpenClaw Release Checks` 使用 `source=ref`、`package_ref=`、`suite_profile=custom`、`docker_lanes=bundled-channel-deps-compat plugins-offline` 和 `telegram_mode=mock-openai` 运行 Package Acceptance。release-path Docker 分块覆盖重叠的安装、更新和插件更新通道;Package Acceptance 针对同一个已解析 tarball 保留工件原生的内置渠道兼容性、离线插件夹具和 Telegram 包 QA。它是 GitHub 原生替代方案,用来替代以前大多数需要 Parallels 的包/更新覆盖。跨 OS 发布检查对于 OS 特定的新手引导、安装器和平台行为仍然重要,但包/更新产品验证应优先使用 Package Acceptance。 -旧版 package-acceptance 宽容性有意设置了时间窗口。到 `2026.4.25` 为止的包可以针对已经发布到 npm 的元数据缺口使用兼容路径:tarball 中缺失的私有 QA 清单条目、缺失的 `gateway install --wrapper`、由 tarball 派生的 git fixture 中缺失的补丁文件、缺失的持久化 `update.channel`、旧版插件安装记录位置、缺失的 marketplace 安装记录持久化,以及 `plugins update` 期间的配置元数据迁移。已发布的 `2026.4.26` 包可以对已经发布的本地构建元数据 stamp 文件给出警告。之后的包必须满足现代包契约;这些相同缺口会导致发布验证失败。 +旧版 package-acceptance 宽松策略有意设置了时间边界。到 `2026.4.25` 为止的包,可以针对已发布到 npm 的元数据缺口使用兼容路径:tarball 中缺少私有 QA 清单条目、缺少 `gateway install --wrapper`、tarball 派生 git 夹具中缺少补丁文件、缺少持久化的 `update.channel`、旧版插件安装记录位置、缺少 marketplace 安装记录持久化,以及 `plugins update` 期间的配置元数据迁移。已发布的 `2026.4.26` 包可能会对已经发布的本地构建元数据戳文件发出警告。之后的包必须满足现代包契约;这些相同缺口会导致发布验证失败。 -当发布问题涉及实际可安装包时,使用更广的 Package Acceptance profile: +当发布问题涉及实际可安装包时,使用更广泛的 Package Acceptance 配置文件: ```bash gh workflow run package-acceptance.yml \ @@ -268,61 +268,76 @@ gh workflow run package-acceptance.yml \ -f workflow_ref=main \ -f source=npm \ -f package_spec=openclaw@beta \ - -f suite_profile=product + -f suite_profile=product \ + -f published_upgrade_survivor_baseline=openclaw@2026.4.26 ``` -常见包 profile: +常见包配置文件: -- `smoke`:快速包安装/渠道/智能体、Gateway 网关网络和配置热重载 lane -- `package`:无 live ClawHub 的安装/更新/插件包契约;这是 release-check 默认值 +- `smoke`:快速包安装/渠道/智能体、Gateway 网关网络和配置重载通道 +- `package`:没有实时 ClawHub 的安装/更新/插件包契约;这是 release-check 默认值 - `product`:`package` 加上 MCP 渠道、cron/subagent 清理、OpenAI web 搜索和 OpenWebUI -- `full`:带 OpenWebUI 的 Docker 发布路径分块 +- `full`:带 OpenWebUI 的 Docker release-path 分块 - `custom`:用于聚焦重跑的精确 `docker_lanes` 列表 -对于包候选 Telegram 证明,在 Package Acceptance 上启用 `telegram_mode=mock-openai` 或 `telegram_mode=live-frontier`。该 workflow 会将已解析的 `package-under-test` tarball 传入 Telegram lane;独立 Telegram workflow 仍接受已发布的 npm spec 用于发布后检查。 +对于包候选 Telegram 证明,在 Package Acceptance 上启用 `telegram_mode=mock-openai` 或 `telegram_mode=live-frontier`。该工作流会将已解析的 `package-under-test` tarball 传入 Telegram 通道;独立 Telegram 工作流仍接受已发布的 npm 规格用于发布后检查。 -## NPM workflow 输入 +## NPM 工作流输入 `OpenClaw NPM Release` 接受这些由操作者控制的输入: -- `tag`:必需的发布标签,例如 `v2026.4.2`、`v2026.4.2-1` 或 `v2026.4.2-beta.1`;当 `preflight_only=true` 时,也可以是当前完整 40 字符 workflow 分支提交 SHA,用于仅验证的 preflight -- `preflight_only`:`true` 表示只验证/构建/打包,`false` 表示真实发布路径 -- `preflight_run_id`:真实发布路径必需,以便 workflow 复用成功 preflight 运行中准备好的 tarball -- `npm_dist_tag`:发布路径的 npm 目标标签;默认值为 `beta` +- `tag`:必需的发布标签,例如 `v2026.4.2`、`v2026.4.2-1` 或 `v2026.4.2-beta.1`;当 `preflight_only=true` 时,它也可以是当前完整 40 字符工作流分支提交 SHA,用于仅验证的预检 +- `preflight_only`:`true` 表示仅验证/构建/打包,`false` 表示真实发布路径 +- `preflight_run_id`:真实发布路径必需,这样工作流可以复用成功预检运行中准备好的 tarball +- `npm_dist_tag`:发布路径的 npm 目标标签;默认为 `beta` `OpenClaw Release Checks` 接受这些由操作者控制的输入: -- `ref`:要验证的分支、标签或完整提交 SHA。带 secret 的检查要求解析出的提交可从 OpenClaw 分支或发布标签到达。 +- `ref`:要验证的分支、标签或完整提交 SHA。带密钥的检查要求解析后的提交可从 OpenClaw 分支或发布标签访问。 规则: -- Stable 和 correction 标签可以发布到 `beta` 或 `latest` +- 稳定版和修正版标签可以发布到 `beta` 或 `latest` - Beta 预发布标签只能发布到 `beta` -- 对于 `OpenClaw NPM Release`,只有在 `preflight_only=true` 时才允许输入完整提交 SHA +- 对于 `OpenClaw NPM Release`,仅当 `preflight_only=true` 时允许输入完整提交 SHA - `OpenClaw Release Checks` 和 `Full Release Validation` 始终仅用于验证 -- 真实发布路径必须使用 preflight 期间使用的同一个 `npm_dist_tag`;workflow 会在发布继续之前验证该元数据 +- 真实发布路径必须使用预检期间使用的同一个 `npm_dist_tag`;工作流会验证发布前的元数据仍然一致 -## Stable npm 发布序列 +## 稳定 npm 发布顺序 -切 stable npm 发布时: +切割稳定 npm 发布时: -1. 使用 `preflight_only=true` 运行 `OpenClaw NPM Release` - - 在标签存在之前,你可以使用当前完整 workflow 分支提交 SHA,对 preflight workflow 进行仅验证的 dry run -2. 对普通 beta-first 流程选择 `npm_dist_tag=beta`,或者仅在你有意直接发布 stable 时选择 `latest` -3. 当你希望通过一个手动 workflow 获得普通 CI 加 live prompt cache、Docker、QA Lab、Matrix 和 Telegram 覆盖时,在发布分支、发布标签或完整提交 SHA 上运行 `Full Release Validation` -4. 如果你明确只需要确定性的普通测试图,请改为在发布 ref 上运行手动 `CI` workflow +1. 运行 `OpenClaw NPM Release` 并设置 `preflight_only=true` + - 在标签存在之前,你可以使用当前完整工作流分支的 commit + SHA,对预检工作流进行仅验证的试运行 +2. 为常规 beta 优先流程选择 `npm_dist_tag=beta`,只有在你明确想要直接发布稳定版时才选择 `latest` +3. 当你想通过一个手动工作流获得常规 CI,以及实时提示缓存、Docker、QA Lab、 + Matrix 和 Telegram 覆盖时,在发布分支、发布标签或完整 + commit SHA 上运行 `Full Release Validation` +4. 如果你明确只需要确定性的常规测试图,请改为在发布 ref 上运行手动 + `CI` 工作流 5. 保存成功的 `preflight_run_id` -6. 再次运行 `OpenClaw NPM Release`,并使用 `preflight_only=false`、相同的 `tag`、相同的 `npm_dist_tag` 和已保存的 `preflight_run_id` -7. 如果发布落在 `beta`,使用私有 `openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml` workflow 将该 stable 版本从 `beta` 提升到 `latest` -8. 如果发布有意直接发布到 `latest`,并且 `beta` 应立即跟随同一个 stable 构建,请使用同一个私有 workflow 将两个 dist-tag 都指向 stable 版本,或让它的定时自愈同步稍后移动 `beta` +6. 再次运行 `OpenClaw NPM Release`,并设置 `preflight_only=false`、相同的 + `tag`、相同的 `npm_dist_tag`,以及保存的 `preflight_run_id` +7. 如果发布落在 `beta` 上,请使用私有的 + `openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml` + 工作流,将该稳定版本从 `beta` 提升到 `latest` +8. 如果发布有意直接发布到 `latest`,并且 `beta` + 应立即跟随同一个稳定构建,请使用同一个私有 + 工作流让两个 dist-tag 都指向该稳定版本,或让它的定时 + 自修复同步稍后移动 `beta` -dist-tag 变更位于私有仓库中,这是出于安全考虑,因为它仍然需要 `NPM_TOKEN`,而公共仓库保持仅 OIDC 发布。 +出于安全原因,dist-tag 变更位于私有仓库中,因为它仍然 +需要 `NPM_TOKEN`,而公共仓库保持仅 OIDC 发布。 -这样可以让直接发布路径和 beta-first 提升路径都被记录在文档中,并且对操作者可见。 +这会让直接发布路径和 beta 优先提升路径都保持 +已文档化且对操作者可见。 -如果维护者必须回退到本地 npm 身份验证,请只在专用 tmux 会话内运行任何 1Password CLI(`op`)命令。不要直接从主智能体 shell 调用 `op`;将它保留在 tmux 内,可以让提示、警报和 OTP 处理可观察,并防止重复的主机警报。 +如果维护者必须回退到本地 npm 身份验证,请只在专用 tmux 会话中运行任何 1Password +CLI(`op`)命令。不要直接从主智能体 shell 调用 `op`;将它保留在 tmux 内可以让提示、 +警报和 OTP 处理可观测,并防止重复的主机警报。 -## 公开参考资料 +## 公共参考 - [`.github/workflows/full-release-validation.yml`](https://github.com/openclaw/openclaw/blob/main/.github/workflows/full-release-validation.yml) - [`.github/workflows/package-acceptance.yml`](https://github.com/openclaw/openclaw/blob/main/.github/workflows/package-acceptance.yml) @@ -338,6 +353,6 @@ dist-tag 变更位于私有仓库中,这是出于安全考虑,因为它仍 [`openclaw/maintainers/release/README.md`](https://github.com/openclaw/maintainers/blob/main/release/README.md) 中的私有发布文档作为实际运行手册。 -## 相关内容 +## 相关 - [发布渠道](/zh-CN/install/development-channels) diff --git a/docs/zh-CN/reference/test.md b/docs/zh-CN/reference/test.md index edc84acae..766ae2aa9 100644 --- a/docs/zh-CN/reference/test.md +++ b/docs/zh-CN/reference/test.md @@ -4,57 +4,57 @@ read_when: summary: 如何在本地运行测试(vitest),以及何时使用强制/覆盖率模式 title: 测试 x-i18n: - generated_at: "2026-04-30T23:43:52Z" + generated_at: "2026-05-01T02:59:50Z" model: gpt-5.5 provider: openai - source_hash: de18ac7d822055ee34885e5e897eff0fe7dde57c945a6b7f2c4bb2a29445c859 + source_hash: 4d50f77fdb8dcf7153c59d1bd9f3d61d745ba17ea846eb0610d0f064ad0d1761 source_path: reference/test.md workflow: 16 --- -- 完整测试工具包(套件、真实环境测试、Docker):[测试](/zh-CN/help/testing) +- 完整测试工具包(套件、实时、Docker):[测试](/zh-CN/help/testing) -- `pnpm test:force`:终止任何仍占用默认控制端口的 Gateway 网关进程,然后使用隔离的 Gateway 网关端口运行完整 Vitest 套件,这样服务器测试就不会与正在运行的实例冲突。当先前的 Gateway 网关运行让端口 18789 被占用时使用此命令。 -- `pnpm test:coverage`:使用 V8 覆盖率运行单元套件(通过 `vitest.unit.config.ts`)。这是已加载文件的单元覆盖率门禁,不是整个仓库的全文件覆盖率。阈值为 70% 的行/函数/语句覆盖率和 55% 的分支覆盖率。因为 `coverage.all` 为 false,所以该门禁衡量的是单元覆盖率套件加载的文件,而不是把每个拆分通道源文件都视为未覆盖。 +- `pnpm test:force`:终止任何占用默认控制端口的残留 Gateway 网关进程,然后使用隔离的 Gateway 网关端口运行完整 Vitest 套件,避免服务器测试与正在运行的实例冲突。当先前的 Gateway 网关运行占用了端口 18789 时使用此命令。 +- `pnpm test:coverage`:使用 V8 覆盖率运行单元套件(通过 `vitest.unit.config.ts`)。这是已加载文件的单元覆盖率门禁,不是整个仓库的全文件覆盖率。阈值为 70% 的行/函数/语句和 55% 的分支。由于 `coverage.all` 为 false,该门禁会衡量单元覆盖率套件加载的文件,而不是把每个拆分通道的源文件都视为未覆盖。 - `pnpm test:coverage:changed`:仅对自 `origin/main` 以来变更的文件运行单元覆盖率。 -- `pnpm test:changed`:低成本的智能变更测试运行。它会从直接测试编辑、相邻的 `*.test.ts` 文件、显式源映射和本地导入图运行精确目标。宽泛/配置/package 变更会被跳过,除非它们映射到精确测试。 -- `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`:显式的宽泛变更测试运行。当测试 harness、配置或 package 编辑应回退到 Vitest 更宽泛的变更测试行为时使用它。 +- `pnpm test:changed`:低成本的智能变更测试运行。它会根据直接测试编辑、同级 `*.test.ts` 文件、显式源映射和本地导入图运行精确目标。宽泛的配置/包变更会被跳过,除非它们映射到精确测试。 +- `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`:显式的宽泛变更测试运行。当测试 harness/配置/包编辑应回退到 Vitest 更宽泛的变更测试行为时使用。 - `pnpm changed:lanes`:显示相对于 `origin/main` 的 diff 触发的架构通道。 -- `pnpm check:changed`:对相对于 `origin/main` 的 diff 运行智能变更检查门禁。它会为受影响的架构通道运行 typecheck、lint 和 guard 命令,但不会运行 Vitest 测试。使用 `pnpm test:changed` 或显式的 `pnpm test ` 提供测试证明。 -- `pnpm test`:将显式文件/目录目标路由到有作用域的 Vitest 通道。无目标运行使用固定分片组,并展开为叶级配置以进行本地并行执行;插件组始终展开为按插件划分的分片配置,而不是一个巨大的根项目进程。 -- 测试包装器运行结束时会输出简短的 `[test] passed|failed|skipped ... in ...` 摘要。Vitest 自己的耗时行保留为每个分片的详细信息。 +- `pnpm check:changed`:针对相对于 `origin/main` 的 diff 运行智能变更检查门禁。它会为受影响的架构通道运行类型检查、lint 和守护命令,但不会运行 Vitest 测试。使用 `pnpm test:changed` 或显式 `pnpm test ` 作为测试证明。 +- `pnpm test`:将显式文件/目录目标路由到有作用域的 Vitest 通道。未指定目标的运行使用固定分片组,并展开为叶子配置以便本地并行执行;插件组始终展开为按插件划分的分片配置,而不是一个巨大的根项目进程。 +- 测试包装器运行结束时会输出一条简短的 `[test] passed|failed|skipped ... in ...` 摘要。Vitest 自己的时长行仍保留为每个分片的详情。 - 共享 OpenClaw 测试状态:当测试需要隔离的 `HOME`、`OPENCLAW_STATE_DIR`、`OPENCLAW_CONFIG_PATH`、配置 fixture、工作区、智能体目录或 auth-profile 存储时,在 Vitest 中使用 `src/test-utils/openclaw-test-state.ts`。 -- 进程 E2E 辅助工具:当 Vitest 进程级 E2E 测试需要在一处完成运行中的 Gateway 网关、CLI 环境、日志捕获和清理时,使用 `test/helpers/openclaw-test-instance.ts`。 -- Docker/Bash E2E 辅助工具:source `scripts/lib/docker-e2e-image.sh` 的通道可以将 `docker_e2e_test_state_shell_b64