extensions/qa-channel: canal de mensagens sintético com superfícies de DM, canal, thread, reação, edição e exclusão.extensions/qa-lab: UI de depuração e barramento de QA para observar a transcrição, injetar mensagens de entrada e exportar um relatório em Markdown.extensions/qa-matrix, futuros plugins de execução: adaptadores de transporte ao vivo que conduzem um canal real dentro de um Gateway de QA filho.qa/: ativos seed mantidos no repo para a tarefa inicial e cenários de QA de linha de base.- Mantis: verificação ao vivo antes e depois para bugs que precisam de transportes reais, capturas de tela do navegador, estado de VM e evidência de PR.
Superfície de comandos
Todo fluxo de QA é executado sobpnpm openclaw qa <subcommand>. Muitos têm aliases de script pnpm qa:*;
ambas as formas são compatíveis.
| Comando | Finalidade |
|---|---|
qa run | Autoverificação de QA empacotada sem --qa-profile; executor de perfil de maturidade baseado em taxonomia com --qa-profile smoke-ci, --qa-profile release ou --qa-profile all. |
qa suite | Executar cenários mantidos no repo contra a via do Gateway de QA. Aliases: pnpm openclaw qa suite --runner multipass para uma VM Linux descartável. |
qa coverage | Imprimir o inventário YAML de cobertura de cenários (--json para saída de máquina). |
qa parity-report | Comparar dois arquivos qa-suite-summary.json e gravar o relatório de paridade agêntica, ou usar --runtime-axis --token-efficiency para gravar relatórios de paridade de runtime Codex-vs-OpenClaw e eficiência de tokens a partir de um resumo de par de runtimes. |
qa character-eval | Executar o cenário de QA de personagem em vários modelos ao vivo com um relatório julgado. Consulte Relatórios. |
qa manual | Executar um prompt avulso contra a via de provedor/modelo selecionada. |
qa ui | Iniciar a UI de depuração de QA e o barramento de QA local (alias: pnpm qa:lab:ui). |
qa docker-build-image | Criar a imagem Docker de QA pré-preparada. |
qa docker-scaffold | Gravar um scaffold docker-compose para o painel de QA + via do Gateway. |
qa up | Criar o site de QA, iniciar a pilha baseada em Docker, imprimir a URL (alias: pnpm qa:lab:up; a variante :fast adiciona --use-prebuilt-image --bind-ui-dist --skip-ui-build). |
qa aimock | Iniciar apenas o servidor provedor AIMock. |
qa mock-openai | Iniciar apenas o servidor provedor mock-openai ciente de cenários. |
qa credentials doctor / add / list / remove | Gerenciar o pool compartilhado de credenciais Convex. |
qa matrix | Via de transporte ao vivo contra um homeserver Tuwunel descartável. Consulte QA Matrix. |
qa telegram | Via de transporte ao vivo contra um grupo privado real do Telegram. |
qa discord | Via de transporte ao vivo contra um canal real de guilda privada do Discord. |
qa slack | Via de transporte ao vivo contra um canal privado real do Slack. |
qa whatsapp | Via de transporte ao vivo contra contas reais do WhatsApp Web. |
qa mantis | Executor de verificação antes e depois para bugs de transporte ao vivo, com evidência de reações de status do Discord, teste de fumaça de desktop/navegador do Crabbox e teste de fumaça do Slack em VNC. Consulte Mantis e Runbook do Mantis Slack Desktop. |
qa run baseado em perfil lê a associação de taxonomy.yaml e então despacha
os cenários resolvidos por meio de qa suite. --surface e
--category filtram o perfil selecionado em vez de definir vias separadas.
O qa-evidence.json resultante inclui um resumo de scorecard do perfil com
contagens por categoria selecionada e IDs de cobertura ausentes; as entradas
individuais de evidência continuam sendo a fonte da verdade para os testes,
funções de cobertura e resultados. IDs de cobertura de recursos da taxonomia são
alvos exatos de prova, não aliases. A cobertura primária de cenário satisfaz IDs
correspondentes; a cobertura secundária permanece consultiva.
IDs de cobertura usam a forma pontuada namespace.behavior com segmentos
alfanuméricos/de hífen em minúsculas; IDs de perfil, superfície e categoria ainda podem usar
os IDs de taxonomia existentes com hífen ou pontuação.
Evidência enxuta omite execution por entrada e define evidenceMode: "slim";
smoke-ci usa enxuta por padrão, e --evidence-mode full restaura entradas completas:
smoke-ci para prova determinística de perfil com provedores de modelo mock e
servidores provedores locais Crabline. Use release para prova Stable/LTS contra canais
ao vivo. Use all apenas para execuções explícitas de evidência de taxonomia completa; ele seleciona
todas as categorias de maturidade ativas e pode ser despachado pelo workflow QA Profile Evidence com qa_profile=all. Quando um comando também precisa de um perfil raiz do OpenClaw,
coloque o perfil raiz antes do comando de QA:
Fluxo do operador
O fluxo atual de operador de QA é um site de QA com dois painéis:- Esquerda: painel do Gateway (Control UI) com o agente.
- Direita: QA Lab, mostrando a transcrição em estilo Slack e o plano de cenário.
qa:lab:up:fast mantém os serviços Docker em uma imagem pré-criada e monta por bind
extensions/qa-lab/web/dist no contêiner qa-lab. qa:lab:watch
recria esse bundle quando há mudanças, e o navegador recarrega automaticamente quando o hash de ativos do QA Lab
muda.
Para um teste de fumaça de sinal local do OpenTelemetry, execute:
otel-trace-smoke
com o plugin diagnostics-otel habilitado e então verifica se traces,
métricas e logs são exportados. Ele decodifica os spans de trace protobuf exportados
e verifica a forma crítica para o lançamento:
openclaw.run, openclaw.harness.run, um span de chamada de modelo da convenção semântica
GenAI mais recente, openclaw.context.assembled e openclaw.message.delivery
devem estar presentes. O teste de fumaça força
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental, então o span de chamada de modelo
deve usar o nome {gen_ai.operation.name} {gen_ai.request.model};
chamadas de modelo não devem exportar StreamAbandoned em turnos bem-sucedidos; IDs diagnósticos brutos e
atributos openclaw.content.* devem ficar fora do trace. Os payloads OTLP brutos
não devem conter o sentinela de prompt, sentinela de resposta ou chave de sessão de QA.
Ele grava otel-smoke-summary.json ao lado dos artefatos da suíte de QA.
Para um teste de fumaça do OpenTelemetry com collector, execute:
docker-prometheus-smoke com
diagnostics-prometheus habilitado, verifica que scrapes não autenticados são
rejeitados e então confere se o scrape autenticado inclui famílias de métricas
críticas para a versão sem conteúdo de prompt, conteúdo de resposta,
identificadores brutos de diagnóstico, tokens de autenticação ou caminhos
locais.
Para executar ambos os smoke tests de observabilidade em sequência, use:
qa. Use pnpm qa:otel:smoke,
pnpm qa:prometheus:smoke ou pnpm qa:observability:smoke a partir de um
checkout de origem compilado ao alterar a instrumentação de diagnósticos.
Para uma faixa de smoke Matrix com transporte real que não exige credenciais de
provedor de modelo, execute o perfil rápido com o provedor mock OpenAI
determinístico:
qa-channel) e então grava um relatório Markdown, um resumo JSON, um artefato de eventos observados e um log de saída combinado em .artifacts/qa-e2e/matrix-<timestamp>/.
Os cenários cobrem comportamento de transporte que testes unitários não conseguem provar de ponta a ponta: bloqueio por menção, políticas allow-bot, listas de permissões, respostas de nível superior e em threads, roteamento de DM, tratamento de reações, supressão de edições de entrada, desduplicação de replay após reinicialização, recuperação de interrupção do homeserver, entrega de metadados de aprovação, tratamento de mídia e fluxos de bootstrap/recuperação/verificação de E2EE do Matrix. O perfil CLI de E2EE também conduz openclaw matrix encryption setup e comandos de verificação pelo mesmo homeserver descartável antes de verificar as respostas do Gateway.
Discord também tem cenários opcionais somente para Mantis para reprodução de bugs. Use
--scenario discord-status-reactions-tool-only para a linha do tempo explícita
de reações de status, ou --scenario discord-thread-reply-filepath-attachment
para criar uma thread real do Discord e verificar que message.thread-reply
preserva um anexo filePath. Esses cenários ficam fora da faixa Discord live
padrão porque são sondas de reprodução antes/depois, e não cobertura ampla de
smoke. O fluxo de trabalho Mantis de anexo em thread também pode adicionar um
vídeo testemunha do Discord Web com login quando
MANTIS_DISCORD_VIEWER_CHROME_PROFILE_DIR ou
MANTIS_DISCORD_VIEWER_CHROME_PROFILE_TGZ_B64 estiver configurado no ambiente
de QA. Esse perfil de visualizador serve apenas para captura visual; a decisão
de aprovado/reprovado ainda vem do oráculo REST do Discord.
A CI usa a mesma superfície de comando em .github/workflows/qa-live-transports-convex.yml.
Execuções agendadas e manuais padrão executam o perfil rápido do Matrix com
credenciais live-frontier fornecidas pelo QA, --fast e
OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS=3000. O matrix_profile=all manual
distribui a execução nos cinco shards de perfil.
Para faixas de smoke com transporte real de Telegram, Discord, Slack e WhatsApp:
slack-qa/, slack-desktop-smoke.png e slack-desktop-smoke.mp4
quando a captura de vídeo estiver disponível de volta para o diretório de
artefatos do Mantis. Aluguéis desktop/navegador do Crabbox fornecem de antemão
as ferramentas de captura e pacotes auxiliares de navegador/compilação nativa,
portanto o cenário só deve instalar fallbacks em aluguéis mais antigos. O
Mantis relata tempos totais e por fase em mantis-slack-desktop-smoke-report.md
para que execuções lentas mostrem se o tempo foi para aquecimento do aluguel,
aquisição de credenciais, configuração remota ou cópia de artefatos. Reutilize
--lease-id <cbx_...> depois de fazer login no Slack Web manualmente pelo VNC;
aluguéis reutilizados também mantêm aquecido o cache da store pnpm do Crabbox.
O padrão --hydrate-mode source verifica a partir de um checkout de origem e
executa instalação/compilação dentro da VM. Use --hydrate-mode prehydrated
somente quando o workspace remoto reutilizado já tiver node_modules e um
dist/ compilado; esse modo pula a etapa cara de instalação/compilação e falha
fechado quando o workspace não está pronto. Com --gateway-setup, o Mantis
deixa um Gateway Slack persistente do OpenClaw em execução dentro da VM na porta
38973; sem isso, o comando executa a faixa normal de QA Slack bot-para-bot e
sai após a captura de artefatos.
Para provar a UI nativa de aprovação do Slack com evidência de desktop, execute
o modo de checkpoint de aprovação do Mantis:
--gateway-setup. Ele executa os cenários
de aprovação do Slack, rejeita ids de cenário que não sejam de aprovação,
aguarda em cada estado de aprovação pendente e resolvida, renderiza a mensagem
observada da API do Slack em approval-checkpoints/<scenario>-pending.png e
approval-checkpoints/<scenario>-resolved.png e então falha se qualquer
checkpoint, evidência de mensagem, confirmação ou screenshot renderizado estiver
ausente ou vazio. Aluguéis frios de CI ainda podem mostrar o login do Slack em
slack-desktop-smoke.png; as imagens de checkpoint de aprovação são a prova
visual desta faixa.
A checklist do operador, o comando de dispatch do fluxo de trabalho do GitHub, o
contrato de comentário de evidência, a tabela de decisão de modo de hidratação,
a interpretação de tempos e as etapas de tratamento de falhas ficam no
Runbook de Desktop Slack do Mantis.
Para uma tarefa desktop em estilo agente/CV, execute:
visual-task aluga ou reutiliza uma máquina Crabbox desktop/navegador, inicia
crabbox record --while, conduz o navegador visível por meio de um
visual-driver aninhado, captura visual-task.png, executa
openclaw infer image describe contra o screenshot quando
--vision-mode image-describe está selecionado e grava visual-task.mp4,
mantis-visual-task-summary.json, mantis-visual-task-driver-result.json e
mantis-visual-task-report.md. Quando --expect-text está definido, o prompt
de visão pede um veredito JSON estruturado e só aprova quando o modelo relata
evidência visível positiva; uma resposta negativa que apenas cita o texto-alvo
falha a asserção. Use --vision-mode metadata para um smoke sem modelo que
prova o encanamento de desktop, navegador, screenshot e vídeo sem chamar um
provedor de compreensão de imagem. A gravação é um artefato obrigatório para
visual-task; se o Crabbox não gravar um visual-task.mp4 não vazio, a tarefa
falha mesmo quando o driver visual aprovou. Em caso de falha, o Mantis mantém o
aluguel para VNC, a menos que a tarefa já tenha sido aprovada e --keep-lease
não tenha sido definido.
Antes de usar credenciais live em pool, execute:
Cobertura de transporte live
Faixas de transporte live compartilham um contrato em vez de cada uma inventar seu próprio formato de lista de cenários.qa-channel é a suíte ampla de comportamento sintético do produto e não faz parte da matriz de cobertura de transporte live.
Runners de transporte live devem importar os ids de cenário compartilhados, os
auxiliares de cobertura de baseline e o auxiliar de seleção de cenário de
openclaw/plugin-sdk/qa-live-transport-scenarios.
| Faixa | Canário | Bloqueio por menção | Bot para bot | Bloqueio por lista de permissões | Resposta de nível superior | Resposta com citação | Retomada após reinício | Acompanhamento em thread | Isolamento de thread | Observação de reação | Comando de ajuda | Registro de comando nativo |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 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 como a suíte ampla de comportamento do produto, enquanto
Matrix, Telegram e outros transportes live compartilham uma checklist explícita
de contrato de transporte.
Para uma faixa de VM Linux descartável sem trazer Docker para o caminho de QA,
execute:
qa suite e então copia o relatório e o
resumo normais de QA de volta para .artifacts/qa-e2e/... no host.
Ela reutiliza o mesmo comportamento de seleção de cenários que qa suite no host.
Execuções da suíte no host e no Multipass executam vários cenários selecionados
em paralelo com workers de Gateway isolados por padrão. qa-channel usa
concorrência 4 por padrão, limitada pela contagem de cenários selecionados. Use
--concurrency <count> para ajustar a contagem de workers, ou --concurrency 1
para execução serial. Use --pack personal-agent para executar o pacote de
benchmark de assistente pessoal. O seletor de pacote é aditivo com flags
--scenario repetidas: cenários explícitos rodam primeiro, depois os cenários
do pacote rodam na ordem do pacote com duplicatas removidas. Use
--pack observability quando um runner de QA personalizado já fornece a
configuração do coletor OpenTelemetry e quer selecionar juntos os cenários de
smoke de diagnósticos OpenTelemetry e Prometheus. O comando sai com código
diferente de zero quando qualquer cenário falha. Use --allow-failures quando
você quiser artefatos sem um código de saída de falha. Execuções live encaminham
as entradas de autenticação de QA compatíveis que são práticas para o guest:
chaves de provedor baseadas em ambiente, o caminho de configuração do provedor
live de QA e CODEX_HOME quando presente. Mantenha --output-dir sob a raiz do
repositório para que o guest consiga gravar de volta pelo workspace montado.
Referência de QA para Telegram, Discord, Slack e WhatsApp
Matrix tem uma página dedicada por causa da contagem de cenários e do provisionamento de homeserver com suporte a Docker. Telegram, Discord, Slack e WhatsApp são executados contra transportes reais preexistentes, portanto sua referência fica aqui.Flags compartilhadas da CLI
Essas lanes são registradas por meio deextensions/qa-lab/src/live-transports/shared/live-transport-cli.ts e aceitam as mesmas flags:
| Flag | Padrão | Descrição |
|---|---|---|
--scenario <id> | - | Executa apenas este cenário. Repetível. |
--output-dir <path> | <repo>/.artifacts/qa-e2e/<transport>-<timestamp> | Onde relatórios, resumos, evidências, artefatos específicos do transporte e o log de saída são gravados. Caminhos relativos são resolvidos em relação a --repo-root. |
--repo-root <path> | process.cwd() | Raiz do repositório ao invocar a partir de um cwd neutro. |
--sut-account <id> | sut | ID de conta temporário dentro da configuração do Gateway de QA. |
--provider-mode <mode> | live-frontier | mock-openai ou live-frontier (live-openai legado ainda funciona). |
--model <ref> / --alt-model <ref> | padrão do provedor | Refs de modelo primário/alternativo. |
--fast | desativado | Modo rápido do provedor quando suportado. |
--credential-source <env|convex> | env | Consulte pool de credenciais Convex. |
--credential-role <maintainer|ci> | ci em CI, caso contrário maintainer | Função usada quando --credential-source convex. |
--allow-failures grava artefatos sem definir um código de saída de falha.
QA do Telegram
@BotFather.
Env obrigatório quando --credential-source env:
OPENCLAW_QA_TELEGRAM_GROUP_ID- ID numérico do chat (string).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 também incluem verificações determinísticas de cadeia de respostas e streaming de mensagem final. telegram-current-session-status-tool continua opt-in porque só é estável quando encadeado diretamente após o canário, não após respostas arbitrárias de comandos nativos. Use pnpm openclaw qa telegram --list-scenarios --provider-mode mock-openai para imprimir a divisão atual entre padrão/opcional com refs de regressão.
Artefatos de saída:
telegram-qa-report.mdqa-evidence.json- entradas de evidência para as verificações de transporte ao vivo, incluindo campos de perfil, cobertura, provedor, canal, artefatos, resultado e RTT.
qa-evidence.json sob result.timing para a verificação de RTT selecionada.
OPENCLAW_QA_CREDENTIAL_SOURCE=convex é definido, o wrapper ao vivo do pacote aluga uma credencial kind: "telegram", exporta o grupo/driver/bot SUT alugados para o ambiente da execução do pacote instalado, envia Heartbeats para a concessão e a libera no encerramento. O wrapper de pacote usa por padrão 20 verificações de RTT de telegram-mentioned-message-reply, um timeout de RTT de 30s e a função Convex maintainer fora de CI quando Convex é selecionado. Sobrescreva OPENCLAW_NPM_TELEGRAM_RTT_SAMPLES, OPENCLAW_NPM_TELEGRAM_RTT_TIMEOUT_MS ou OPENCLAW_NPM_TELEGRAM_RTT_MAX_FAILURES para ajustar a medição de RTT sem criar um comando RTT separado ou formato de resumo específico do Telegram.
QA do Discord
/help no Discord e cenários de evidência Mantis opt-in.
Env obrigatório quando --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- deve corresponder ao ID de usuário do bot SUT retornado pelo Discord (caso contrário, a lane falha rapidamente).
OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1mantém os corpos das mensagens nos artefatos de mensagens observadas.OPENCLAW_QA_DISCORD_VOICE_CHANNEL_IDseleciona o canal de voz/palco paradiscord-voice-autojoin; sem isso, o cenário escolhe o primeiro canal de voz/palco visível para o bot SUT.
extensions/qa-lab/src/live-transports/discord/discord-live.runtime.ts:36):
discord-canarydiscord-mention-gatingdiscord-native-help-command-registrationdiscord-voice-autojoin- cenário de voz opt-in. Executa sozinho, habilitachannels.discord.voice.autoJoine verifica se o estado de voz atual no Discord do bot SUT é o canal de voz/palco alvo. As credenciais Discord do Convex podem incluirvoiceChannelIdopcional; caso contrário, o executor descobre o primeiro canal de voz/palco visível na guilda.discord-status-reactions-tool-only- cenário Mantis opt-in. Executa sozinho porque alterna o SUT para respostas de guilda sempre ativas e somente por ferramenta commessages.statusReactions.enabled=true, depois captura uma linha do tempo de reações REST mais artefatos visuais HTML/PNG. Relatórios antes/depois do Mantis também preservam artefatos MP4 fornecidos pelo cenário comobaseline.mp4ecandidate.mp4.
discord-qa-report.mdqa-evidence.json- entradas de evidência para as verificações de transporte ao vivo.discord-qa-observed-messages.json- corpos redigidos, a menos queOPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1.discord-qa-reaction-timelines.jsonediscord-status-reactions-tool-only-timeline.pngquando o cenário de reação de status é executado.
QA do Slack
--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=1mantém os corpos das mensagens nos artefatos de mensagens observadas.OPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_DIRhabilita checkpoints de aprovação visual para o Mantis. O executor grava<scenario>.pending.jsone<scenario>.resolved.json, depois espera por arquivos.ack.jsoncorrespondentes.OPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_TIMEOUT_MSsubstitui o timeout de confirmação do checkpoint. O padrão é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- cenário opt-in de aprovação de exec nativa do Slack. Solicita uma aprovação de exec por meio do Gateway, verifica se a mensagem do Slack tem botões de aprovação nativos, resolve-a e verifica a atualização resolvida do Slack.slack-approval-plugin-native- cenário opt-in de aprovação nativa de Plugin do Slack. Habilita o encaminhamento de aprovação de exec e Plugin em conjunto para que eventos de Plugin não sejam suprimidos pelo roteamento de aprovação de exec, depois verifica o mesmo caminho de IU nativa do Slack pendente/resolvido.
slack-qa-report.mdqa-evidence.json- entradas de evidência para as verificações de transporte ao vivo.slack-qa-observed-messages.json- corpos redigidos, a menos queOPENCLAW_QA_SLACK_CAPTURE_CONTENT=1.approval-checkpoints/- somente quando o Mantis defineOPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_DIR; contém JSON de checkpoint, JSON de confirmação e capturas de tela pendente/resolvida.
Configurando o workspace do Slack
A lane precisa de dois apps Slack distintos em um workspace, além de um canal do qual ambos os bots sejam membros:channelId- o IDCxxxxxxxxxxde um canal para o qual ambos os bots foram convidados. Use um canal dedicado; a lane publica a cada execução.driverBotToken- token de bot (xoxb-...) do app Driver.sutBotToken- token de bot (xoxb-...) do app SUT, que deve ser um app Slack separado do driver para que seu ID de usuário de bot seja distinto.sutAppToken- token no nível do app (xapp-...) do app SUT comconnections:write, usado pelo Socket Mode para que o app SUT possa receber eventos.
extensions/slack/src/setup-shared.ts:10) para as permissões e eventos cobertos pela suíte de QA ao vivo do Slack. Para a configuração do canal de produção como os usuários a veem, consulte configuração rápida do canal Slack; o par Driver/SUT de QA é intencionalmente separado porque a lane precisa de dois IDs de usuário de bot distintos em um workspace.
1. Crie o app Driver
Acesse api.slack.com/apps → Criar novo app → A partir de um manifesto → escolha o workspace de QA, cole o manifesto a seguir e então Instalar no workspace:
xoxb-...) - isso se torna driverBotToken. O driver só precisa postar mensagens e identificar a si mesmo; sem eventos, sem Socket Mode.
2. Criar o app SUT
Repita Criar novo app → A partir de um manifesto no mesmo workspace. Este app de QA usa intencionalmente uma versão mais restrita do manifesto de produção do Plugin Slack incluído (extensions/slack/src/setup-shared.ts:10): escopos e eventos de reação são omitidos porque a suíte de QA ao vivo do Slack ainda não cobre o tratamento de reações.
- Instalar no workspace → copie o Token OAuth de usuário bot → isso se torna
sutBotToken. - Informações básicas → Tokens no nível do app → Gerar token e escopos → adicione o escopo
connections:write→ salve → copie o valorxapp-...→ isso se tornasutAppToken.
auth.test em cada token. O runtime distingue o driver e o SUT pelo id de usuário; reutilizar um app para ambos fará o controle por menções falhar imediatamente.
3. Criar o canal
No workspace de QA, crie um canal (por exemplo, #openclaw-qa) e convide ambos os bots de dentro do canal:
Cxxxxxxxxxx em informações do canal → Sobre → ID do canal - isso se torna channelId. Um canal público funciona; se você usar um canal privado, ambos os apps já têm groups:history, então as leituras de histórico do harness ainda terão sucesso.
4. Registrar as credenciais
Duas opções. Use variáveis de ambiente para depuração em uma única máquina (defina as quatro variáveis OPENCLAW_QA_SLACK_* e passe --credential-source env), ou alimente o pool compartilhado do Convex para que CI e outros mantenedores possam reservá-las.
Para o pool do Convex, escreva os quatro campos em um arquivo JSON:
OPENCLAW_QA_CONVEX_SITE_URL e OPENCLAW_QA_CONVEX_SECRET_MAINTAINER exportados no seu shell, registre e verifique:
count: 1, status: "active", sem campo lease.
5. Verifique de ponta a ponta
Execute a trilha localmente para confirmar que ambos os bots conseguem conversar entre si por meio do intermediador:
slack-qa-report.md mostra tanto slack-canary quanto slack-mention-gating com status pass. Se a trilha ficar travada por ~90 segundos e sair com Convex credential pool exhausted for kind "slack", ou o pool está vazio ou todas as linhas estão concedidas por lease - qa credentials list --kind slack --status all --json indicará qual é o caso.
QA do WhatsApp
--credential-source 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_JIDhabilita cenários de grupo comowhatsapp-mention-gating,whatsapp-group-pending-history-context,whatsapp-broadcast-group-fanout,whatsapp-group-activation-always,whatsapp-group-reply-to-bot-triggers, cenários de ação/mídia/enquete em grupo ewhatsapp-group-allowlist-block.OPENCLAW_QA_WHATSAPP_CAPTURE_CONTENT=1mantém corpos de mensagens em artefatos de mensagens observadas.
extensions/qa-lab/src/live-transports/whatsapp/whatsapp-live.runtime.ts):
- Linha de base e controle de acesso por menção em grupo:
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. - Comandos nativos:
whatsapp-help-command,whatsapp-status-command,whatsapp-commands-command,whatsapp-tools-compact-command,whatsapp-whoami-command,whatsapp-context-command,whatsapp-native-new-command. - Comportamento de resposta e saída final:
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. - Ações de mensagem pelo caminho do usuário:
whatsapp-agent-message-action-reactcomeça a partir de uma DM real do controlador, permite que o modelo chame a ferramentamessagee observa a reação nativa do WhatsApp.whatsapp-agent-message-action-upload-fileusa a mesma postura paramessage(action=upload-file)e observa mídia nativa do WhatsApp.whatsapp-group-agent-message-action-reactewhatsapp-group-agent-message-action-upload-filecomprovam as mesmas ações visíveis ao usuário em um grupo real do WhatsApp. - Distribuição para grupo:
whatsapp-broadcast-group-fanoutcomeça a partir de uma mensagem mencionada em grupo do WhatsApp e verifica respostas visíveis distintas demaineqa-second. - Ativação em grupo:
whatsapp-group-activation-alwaysaltera uma sessão real de grupo para/activation always, comprova que uma mensagem de grupo sem menção desperta o agente e então restaura/activation mention.whatsapp-group-reply-to-bot-triggerssemeia uma resposta do bot, envia uma resposta nativa citada a ela sem uma menção explícita e verifica que o agente desperta a partir desse contexto de resposta. - Mídia recebida e mensagens estruturadas:
whatsapp-inbound-image-caption,whatsapp-audio-preflight,whatsapp-inbound-structured-messages,whatsapp-group-audio-gating,whatsapp-inbound-reaction-no-trigger. Esses cenários enviam eventos reais de imagem, áudio, documento, localização, contato, figurinha e reação do WhatsApp por meio do controlador. - Sondas diretas de contrato do Gateway:
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. Elas ignoram intencionalmente o prompt do modelo e comprovam contratos determinísticos de Gateway/canal parasend,pollemessage.action. - Cobertura de controle de acesso:
whatsapp-access-control-dm-open,whatsapp-access-control-dm-disabled,whatsapp-access-control-group-open,whatsapp-access-control-group-disabled,whatsapp-group-allowlist-block. - Aprovações nativas:
whatsapp-approval-exec-deny-native,whatsapp-approval-exec-native,whatsapp-approval-exec-reaction-native,whatsapp-approval-exec-group-reaction-native,whatsapp-approval-plugin-native. - Reações de status:
whatsapp-status-reactions,whatsapp-status-reaction-lifecycle.
live-frontier é
mantida pequena, com 10 cenários, para cobertura rápida de verificação. A trilha padrão
mock-openai executa 44 cenários determinísticos pelo transporte real do WhatsApp enquanto
simula apenas a saída do modelo. Cenários de aprovação e algumas verificações mais pesadas/bloqueantes
continuam explícitos por ID de cenário.
O controlador de QA do WhatsApp observa eventos vivos estruturados (text, media,
location, reaction e poll) e pode enviar ativamente mídia, enquetes,
contatos, localizações e figurinhas. O QA Lab importa esse controlador pela
superfície do pacote @openclaw/whatsapp/api.js, em vez de acessar arquivos privados
do runtime do WhatsApp. Para observações de grupo, fromJid é o JID do grupo, enquanto
participantJid e fromPhoneE164 identificam o remetente participante. O conteúdo
da mensagem é redigido por padrão. Sondas diretas de Gateway
para enquete, envio de arquivo, mídia, enquete em grupo, mídia em grupo e formato de resposta são verificações de contrato
de transporte/API; elas não são tratadas como prova de que um prompt de usuário fez o agente escolher
a mesma ação. A prova de ação pelo caminho do usuário vem de cenários como
whatsapp-agent-message-action-react e
whatsapp-group-agent-message-action-react, nos quais o controlador envia uma mensagem normal do
WhatsApp e o QA Lab observa o artefato nativo do WhatsApp resultante.
Relatórios do WhatsApp incluem a postura de cada cenário (user-path, direct-gateway
ou native-approval) para que a evidência não seja confundida com um contrato mais forte
do que ela de fato comprova.
Artefatos de saída:
whatsapp-qa-report.mdqa-evidence.json- entradas de evidência para as verificações do transporte vivo.whatsapp-qa-observed-messages.json- corpos redigidos, a menos queOPENCLAW_QA_WHATSAPP_CAPTURE_CONTENT=1.
Pool de credenciais do Convex
As trilhas Telegram, Discord, Slack e WhatsApp podem conceder credenciais por lease a partir de um pool compartilhado do Convex em vez de ler as variáveis de ambiente acima. Passe--credential-source convex (ou defina OPENCLAW_QA_CREDENTIAL_SOURCE=convex); o QA Lab adquire um lease exclusivo, envia Heartbeats durante a execução e o libera no encerramento. Os tipos de pool são "telegram", "discord", "slack" e "whatsapp".
Formatos de payload que o intermediador valida em admin/add:
- Telegram (
kind: "telegram"):{ groupId: string, driverToken: string, sutToken: string }-groupIddeve ser uma string numérica de chat-id. - Usuário real do 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 }- somente prova do Mantis Telegram Desktop. As faixas genéricas do QA Lab não devem adquirir esse tipo. - 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 }- os números de telefone devem ser strings E.164 distintas.
telegram-user do Convex para o driver de CLI TDLib e a testemunha do
Telegram Desktop, depois a libera após publicar a prova.
Quando um PR precisa de um diff visual determinístico, o Mantis pode usar a
mesma resposta de modelo simulado em main e na cabeça do PR enquanto o
formatador do Telegram ou a camada de entrega muda. Os padrões de captura são
ajustados para comentários de PR: classe Crabbox padrão, gravação de desktop a
24 fps, GIF de movimento a 24 fps e largura de pré-visualização de 1920 px.
Comentários de antes/depois devem publicar um pacote limpo que contenha somente
os GIFs pretendidos.
As faixas do Slack também podem usar o pool. As verificações de formato de payload do Slack atualmente ficam no executor de QA do Slack, e não no intermediador; use { channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string }, com um id de canal do Slack como Cxxxxxxxxxx. Consulte Configurar o workspace do Slack para provisionar o app e os escopos.
As variáveis de ambiente operacionais e o contrato de endpoint do intermediador Convex ficam em Testes → Credenciais compartilhadas do Telegram via Convex (o nome da seção é anterior ao pool multicanal; a semântica de concessão é compartilhada entre os tipos).
Seeds versionados no repositório
Os ativos de seed ficam emqa/:
qa/scenarios/index.yamlqa/scenarios/<theme>/*.yaml
qa-lab deve permanecer um executor genérico de cenários YAML. Cada arquivo
YAML de cenário é a fonte da verdade para uma execução de teste e deve definir:
titleno nível superior- metadados de
scenario - metadados opcionais de categoria, capability, faixa e risco em
scenario - referências de docs e código em
scenario - requisitos opcionais de plugin em
scenario - patch opcional de config do gateway em
scenario flowexecutável no nível superior para cenários de fluxo, ouscenario.execution.kind/scenario.execution.pathpara cenários de Vitest e Playwright
flow pode permanecer
genérica e transversal. Por exemplo, cenários YAML podem combinar helpers do
lado do transporte com helpers do lado do navegador que conduzem a Control UI
embutida pelo ponto de integração browser.request do Gateway sem adicionar um
executor especial.
Arquivos de cenário devem ser agrupados por capability do produto em vez de
pasta da árvore de código-fonte. Mantenha os IDs de cenário estáveis quando os
arquivos forem movidos; use docsRefs e codeRefs para rastreabilidade da
implementação.
A lista baseline deve permanecer ampla o suficiente para cobrir:
- chat por DM e canal
- comportamento de thread
- ciclo de vida de ações de mensagem
- callbacks cron
- recuperação de memória
- troca de modelo
- passagem para subagente
- leitura de repositório e leitura de docs
- uma pequena tarefa de build, como Lobster Invaders
Faixas de mock de provider
qa suite tem duas faixas locais de mock de provider:
mock-openaié o mock do OpenClaw ciente de cenários. Ele continua sendo a faixa de mock determinística padrão para QA versionado no repositório e gates de paridade.aimockinicia um servidor de provider baseado em AIMock para cobertura experimental de protocolo, fixture, gravação/reprodução e caos. Ele é aditivo e não substitui o despachante de cenáriosmock-openai.
extensions/qa-lab/src/providers/.
Cada provider é dono de seus padrões, inicialização do servidor local, config de
modelo do gateway, necessidades de staging de perfil de autenticação e flags de
capability live/mock. O código compartilhado da suite e do gateway deve rotear
pelo registro de providers em vez de ramificar em nomes de providers.
Adaptadores de transporte
qa-lab possui um ponto de integração de transporte genérico para cenários QA
YAML. qa-channel é o padrão sintético. crabline inicia servidores locais em
formato de provider e executa os plugins de canal normais do OpenClaw contra
eles. live é reservado para credenciais reais de provider e canais externos.
No nível de arquitetura, a divisão é:
qa-labpossui execução genérica de cenários, concorrência de workers, escrita de artefatos e relatórios.- O adaptador de transporte possui config do gateway, prontidão, observação de entrada e saída, ações de transporte e estado de transporte normalizado.
- Arquivos de cenário YAML em
qa/scenarios/definem a execução de teste;qa-labfornece a superfície de runtime reutilizável que os executa.
Adicionar um canal
Adicionar um canal ao sistema de QA YAML exige a implementação do canal mais um pacote de cenários que exercite o contrato do canal. Para cobertura smoke em CI, adicione o servidor local de provider Crabline correspondente e exponha-o pelo drivercrabline.
Não adicione uma nova raiz de comando QA de nível superior quando o host compartilhado qa-lab puder possuir o fluxo.
qa-lab possui a mecânica de host compartilhado:
- a raiz de comando
openclaw qa - inicialização e teardown da suite
- concorrência de workers
- escrita de artefatos
- geração de relatórios
- execução de cenários
- aliases de compatibilidade para cenários
qa-channelmais antigos
- como
openclaw qa <runner>é montado sob a raiz compartilhadaqa - como o gateway é configurado para esse transporte
- como a prontidão é verificada
- como eventos de entrada são injetados
- como mensagens de saída são observadas
- como transcrições e estado de transporte normalizado são expostos
- como ações com suporte de transporte são executadas
- como reset ou limpeza específicos do transporte são tratados
- Mantenha
qa-labcomo dono da raiz compartilhadaqa. - Implemente o executor de transporte no ponto de integração do host compartilhado
qa-lab. - Mantenha a mecânica específica do transporte dentro do plugin executor ou harness de canal.
- Monte o executor como
openclaw qa <runner>em vez de registrar um comando raiz concorrente. Plugins executores devem declararqaRunnersemopenclaw.plugin.jsone exportar um arrayqaRunnerCliRegistrationscorrespondente deruntime-api.ts. Mantenharuntime-api.tsleve; CLI lazy e execução do executor devem permanecer atrás de entrypoints separados. - Crie ou adapte cenários YAML nos diretórios temáticos
qa/scenarios/. - Use os helpers genéricos de cenário para novos cenários.
- Mantenha os aliases de compatibilidade existentes funcionando, a menos que o repositório esteja fazendo uma migração intencional.
- Se o comportamento puder ser expresso uma vez em
qa-lab, coloque-o emqa-lab. - Se o comportamento depender de um transporte de canal, mantenha-o nesse plugin executor ou harness de plugin.
- Se um cenário precisar de uma nova capability que mais de um canal pode usar, adicione um helper genérico em vez de uma ramificação específica de canal em
suite.ts. - Se um comportamento só fizer sentido para um transporte, mantenha o cenário específico do transporte e deixe isso explícito no contrato do cenário.
Nomes de helpers de cenário
Helpers genéricos preferidos para novos cenários:waitForTransportReadywaitForChannelReadyinjectInboundMessageinjectOutboundMessagewaitForTransportOutboundMessagewaitForChannelOutboundMessagewaitForNoTransportOutboundgetTransportSnapshotreadTransportMessagereadTransportTranscriptformatTransportTranscriptresetTransport
waitForQaChannelReady, waitForOutboundMessage, waitForNoOutbound, formatConversationTranscript, resetBus - mas a autoria de novos cenários deve usar os nomes genéricos. Os aliases existem para evitar uma migração em flag day, não como o modelo daqui em diante.
Relatórios
qa-lab exporta um relatório de protocolo em Markdown a partir da linha do tempo observada do bus.
O relatório deve responder:
- O que funcionou
- O que falhou
- O que permaneceu bloqueado
- Quais cenários de acompanhamento vale a pena adicionar
pnpm openclaw qa coverage (adicione --json para saída legível por máquina).
Ao escolher prova focada para um comportamento ou caminho de arquivo tocado, execute pnpm openclaw qa coverage --match <query>.
O relatório de correspondência pesquisa metadados de cenário, refs de docs, refs de código, IDs de cobertura, plugins e requisitos de provider, depois imprime alvos qa suite --scenario ... correspondentes.
Cada execução de qa suite grava artefatos qa-evidence.json,
qa-suite-summary.json e qa-suite-report.md no nível superior para o conjunto
de cenários selecionado. Cenários que declaram execution.kind: vitest ou
execution.kind: playwright executam o caminho de teste correspondente e também
gravam logs por cenário. Cenários que declaram execution.kind: script executam
o produtor de evidências em execution.path por node --import tsx (com
${outputDir} e ${scenarioId} expandidos em execution.args); o produtor
grava seu próprio qa-evidence.json, cujas entradas são importadas para a
saída da suite e cujos caminhos de artefato são resolvidos em relação a esse
qa-evidence.json do produtor. Quando qa suite é alcançado por
qa run --qa-profile, o mesmo qa-evidence.json também inclui o resumo do
scorecard de perfil para as categorias de taxonomia selecionadas.
Trate isso como auxílio de descoberta, não como substituto de gate; o cenário selecionado ainda precisa do modo de provider, transporte live, Multipass, Testbox ou faixa de release corretos para o comportamento em teste.
Para contexto do scorecard, consulte Scorecard de maturidade.
Para verificações de caráter e estilo, execute o mesmo cenário em múltiplas refs
de modelo live e grave um relatório julgado em Markdown:
SOUL.md e então executar turnos comuns do usuário
como chat, ajuda no workspace e pequenas tarefas de arquivo. O modelo candidato não deve
ser informado de que está sendo avaliado. O comando preserva cada transcrição completa,
registra estatísticas básicas da execução e então pede aos modelos juízes, em modo rápido com
raciocínio xhigh quando compatível, que classifiquem as execuções por naturalidade, vibe e humor.
Use --blind-judge-models ao comparar provedores: o prompt do juiz ainda recebe
cada transcrição e status de execução, mas as refs candidatas são substituídas por rótulos neutros
como candidate-01; o relatório mapeia as classificações de volta para as refs reais após
o parsing.
As execuções candidatas usam high como thinking padrão, com medium para GPT-5.5 e xhigh
para refs de avaliação OpenAI mais antigas que o suportam. Sobrescreva um candidato específico inline com
--model provider/model,thinking=<level>. --thinking <level> ainda define um
fallback global, e a forma mais antiga --model-thinking <provider/model=level> é
mantida por compatibilidade.
Refs candidatas OpenAI usam modo rápido por padrão para que o processamento prioritário seja usado onde
o provedor o suporta. Adicione ,fast, ,no-fast ou ,fast=false inline quando um
único candidato ou juiz precisar de uma sobrescrita. Passe --fast somente quando quiser
forçar o modo rápido para todos os modelos candidatos. As durações de candidatos e juízes são
registradas no relatório para análise de benchmark, mas os prompts dos juízes dizem explicitamente
para não classificar por velocidade.
As execuções dos modelos candidatos e juízes usam concorrência 16 por padrão. Reduza
--concurrency ou --judge-concurrency quando limites do provedor ou pressão do Gateway local
tornarem uma execução ruidosa demais.
Quando nenhum candidato --model é passado, a avaliação de personagem usa por padrão
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 e
google/gemini-3.1-pro-preview quando nenhum --model é passado.
Quando nenhum --judge-model é passado, os juízes usam por padrão
openai/gpt-5.5,thinking=xhigh,fast e
anthropic/claude-opus-4-8,thinking=high.