Fundamentals
Огляд забезпечення якості
Приватний QA-стек призначений для перевірки OpenClaw у реалістичніший, канально-орієнтований спосіб, ніж це може зробити один unit-тест.
Поточні складники:
extensions/qa-channel: синтетичний канал повідомлень із поверхнями DM, каналу, треду, реакції, редагування та видалення.extensions/qa-lab: UI дебагера та QA-шина для спостереження за транскриптом, ін’єкції вхідних повідомлень і експорту Markdown-звіту.extensions/qa-matrix, майбутні runner plugins: адаптери live-транспортів, які керують реальним каналом усередині дочірнього QA gateway.qa/: seed-ресурси з репозиторію для стартового завдання та базових QA сценаріїв.- Mantis: перевірка до та після live-верифікації для багів, яким потрібні реальні транспорти, знімки браузера, стан VM і докази PR.
Поверхня команд
Кожен QA-потік виконується через pnpm openclaw qa <subcommand>. Багато з них мають
аліаси скриптів pnpm qa:*; підтримуються обидві форми.
| Команда | Призначення |
|---|---|
qa run |
Вбудована самоперевірка QA; записує Markdown-звіт. |
qa suite |
Запустити сценарії з репозиторію проти QA gateway lane. Аліаси: pnpm openclaw qa suite --runner multipass для одноразової Linux VM. |
qa coverage |
Вивести markdown-інвентар покриття сценаріїв (--json для машинного виводу). |
qa parity-report |
Порівняти два файли qa-suite-summary.json і записати agentic-звіт про паритет. |
qa character-eval |
Запустити character QA scenario на кількох live-моделях зі звітом від оцінювача. Див. Звітування. |
qa manual |
Запустити одноразовий prompt проти вибраної lane провайдера/моделі. |
qa ui |
Запустити QA debugger UI і локальну QA-шину (аліас: pnpm qa:lab:ui). |
qa docker-build-image |
Зібрати попередньо підготовлений QA Docker image. |
qa docker-scaffold |
Записати docker-compose scaffold для QA dashboard + gateway lane. |
qa up |
Зібрати QA site, запустити Docker-backed stack, вивести URL (аліас: pnpm qa:lab:up; варіант :fast додає --use-prebuilt-image --bind-ui-dist --skip-ui-build). |
qa aimock |
Запустити лише сервер AIMock provider. |
qa mock-openai |
Запустити лише scenario-aware сервер mock-openai provider. |
qa credentials doctor / add / list / remove |
Керувати спільним пулом облікових даних Convex. |
qa matrix |
Live transport lane проти одноразового Tuwunel homeserver. Див. Matrix QA. |
qa telegram |
Live transport lane проти реальної приватної групи Telegram. |
qa discord |
Live transport lane проти реального приватного каналу Discord guild. |
qa slack |
Live transport lane проти реального приватного каналу Slack. |
qa mantis |
Runner перевірки до та після для багів live-транспортів, з доказами статус-реакцій Discord, smoke-перевіркою Crabbox desktop/browser і smoke-перевіркою Slack-in-VNC. Див. Mantis і Mantis Slack Desktop Runbook. |
Потік оператора
Поточний QA operator flow — це QA site з двома панелями:
- Ліворуч: Gateway dashboard (Control UI) з агентом.
- Праворуч: QA Lab, що показує Slack-подібний transcript і план сценарію.
Запустіть його так:
pnpm qa:lab:upЦе збирає QA site, запускає Docker-backed gateway lane і відкриває сторінку QA Lab, де оператор або automation loop може дати агенту QA-місію, спостерігати реальну поведінку каналу та записати, що спрацювало, не спрацювало або залишилося заблокованим.
Для швидшої ітерації QA Lab UI без перебудови Docker image щоразу запустіть стек із bind-mounted QA Lab bundle:
pnpm openclaw qa docker-build-imagepnpm qa:lab:buildpnpm qa:lab:up:fastpnpm qa:lab:watchqa:lab:up:fast утримує Docker services на попередньо зібраному image і bind-mount-ить
extensions/qa-lab/web/dist у контейнер qa-lab. qa:lab:watch
перезбирає цей bundle при зміні, а браузер автоматично перезавантажується, коли змінюється hash ресурсу QA Lab.
Для локального OpenTelemetry trace smoke запустіть:
pnpm qa:otel:smokeЦей скрипт запускає локальний OTLP/HTTP trace receiver, виконує
QA-сценарій otel-trace-smoke з увімкненим plugin diagnostics-otel, потім
декодує експортовані protobuf spans і перевіряє release-critical форму:
openclaw.run, openclaw.harness.run, openclaw.model.call,
openclaw.context.assembled і openclaw.message.delivery мають бути присутні;
model calls не мають експортувати StreamAbandoned на успішних turns; raw diagnostic IDs і
атрибути openclaw.content.* мають залишатися поза trace. Він записує
otel-smoke-summary.json поруч із артефактами QA suite.
Observability QA лишається доступним лише з source checkout. npm tarball навмисно не містить
QA Lab, тому package Docker release lanes не виконують команди qa. Використовуйте
pnpm qa:otel:smoke із зібраного source checkout, коли змінюєте diagnostics
instrumentation.
Для transport-real Matrix smoke lane запустіть:
pnpm openclaw qa matrix --profile fast --fail-fastПовна CLI-довідка, каталог профілів/сценаріїв, env vars і структура артефактів для цієї lane наведені в Matrix QA. Коротко: вона створює одноразовий Tuwunel homeserver у Docker, реєструє тимчасових користувачів driver/SUT/observer, запускає реальний Matrix plugin усередині дочірнього QA gateway, обмеженого цим транспортом (без qa-channel), а потім записує Markdown-звіт, JSON summary, артефакт observed-events і об’єднаний output log у .artifacts/qa-e2e/matrix-<timestamp>/.
Сценарії покривають transport behavior, яку unit-тести не можуть довести end to end: mention gating, allow-bot policies, allowlists, top-level і threaded replies, DM routing, reaction handling, inbound edit suppression, restart replay dedupe, homeserver interruption recovery, approval metadata delivery, media handling і Matrix E2EE bootstrap/recovery/verification flows. Профіль E2EE CLI також проганяє openclaw matrix encryption setup і команди верифікації через той самий одноразовий homeserver перед перевіркою gateway replies.
Discord також має Mantis-only opt-in сценарії для відтворення багів. Використовуйте
--scenario discord-status-reactions-tool-only для явного timeline статус-реакцій
або --scenario discord-thread-reply-filepath-attachment, щоб створити
реальний Discord thread і перевірити, що message.thread-reply зберігає
attachment filePath. Ці сценарії не входять до default live Discord lane,
бо це before/after repro probes, а не широке smoke coverage.
Thread-attachment Mantis workflow також може додати logged-in Discord Web
witness video, коли MANTIS_DISCORD_VIEWER_CHROME_PROFILE_DIR або
MANTIS_DISCORD_VIEWER_CHROME_PROFILE_TGZ_B64 налаштовано в QA
environment. Цей viewer profile призначений лише для visual capture; рішення pass/fail
і далі надходить від Discord REST oracle.
CI використовує ту саму command surface у .github/workflows/qa-live-transports-convex.yml. Scheduled і default manual runs виконують fast Matrix profile з live frontier credentials, --fast і OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS=3000. Manual matrix_profile=all розгалужується на п’ять profile shards, щоб exhaustive catalog міг виконуватися паралельно, зберігаючи по одному artifact directory на shard.
Для transport-real Telegram, Discord і Slack smoke lanes:
pnpm openclaw qa telegrampnpm openclaw qa discordpnpm openclaw qa slackВони націлені на вже наявний реальний канал із двома bots (driver + SUT). Необхідні env vars, списки сценаріїв, output artifacts і Convex credential pool задокументовані в довідці QA для Telegram, Discord і Slack нижче.
Для повного запуску Slack desktop VM із резервним доступом через VNC виконайте:
pnpm openclaw qa mantis slack-desktop-smoke \ --gateway-setup \ --scenario slack-canary \ --keep-leaseЦя команда орендує Crabbox машину з робочим столом/браузером, запускає Slack live lane
усередині VM, відкриває Slack Web у браузері VNC, захоплює робочий стіл і
копіює slack-qa/, slack-desktop-smoke.png та slack-desktop-smoke.mp4,
коли захоплення відео доступне, назад до каталогу артефактів Mantis. Оренди Crabbox
для робочого столу/браузера одразу надають інструменти захоплення та допоміжні
пакети для браузера/нативної збірки, тому сценарій має встановлювати резервні
варіанти лише на старіших орендах. Mantis звітує про загальний час і час за фазами в
mantis-slack-desktop-smoke-report.md, щоб повільні запуски показували, чи час пішов на
прогрів оренди, отримання облікових даних, віддалене налаштування або копіювання артефактів. Повторно використовуйте
--lease-id <cbx_...> після ручного входу в Slack Web через VNC;
повторно використані оренди також зберігають прогрітим кеш pnpm store у Crabbox. Типовий
--hydrate-mode source перевіряє з вихідного checkout і запускає встановлення/збірку
всередині VM. Використовуйте --hydrate-mode prehydrated лише коли повторно використаний віддалений
workspace уже має node_modules і зібраний dist/; цей режим пропускає
дорогий крок встановлення/збірки та завершується відмовою, коли workspace не готовий.
З --gateway-setup Mantis залишає постійний OpenClaw Slack gateway
запущеним усередині VM на порту 38973; без нього команда запускає звичайний
bot-to-bot Slack QA lane і завершується після захоплення артефактів.
Контрольний список оператора, команда dispatch для GitHub workflow, контракт коментаря з доказами, таблиця вибору hydrate-mode, інтерпретація часу та кроки обробки збоїв містяться в Mantis Slack Desktop Runbook.
Для desktop-завдання у стилі agent/CV виконайте:
pnpm openclaw qa mantis visual-task \ --browser-url https://example.net \ --expect-text "Example Domain" \ --vision-model openai/gpt-5.4visual-task орендує або повторно використовує Crabbox машину з робочим столом/браузером, запускає
crabbox record --while, керує видимим браузером через вкладений
visual-driver, захоплює visual-task.png, запускає openclaw infer image describe
для знімка екрана, коли вибрано --vision-mode 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
вердикт і проходить лише тоді, коли модель повідомляє про позитивний видимий доказ; негативна
відповідь, яка лише цитує цільовий текст, провалює перевірку.
Використовуйте --vision-mode metadata для smoke без моделі, який доводить роботу робочого столу,
браузера, знімка екрана та відеоінфраструктури без виклику провайдера
розуміння зображень. Запис є обов’язковим артефактом для visual-task; якщо Crabbox не записує
непорожній visual-task.mp4, завдання завершується з помилкою навіть тоді, коли visual driver
пройшов. У разі збою Mantis зберігає оренду для VNC, якщо завдання ще не
пройшло і --keep-lease не було задано.
Перед використанням pooled live credentials виконайте:
pnpm openclaw qa credentials doctorDoctor перевіряє env брокера Convex, валідовує налаштування endpoint і перевіряє досяжність admin/list, коли присутній секрет maintainer. Він повідомляє для секретів лише статус set/missing.
Покриття live transport
Live transport lanes використовують один спільний контракт замість того, щоб кожен винаходив власну форму списку сценаріїв. qa-channel є широким синтетичним набором перевірок поведінки продукту й не входить до матриці покриття live transport.
| Lane | Canary | Гейтинг згадки | Bot-to-bot | Блокування allowlist | Відповідь верхнього рівня | Відновлення після перезапуску | Подальша відповідь у thread | Ізоляція thread | Спостереження за реакціями | Команда help | Реєстрація нативної команди |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 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 |
Це зберігає qa-channel як широкий набір перевірок поведінки продукту, тоді як Matrix,
Telegram і майбутні live transports використовують один явний контрольний список
transport-contract.
Для одноразового Linux VM lane без залучення Docker до QA path виконайте:
pnpm openclaw qa suite --runner multipass --scenario channel-chat-baselineЦе завантажує свіжий Multipass guest, встановлює залежності, збирає OpenClaw
усередині guest, запускає qa suite, а потім копіює звичайний QA report і
summary назад у .artifacts/qa-e2e/... на host.
Він повторно використовує ту саму поведінку вибору сценаріїв, що й qa suite на host.
Запуски suite на host і Multipass виконують кілька вибраних сценаріїв паралельно
з ізольованими gateway workers за замовчуванням. qa-channel типово має concurrency
4, обмежену кількістю вибраних сценаріїв. Використовуйте --concurrency <count>, щоб налаштувати
кількість workers, або --concurrency 1 для послідовного виконання.
Команда завершується з ненульовим кодом, коли будь-який сценарій завершується з помилкою. Використовуйте --allow-failures, коли
потрібні артефакти без коду виходу, що позначає помилку.
Live-запуски передають підтримувані QA auth inputs, які практичні для
guest: env-based provider keys, шлях QA live provider config і
CODEX_HOME, коли він присутній. Тримайте --output-dir під коренем репозиторію, щоб guest
міг записувати назад через змонтований workspace.
Довідка QA для Telegram, Discord і Slack
Matrix має окрему сторінку через кількість сценаріїв і Docker-backed homeserver provisioning. Telegram, Discord і Slack менші - кілька сценаріїв кожен, без системи профілів, проти вже наявних реальних каналів - тому їхня довідка міститься тут.
Спільні прапорці CLI
Ці lanes реєструються через extensions/qa-lab/src/live-transports/shared/live-transport-cli.ts і приймають однакові прапорці:
| Прапорець | Типове значення | Опис |
|---|---|---|
--scenario <id> |
- | Запустити лише цей сценарій. Можна повторювати. |
--output-dir <path> |
<repo>/.artifacts/qa-e2e/{telegram,discord,slack}-<timestamp> |
Куди записуються звіти/summary/observed messages і output log. Відносні шляхи розв’язуються відносно --repo-root. |
--repo-root <path> |
process.cwd() |
Корінь репозиторію під час виклику з нейтрального cwd. |
--sut-account <id> |
sut |
Тимчасовий account id усередині QA gateway config. |
--provider-mode <mode> |
live-frontier |
mock-openai або live-frontier (застарілий live-openai досі працює). |
--model <ref> / --alt-model <ref> |
типове значення провайдера | Основні/альтернативні model refs. |
--fast |
вимкнено | Швидкий режим провайдера, де підтримується. |
--credential-source <env|convex> |
env |
Див. пул облікових даних Convex. |
--credential-role <maintainer|ci> |
ci у CI, інакше maintainer |
Роль, що використовується, коли --credential-source convex. |
Кожен lane завершується з ненульовим кодом у разі будь-якого невдалого сценарію. --allow-failures записує артефакти без встановлення коду виходу, що позначає помилку.
Telegram QA
pnpm openclaw qa telegramНацілюється на одну реальну приватну групу Telegram із двома окремими ботами (driver + SUT). SUT bot повинен мати Telegram username; bot-to-bot observation працює найкраще, коли обидва боти мають увімкнений Bot-to-Bot Communication Mode у @BotFather.
Обов’язкові env, коли --credential-source env:
OPENCLAW_QA_TELEGRAM_GROUP_ID- числовий chat id (рядок).OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKENOPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN
Необов’язково:
OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1зберігає тіла повідомлень в observed-message artifacts (типово редагує).
Сценарії (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
Неявний типовий набір завжди покриває canary, mention gating, native command replies, command addressing і bot-to-bot group replies. Типові значення mock-openai також включають детерміновані перевірки reply-chain і final-message streaming. telegram-current-session-status-tool залишається opt-in, бо він стабільний лише коли виконується в thread безпосередньо після canary, а не після довільних native command replies. Використовуйте pnpm openclaw qa telegram --list-scenarios --provider-mode mock-openai, щоб вивести поточний поділ default/optional з regression refs.
Вихідні артефакти:
telegram-qa-report.mdtelegram-qa-summary.json- включає per-reply RTT (driver send → observed SUT reply), починаючи з canary.telegram-qa-observed-messages.json- тіла редагуються, якщо не заданоOPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1.
Discord QA
pnpm openclaw qa discordНацілюється на один реальний приватний канал Discord guild із двома ботами: driver bot, яким керує harness, і SUT bot, запущений child OpenClaw gateway через bundled Discord plugin. Перевіряє обробку згадок каналу, що SUT bot зареєстрував нативну команду /help у Discord, і opt-in сценарії доказів Mantis.
Обов’язкові env, коли --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- має відповідати id користувача SUT-бота, який повертає Discord (інакше лінія швидко завершується з помилкою).
Необов’язково:
OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1зберігає тіла повідомлень в артефактах спостережених повідомлень.OPENCLAW_QA_DISCORD_VOICE_CHANNEL_IDвибирає голосовий/сценічний канал дляdiscord-voice-autojoin; без нього сценарій вибирає перший видимий голосовий/сценічний канал для SUT-бота.
Сценарії (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-бота в Discord є цільовим голосовим/сценічним каналом. Облікові дані Convex для Discord можуть містити необов’язковийvoiceChannelId; інакше runner виявляє перший видимий голосовий/сценічний канал у гільдії.discord-status-reactions-tool-only- сценарій Mantis із явним увімкненням. Запускається самостійно, бо перемикає SUT на постійні відповіді в гільдії лише через інструменти зmessages.statusReactions.enabled=true, а потім захоплює часову шкалу REST-реакцій плюс візуальні артефакти HTML/PNG. Звіти Mantis до/після також зберігають надані сценарієм MP4-артефакти якbaseline.mp4іcandidate.mp4.
Запустіть сценарій автоматичного приєднання до голосового каналу Discord явно:
pnpm openclaw qa discord \ --scenario discord-voice-autojoin \ --provider-mode mock-openaiЗапустіть сценарій реакцій статусу Mantis явно:
pnpm openclaw qa discord \ --scenario discord-status-reactions-tool-only \ --provider-mode live-frontier \ --model openai/gpt-5.4 \ --alt-model openai/gpt-5.4 \ --fastВихідні артефакти:
discord-qa-report.mddiscord-qa-summary.jsondiscord-qa-observed-messages.json- тіла заредаговано, якщо не заданоOPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1.discord-qa-reaction-timelines.jsonіdiscord-status-reactions-tool-only-timeline.png, коли запускається сценарій реакцій статусу.
QA Slack
pnpm openclaw qa slackНацілюється на один реальний приватний канал Slack із двома окремими ботами: драйвер-ботом, яким керує тестовий стенд, і SUT-ботом, запущеним дочірнім OpenClaw Gateway через вбудований Slack Plugin.
Обов’язкові змінні середовища, коли --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зберігає тіла повідомлень в артефактах спостережених повідомлень.
Сценарії (extensions/qa-lab/src/live-transports/slack/slack-live.runtime.ts:39):
slack-canaryslack-mention-gatingslack-allowlist-blockslack-top-level-reply-shapeslack-restart-resumeslack-thread-follow-upslack-thread-isolation
Вихідні артефакти:
slack-qa-report.mdslack-qa-summary.jsonslack-qa-observed-messages.json- тіла заредаговано, якщо не заданоOPENCLAW_QA_SLACK_CAPTURE_CONTENT=1.
Налаштування робочого простору Slack
Лінії потрібні два окремі застосунки Slack в одному робочому просторі, а також канал, учасниками якого є обидва боти:
channelId- idCxxxxxxxxxxканалу, до якого запрошено обох ботів. Використовуйте виділений канал; лінія публікує повідомлення під час кожного запуску.driverBotToken- токен бота (xoxb-...) застосунку Driver.sutBotToken- токен бота (xoxb-...) застосунку SUT, який має бути окремим застосунком Slack від драйвера, щоб id користувача його бота був іншим.sutAppToken- токен рівня застосунку (xapp-...) застосунку SUT зconnections:write, який використовується Socket Mode, щоб застосунок SUT міг отримувати події.
Надавайте перевагу робочому простору Slack, виділеному для QA, замість повторного використання робочого простору production.
Маніфест SUT нижче навмисно звужує production-інсталяцію вбудованого Slack Plugin (extensions/slack/src/setup-shared.ts:10) до дозволів і подій, охоплених live-набором QA Slack. Для налаштування production-каналу так, як його бачать користувачі, див. Швидке налаштування каналу Slack; пара QA Driver/SUT навмисно окрема, бо лінії потрібні два різні id користувачів-ботів в одному робочому просторі.
1. Створіть застосунок Driver
Перейдіть до api.slack.com/apps → Create New App → From a manifest → виберіть робочий простір QA, вставте наведений нижче маніфест, потім Install to Workspace:
{ "display_information": { "name": "OpenClaw QA Driver", "description": "Test driver bot for OpenClaw QA Slack live lane" }, "features": { "bot_user": { "display_name": "OpenClaw QA Driver", "always_online": true } }, "oauth_config": { "scopes": { "bot": ["chat:write", "channels:history", "groups:history", "users:read"] } }, "settings": { "socket_mode_enabled": false }}Скопіюйте Bot User OAuth Token (xoxb-...) - він стане driverBotToken. Драйверу потрібно лише публікувати повідомлення й ідентифікувати себе; без подій, без Socket Mode.
2. Створіть застосунок SUT
Повторіть Create New App → From a manifest у тому самому робочому просторі. Цей QA-застосунок навмисно використовує вужчу версію production-маніфесту вбудованого Slack Plugin (extensions/slack/src/setup-shared.ts:10): scopes і події реакцій пропущено, бо live-набір QA Slack ще не охоплює обробку реакцій.
{ "display_information": { "name": "OpenClaw QA SUT", "description": "OpenClaw QA SUT connector for OpenClaw" }, "features": { "bot_user": { "display_name": "OpenClaw QA SUT", "always_online": true }, "app_home": { "home_tab_enabled": true, "messages_tab_enabled": true, "messages_tab_read_only_enabled": false } }, "oauth_config": { "scopes": { "bot": [ "app_mentions:read", "assistant:write", "channels:history", "channels:read", "chat:write", "commands", "emoji:read", "files:read", "files:write", "groups:history", "groups:read", "im:history", "im:read", "im:write", "mpim:history", "mpim:read", "mpim:write", "pins:read", "pins:write", "usergroups:read", "users:read" ] } }, "settings": { "socket_mode_enabled": true, "event_subscriptions": { "bot_events": [ "app_home_opened", "app_mention", "channel_rename", "member_joined_channel", "member_left_channel", "message.channels", "message.groups", "message.im", "message.mpim", "pin_added", "pin_removed" ] } }}Після того як Slack створить застосунок, виконайте дві дії на його сторінці налаштувань:
- Install to Workspace → скопіюйте Bot User OAuth Token → він стане
sutBotToken. - Basic Information → App-Level Tokens → Generate Token and Scopes → додайте scope
connections:write→ збережіть → скопіюйте значенняxapp-...→ воно станеsutAppToken.
Перевірте, що два боти мають різні id користувачів, викликавши auth.test для кожного токена. Runtime розрізняє driver і SUT за id користувача; повторне використання одного застосунку для обох негайно провалить mention-gating.
3. Створіть канал
У робочому просторі QA створіть канал (наприклад, #openclaw-qa) і запросіть обох ботів ізсередини каналу:
/invite @OpenClaw QA Driver/invite @OpenClaw QA SUTСкопіюйте id Cxxxxxxxxxx з channel info → About → Channel ID - він стане channelId. Публічний канал підходить; якщо використовуєте приватний канал, обидва застосунки вже мають groups:history, тому читання історії тестовим стендом усе одно успішно працюватиме.
4. Зареєструйте облікові дані
Є два варіанти. Використовуйте змінні середовища для налагодження на одній машині (задайте чотири змінні OPENCLAW_QA_SLACK_* і передайте --credential-source env) або засійте спільний пул Convex, щоб CI та інші мейнтейнери могли орендувати їх.
Для пулу Convex запишіть чотири поля у файл JSON:
{ "channelId": "Cxxxxxxxxxx", "driverBotToken": "xoxb-...", "sutBotToken": "xoxb-...", "sutAppToken": "xapp-..."}З експортованими у вашій оболонці OPENCLAW_QA_CONVEX_SITE_URL і OPENCLAW_QA_CONVEX_SECRET_MAINTAINER зареєструйте й перевірте:
pnpm openclaw qa credentials add \ --kind slack \ --payload-file slack-creds.json \ --note "QA Slack pool seed" pnpm openclaw qa credentials list --kind slack --status all --jsonОчікуйте count: 1, status: "active", без поля lease.
5. Перевірте end to end
Запустіть лінію локально, щоб підтвердити, що обидва боти можуть спілкуватися один з одним через брокер:
pnpm openclaw qa slack \ --credential-source convex \ --credential-role maintainer \ --output-dir .artifacts/qa-e2e/slack-localУспішний запуск завершується значно швидше ніж за 30 секунд, а slack-qa-report.md показує і slack-canary, і slack-mention-gating зі статусом pass. Якщо лінія зависає приблизно на 90 секунд і завершується з Convex credential pool exhausted for kind "slack", то пул порожній або кожен рядок орендовано - qa credentials list --kind slack --status all --json покаже, що саме.
Пул облікових даних Convex
Лінії Telegram, Discord, Slack і WhatsApp можуть орендувати облікові дані зі спільного пулу Convex замість читання наведених вище змінних середовища. Передайте --credential-source convex (або задайте OPENCLAW_QA_CREDENTIAL_SOURCE=convex); QA Lab отримує ексклюзивну оренду, надсилає для неї Heartbeat протягом виконання запуску й звільняє її під час завершення. Види пулу: "telegram", "discord", "slack" і "whatsapp".
Форми payload, які брокер перевіряє на admin/add:
- 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 }- одна ексклюзивна оренда burner-account, яку використовують і TDLib CLI driver, і візуальний свідок Telegram Desktop. - 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.
Для візуального proof Telegram з реальним користувачем надавайте перевагу утримуваній сесії Crabbox:
pnpm qa:telegram-user:crabbox -- start --tdlib-url http://artifacts.openclaw.ai/tdlib-v1.8.0-linux-x64.tgz --output-dir .artifacts/qa-e2e/telegram-user-crabbox/pr-reviewpnpm qa:telegram-user:crabbox -- send --session .artifacts/qa-e2e/telegram-user-crabbox/pr-review/session.json --text /statuspnpm qa:telegram-user:crabbox -- finish --session .artifacts/qa-e2e/telegram-user-crabbox/pr-review/session.jsonstart утримує одну ексклюзивну оренду Convex telegram-user і для TDLib CLI
driver, і для свідка Telegram Desktop, запускає запис робочого столу та залишає
Crabbox живим для довільних кроків відтворення, керованих агентом. Агенти можуть використовувати send,
run, screenshot і status, доки не будуть задоволені, потім finish
збирає знімок екрана, відео, обрізане за рухом відео/GIF, виходи TDLib probe
і логи перед звільненням облікових даних. publish --session <file> --pr <number> за замовчуванням коментує лише motion GIF; --full-artifacts є
явним увімкненням для логів і JSON-виходу. Стандартна команда probe залишається
скороченням з однієї команди для швидких smoke-перевірок /status.
Використовуйте --mock-response-file <path>, коли PR потребує детермінованого візуального diff:
ту саму відповідь mock-моделі можна запускати на main і на голові PR, поки змінюється
форматер Telegram або шар доставки. Типові параметри захоплення налаштовані для коментарів PR:
стандартний клас Crabbox, запис робочого столу 24fps, GIF із рухом 24fps і
ширина прев'ю 1920px. Коментарі before/after мають публікувати чистий пакет, що
містить лише потрібні GIF.
Лінії Slack також можуть використовувати пул. Перевірки форми payload Slack наразі живуть у Slack QA runner, а не в брокері; використовуйте { channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string }, з ідентифікатором каналу Slack на кшталт Cxxxxxxxxxx. Див. Налаштування робочого простору Slack для підготовки застосунку й scope.
Операційні змінні середовища та контракт кінцевої точки брокера Convex описані в Тестування → Спільні облікові дані Telegram через Convex (назва розділу передує багатоканальному пулу; семантика lease спільна для всіх kind).
Сіди з репозиторія
Ресурси seed живуть у qa/:
qa/scenarios/index.mdqa/scenarios/<theme>/*.md
Вони навмисно зберігаються в git, щоб план QA був видимим і людям, і агенту.
qa-lab має залишатися універсальним markdown runner. Кожен markdown-файл сценарію є
джерелом істини для одного тестового запуску й має визначати:
- метадані сценарію
- необов'язкові метадані категорії, capability, лінії та ризику
- посилання на документацію й код
- необов'язкові вимоги до plugin
- необов'язковий patch конфігурації Gateway
- виконуваний
qa-flow
Багаторазова runtime-поверхня, що підтримує qa-flow, може залишатися універсальною
та наскрізною. Наприклад, markdown-сценарії можуть поєднувати transport-side
helper-и з browser-side helper-ами, які керують вбудованим Control UI через
шов Gateway browser.request без додавання runner для окремого випадку.
Файли сценаріїв слід групувати за можливістю продукту, а не за папкою дерева
джерел. Зберігайте ID сценаріїв стабільними під час переміщення файлів; використовуйте docsRefs і codeRefs
для трасованості реалізації.
Базовий список має залишатися достатньо широким, щоб покривати:
- DM і чат каналу
- поведінку тредів
- життєвий цикл дій із повідомленнями
- callbacks Cron
- пригадування пам'яті
- перемикання моделі
- передачу subagent
- читання репозиторія та документації
- одне невелике завдання збірки, як-от Lobster Invaders
Mock-лінії провайдера
qa suite має дві локальні mock-лінії провайдера:
mock-openai— scenario-aware mock OpenClaw. Він залишається типовою детермінованою mock-лінією для QA з репозиторія та parity gates.aimockзапускає AIMock-backed сервер провайдера для експериментального protocol, fixture, record/replay і chaos coverage. Це доповнення, яке не замінює scenario dispatchermock-openai.
Реалізація ліній провайдера живе в extensions/qa-lab/src/providers/.
Кожен провайдер володіє своїми типовими параметрами, запуском локального сервера, конфігурацією моделі Gateway,
потребами staging auth-profile, а також прапорцями live/mock capability. Спільний код suite і
Gateway має маршрутизуватися через registry провайдерів, а не розгалужуватися за
іменами провайдерів.
Transport adapters
qa-lab володіє універсальним transport seam для markdown QA-сценаріїв. qa-channel є першим adapter на цьому seam, але ціль дизайну ширша: майбутні реальні або синтетичні канали мають підключатися до того самого suite runner замість додавання transport-specific QA runner.
На архітектурному рівні поділ такий:
qa-labволодіє універсальним виконанням сценаріїв, worker concurrency, записом артефактів і звітністю.- Transport adapter володіє конфігурацією Gateway, готовністю, inbound і outbound спостереженням, transport actions і нормалізованим transport state.
- Markdown-файли сценаріїв у
qa/scenarios/визначають тестовий запуск;qa-labнадає багаторазову runtime-поверхню, яка їх виконує.
Додавання каналу
Додавання каналу до markdown QA-системи потребує рівно двох речей:
- Transport adapter для каналу.
- Пак сценаріїв, що перевіряє контракт каналу.
Не додавайте новий top-level корінь QA-команди, коли спільний host qa-lab може володіти потоком.
qa-lab володіє спільною host-механікою:
- корінь команди
openclaw qa - запуск і teardown suite
- worker concurrency
- запис артефактів
- генерація звітів
- виконання сценаріїв
- compatibility aliases для старіших сценаріїв
qa-channel
Runner plugins володіють transport contract:
- як
openclaw qa <runner>монтується під спільним коренемqa - як Gateway налаштовується для цього transport
- як перевіряється готовність
- як injected inbound events
- як observed outbound messages
- як відкриваються transcripts і нормалізований transport state
- як виконуються transport-backed actions
- як обробляється transport-specific reset або cleanup
Мінімальна планка впровадження для нового каналу:
- Зберігайте
qa-labвласником спільного кореняqa. - Реалізуйте transport runner на спільному host seam
qa-lab. - Тримайте transport-specific механіку всередині runner plugin або channel harness.
- Монтуйте runner як
openclaw qa <runner>, а не реєструйте конкуруючу кореневу команду. Runner plugins мають оголошуватиqaRunnersвopenclaw.plugin.jsonі експортувати відповідний масивqaRunnerCliRegistrationsзruntime-api.ts. Тримайтеruntime-api.tsлегким; lazy CLI та виконання runner мають залишатися за окремими entrypoints. - Створюйте або адаптуйте markdown-сценарії в тематичних директоріях
qa/scenarios/. - Використовуйте універсальні scenario helpers для нових сценаріїв.
- Зберігайте наявні compatibility aliases робочими, якщо репозиторій не виконує навмисну міграцію.
Правило ухвалення рішення суворе:
- Якщо поведінку можна виразити один раз у
qa-lab, розмістіть її вqa-lab. - Якщо поведінка залежить від одного channel transport, тримайте її в цьому runner plugin або plugin harness.
- Якщо сценарію потрібна нова capability, яку може використовувати більше ніж один канал, додайте універсальний helper замість channel-specific гілки в
suite.ts. - Якщо поведінка має сенс лише для одного transport, залиште сценарій transport-specific і явно вкажіть це в контракті сценарію.
Назви scenario helper
Бажані універсальні helper-и для нових сценаріїв:
waitForTransportReadywaitForChannelReadyinjectInboundMessageinjectOutboundMessagewaitForTransportOutboundMessagewaitForChannelOutboundMessagewaitForNoTransportOutboundgetTransportSnapshotreadTransportMessagereadTransportTranscriptformatTransportTranscriptresetTransport
Compatibility aliases залишаються доступними для наявних сценаріїв - waitForQaChannelReady, waitForOutboundMessage, waitForNoOutbound, formatConversationTranscript, resetBus - але нові сценарії слід писати з універсальними назвами. Aliases існують, щоб уникнути одночасної міграції всього набору, а не як модель на майбутнє.
Звітність
qa-lab експортує Markdown-звіт протоколу зі спостереженої bus timeline.
Звіт має відповідати на такі питання:
- Що спрацювало
- Що не вдалося
- Що залишилося заблокованим
- Які подальші сценарії варто додати
Щоб отримати інвентар доступних сценаріїв - корисний під час оцінки подальшої роботи або підключення нового transport - запустіть pnpm openclaw qa coverage (додайте --json для machine-readable output).
Для перевірок характеру й стилю запустіть той самий сценарій на кількох live model refs і запишіть judged Markdown report:
pnpm openclaw qa character-eval \ --model openai/gpt-5.5,thinking=medium,fast \ --model openai/gpt-5.2,thinking=xhigh \ --model openai/gpt-5,thinking=xhigh \ --model anthropic/claude-opus-4-6,thinking=high \ --model anthropic/claude-sonnet-4-6,thinking=high \ --model zai/glm-5.1,thinking=high \ --model moonshot/kimi-k2.5,thinking=high \ --model google/gemini-3.1-pro-preview,thinking=high \ --judge-model openai/gpt-5.5,thinking=xhigh,fast \ --judge-model anthropic/claude-opus-4-6,thinking=high \ --blind-judge-models \ --concurrency 16 \ --judge-concurrency 16Команда запускає дочірні процеси локального QA Gateway, а не Docker. Сценарії character eval
мають задавати persona через SOUL.md, а потім виконувати звичайні ходи користувача,
як-от чат, допомогу з workspace і невеликі файлові завдання. Candidate model не має
знати, що її оцінюють. Команда зберігає кожен повний
transcript, записує базову статистику запуску, а потім просить judge models у fast mode з
reasoning xhigh, де підтримується, ранжувати запуски за природністю, vibe і humor.
Використовуйте --blind-judge-models, коли порівнюєте провайдерів: judge prompt усе ще отримує
кожен transcript і run status, але candidate refs замінюються нейтральними
мітками на кшталт candidate-01; звіт зіставляє rankings назад із реальними refs після
парсингу.
Candidate runs типово використовують thinking high, з medium для GPT-5.5 і xhigh
для старіших OpenAI eval refs, які це підтримують. Перевизначайте конкретного candidate inline за допомогою
--model provider/model,thinking=<level>. --thinking <level> усе ще задає
глобальний fallback, а старіша форма --model-thinking <provider/model=level> збережена
для сумісності.
OpenAI candidate refs типово використовують fast mode, щоб priority processing застосовувався там, де
провайдер його підтримує. Додавайте ,fast, ,no-fast або ,fast=false inline, коли
окремому candidate або judge потрібне перевизначення. Передавайте --fast лише тоді, коли хочете
примусово ввімкнути fast mode для кожної candidate model. Тривалості candidate і judge
записуються у звіт для benchmark analysis, але judge prompts явно кажуть
не ранжувати за швидкістю.
Запуски candidate і judge models обидва типово мають concurrency 16. Зменшуйте
--concurrency або --judge-concurrency, коли ліміти провайдера або тиск на локальний Gateway
роблять запуск надто шумним.
Коли candidate --model не передано, character eval типово використовує
openai/gpt-5.5, openai/gpt-5.2, openai/gpt-5, anthropic/claude-opus-4-6,
anthropic/claude-sonnet-4-6, zai/glm-5.1,
moonshot/kimi-k2.5 і
google/gemini-3.1-pro-preview, коли --model не передано.
Коли --judge-model не передано, judges типово використовують
openai/gpt-5.5,thinking=xhigh,fast і
anthropic/claude-opus-4-6,thinking=high.