
























@@ -1,10 +1,11 @@
11---
2-summary: "Private QA automation shape for qa-lab, qa-channel, seeded scenarios, and protocol reports"
2+summary: "QA stack overview: qa-lab, qa-channel, repo-backed scenarios, live transport lanes, transport adapters, and reporting."
33read_when:
4- - Extending qa-lab or qa-channel
4+ - Understanding how the QA stack fits together
5+ - Extending qa-lab, qa-channel, or a transport adapter
56 - Adding repo-backed QA scenarios
67 - Building higher-realism QA automation around the Gateway dashboard
7-title: "QA E2E automation"
8+title: "QA overview"
89---
9101011The private QA stack is meant to exercise OpenClaw in a more realistic,
@@ -16,9 +17,37 @@ Current pieces:
1617 reaction, edit, and delete surfaces.
1718- `extensions/qa-lab`: debugger UI and QA bus for observing the transcript,
1819 injecting inbound messages, and exporting a Markdown report.
20+- `extensions/qa-matrix`, future runner plugins: live-transport adapters that
21+ drive a real channel inside a child QA gateway.
1922- `qa/`: repo-backed seed assets for the kickoff task and baseline QA
2023 scenarios.
212425+## Command surface
26+27+Every QA flow runs under `pnpm openclaw qa <subcommand>`. Many have `pnpm qa:*`
28+script aliases; both forms are supported.
29+30+| Command | Purpose |
31+| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
32+| `qa run` | Bundled QA self-check; writes a Markdown report. |
33+| `qa suite` | Run repo-backed scenarios against the QA gateway lane. Aliases: `pnpm openclaw qa suite --runner multipass` for a disposable Linux VM. |
34+| `qa coverage` | Print the markdown scenario-coverage inventory (`--json` for machine output). |
35+| `qa parity-report` | Compare two `qa-suite-summary.json` files and write the agentic parity-gate report. |
36+| `qa character-eval` | Run the character QA scenario across multiple live models with a judged report. See [Reporting](#reporting). |
37+| `qa manual` | Run a one-off prompt against the selected provider/model lane. |
38+| `qa ui` | Start the QA debugger UI and local QA bus (alias: `pnpm qa:lab:ui`). |
39+| `qa docker-build-image` | Build the prebaked QA Docker image. |
40+| `qa docker-scaffold` | Write a docker-compose scaffold for the QA dashboard + gateway lane. |
41+| `qa up` | Build the QA site, start the Docker-backed stack, print the URL (alias: `pnpm qa:lab:up`; `:fast` variant adds `--use-prebuilt-image --bind-ui-dist --skip-ui-build`). |
42+| `qa aimock` | Start only the AIMock provider server. |
43+| `qa mock-openai` | Start only the scenario-aware `mock-openai` provider server. |
44+| `qa credentials doctor` / `add` / `list` / `remove` | Manage the shared Convex credential pool. |
45+| `qa matrix` | Live transport lane against a disposable Tuwunel homeserver. See [Matrix QA](/concepts/qa-matrix). |
46+| `qa telegram` | Live transport lane against a real private Telegram group. |
47+| `qa discord` | Live transport lane against a real private Discord guild channel. |
48+49+## Operator flow
50+2251The current QA operator flow is a two-pane QA site:
23522453- Left: Gateway dashboard (Control UI) with the agent.
@@ -76,23 +105,7 @@ For a transport-real Matrix smoke lane, run:
76105pnpm openclaw qa matrix --profile fast --fail-fast
77106```
7810779-That lane provisions a disposable Tuwunel homeserver in Docker, registers
80-temporary driver, SUT, and observer users, creates one private room, then runs
81-the real Matrix plugin inside a QA gateway child. The live transport lane keeps
82-the child config scoped to the transport under test, so Matrix runs without
83-`qa-channel` in the child config. It writes the structured report artifacts and
84-a combined stdout/stderr log into the selected Matrix QA output directory. To
85-capture the outer `scripts/run-node.mjs` build/launcher output too, set
86-`OPENCLAW_RUN_NODE_OUTPUT_LOG=<path>` to a repo-local log file.
87-Matrix progress is printed by default. The CLI default profile is `all`, so
88-plain `pnpm openclaw qa matrix` still runs the full catalog. Use `--profile
89-fast` for the release-critical transport contract, or shard full coverage with
90-`transport`, `media`, `e2ee-smoke`, `e2ee-deep`, and `e2ee-cli`. `--fail-fast`
91-stops after the first failed scenario when you want a release gate instead of a
92-full inventory. `OPENCLAW_QA_MATRIX_TIMEOUT_MS` bounds the full run,
93-`OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS` can shorten no-reply quiet windows for
94-CI, and `OPENCLAW_QA_MATRIX_CLEANUP_TIMEOUT_MS` bounds cleanup so a stuck
95-Docker teardown reports the exact recovery command instead of hanging.
108+The full CLI reference, profile/scenario catalog, env vars, and artifact layout for this lane live in [Matrix QA](/concepts/qa-matrix). At a glance: it provisions a disposable Tuwunel homeserver in Docker, registers temporary driver/SUT/observer users, runs the real Matrix plugin inside a child QA gateway scoped to that transport (no `qa-channel`), then writes a Markdown report, JSON summary, observed-events artifact, and combined output log under `.artifacts/qa-e2e/matrix-<timestamp>/`.
9610997110For a transport-real Telegram smoke lane, run:
98111@@ -106,7 +119,8 @@ disposable server. It requires `OPENCLAW_QA_TELEGRAM_GROUP_ID`,
106119`OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`, plus two distinct bots in the same
107120private group. The SUT bot must have a Telegram username, and bot-to-bot
108121observation works best when both bots have Bot-to-Bot Communication Mode
109-enabled in `@BotFather`.
122+enabled in `@BotFather`. Set `OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1` to keep
123+message bodies in observed-message artifacts (default redacts).
110124The command exits non-zero when any scenario fails. Use `--allow-failures` when
111125you want artifacts without a failing exit code.
112126The Telegram report and summary include per-reply RTT from the driver message
@@ -133,17 +147,17 @@ driver bot controlled by the harness and a SUT bot started by the child
133147OpenClaw gateway through the bundled Discord plugin. It requires
134148`OPENCLAW_QA_DISCORD_GUILD_ID`, `OPENCLAW_QA_DISCORD_CHANNEL_ID`,
135149`OPENCLAW_QA_DISCORD_DRIVER_BOT_TOKEN`, `OPENCLAW_QA_DISCORD_SUT_BOT_TOKEN`,
136-and `OPENCLAW_QA_DISCORD_SUT_APPLICATION_ID` when using env credentials.
150+and `OPENCLAW_QA_DISCORD_SUT_APPLICATION_ID` when using env credentials. Set
151+`OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1` to keep message bodies in
152+observed-message artifacts (default redacts).
137153The lane verifies channel mention handling and checks that the SUT bot has
138154registered the native `/help` command with Discord.
139155The command exits non-zero when any scenario fails. Use `--allow-failures` when
140156you want artifacts without a failing exit code.
141157142-Live transport lanes now share one smaller contract instead of each inventing
143-their own scenario list shape:
158+## Live transport coverage
144159145-`qa-channel` remains the broad synthetic product-behavior suite and is not part
146-of the live transport coverage matrix.
160+Live transport lanes share one contract instead of each inventing their own scenario list shape. `qa-channel` is the broad synthetic product-behavior suite and is not part of the live transport coverage matrix.
147161148162| Lane | Canary | Mention gating | Allowlist block | Top-level reply | Restart resume | Thread follow-up | Thread isolation | Reaction observation | Help command | Native command registration |
149163| -------- | ------ | -------------- | --------------- | --------------- | -------------- | ---------------- | ---------------- | -------------------- | ------------ | --------------------------- |
@@ -235,19 +249,79 @@ provider names.
235249236250## Transport adapters
237251238-`qa-lab` owns a generic transport seam for markdown QA scenarios.
239-`qa-channel` is the first adapter on that seam, but the design target is wider:
240-future real or synthetic channels should plug into the same suite runner
241-instead of adding a transport-specific QA runner.
252+`qa-lab` owns a generic transport seam for markdown QA scenarios. `qa-channel` is the first adapter on that seam, but the design target is wider: future real or synthetic channels should plug into the same suite runner instead of adding a transport-specific QA runner.
242253243254At the architecture level, the split is:
244255245256- `qa-lab` owns generic scenario execution, worker concurrency, artifact writing, and reporting.
246-- the transport adapter owns gateway config, readiness, inbound and outbound observation, transport actions, and normalized transport state.
247-- markdown scenario files under `qa/scenarios/` define the test run; `qa-lab` provides the reusable runtime surface that executes them.
257+- The transport adapter owns gateway config, readiness, inbound and outbound observation, transport actions, and normalized transport state.
258+- Markdown scenario files under `qa/scenarios/` define the test run; `qa-lab` provides the reusable runtime surface that executes them.
259+260+### Adding a channel
261+262+Adding a channel to the markdown QA system requires exactly two things:
263+264+1. A transport adapter for the channel.
265+2. A scenario pack that exercises the channel contract.
266+267+Do not add a new top-level QA command root when the shared `qa-lab` host can own the flow.
268+269+`qa-lab` owns the shared host mechanics:
270+271+- the `openclaw qa` command root
272+- suite startup and teardown
273+- worker concurrency
274+- artifact writing
275+- report generation
276+- scenario execution
277+- compatibility aliases for older `qa-channel` scenarios
278+279+Runner plugins own the transport contract:
280+281+- how `openclaw qa <runner>` is mounted beneath the shared `qa` root
282+- how the gateway is configured for that transport
283+- how readiness is checked
284+- how inbound events are injected
285+- how outbound messages are observed
286+- how transcripts and normalized transport state are exposed
287+- how transport-backed actions are executed
288+- how transport-specific reset or cleanup is handled
289+290+The minimum adoption bar for a new channel:
248291249-Maintainer-facing adoption guidance for new channel adapters lives in
250-[Testing](/help/testing#adding-a-channel-to-qa).
292+1. Keep `qa-lab` as the owner of the shared `qa` root.
293+2. Implement the transport runner on the shared `qa-lab` host seam.
294+3. Keep transport-specific mechanics inside the runner plugin or channel harness.
295+4. Mount the runner as `openclaw qa <runner>` instead of registering a competing root command. Runner plugins should declare `qaRunners` in `openclaw.plugin.json` and export a matching `qaRunnerCliRegistrations` array from `runtime-api.ts`. Keep `runtime-api.ts` light; lazy CLI and runner execution should stay behind separate entrypoints.
296+5. Author or adapt markdown scenarios under the themed `qa/scenarios/` directories.
297+6. Use the generic scenario helpers for new scenarios.
298+7. Keep existing compatibility aliases working unless the repo is doing an intentional migration.
299+300+The decision rule is strict:
301+302+- If behavior can be expressed once in `qa-lab`, put it in `qa-lab`.
303+- If behavior depends on one channel transport, keep it in that runner plugin or plugin harness.
304+- If a scenario needs a new capability that more than one channel can use, add a generic helper instead of a channel-specific branch in `suite.ts`.
305+- If a behavior is only meaningful for one transport, keep the scenario transport-specific and make that explicit in the scenario contract.
306+307+### Scenario helper names
308+309+Preferred generic helpers for new scenarios:
310+311+- `waitForTransportReady`
312+- `waitForChannelReady`
313+- `injectInboundMessage`
314+- `injectOutboundMessage`
315+- `waitForTransportOutboundMessage`
316+- `waitForChannelOutboundMessage`
317+- `waitForNoTransportOutbound`
318+- `getTransportSnapshot`
319+- `readTransportMessage`
320+- `readTransportTranscript`
321+- `formatTransportTranscript`
322+- `resetTransport`
323+324+Compatibility aliases remain available for existing scenarios — `waitForQaChannelReady`, `waitForOutboundMessage`, `waitForNoOutbound`, `formatConversationTranscript`, `resetBus` — but new scenario authoring should use the generic names. The aliases exist to avoid a flag-day migration, not as the model going forward.
251325252326## Reporting
253327@@ -259,6 +333,8 @@ The report should answer:
259333- What stayed blocked
260334- What follow-up scenarios are worth adding
261335336+For the inventory of available scenarios — useful when sizing follow-up work or wiring a new transport — run `pnpm openclaw qa coverage` (add `--json` for machine-readable output).
337+262338For character and style checks, run the same scenario across multiple live model
263339refs and write a judged Markdown report:
264340@@ -314,6 +390,7 @@ When no `--judge-model` is passed, the judges default to
314390315391## Related docs
316392317-- [Testing](/help/testing)
393+- [Matrix QA](/concepts/qa-matrix)
318394- [QA Channel](/channels/qa-channel)
395+- [Testing](/help/testing)
319396- [Dashboard](/web/dashboard)
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。