

























@@ -240,15 +240,15 @@ can write back through the mounted workspace.
240240241241## Telegram, Discord, and Slack QA reference
242242243-Matrix has a [dedicated page](/concepts/qa-matrix) because of its scenario count and Docker-backed homeserver provisioning. Telegram, Discord, and Slack are smaller — a handful of scenarios each, no profile system, against pre-existing real channels — so their reference lives here.
243+Matrix has a [dedicated page](/concepts/qa-matrix) because of its scenario count and Docker-backed homeserver provisioning. Telegram, Discord, and Slack are smaller - a handful of scenarios each, no profile system, against pre-existing real channels - so their reference lives here.
244244245245### Shared CLI flags
246246247247These lanes register through `extensions/qa-lab/src/live-transports/shared/live-transport-cli.ts` and accept the same flags:
248248249249| Flag | Default | Description |
250250| ------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
251-| `--scenario <id>` | — | Run only this scenario. Repeatable. |
251+| `--scenario <id>` | - | Run only this scenario. Repeatable. |
252252| `--output-dir <path>` | `<repo>/.artifacts/qa-e2e/{telegram,discord,slack}-<timestamp>` | Where reports/summary/observed messages and the output log are written. Relative paths resolve against `--repo-root`. |
253253| `--repo-root <path>` | `process.cwd()` | Repository root when invoking from a neutral cwd. |
254254| `--sut-account <id>` | `sut` | Temporary account id inside the QA gateway config. |
@@ -270,7 +270,7 @@ Targets one real private Telegram group with two distinct bots (driver + SUT). T
270270271271Required env when `--credential-source env`:
272272273-- `OPENCLAW_QA_TELEGRAM_GROUP_ID` — numeric chat id (string).
273+- `OPENCLAW_QA_TELEGRAM_GROUP_ID` - numeric chat id (string).
274274- `OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN`
275275- `OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN`
276276@@ -294,8 +294,8 @@ Scenarios (`extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime
294294Output artifacts:
295295296296- `telegram-qa-report.md`
297-- `telegram-qa-summary.json` — includes per-reply RTT (driver send → observed SUT reply) starting with the canary.
298-- `telegram-qa-observed-messages.json` — bodies redacted unless `OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1`.
297+- `telegram-qa-summary.json` - includes per-reply RTT (driver send → observed SUT reply) starting with the canary.
298+- `telegram-qa-observed-messages.json` - bodies redacted unless `OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1`.
299299300300### Discord QA
301301@@ -311,7 +311,7 @@ Required env when `--credential-source env`:
311311- `OPENCLAW_QA_DISCORD_CHANNEL_ID`
312312- `OPENCLAW_QA_DISCORD_DRIVER_BOT_TOKEN`
313313- `OPENCLAW_QA_DISCORD_SUT_BOT_TOKEN`
314-- `OPENCLAW_QA_DISCORD_SUT_APPLICATION_ID` — must match the SUT bot user id returned by Discord (the lane fails fast otherwise).
314+- `OPENCLAW_QA_DISCORD_SUT_APPLICATION_ID` - must match the SUT bot user id returned by Discord (the lane fails fast otherwise).
315315316316Optional:
317317@@ -322,7 +322,7 @@ Scenarios (`extensions/qa-lab/src/live-transports/discord/discord-live.runtime.t
322322- `discord-canary`
323323- `discord-mention-gating`
324324- `discord-native-help-command-registration`
325-- `discord-status-reactions-tool-only` — opt-in Mantis scenario. Runs by itself because it switches the SUT to always-on, tool-only guild replies with `messages.statusReactions.enabled=true`, then captures a REST reaction timeline plus HTML/PNG visual artifacts. Mantis before/after reports also preserve scenario-provided MP4 artifacts as `baseline.mp4` and `candidate.mp4`.
325+- `discord-status-reactions-tool-only` - opt-in Mantis scenario. Runs by itself because it switches the SUT to always-on, tool-only guild replies with `messages.statusReactions.enabled=true`, then captures a REST reaction timeline plus HTML/PNG visual artifacts. Mantis before/after reports also preserve scenario-provided MP4 artifacts as `baseline.mp4` and `candidate.mp4`.
326326327327Run the Mantis status-reaction scenario explicitly:
328328@@ -339,7 +339,7 @@ Output artifacts:
339339340340- `discord-qa-report.md`
341341- `discord-qa-summary.json`
342-- `discord-qa-observed-messages.json` — bodies redacted unless `OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1`.
342+- `discord-qa-observed-messages.json` - bodies redacted unless `OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1`.
343343- `discord-qa-reaction-timelines.json` and `discord-status-reactions-tool-only-timeline.png` when the status-reaction scenario runs.
344344345345### Slack QA
@@ -375,16 +375,16 @@ Output artifacts:
375375376376- `slack-qa-report.md`
377377- `slack-qa-summary.json`
378-- `slack-qa-observed-messages.json` — bodies redacted unless `OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1`.
378+- `slack-qa-observed-messages.json` - bodies redacted unless `OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1`.
379379380380#### Setting up the Slack workspace
381381382382The lane needs two distinct Slack apps in one workspace, plus a channel both bots are members of:
383383384-- `channelId` — the `Cxxxxxxxxxx` id of a channel both bots have been invited to. Use a dedicated channel; the lane posts on every run.
385-- `driverBotToken` — bot token (`xoxb-...`) of the **Driver** app.
386-- `sutBotToken` — bot token (`xoxb-...`) of the **SUT** app, which must be a separate Slack app from the driver so its bot user id is distinct.
387-- `sutAppToken` — app-level token (`xapp-...`) of the SUT app with `connections:write`, used by Socket Mode so the SUT app can receive events.
384+- `channelId` - the `Cxxxxxxxxxx` id of a channel both bots have been invited to. Use a dedicated channel; the lane posts on every run.
385+- `driverBotToken` - bot token (`xoxb-...`) of the **Driver** app.
386+- `sutBotToken` - bot token (`xoxb-...`) of the **SUT** app, which must be a separate Slack app from the driver so its bot user id is distinct.
387+- `sutAppToken` - app-level token (`xapp-...`) of the SUT app with `connections:write`, used by Socket Mode so the SUT app can receive events.
388388389389Prefer a Slack workspace dedicated to QA over reusing a production workspace.
390390@@ -417,7 +417,7 @@ Go to [api.slack.com/apps](https://api.slack.com/apps) → _Create New App_ →
417417}
418418```
419419420-Copy the _Bot User OAuth Token_ (`xoxb-...`) — that becomes `driverBotToken`. The driver only needs to post messages and identify itself; no events, no Socket Mode.
420+Copy the _Bot User OAuth Token_ (`xoxb-...`) - that becomes `driverBotToken`. The driver only needs to post messages and identify itself; no events, no Socket Mode.
421421422422**2. Create the SUT app**
423423@@ -504,7 +504,7 @@ In the QA workspace, create a channel (e.g. `#openclaw-qa`) and invite both bots
504504/invite @OpenClaw QA SUT
505505```
506506507-Copy the `Cxxxxxxxxxx` id from _channel info → About → Channel ID_ — that becomes `channelId`. A public channel works; if you use a private channel both apps already have `groups:history` so the harness's history reads will still succeed.
507+Copy the `Cxxxxxxxxxx` id from _channel info → About → Channel ID_ - that becomes `channelId`. A public channel works; if you use a private channel both apps already have `groups:history` so the harness's history reads will still succeed.
508508509509**4. Register the credentials**
510510@@ -545,17 +545,17 @@ pnpm openclaw qa slack \
545545 --output-dir .artifacts/qa-e2e/slack-local
546546```
547547548-A green run completes in well under 30 seconds and `slack-qa-report.md` shows both `slack-canary` and `slack-mention-gating` at status `pass`. If the lane hangs for ~90 seconds and exits with `Convex credential pool exhausted for kind "slack"`, either the pool is empty or every row is leased — `qa credentials list --kind slack --status all --json` will tell you which.
548+A green run completes in well under 30 seconds and `slack-qa-report.md` shows both `slack-canary` and `slack-mention-gating` at status `pass`. If the lane hangs for ~90 seconds and exits with `Convex credential pool exhausted for kind "slack"`, either the pool is empty or every row is leased - `qa credentials list --kind slack --status all --json` will tell you which.
549549550550### Convex credential pool
551551552552Telegram, Discord, and Slack lanes can lease credentials from a shared Convex pool instead of reading the env vars above. Pass `--credential-source convex` (or set `OPENCLAW_QA_CREDENTIAL_SOURCE=convex`); QA Lab acquires an exclusive lease, heartbeats it for the duration of the run, and releases it on shutdown. Pool kinds are `"telegram"`, `"discord"`, and `"slack"`.
553553554554Payload shapes the broker validates on `admin/add`:
555555556-- Telegram (`kind: "telegram"`): `{ groupId: string, driverToken: string, sutToken: string }` — `groupId` must be a numeric chat-id string.
556+- Telegram (`kind: "telegram"`): `{ groupId: string, driverToken: string, sutToken: string }` - `groupId` must be a numeric chat-id string.
557557- Discord (`kind: "discord"`): `{ guildId: string, channelId: string, driverBotToken: string, sutBotToken: string, sutApplicationId: string }`.
558-- Slack (`kind: "slack"`): `{ channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string }` — `channelId` must match `^[A-Z][A-Z0-9]+$` (a Slack id like `Cxxxxxxxxxx`). See [Setting up the Slack workspace](#setting-up-the-slack-workspace) for app and scope provisioning.
558+- Slack (`kind: "slack"`): `{ channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string }` - `channelId` must match `^[A-Z][A-Z0-9]+$` (a Slack id like `Cxxxxxxxxxx`). See [Setting up the Slack workspace](#setting-up-the-slack-workspace) for app and scope provisioning.
559559560560Operational env vars and the Convex broker endpoint contract live in [Testing → Shared Telegram credentials via Convex](/help/testing#shared-telegram-credentials-via-convex-v1) (the section name predates Discord support; the broker semantics are identical for both kinds).
561561@@ -690,7 +690,7 @@ Preferred generic helpers for new scenarios:
690690- `formatTransportTranscript`
691691- `resetTransport`
692692693-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.
693+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.
694694695695## Reporting
696696@@ -702,7 +702,7 @@ The report should answer:
702702- What stayed blocked
703703- What follow-up scenarios are worth adding
704704705-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).
705+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).
706706707707For character and style checks, run the same scenario across multiple live model
708708refs and write a judged Markdown report:
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。