extensions/qa-channel:合成訊息通道,具備 DM、頻道、執行緒、 reaction、編輯與刪除介面。extensions/qa-lab:用於觀察 transcript、注入入站訊息, 以及匯出 Markdown 報告的偵錯器 UI 與 QA bus。extensions/qa-matrix、未來 runner 外掛:live-transport adapter, 會在子 QA 閘道內驅動真實通道。qa/:由 repo 支援的 kickoff 任務種子資產與基準 QA 情境。- Mantis:針對需要真實傳輸、瀏覽器截圖、VM 狀態與 PR 證據的 bug, 進行前後 live verification。
命令介面
每個 QA flow 都在pnpm openclaw qa <subcommand> 下執行。許多都有 pnpm qa:*
script alias;兩種形式都支援。
| 命令 | 用途 |
|---|---|
qa run | 不帶 --qa-profile 的 bundled QA self-check;帶 --qa-profile smoke-ci、--qa-profile release 或 --qa-profile all 時,則是 taxonomy-backed maturity profile runner。 |
qa suite | 對 QA 閘道 lane 執行 repo-backed scenarios。Alias:pnpm openclaw qa suite --runner multipass 用於一次性的 Linux VM。 |
qa coverage | 列印 YAML scenario-coverage inventory(--json 用於機器輸出)。 |
qa parity-report | 比較兩個 qa-suite-summary.json 檔案並寫入 agentic parity report,或使用 --runtime-axis --token-efficiency 從單一 runtime-pair summary 寫入 Codex-vs-OpenClaw runtime parity 與 token-efficiency 報告。 |
qa character-eval | 跨多個即時模型執行 character QA 情境,並產生經評審的報告。請參閱報告。 |
qa manual | 對選定的 provider/model lane 執行一次性 prompt。 |
qa ui | 啟動 QA 偵錯器 UI 與本機 QA bus(alias:pnpm qa:lab:ui)。 |
qa docker-build-image | 建置預先烘焙的 QA Docker image。 |
qa docker-scaffold | 寫入 QA dashboard + 閘道 lane 的 docker-compose scaffold。 |
qa up | 建置 QA site、啟動 Docker-backed stack,並列印 URL(alias:pnpm qa:lab:up;:fast variant 會加入 --use-prebuilt-image --bind-ui-dist --skip-ui-build)。 |
qa aimock | 只啟動 AIMock provider server。 |
qa mock-openai | 只啟動 scenario-aware mock-openai provider server。 |
qa credentials doctor / add / list / remove | 管理共享的 Convex credential pool。 |
qa matrix | 針對一次性 Tuwunel homeserver 的 live transport lane。請參閱 Matrix QA。 |
qa telegram | 針對真實私人 Telegram 群組的 live transport lane。 |
qa discord | 針對真實私人 Discord guild channel 的 live transport lane。 |
qa slack | 針對真實私人 Slack channel 的 live transport lane。 |
qa whatsapp | 針對真實 WhatsApp Web 帳號的 live transport lane。 |
qa mantis | 用於 live transport bug 的前後驗證 runner,包含 Discord status-reactions 證據、Crabbox desktop/browser smoke,以及 Slack-in-VNC smoke。請參閱 Mantis 與 Mantis Slack Desktop Runbook。 |
qa run 會從 taxonomy.yaml 讀取 membership,然後透過
qa suite 分派解析出的 scenarios。--surface 與
--category 會篩選選定的 profile,而不是定義獨立 lane。
產生的 qa-evidence.json 會包含 profile scorecard 摘要,其中有
selected-category counts 與 missing coverage IDs;各個 evidence
entries 仍是 tests、coverage roles 與 results 的事實來源。
Taxonomy feature coverage IDs 是精確的 proof targets,而不是 aliases。Primary
scenario coverage 會滿足相符 IDs;secondary coverage 則維持 advisory。
Coverage IDs 使用帶有小寫英數字/dash segments 的 dotted
namespace.behavior 形式;profile、surface 與 category IDs 仍可使用
既有的 dashed 或 dotted taxonomy IDs。
Slim evidence 會省略每個 entry 的 execution,並設定 evidenceMode: "slim";
smoke-ci 預設為 slim,而 --evidence-mode full 會還原完整 entries:
smoke-ci 搭配 mock model providers 與
Crabline local provider servers 進行可決定性的 profile proof。使用 release 針對 live
channels 進行 Stable/LTS proof。只有在明確執行 full-taxonomy evidence runs 時才使用
all;它會選取每個 active maturity category,並可透過 QA Profile Evidence workflow 搭配 qa_profile=all 分派。當命令也需要 OpenClaw
root profile 時,請將 root profile 放在 QA 命令之前:
操作者流程
目前的 QA operator flow 是雙窗格 QA site:- 左側:包含 agent 的閘道 dashboard(Control UI)。
- 右側:QA Lab,顯示類 Slack transcript 與 scenario plan。
qa:lab:up:fast 會讓 Docker services 使用 prebuilt image,並將
extensions/qa-lab/web/dist bind-mount 到 qa-lab container。qa:lab:watch
會在變更時重建該 bundle,而當 QA Lab
asset hash 變更時,瀏覽器會自動重新載入。
若要執行本機 OpenTelemetry signal smoke,請執行:
diagnostics-otel 外掛後執行
otel-trace-smoke QA
情境,接著斷言 traces、
metrics 與 logs 已匯出。它會解碼匯出的 protobuf trace spans,
並檢查 release-critical shape:
openclaw.run、openclaw.harness.run、latest GenAI semantic-convention
model-call span、openclaw.context.assembled 與 openclaw.message.delivery
必須存在。smoke 會強制
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental,因此 model-call
span 必須使用 {gen_ai.operation.name} {gen_ai.request.model} name;
成功 turns 的 model calls 不得匯出 StreamAbandoned;raw diagnostic IDs 與
openclaw.content.* attributes 必須保持在 trace 之外。raw OTLP
payloads 不得包含 prompt sentinel、response sentinel 或 QA session
key。它會在 QA suite artifacts 旁寫入 otel-smoke-summary.json。
若要執行由 collector 支援的 OpenTelemetry smoke,請執行:
diagnostics-prometheus 的情況下執行 docker-prometheus-smoke QA 情境,驗證未經驗證的 scrape 會被拒絕,接著檢查經驗證的 scrape 是否包含發布關鍵的指標系列,且不含提示內容、回應內容、原始診斷識別碼、驗證權杖或本機路徑。
若要連續執行兩個可觀測性 smoke,請使用:
qa 命令。變更診斷 instrumentation 時,請從已建置的原始碼 checkout 使用 pnpm qa:otel:smoke、pnpm qa:prometheus:smoke 或 pnpm qa:observability:smoke。
若要執行不需要模型供應商認證的真實傳輸 Matrix smoke lane,請使用 deterministic mock OpenAI provider 執行 fast profile:
qa-channel),接著在 .artifacts/qa-e2e/matrix-<timestamp>/ 下寫入 Markdown 報告、JSON 摘要、observed-events artifact 與合併輸出記錄。
這些情境涵蓋單元測試無法端到端證明的傳輸行為:mention gating、allow-bot 政策、allowlist、頂層與 thread 回覆、DM 路由、reaction handling、inbound edit suppression、restart replay dedupe、homeserver interruption recovery、approval metadata delivery、media handling,以及 Matrix E2EE bootstrap/recovery/verification 流程。E2EE 命令列介面 profile 也會透過同一個一次性 homeserver 驅動 openclaw matrix encryption setup 與 verification 命令,然後檢查閘道回覆。
Discord 也有僅限 Mantis 的選擇性情境,用於重現 bug。使用 --scenario discord-status-reactions-tool-only 可執行明確的狀態 reaction 時間軸,或使用 --scenario discord-thread-reply-filepath-attachment 建立真正的 Discord thread,並驗證 message.thread-reply 會保留 filePath 附件。這些情境不包含在預設 live Discord lane 中,因為它們是 before/after 重現探針,而不是廣泛的 smoke 覆蓋。當 QA 環境中設定了 MANTIS_DISCORD_VIEWER_CHROME_PROFILE_DIR 或 MANTIS_DISCORD_VIEWER_CHROME_PROFILE_TGZ_B64 時,thread-attachment Mantis workflow 也可以加入已登入 Discord Web 的見證影片。該 viewer profile 只用於視覺擷取;pass/fail 判定仍來自 Discord REST oracle。
CI 在 .github/workflows/qa-live-transports-convex.yml 中使用同一組命令介面。排程與預設手動執行會使用 QA 提供的 live-frontier 認證、--fast 與 OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS=3000 執行 fast Matrix profile。手動 matrix_profile=all 會展開成五個 profile shard。
若要執行真實傳輸的 Telegram、Discord、Slack 與 WhatsApp smoke lane:
slack-qa/、slack-desktop-smoke.png 與 slack-desktop-smoke.mp4 複製回 Mantis artifact directory。Crabbox desktop/browser leases 會預先提供 capture tools 與 browser/native-build helper packages,因此情境應只在較舊的 lease 上安裝 fallback。Mantis 會在 mantis-slack-desktop-smoke-report.md 中回報總時間與各階段時間,讓緩慢執行能顯示時間花在 lease warmup、credential acquisition、remote setup 或 artifact copy。透過 VNC 手動登入 Slack Web 後,請重複使用 --lease-id <cbx_...>;重複使用的 lease 也會讓 Crabbox 的 pnpm store cache 保持溫熱。預設的 --hydrate-mode source 會從原始碼 checkout 驗證,並在 VM 內執行 install/build。只有在重複使用的遠端 workspace 已有 node_modules 與已建置的 dist/ 時,才使用 --hydrate-mode prehydrated;該模式會略過昂貴的 install/build 步驟,並在 workspace 尚未準備好時 fail closed。使用 --gateway-setup 時,Mantis 會讓持久性 OpenClaw Slack 閘道在 VM 內的連接埠 38973 上持續執行;不使用時,該命令會執行一般 bot-to-bot Slack QA lane,並在 artifact capture 後結束。
若要以 desktop evidence 證明 native Slack approval UI,請執行 Mantis approval checkpoint mode:
--gateway-setup 互斥。它會執行 Slack approval scenarios、拒絕非 approval scenario id、在每個 pending 與 resolved approval state 等待、將觀察到的 Slack API message render 成 approval-checkpoints/<scenario>-pending.png 與 approval-checkpoints/<scenario>-resolved.png,然後在任何 checkpoint、message evidence、acknowledgement 或 rendered screenshot 遺失或為空時失敗。Cold CI leases 仍可能在 slack-desktop-smoke.png 中顯示 Slack sign-in;approval checkpoint images 是此 lane 的視覺證明。
Operator checklist、GitHub workflow dispatch 命令、evidence-comment contract、hydrate-mode decision table、timing interpretation 與 failure handling steps 位於 Mantis Slack Desktop Runbook。
若要執行 agent/CV 風格 desktop task,請執行:
visual-task 會租用或重複使用 Crabbox desktop/browser machine、啟動 crabbox record --while、透過巢狀 visual-driver 驅動可見 browser、擷取 visual-task.png、在選取 --vision-mode image-describe 時對 screenshot 執行 openclaw infer image describe,並寫入 visual-task.mp4、mantis-visual-task-summary.json、mantis-visual-task-driver-result.json 與 mantis-visual-task-report.md。設定 --expect-text 時,vision prompt 會要求結構化 JSON verdict,且只有在模型回報正面的 visible evidence 時才通過;僅引用 target text 的 negative response 會讓 assertion 失敗。使用 --vision-mode metadata 可執行不呼叫 image-understanding provider 的 no-model smoke,用來證明 desktop、browser、screenshot 與 video plumbing。Recording 是 visual-task 的必要 artifact;如果 Crabbox 未錄到非空的 visual-task.mp4,即使 visual driver 通過,task 也會失敗。失敗時,除非 task 已經通過且未設定 --keep-lease,否則 Mantis 會保留 lease 供 VNC 使用。
使用 pooled live credentials 前,請執行:
Live transport coverage
Live transport lanes 共用一份 contract,而不是各自發明自己的 scenario list shape。qa-channel 是廣泛的 synthetic product-behavior suite,不屬於 live transport coverage matrix。
Live transport runners 應從 openclaw/plugin-sdk/qa-live-transport-scenarios 匯入 shared scenario ids、baseline coverage helpers 與 scenario-selection helper。
| Lane | Canary | Mention gating | Bot-to-bot | Allowlist block | Top-level reply | Quote reply | Restart resume | Thread follow-up | Thread isolation | Reaction observation | Help command | Native command registration |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Matrix | x | x | x | x | x | x | x | x | x | |||
| Telegram | x | x | x | x | ||||||||
| Discord | x | x | x | x | ||||||||
| Slack | x | x | x | x | x | x | x | x | ||||
| x | x | x | x | x | x | x | x |
qa-channel 保持為廣泛的 product-behavior suite,同時讓 Matrix、Telegram 與其他 live transports 共用一份明確的 transport-contract checklist。
若要執行不把 Docker 帶入 QA path 的一次性 Linux VM lane,請執行:
qa suite,然後將一般 QA report 與 summary 複製回 host 上的 .artifacts/qa-e2e/...。它會重複使用與 host 上 qa suite 相同的 scenario-selection behavior。Host 與 Multipass suite runs 預設會使用隔離的 gateway workers 平行執行多個 selected scenarios。qa-channel 預設 concurrency 為 4,並受 selected scenario count 上限限制。使用 --concurrency <count> 調整 worker count,或使用 --concurrency 1 進行 serial execution。使用 --pack personal-agent 可執行 personal assistant benchmark pack。pack selector 可與重複的 --scenario flags 相加:explicit scenarios 先執行,接著 pack scenarios 依 pack order 執行並移除重複項。當自訂 QA runner 已提供 OpenTelemetry collector setup,並想要同時選取 OpenTelemetry 與 Prometheus diagnostics smoke scenarios 時,請使用 --pack observability。任何 scenario 失敗時,命令會以非零狀態結束。若想要取得 artifacts 但不讓 exit code 失敗,請使用 --allow-failures。Live runs 會轉送對 guest 實用的 supported QA auth inputs:env-based provider keys、QA live provider config path,以及存在時的 CODEX_HOME。請將 --output-dir 保持在 repo root 下,讓 guest 能透過已掛載的 workspace 寫回。
Telegram、Discord、Slack 與 WhatsApp QA 參考
Matrix 有專屬頁面,因為它的情境數量多,且需要 Docker 支援的 homeserver 佈建。Telegram、Discord、Slack 與 WhatsApp 會針對既有的真實傳輸執行,因此其參考資料放在這裡。共用命令列介面旗標
這些通道會透過extensions/qa-lab/src/live-transports/shared/live-transport-cli.ts 註冊,並接受相同旗標:
| 旗標 | 預設值 | 說明 |
|---|---|---|
--scenario <id> | - | 只執行此情境。可重複指定。 |
--output-dir <path> | <repo>/.artifacts/qa-e2e/<transport>-<timestamp> | 寫入報告、摘要、證據、傳輸特定成品與輸出記錄的位置。相對路徑會相對於 --repo-root 解析。 |
--repo-root <path> | process.cwd() | 從中立的 cwd 呼叫時使用的儲存庫根目錄。 |
--sut-account <id> | sut | QA 閘道設定中的暫時帳號 id。 |
--provider-mode <mode> | live-frontier | mock-openai 或 live-frontier(舊版 live-openai 仍可使用)。 |
--model <ref> / --alt-model <ref> | provider default | 主要/替代模型 refs。 |
--fast | off | 在支援時使用供應商快速模式。 |
--credential-source <env|convex> | env | 請參閱 Convex 憑證集區。 |
--credential-role <maintainer|ci> | CI 中為 ci,否則為 maintainer | 使用 --credential-source convex 時使用的角色。 |
--allow-failures 會寫入成品,但不會設定失敗的結束代碼。
Telegram QA
@BotFather 啟用 Bot-to-Bot Communication Mode 時,bot 對 bot 觀察效果最佳。
使用 --credential-source env 時需要的環境變數:
OPENCLAW_QA_TELEGRAM_GROUP_ID- 數字聊天 id(字串)。OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKENOPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN
extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts):
telegram-canarytelegram-mention-gatingtelegram-mentioned-message-replytelegram-help-commandtelegram-commands-commandtelegram-tools-compact-commandtelegram-whoami-commandtelegram-status-commandtelegram-repeated-command-authorizationtelegram-other-bot-command-gatingtelegram-context-commandtelegram-current-session-status-tooltelegram-reply-chain-exact-markertelegram-stream-final-single-messagetelegram-long-final-reuses-previewtelegram-long-final-three-chunks
mock-openai 預設也包含確定性的回覆鏈與最終訊息串流檢查。telegram-current-session-status-tool 仍為選擇加入,因為它只有在 canary 後直接串接時才穩定,而不是在任意原生命令回覆之後。使用 pnpm openclaw qa telegram --list-scenarios --provider-mode mock-openai 可列印目前預設/選用分組與回歸 refs。
輸出成品:
telegram-qa-report.mdqa-evidence.json- 即時傳輸檢查的證據項目,包含 profile、coverage、provider、channel、artifacts、result 與 RTT 欄位。
qa-evidence.json 的 result.timing 底下。
OPENCLAW_QA_CREDENTIAL_SOURCE=convex 時,套件即時包裝器會租用一組 kind: "telegram" 憑證,將租用的群組/driver/SUT bot
環境變數匯出到已安裝套件的執行中,對租約進行心跳偵測,並在關閉時釋放。
選取 Convex 時,套件包裝器在 CI 之外預設會對 telegram-mentioned-message-reply 執行 20 次 RTT 檢查、使用 30 秒 RTT 逾時,以及 Convex 角色
maintainer。覆寫
OPENCLAW_NPM_TELEGRAM_RTT_SAMPLES、OPENCLAW_NPM_TELEGRAM_RTT_TIMEOUT_MS
或 OPENCLAW_NPM_TELEGRAM_RTT_MAX_FAILURES,即可調整 RTT 測量,而不需要
建立獨立的 RTT 命令或 Telegram 專用摘要格式。
Discord QA
/help 命令,以及選擇加入的 Mantis 證據情境。
使用 --credential-source env 時需要的環境變數:
OPENCLAW_QA_DISCORD_GUILD_IDOPENCLAW_QA_DISCORD_CHANNEL_IDOPENCLAW_QA_DISCORD_DRIVER_BOT_TOKENOPENCLAW_QA_DISCORD_SUT_BOT_TOKENOPENCLAW_QA_DISCORD_SUT_APPLICATION_ID- 必須符合 Discord 傳回的 SUT bot 使用者 id(否則通道會快速失敗)。
OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1會在觀察訊息成品中保留訊息本文。OPENCLAW_QA_DISCORD_VOICE_CHANNEL_ID會為discord-voice-autojoin選擇語音/舞台頻道;若未設定,情境會為 SUT bot 選取第一個可見的語音/舞台頻道。
extensions/qa-lab/src/live-transports/discord/discord-live.runtime.ts:36):
discord-canarydiscord-mention-gatingdiscord-native-help-command-registrationdiscord-voice-autojoin- 選擇加入的語音情境。單獨執行,啟用channels.discord.voice.autoJoin,並驗證 SUT bot 目前的 Discord 語音狀態是目標語音/舞台頻道。Convex Discord 憑證可包含選用的voiceChannelId;否則執行器會在 guild 中探索第一個可見的語音/舞台頻道。discord-status-reactions-tool-only- 選擇加入的 Mantis 情境。因為它會將 SUT 切換為永遠開啟、僅工具的 guild 回覆並設定messages.statusReactions.enabled=true,所以會單獨執行,接著擷取 REST reaction 時間軸與 HTML/PNG 視覺成品。Mantis 前後對照報告也會將情境提供的 MP4 成品保留為baseline.mp4和candidate.mp4。
discord-qa-report.mdqa-evidence.json- 即時傳輸檢查的證據項目。discord-qa-observed-messages.json- 除非設定OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1,否則本文會被遮蔽。- 執行狀態 reaction 情境時,會產生
discord-qa-reaction-timelines.json與discord-status-reactions-tool-only-timeline.png。
Slack QA
--credential-source env 時需要的環境變數:
OPENCLAW_QA_SLACK_CHANNEL_IDOPENCLAW_QA_SLACK_DRIVER_BOT_TOKENOPENCLAW_QA_SLACK_SUT_BOT_TOKENOPENCLAW_QA_SLACK_SUT_APP_TOKEN
OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1會在觀察訊息成品中保留訊息本文。OPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_DIR會為 Mantis 啟用視覺核准 檢查點。執行器會寫入<scenario>.pending.json與<scenario>.resolved.json,然後等待相符的.ack.json檔案。OPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_TIMEOUT_MS會覆寫檢查點 確認逾時。預設值為120000。
extensions/qa-lab/src/live-transports/slack/slack-live.runtime.ts):
slack-canaryslack-mention-gatingslack-allowlist-blockslack-top-level-reply-shapeslack-restart-resumeslack-thread-follow-upslack-thread-isolationslack-approval-exec-native- 選擇加入的原生 Slack exec 核准情境。 透過閘道要求 exec 核准,驗證 Slack 訊息有 原生核准按鈕、解析它,並驗證已解析的 Slack 更新。slack-approval-plugin-native- 選擇加入的原生 Slack 外掛核准情境。 同時啟用 exec 與外掛核准轉送,使外掛事件不會 被 exec 核准路由抑制,接著驗證相同的待處理/已解析 原生 Slack UI 路徑。
slack-qa-report.mdqa-evidence.json- 即時傳輸檢查的證據項目。slack-qa-observed-messages.json- 除非設定OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1,否則本文會被遮蔽。approval-checkpoints/- 僅在 Mantis 設定OPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_DIR時;包含檢查點 JSON、 確認 JSON,以及待處理/已解析螢幕截圖。
設定 Slack 工作區
此通道需要同一個工作區中的兩個不同 Slack app,以及兩個 bot 都已加入的頻道:channelId- 兩個 bot 都已受邀加入的頻道Cxxxxxxxxxxid。請使用專用頻道;此通道每次執行都會發文。driverBotToken- Driver app 的 bot token(xoxb-...)。sutBotToken- SUT app 的 bot token(xoxb-...),它必須是與 driver 不同的 Slack app,才能有不同的 bot 使用者 id。sutAppToken- SUT app 的 app 層級 token(xapp-...),具備connections:write,供 Socket Mode 使用,讓 SUT app 能接收事件。
extensions/slack/src/setup-shared.ts:10)限縮為即時 Slack QA 套件涵蓋的權限與事件。關於使用者看到的正式頻道設定,請參閱 Slack 頻道快速設定;QA Driver/SUT 配對是刻意分開的,因為此通道需要同一個工作區中兩個不同的 bot 使用者 id。
1. 建立 Driver app
前往 api.slack.com/apps → Create New App → From a manifest → 選取 QA 工作區、貼上下列 manifest,然後 Install to Workspace:
xoxb-...)- 這會成為 driverBotToken。驅動程式只需要張貼訊息並識別自身;不需要事件,也不需要 Socket Mode。
2. 建立 SUT app
在同一個工作區重複 Create New App → From a manifest。這個 QA app 刻意使用隨附 Slack 外掛生產 manifest 的較窄版本(extensions/slack/src/setup-shared.ts:10):因為即時 Slack QA 套件尚未涵蓋反應處理,所以省略反應 scope 和事件。
- Install to Workspace → 複製 Bot User OAuth Token → 這會成為
sutBotToken。 - Basic Information → App-Level Tokens → Generate Token and Scopes → 新增 scope
connections:write→ 儲存 → 複製xapp-...值 → 這會成為sutAppToken。
auth.test,確認兩個 Bot 有不同的使用者 id。執行階段會依使用者 id 區分驅動程式與 SUT;重複使用同一個 app 來擔任兩者,會立刻在提及閘控失敗。
3. 建立頻道
在 QA 工作區中建立頻道(例如 #openclaw-qa),並從頻道內邀請兩個 Bot:
Cxxxxxxxxxx id - 這會成為 channelId。公開頻道可行;如果使用私人頻道,兩個 app 都已具備 groups:history,因此 harness 的歷史讀取仍會成功。
4. 註冊憑證
有兩種選項。單機除錯時使用 env vars(設定四個 OPENCLAW_QA_SLACK_* 變數並傳入 --credential-source env),或將共享 Convex pool 植入資料,讓 CI 和其他維護者可以租用。
對於 Convex pool,將四個欄位寫入 JSON 檔:
OPENCLAW_QA_CONVEX_SITE_URL 和 OPENCLAW_QA_CONVEX_SECRET_MAINTAINER 後,註冊並驗證:
count: 1、status: "active",且沒有 lease 欄位。
5. 端對端驗證
在本機執行 lane,確認兩個 Bot 能透過 broker 互相對話:
slack-qa-report.md 會顯示 slack-canary 和 slack-mention-gating 的狀態皆為 pass。如果 lane 卡住約 90 秒並以 Convex credential pool exhausted for kind "slack" 結束,表示 pool 為空,或每一列都已被租用 - qa credentials list --kind slack --status all --json 會告訴你是哪一種情況。
WhatsApp QA
--credential-source env 時必要的 env:
OPENCLAW_QA_WHATSAPP_DRIVER_PHONE_E164OPENCLAW_QA_WHATSAPP_SUT_PHONE_E164OPENCLAW_QA_WHATSAPP_DRIVER_AUTH_ARCHIVE_BASE64OPENCLAW_QA_WHATSAPP_SUT_AUTH_ARCHIVE_BASE64
OPENCLAW_QA_WHATSAPP_GROUP_JID會啟用群組情境,例如whatsapp-mention-gating、whatsapp-group-pending-history-context、whatsapp-broadcast-group-fanout、whatsapp-group-activation-always、whatsapp-group-reply-to-bot-triggers、群組 action/media/poll 情境,以及whatsapp-group-allowlist-block。OPENCLAW_QA_WHATSAPP_CAPTURE_CONTENT=1會在 observed-message 成品中保留訊息本文。
extensions/qa-lab/src/live-transports/whatsapp/whatsapp-live.runtime.ts):
- 基準與群組閘控:
whatsapp-canary、whatsapp-pairing-block、whatsapp-mention-gating、whatsapp-group-pending-history-context、whatsapp-group-activation-always、whatsapp-group-reply-to-bot-triggers、whatsapp-top-level-reply-shape、whatsapp-restart-resume、whatsapp-group-allowlist-block。 - 原生命令:
whatsapp-help-command、whatsapp-status-command、whatsapp-commands-command、whatsapp-tools-compact-command、whatsapp-whoami-command、whatsapp-context-command、whatsapp-native-new-command。 - 回覆與最終輸出行為:
whatsapp-tool-only-usage-footer、whatsapp-reply-to-message、whatsapp-group-reply-to-message、whatsapp-reply-to-mode-batched、whatsapp-reply-context-isolation、whatsapp-reply-delivery-shape、whatsapp-stream-final-message-accounting。 - 使用者路徑訊息動作:
whatsapp-agent-message-action-react會從 真實驅動程式 DM 開始,讓模型呼叫message工具,並觀察原生 WhatsApp 反應。whatsapp-agent-message-action-upload-file以相同姿態使用message(action=upload-file),並觀察原生 WhatsApp 媒體。whatsapp-group-agent-message-action-react和whatsapp-group-agent-message-action-upload-file會在真實 WhatsApp 群組中證明相同的使用者可見動作。 - 群組 fanout:
whatsapp-broadcast-group-fanout會從一則被提及的 WhatsApp 群組訊息開始,並驗證來自main和qa-second的不同可見回覆。 - 群組啟用:
whatsapp-group-activation-always會將真實群組 工作階段變更為/activation always,證明未提及的群組訊息會喚醒 agent,然後還原為/activation mention。whatsapp-group-reply-to-bot-triggers會植入一則 Bot 回覆,傳送一則沒有明確提及的原生引用回覆, 並驗證 agent 會從該回覆脈絡中醒來。 - 傳入媒體與結構化訊息:
whatsapp-inbound-image-caption、whatsapp-audio-preflight、whatsapp-inbound-structured-messages、whatsapp-group-audio-gating、whatsapp-inbound-reaction-no-trigger。 這些會透過驅動程式傳送真實 WhatsApp 圖片、音訊、文件、位置、聯絡人、貼圖, 和反應事件。 - 直接 Gateway contract probes:
whatsapp-outbound-media-matrix、whatsapp-outbound-document-preserves-filename、whatsapp-outbound-poll、whatsapp-group-outbound-media、whatsapp-group-outbound-poll、whatsapp-message-actions、whatsapp-reply-context-isolation、whatsapp-reply-delivery-shape。這些會刻意繞過模型提示, 並證明確定性的閘道/channelsend、poll和message.actioncontract。 - 存取控制涵蓋範圍:
whatsapp-access-control-dm-open、whatsapp-access-control-dm-disabled、whatsapp-access-control-group-open、whatsapp-access-control-group-disabled、whatsapp-group-allowlist-block。 - 原生核准:
whatsapp-approval-exec-deny-native、whatsapp-approval-exec-native、whatsapp-approval-exec-reaction-native、whatsapp-approval-exec-group-reaction-native、whatsapp-approval-plugin-native。 - 狀態反應:
whatsapp-status-reactions、whatsapp-status-reaction-lifecycle。
live-frontier 預設 lane 維持較小規模,包含 10 個情境,以提供快速冒煙涵蓋。mock-openai 預設 lane 會在只模擬模型輸出的情況下,透過真實 WhatsApp 傳輸執行 44 個確定性情境。核准情境與少數較重或阻塞的檢查,仍需以情境 id 明確指定。
WhatsApp QA 驅動程式會觀察結構化即時事件(text、media、
location、reaction 和 poll),也可以主動傳送媒體、投票、
聯絡人、位置和貼圖。QA Lab 會透過
@openclaw/whatsapp/api.js 套件介面匯入該驅動程式,而不是深入私有
WhatsApp 執行階段檔案。對於群組觀察,fromJid 是群組 JID,而
participantJid 和 fromPhoneE164 會識別參與者傳送者。訊息
內容預設會被遮蔽。直接閘道
poll、upload-file、media、group poll、group media 和 reply-shape probe 是 transport/API contract
檢查;它們不會被視為使用者提示讓 agent 選擇相同動作的證明。使用者路徑動作證明來自
whatsapp-agent-message-action-react 和
whatsapp-group-agent-message-action-react 等情境,其中驅動程式會傳送一般
WhatsApp 訊息,而 QA Lab 會觀察產生的原生 WhatsApp 成品。
WhatsApp 報告包含每個情境的姿態(user-path、direct-gateway
或 native-approval),因此證據不會被誤認為比實際證明更強的 contract。
輸出成品:
whatsapp-qa-report.mdqa-evidence.json- 即時傳輸檢查的證據項目。whatsapp-qa-observed-messages.json- 除非OPENCLAW_QA_WHATSAPP_CAPTURE_CONTENT=1,否則本文會被遮蔽。
Convex 憑證 pool
Telegram、Discord、Slack 和 WhatsApp lane 可以從共享 Convex pool 租用憑證,而不是讀取上述 env vars。傳入--credential-source convex(或設定 OPENCLAW_QA_CREDENTIAL_SOURCE=convex);QA Lab 會取得排他租約,在執行期間為其送出心跳偵測,並在關閉時釋放。Pool kinds 為 "telegram"、"discord"、"slack" 和 "whatsapp"。
Broker 在 admin/add 上驗證的 payload 形狀:
- Telegram (
kind: "telegram"):{ groupId: string, driverToken: string, sutToken: string }-groupId必須是數值型 chat-id 字串。 - Telegram 真實使用者 (
kind: "telegram-user"):{ groupId: string, sutToken: string, testerUserId: string, testerUsername: string, telegramApiId: string, telegramApiHash: string, tdlibDatabaseEncryptionKey: string, tdlibArchiveBase64: string, tdlibArchiveSha256: string, desktopTdataArchiveBase64: string, desktopTdataArchiveSha256: string }- 僅供 Mantis Telegram Desktop 證明使用。通用 QA Lab 路徑不得取得此類型。 - Discord (
kind: "discord"):{ guildId: string, channelId: string, driverBotToken: string, sutBotToken: string, sutApplicationId: string }。 - WhatsApp (
kind: "whatsapp"):{ driverPhoneE164: string, sutPhoneE164: string, driverAuthArchiveBase64: string, sutAuthArchiveBase64: string, groupJid?: string }- 電話號碼必須是彼此不同的 E.164 字串。
telegram-user 租約,同時供 TDLib 命令列介面驅動程式和 Telegram Desktop
見證者使用,然後在發布證明後釋放。
當 PR 需要確定性的視覺差異時,Mantis 可以在 main 和 PR head 上使用相同的模擬模型
回覆,同時變更 Telegram 格式化器或傳遞
層。擷取預設值已針對 PR 評論調校:標準 Crabbox
類別、24fps 桌面錄影、24fps 動態 GIF,以及 1920px 預覽寬度。
前後對照評論應發布乾淨的套件組合,其中只包含
預期的 GIF。
Slack 路徑也可以使用該集區。Slack payload 形狀檢查目前位於 Slack QA runner,而不是 broker;請使用 { channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string },並使用像 Cxxxxxxxxxx 這樣的 Slack 頻道 ID。請參閱設定 Slack 工作區以了解 app 和 scope 佈建。
操作用環境變數與 Convex broker 端點契約位於測試 → 透過 Convex 共用 Telegram 認證(章節名稱早於多頻道集區;租約語意在各種類型之間共用)。
由 repo 支援的種子資料
種子資產位於qa/:
qa/scenarios/index.yamlqa/scenarios/<theme>/*.yaml
qa-lab 應維持為通用 YAML 情境執行器。每個情境 YAML 檔案都是
單次測試執行的事實來源,並應定義:
- 頂層
title scenariometadatascenario中選用的 category、capability、lane 和 risk metadatascenario中的 docs 和 code refsscenario中選用的外掛需求scenario中選用的閘道設定 patch- flow 情境的可執行頂層
flow,或 Vitest 與 Playwright 情境的scenario.execution.kind/scenario.execution.path
flow 的可重用 runtime surface 可以保持通用
且橫跨多個關注面。例如,YAML 情境可以結合傳輸端
helper 與瀏覽器端 helper,透過閘道
browser.request seam 驅動嵌入式 Control UI,而不需要加入特殊案例 runner。
情境檔案應依產品能力分組,而不是依原始碼樹
資料夾分組。檔案移動時,請保持情境 ID 穩定;使用 docsRefs 和 codeRefs
追蹤實作。
基準清單應保持足夠廣泛,以涵蓋:
- DM 和頻道聊天
- thread 行為
- 訊息 action 生命週期
- 排程 callback
- 記憶回想
- 模型切換
- 子代理交接
- repo 讀取和文件讀取
- 一個小型建置任務,例如 Lobster Invaders
供應商模擬路徑
qa suite 有兩個本機供應商模擬路徑:
mock-openai是具情境感知能力的 OpenClaw 模擬。它仍是 repo 支援 QA 和 parity gate 的預設 確定性模擬路徑。aimock會啟動 AIMock 支援的供應商伺服器,用於實驗性 protocol、 fixture、record/replay 和 chaos 覆蓋。它是附加項目,不會 取代mock-openai情境 dispatcher。
extensions/qa-lab/src/providers/ 之下。
每個供應商擁有其預設值、本機伺服器啟動、閘道模型設定、
auth-profile staging 需求,以及 live/mock capability flags。共用 suite 和
閘道程式碼應透過供應商 registry 路由,而不是依供應商名稱分支。
傳輸 adapter
qa-lab 擁有適用於 YAML QA 情境的通用傳輸 seam。qa-channel 是
合成預設值。crabline 會啟動符合本機供應商形狀的伺服器,並對其執行
OpenClaw 的一般頻道外掛。live 保留給真實
供應商認證和外部頻道使用。
在架構層級,分工如下:
qa-lab擁有通用情境執行、worker concurrency、artifact 寫入,以及 reporting。- 傳輸 adapter 擁有閘道設定、readiness、inbound 和 outbound observation、transport actions,以及 normalized transport state。
qa/scenarios/下的 YAML 情境檔案定義測試執行;qa-lab提供用來執行它們的可重用 runtime surface。
新增頻道
將頻道新增至 YAML QA 系統需要頻道實作,加上 一組用於驗證頻道契約的情境包。若要取得 smoke CI 覆蓋,請新增 對應的 Crabline 本機供應商伺服器,並透過crabline
driver 對外提供。
當共用 qa-lab host 可以擁有該 flow 時,不要新增新的頂層 QA command root。
qa-lab 擁有共用 host 機制:
openclaw qacommand root- suite startup 和 teardown
- worker concurrency
- artifact 寫入
- report 產生
- 情境執行
- 舊版
qa-channel情境的 compatibility aliases
openclaw qa <runner>如何掛載於共用qaroot 之下- 閘道如何針對該傳輸設定
- readiness 如何檢查
- inbound events 如何注入
- outbound messages 如何觀察
- transcripts 和 normalized transport state 如何公開
- transport-backed actions 如何執行
- transport-specific reset 或 cleanup 如何處理
- 保持
qa-lab作為共用qaroot 的擁有者。 - 在共用
qa-labhost seam 上實作 transport runner。 - 將傳輸專屬機制保留在 runner 外掛或 channel harness 內。
- 將 runner 掛載為
openclaw qa <runner>,而不是註冊競爭性的 root command。Runner 外掛應在openclaw.plugin.json中宣告qaRunners,並從runtime-api.ts匯出相符的qaRunnerCliRegistrations陣列。保持runtime-api.ts輕量;lazy CLI 和 runner 執行應維持在個別 entrypoints 之後。 - 在主題式
qa/scenarios/目錄下撰寫或改寫 YAML 情境。 - 針對新情境使用通用情境 helper。
- 除非 repo 正在進行有意的遷移,否則保持既有 compatibility aliases 可運作。
- 如果行為可以在
qa-lab中表達一次,請放在qa-lab。 - 如果行為依賴單一頻道傳輸,請將它保留在該 runner 外掛或外掛 harness 中。
- 如果情境需要一項可由多個頻道使用的新 capability,請新增通用 helper,而不是在
suite.ts中新增頻道專屬分支。 - 如果某個行為只對單一傳輸有意義,請保持該情境為傳輸專屬,並在情境契約中明確表示。
情境 helper 名稱
新情境偏好的通用 helper:waitForTransportReadywaitForChannelReadyinjectInboundMessageinjectOutboundMessagewaitForTransportOutboundMessagewaitForChannelOutboundMessagewaitForNoTransportOutboundgetTransportSnapshotreadTransportMessagereadTransportTranscriptformatTransportTranscriptresetTransport
waitForQaChannelReady、waitForOutboundMessage、waitForNoOutbound、formatConversationTranscript、resetBus - 但新情境撰寫應使用通用名稱。這些 aliases 存在是為了避免一次性遷移,而不是作為未來的模型。
報告
qa-lab 會從觀察到的 bus timeline 匯出 Markdown protocol report。
該報告應回答:
- 哪些有效
- 哪些失敗
- 哪些仍受阻
- 哪些後續情境值得新增
pnpm openclaw qa coverage(加入 --json 可取得機器可讀輸出)。
為受影響行為或檔案路徑選擇聚焦證明時,請執行 pnpm openclaw qa coverage --match <query>。
match report 會搜尋情境 metadata、docs refs、code refs、coverage IDs、外掛和供應商需求,然後列印相符的 qa suite --scenario ... targets。
每次 qa suite 執行都會為選取的
情境集合寫入頂層 qa-evidence.json、
qa-suite-summary.json 和 qa-suite-report.md artifacts。宣告 execution.kind: vitest 或
execution.kind: playwright 的情境會執行相符的測試路徑,並且也會寫入
每個情境的 logs。宣告 execution.kind: script 的情境會透過 node --import tsx 執行
位於 execution.path 的
evidence producer(其中
${outputDir} 和 ${scenarioId} 會在 execution.args 中展開);producer
會寫入自己的 qa-evidence.json,其 entries 會匯入 suite
輸出,而其 artifact paths 會相對於該 producer 的
qa-evidence.json 解析。當 qa suite 透過
qa run --qa-profile 進入時,同一個 qa-evidence.json 也會包含所選 taxonomy categories 的 profile
scorecard summary。
請將它視為探索輔助,而不是 gate 替代品;所選情境仍需要正確的供應商模式、live transport、Multipass、Testbox 或 release lane,才能驗證受測行為。
如需 scorecard 脈絡,請參閱成熟度 scorecard。
若要進行角色和風格檢查,請跨多個 live model
refs 執行相同情境,並寫入經評審的 Markdown report:
SOUL.md 設定角色人格,然後執行一般使用者回合,
例如聊天、工作區協助和小型檔案任務。不應告知候選模型
它正在接受評估。該命令會保留每份完整
逐字稿、記錄基本執行統計,然後以快速模式要求評審模型,
並在支援時使用 xhigh 推理,依自然度、氛圍和幽默感為各次執行排名。
比較提供者時請使用 --blind-judge-models:評審提示仍會取得
每份逐字稿和執行狀態,但候選參照會替換為中性的
標籤,例如 candidate-01;報告會在解析後將排名對應回真實參照。
候選執行預設使用 high 思考,GPT-5.5 使用 medium,較舊且支援的 OpenAI 評估參照則使用 xhigh。
可使用 --model provider/model,thinking=<level> 內嵌覆寫特定候選。
--thinking <level> 仍會設定全域備用值,而較舊的 --model-thinking <provider/model=level> 形式
會保留以維持相容性。
OpenAI 候選參照預設為快速模式,因此在提供者支援時會使用
優先處理。當單一候選或評審需要覆寫時,請內嵌加入 ,fast、,no-fast 或 ,fast=false。
只有在想要強制每個候選模型都啟用快速模式時,才傳入 --fast。
候選與評審的耗時會記錄在報告中以供基準分析,但評審提示會明確要求
不要依速度排名。
候選與評審模型執行預設並行度皆為 16。當提供者限制或本機閘道
壓力使執行結果過於嘈雜時,請降低 --concurrency 或 --judge-concurrency。
未傳入候選 --model 時,角色評估預設使用
openai/gpt-5.5、openai/gpt-5.2、openai/gpt-5、anthropic/claude-opus-4-8、
anthropic/claude-sonnet-4-6、zai/glm-5.1、
moonshot/kimi-k2.5,以及
google/gemini-3.1-pro-preview。
未傳入 --judge-model 時,評審預設使用
openai/gpt-5.5,thinking=xhigh,fast 和
anthropic/claude-opus-4-8,thinking=high。