extensions/qa-channel: canale di messaggi sintetico con superfici per DM, canale, thread, reazione, modifica ed eliminazione.extensions/qa-lab: UI di debug e bus QA per osservare la trascrizione, iniettare messaggi in ingresso ed esportare un report Markdown.extensions/qa-matrix, Plugin runner futuri: adattatori di trasporto live che guidano un canale reale dentro un Gateway QA figlio.qa/: asset seed supportati dal repository per il task di avvio e gli scenari QA baseline.- Mantis: verifica live prima e dopo per bug che richiedono trasporti reali, screenshot del browser, stato della VM ed evidenze di PR.
Superficie dei comandi
Ogni flusso QA viene eseguito sottopnpm openclaw qa <subcommand>. Molti hanno
alias di script pnpm qa:*; entrambe le forme sono supportate.
| Comando | Scopo |
|---|---|
qa run | Autoverifica QA in bundle senza --qa-profile; runner di profili di maturità basato sulla tassonomia con --qa-profile smoke-ci, --qa-profile release o --qa-profile all. |
qa suite | Esegue scenari supportati dal repository contro la corsia del Gateway QA. Alias: pnpm openclaw qa suite --runner multipass per una VM Linux usa e getta. |
qa coverage | Stampa l’inventario della copertura degli scenari YAML (--json per output macchina). |
qa parity-report | Confronta due file qa-suite-summary.json e scrive il report di parità agentico, oppure usa --runtime-axis --token-efficiency per scrivere report di parità runtime Codex-vs-OpenClaw ed efficienza dei token da un riepilogo di coppia runtime. |
qa character-eval | Esegue lo scenario QA del personaggio su più modelli live con un report giudicato. Vedi Reportistica. |
qa manual | Esegue un prompt una tantum contro la corsia provider/modello selezionata. |
qa ui | Avvia la UI di debug QA e il bus QA locale (alias: pnpm qa:lab:ui). |
qa docker-build-image | Crea l’immagine Docker QA precostruita. |
qa docker-scaffold | Scrive uno scaffold docker-compose per la dashboard QA + corsia Gateway. |
qa up | Compila il sito QA, avvia lo stack supportato da Docker, stampa l’URL (alias: pnpm qa:lab:up; la variante :fast aggiunge --use-prebuilt-image --bind-ui-dist --skip-ui-build). |
qa aimock | Avvia solo il server provider AIMock. |
qa mock-openai | Avvia solo il server provider mock-openai consapevole degli scenari. |
qa credentials doctor / add / list / remove | Gestisce il pool condiviso di credenziali Convex. |
qa matrix | Corsia di trasporto live contro un homeserver Tuwunel usa e getta. Vedi QA Matrix. |
qa telegram | Corsia di trasporto live contro un vero gruppo privato Telegram. |
qa discord | Corsia di trasporto live contro un vero canale di guild privata Discord. |
qa slack | Corsia di trasporto live contro un vero canale privato Slack. |
qa whatsapp | Corsia di trasporto live contro account WhatsApp Web reali. |
qa mantis | Runner di verifica prima e dopo per bug di trasporto live, con evidenza di reazioni di stato Discord, smoke desktop/browser Crabbox e smoke Slack-in-VNC. Vedi Mantis e Runbook Mantis Slack Desktop. |
qa run supportato da profili legge l’appartenenza da taxonomy.yaml, quindi
invia gli scenari risolti tramite qa suite. --surface e
--category filtrano il profilo selezionato invece di definire corsie separate.
Il qa-evidence.json risultante include un riepilogo della scorecard del
profilo con conteggi delle categorie selezionate e ID di copertura mancanti; le
singole voci di evidenza restano la fonte di verità per i test, i ruoli di
copertura e i risultati. Gli ID di copertura delle feature della tassonomia sono
target di prova esatti, non alias. La copertura primaria degli scenari soddisfa
gli ID corrispondenti; la copertura secondaria resta consultiva. Gli ID di
copertura usano la forma puntata namespace.behavior con segmenti minuscoli
alfanumerici/con trattino; gli ID di profilo, superficie e categoria possono
ancora usare gli ID di tassonomia esistenti con trattini o punti.
L’evidenza snella omette execution per voce e imposta evidenceMode: "slim";
smoke-ci usa slim per impostazione predefinita, e --evidence-mode full
ripristina le voci complete:
smoke-ci per prove deterministiche di profilo con provider di modelli mock
e server provider locali Crabline. Usa release per prove Stable/LTS contro
canali live. Usa all solo per esecuzioni esplicite di evidenza sull’intera
tassonomia; seleziona ogni categoria di maturità attiva e può essere inviato
tramite il workflow QA Profile Evidence con qa_profile=all. Quando un
comando richiede anche un profilo root OpenClaw, metti il profilo root prima del
comando QA:
Flusso operatore
L’attuale flusso operatore QA è un sito QA a due pannelli:- Sinistra: dashboard Gateway (Control UI) con l’agente.
- Destra: QA Lab, che mostra la trascrizione in stile Slack e il piano dello scenario.
qa:lab:up:fast mantiene i servizi Docker su un’immagine precostruita e monta
via bind extensions/qa-lab/web/dist nel container qa-lab. qa:lab:watch
ricompila quel bundle al cambiamento, e il browser si ricarica automaticamente
quando cambia l’hash degli asset QA Lab.
Per uno smoke locale del segnale OpenTelemetry, esegui:
otel-trace-smoke con il Plugin diagnostics-otel abilitato, quindi verifica
che tracce, metriche e log siano esportati. Decodifica gli span di traccia
protobuf esportati e controlla la forma critica per il rilascio:
openclaw.run, openclaw.harness.run, uno span di chiamata modello secondo la
più recente convenzione semantica GenAI, openclaw.context.assembled e
openclaw.message.delivery devono essere presenti. Lo smoke forza
OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental, quindi lo span di
chiamata modello deve usare il nome {gen_ai.operation.name} {gen_ai.request.model};
le chiamate modello non devono esportare StreamAbandoned nei turni riusciti; gli ID diagnostici grezzi e
gli attributi openclaw.content.* devono restare fuori dalla traccia. I payload
OTLP grezzi non devono contenere il sentinel del prompt, il sentinel della
risposta o la chiave di sessione QA. Scrive otel-smoke-summary.json accanto
agli artefatti della suite QA.
Per uno smoke OpenTelemetry supportato da collector, esegui:
docker-prometheus-smoke con
diagnostics-prometheus abilitato, verifica che gli scrape non autenticati vengano rifiutati,
quindi controlla che lo scrape autenticato includa famiglie di metriche critiche per il rilascio
senza contenuto dei prompt, contenuto delle risposte, identificatori diagnostici grezzi, token di
autenticazione o percorsi locali.
Per eseguire entrambi gli smoke di osservabilità in sequenza, usa:
qa.
Usa pnpm qa:otel:smoke, pnpm qa:prometheus:smoke o
pnpm qa:observability:smoke da un checkout del sorgente compilato quando modifichi
la strumentazione diagnostica.
Per una corsia smoke Matrix con trasporto reale che non richiede credenziali del provider del modello,
esegui il profilo rapido con il provider OpenAI mock deterministico:
qa-channel), quindi scrive un report Markdown, un riepilogo JSON, un artefatto observed-events e un log di output combinato sotto .artifacts/qa-e2e/matrix-<timestamp>/.
Gli scenari coprono comportamenti di trasporto che gli unit test non possono dimostrare end to end: gating delle menzioni, policy allow-bot, allowlist, risposte di primo livello e in thread, routing DM, gestione delle reazioni, soppressione delle modifiche in ingresso, deduplicazione del replay al riavvio, ripristino da interruzione dell’homeserver, consegna dei metadati di approvazione, gestione dei media e flussi di bootstrap/ripristino/verifica Matrix E2EE. Il profilo CLI E2EE esegue anche openclaw matrix encryption setup e i comandi di verifica tramite lo stesso homeserver usa e getta prima di controllare le risposte del Gateway.
Discord ha anche scenari opt-in solo Mantis per la riproduzione di bug. Usa
--scenario discord-status-reactions-tool-only per la timeline esplicita delle reazioni di stato,
oppure --scenario discord-thread-reply-filepath-attachment per creare un
thread Discord reale e verificare che message.thread-reply preservi un allegato
filePath. Questi scenari restano fuori dalla corsia Discord live predefinita
perché sono sonde di riproduzione prima/dopo invece di una copertura smoke ampia.
Il workflow Mantis per l’allegato nel thread può anche aggiungere un video testimone di Discord Web
con accesso effettuato quando MANTIS_DISCORD_VIEWER_CHROME_PROFILE_DIR o
MANTIS_DISCORD_VIEWER_CHROME_PROFILE_TGZ_B64 è configurato nell’ambiente QA.
Quel profilo viewer serve solo per l’acquisizione visiva; la decisione pass/fail
arriva comunque dall’oracolo REST di Discord.
La CI usa la stessa superficie di comando in .github/workflows/qa-live-transports-convex.yml.
Le esecuzioni pianificate e manuali predefinite eseguono il profilo Matrix rapido con
credenziali live-frontier fornite dalla QA, --fast e
OPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS=3000. Il matrix_profile=all manuale si distribuisce
nei cinque shard di profilo.
Per corsie smoke con trasporto reale Telegram, Discord, Slack e WhatsApp:
slack-qa/, slack-desktop-smoke.png e slack-desktop-smoke.mp4
quando l’acquisizione video è disponibile nella directory degli artefatti Mantis. I lease
desktop/browser Crabbox forniscono in anticipo gli strumenti di acquisizione e i pacchetti helper
browser/native-build, quindi lo scenario dovrebbe installare fallback solo su lease più vecchi.
Mantis riporta tempi totali e per fase in
mantis-slack-desktop-smoke-report.md, così le esecuzioni lente mostrano se il tempo è stato speso in
warmup del lease, acquisizione credenziali, configurazione remota o copia degli artefatti. Riusa
--lease-id <cbx_...> dopo aver effettuato manualmente l’accesso a Slack Web tramite VNC;
i lease riutilizzati mantengono anche calda la cache dello store pnpm di Crabbox. Il valore predefinito
--hydrate-mode source verifica da un checkout del sorgente ed esegue install/build
dentro la VM. Usa --hydrate-mode prehydrated solo quando il workspace remoto riutilizzato
ha già node_modules e un dist/ compilato; quella modalità salta il costoso passaggio
install/build e fallisce in modo chiuso quando il workspace non è pronto.
Con --gateway-setup, Mantis lascia un Gateway OpenClaw Slack persistente
in esecuzione dentro la VM sulla porta 38973; senza, il comando esegue la normale
corsia QA Slack bot-to-bot ed esce dopo l’acquisizione degli artefatti.
Per dimostrare la UI nativa di approvazione Slack con evidenza desktop, esegui la modalità
checkpoint di approvazione Mantis:
--gateway-setup. Esegue gli scenari di
approvazione Slack, rifiuta gli id scenario non di approvazione, attende a ogni stato di approvazione
pendente e risolto, renderizza il messaggio Slack API osservato in
approval-checkpoints/<scenario>-pending.png e
approval-checkpoints/<scenario>-resolved.png, quindi fallisce se qualsiasi checkpoint,
evidenza del messaggio, conferma o screenshot renderizzato manca o è vuoto.
I lease CI a freddo possono comunque mostrare l’accesso a Slack in slack-desktop-smoke.png;
le immagini dei checkpoint di approvazione sono la prova visiva per questa corsia.
La checklist operatore, il comando di dispatch del workflow GitHub, il contratto del commento di evidenza, la tabella decisionale hydrate-mode, l’interpretazione dei tempi e i passaggi di gestione degli errori si trovano nel Runbook Mantis Slack Desktop.
Per un’attività desktop in stile agente/CV, esegui:
visual-task affitta o riusa una macchina desktop/browser Crabbox, avvia
crabbox record --while, guida il browser visibile tramite un
visual-driver annidato, acquisisce visual-task.png, esegue openclaw infer image describe
sullo screenshot quando --vision-mode image-describe è selezionato e
scrive visual-task.mp4, mantis-visual-task-summary.json,
mantis-visual-task-driver-result.json e mantis-visual-task-report.md.
Quando --expect-text è impostato, il prompt di visione richiede un verdetto JSON strutturato
e passa solo quando il modello riporta evidenza visibile positiva; una risposta
negativa che si limita a citare il testo target fallisce l’asserzione.
Usa --vision-mode metadata per uno smoke senza modello che dimostra il collegamento tra desktop,
browser, screenshot e video senza chiamare un provider di comprensione immagini.
La registrazione è un artefatto richiesto per visual-task; se Crabbox non registra
un visual-task.mp4 non vuoto, l’attività fallisce anche quando il visual driver
è passato. In caso di errore, Mantis conserva il lease per VNC a meno che l’attività
non fosse già passata e --keep-lease non fosse impostato.
Prima di usare credenziali live in pool, esegui:
Copertura dei trasporti live
Le corsie di trasporto live condividono un unico contratto invece di inventare ciascuna la propria forma di elenco scenari.qa-channel è la suite sintetica ampia per il comportamento del prodotto e non fa parte della matrice di copertura dei trasporti live.
I runner dei trasporti live dovrebbero importare gli id scenario condivisi, gli helper di copertura
baseline e l’helper di selezione scenario da
openclaw/plugin-sdk/qa-live-transport-scenarios.
| Corsia | Canary | Gating menzioni | Bot-to-bot | Blocco allowlist | Risposta di primo livello | Risposta citata | Ripresa al riavvio | Follow-up thread | Isolamento thread | Osservazione reazioni | Comando help | Registrazione 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 come suite ampia per il comportamento del prodotto mentre Matrix,
Telegram e altri trasporti live condividono una checklist esplicita del contratto di trasporto.
Per una corsia VM Linux usa e getta senza introdurre Docker nel percorso QA, esegui:
qa suite, quindi copia il normale report QA e il
riepilogo in .artifacts/qa-e2e/... sull’host.
Riusa lo stesso comportamento di selezione scenario di qa suite sull’host.
Le esecuzioni della suite su host e Multipass eseguono più scenari selezionati in parallelo
con worker Gateway isolati per impostazione predefinita. qa-channel usa per impostazione predefinita una concorrenza
4, limitata dal numero di scenari selezionati. Usa --concurrency <count> per regolare
il numero di worker, oppure --concurrency 1 per l’esecuzione seriale.
Usa --pack personal-agent per eseguire il pacchetto benchmark dell’assistente personale. Il
selettore di pacchetto è additivo con flag --scenario ripetuti: gli scenari espliciti
vengono eseguiti prima, poi gli scenari del pacchetto vengono eseguiti nell’ordine del pacchetto con i duplicati rimossi.
Usa --pack observability quando un runner QA personalizzato fornisce già la configurazione
del collector OpenTelemetry e vuole selezionare insieme gli scenari smoke diagnostici
OpenTelemetry e Prometheus.
Il comando esce con stato non zero quando qualsiasi scenario fallisce. Usa --allow-failures quando
vuoi gli artefatti senza un codice di uscita di errore.
Le esecuzioni live inoltrano gli input di autenticazione QA supportati che sono pratici per il
guest: chiavi provider basate su env, il percorso della configurazione del provider live QA e
CODEX_HOME quando presente. Mantieni --output-dir sotto la root del repo così il guest
può scrivere indietro tramite il workspace montato.
Riferimento QA per Telegram, Discord, Slack e WhatsApp
Matrix ha una pagina dedicata a causa del numero di scenari e del provisioning dell’homeserver basato su Docker. Telegram, Discord, Slack e WhatsApp vengono eseguiti su trasporti reali preesistenti, quindi il loro riferimento si trova qui.Flag CLI condivisi
Queste lane si registrano tramiteextensions/qa-lab/src/live-transports/shared/live-transport-cli.ts e accettano gli stessi flag:
| Flag | Predefinito | Descrizione |
|---|---|---|
--scenario <id> | - | Esegue solo questo scenario. Ripetibile. |
--output-dir <path> | <repo>/.artifacts/qa-e2e/<transport>-<timestamp> | Dove vengono scritti report, riepiloghi, evidenze, artefatti specifici del trasporto e il log di output. I percorsi relativi si risolvono rispetto a --repo-root. |
--repo-root <path> | process.cwd() | Root del repository quando si invoca da una cwd neutra. |
--sut-account <id> | sut | ID account temporaneo nella configurazione del gateway QA. |
--provider-mode <mode> | live-frontier | mock-openai o live-frontier (live-openai legacy funziona ancora). |
--model <ref> / --alt-model <ref> | predefinito del provider | Riferimenti del modello primario/alternativo. |
--fast | disattivato | Modalità rapida del provider dove supportata. |
--credential-source <env|convex> | env | Vedi pool di credenziali Convex. |
--credential-role <maintainer|ci> | ci in CI, altrimenti maintainer | Ruolo usato quando --credential-source convex. |
--allow-failures scrive gli artefatti senza impostare un codice di uscita di errore.
QA Telegram
@BotFather.
Env richieste quando --credential-source env:
OPENCLAW_QA_TELEGRAM_GROUP_ID- ID chat numerico (stringa).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 includono anche controlli deterministici della catena di risposte e dello streaming del messaggio finale. telegram-current-session-status-tool resta opt-in perché è stabile solo quando eseguito direttamente dopo canary, non dopo risposte arbitrarie ai comandi nativi. Usa pnpm openclaw qa telegram --list-scenarios --provider-mode mock-openai per stampare l’attuale suddivisione predefinita/opzionale con riferimenti di regressione.
Artefatti di output:
telegram-qa-report.mdqa-evidence.json- voci di evidenza per i controlli del trasporto live, inclusi profilo, copertura, provider, canale, artefatti, risultato e campi RTT.
qa-evidence.json sotto result.timing per il controllo RTT selezionato.
OPENCLAW_QA_CREDENTIAL_SOURCE=convex è impostato, il wrapper live del pacchetto prende in lease una credenziale kind: "telegram", esporta gli env del gruppo/driver/bot SUT in lease nell’esecuzione del pacchetto installato, invia Heartbeat per il lease e lo rilascia allo shutdown. Il wrapper del pacchetto usa per impostazione predefinita 20 controlli RTT di telegram-mentioned-message-reply, un timeout RTT di 30s e il ruolo Convex maintainer fuori dalla CI quando Convex è selezionato. Sovrascrivi OPENCLAW_NPM_TELEGRAM_RTT_SAMPLES, OPENCLAW_NPM_TELEGRAM_RTT_TIMEOUT_MS o OPENCLAW_NPM_TELEGRAM_RTT_MAX_FAILURES per regolare la misurazione RTT senza creare un comando RTT separato o un formato di riepilogo specifico per Telegram.
QA Discord
/help con Discord, e scenari di evidenza Mantis opt-in.
Env richieste 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 corrispondere all’ID utente del bot SUT restituito da Discord (altrimenti la lane fallisce rapidamente).
OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1mantiene i corpi dei messaggi negli artefatti dei messaggi osservati.OPENCLAW_QA_DISCORD_VOICE_CHANNEL_IDseleziona il canale voce/stage perdiscord-voice-autojoin; senza di esso, lo scenario sceglie il primo canale voce/stage visibile per il bot SUT.
extensions/qa-lab/src/live-transports/discord/discord-live.runtime.ts:36):
discord-canarydiscord-mention-gatingdiscord-native-help-command-registrationdiscord-voice-autojoin- scenario voce opt-in. Viene eseguito da solo, abilitachannels.discord.voice.autoJoine verifica che lo stato voce Discord corrente del bot SUT sia il canale voce/stage di destinazione. Le credenziali Discord Convex possono includerevoiceChannelIdopzionale; altrimenti il runner rileva il primo canale voce/stage visibile nella guild.discord-status-reactions-tool-only- scenario Mantis opt-in. Viene eseguito da solo perché imposta il SUT su risposte guild sempre attive e solo tool conmessages.statusReactions.enabled=true, quindi cattura una timeline di reazioni REST più artefatti visivi HTML/PNG. I report prima/dopo di Mantis preservano anche gli artefatti MP4 forniti dallo scenario comebaseline.mp4ecandidate.mp4.
discord-qa-report.mdqa-evidence.json- voci di evidenza per i controlli del trasporto live.discord-qa-observed-messages.json- corpi oscurati salvoOPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1.discord-qa-reaction-timelines.jsonediscord-status-reactions-tool-only-timeline.pngquando viene eseguito lo scenario di reazioni di stato.
QA 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=1mantiene i corpi dei messaggi negli artefatti dei messaggi osservati.OPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_DIRabilita checkpoint di approvazione visiva per Mantis. Il runner scrive<scenario>.pending.jsone<scenario>.resolved.json, poi attende file.ack.jsoncorrispondenti.OPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_TIMEOUT_MSsovrascrive il timeout di conferma del checkpoint. Il valore predefinito è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- scenario opt-in di approvazione exec nativa Slack. Richiede un’approvazione exec tramite il Gateway, verifica che il messaggio Slack abbia pulsanti di approvazione nativi, la risolve e verifica l’aggiornamento Slack risolto.slack-approval-plugin-native- scenario opt-in di approvazione Plugin nativa Slack. Abilita insieme l’inoltro delle approvazioni exec e Plugin, così gli eventi Plugin non vengono soppressi dal routing dell’approvazione exec, poi verifica lo stesso percorso UI nativo Slack in sospeso/risolto.
slack-qa-report.mdqa-evidence.json- voci di evidenza per i controlli del trasporto live.slack-qa-observed-messages.json- corpi oscurati salvoOPENCLAW_QA_SLACK_CAPTURE_CONTENT=1.approval-checkpoints/- solo quando Mantis impostaOPENCLAW_QA_SLACK_APPROVAL_CHECKPOINT_DIR; contiene JSON dei checkpoint, JSON di conferma e screenshot in sospeso/risolti.
Configurazione dello workspace Slack
La lane richiede due app Slack distinte in uno workspace, più un canale di cui entrambi i bot siano membri:channelId- l’IDCxxxxxxxxxxdi un canale a cui entrambi i bot sono stati invitati. Usa un canale dedicato; la lane pubblica a ogni esecuzione.driverBotToken- token bot (xoxb-...) dell’app Driver.sutBotToken- token bot (xoxb-...) dell’app SUT, che deve essere un’app Slack separata dal driver affinché il suo ID utente bot sia distinto.sutAppToken- token a livello app (xapp-...) dell’app SUT conconnections:write, usato da Socket Mode affinché l’app SUT possa ricevere eventi.
extensions/slack/src/setup-shared.ts:10) alle autorizzazioni e agli eventi coperti dalla suite QA Slack live. Per la configurazione del canale di produzione come la vedono gli utenti, vedi configurazione rapida del canale Slack; la coppia Driver/SUT QA è intenzionalmente separata perché la lane richiede due ID utente bot distinti in uno workspace.
1. Crea l’app Driver
Vai su api.slack.com/apps → Create New App → From a manifest → scegli il workspace QA, incolla il seguente manifest, quindi Install to Workspace:
xoxb-...) - diventa driverBotToken. Al driver serve solo pubblicare messaggi e identificarsi; nessun evento, nessuna Socket Mode.
2. Crea l’app SUT
Ripeti Create New App → From a manifest nello stesso workspace. Questa app QA usa intenzionalmente una versione più ristretta del manifest di produzione del Plugin Slack incluso (extensions/slack/src/setup-shared.ts:10): gli scope e gli eventi delle reazioni sono omessi perché la suite QA Slack live non copre ancora la gestione delle reazioni.
- Install to Workspace → copia il Bot User OAuth Token → diventa
sutBotToken. - Basic Information → App-Level Tokens → Generate Token and Scopes → aggiungi lo scope
connections:write→ salva → copia il valorexapp-...→ diventasutAppToken.
auth.test su ciascun token. Il runtime distingue driver e SUT in base all’id utente; riutilizzare un’unica app per entrambi farà fallire immediatamente il gating delle menzioni.
3. Crea il canale
Nel workspace QA, crea un canale (ad esempio #openclaw-qa) e invita entrambi i bot dall’interno del canale:
Cxxxxxxxxxx da channel info → About → Channel ID - diventa channelId. Un canale pubblico va bene; se usi un canale privato, entrambe le app hanno già groups:history, quindi le letture della cronologia dell’harness riusciranno comunque.
4. Registra le credenziali
Due opzioni. Usa variabili env per il debugging su una singola macchina (imposta le quattro variabili OPENCLAW_QA_SLACK_* e passa --credential-source env), oppure popola il pool Convex condiviso in modo che CI e altri maintainer possano prenderle in lease.
Per il pool Convex, scrivi i quattro campi in un file JSON:
OPENCLAW_QA_CONVEX_SITE_URL e OPENCLAW_QA_CONVEX_SECRET_MAINTAINER esportati nella tua shell, registra e verifica:
count: 1, status: "active", nessun campo lease.
5. Verifica end to end
Esegui la lane localmente per confermare che entrambi i bot possano parlarsi tramite il broker:
slack-qa-report.md mostra sia slack-canary sia slack-mention-gating con stato pass. Se la lane resta sospesa per ~90 secondi ed esce con Convex credential pool exhausted for kind "slack", il pool è vuoto oppure ogni riga è in lease - qa credentials list --kind slack --status all --json ti dirà quale dei due casi.
QA 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_JIDabilita scenari di gruppo comewhatsapp-mention-gating,whatsapp-group-pending-history-context,whatsapp-broadcast-group-fanout,whatsapp-group-activation-always,whatsapp-group-reply-to-bot-triggers, scenari di gruppo per azioni/media/sondaggi ewhatsapp-group-allowlist-block.OPENCLAW_QA_WHATSAPP_CAPTURE_CONTENT=1mantiene i corpi dei messaggi negli artefatti observed-message.
extensions/qa-lab/src/live-transports/whatsapp/whatsapp-live.runtime.ts):
- Baseline e gating di gruppo:
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. - Comandi nativi:
whatsapp-help-command,whatsapp-status-command,whatsapp-commands-command,whatsapp-tools-compact-command,whatsapp-whoami-command,whatsapp-context-command,whatsapp-native-new-command. - Comportamento di risposta e output finale:
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. - Azioni messaggio sul percorso utente:
whatsapp-agent-message-action-reactparte da un vero DM del driver, consente al modello di chiamare lo strumentomessagee osserva la reazione nativa di WhatsApp.whatsapp-agent-message-action-upload-fileusa la stessa postura permessage(action=upload-file)e osserva media nativi WhatsApp.whatsapp-group-agent-message-action-reactewhatsapp-group-agent-message-action-upload-fileprovano le stesse azioni visibili all’utente in un vero gruppo WhatsApp. - Fanout di gruppo:
whatsapp-broadcast-group-fanoutparte da un messaggio di gruppo WhatsApp con menzione e verifica risposte visibili distinte damaineqa-second. - Attivazione di gruppo:
whatsapp-group-activation-alwayscambia una vera sessione di gruppo a/activation always, prova che un messaggio di gruppo senza menzione risveglia l’agente, poi ripristina/activation mention.whatsapp-group-reply-to-bot-triggerssemina una risposta del bot, invia una risposta nativa citata a essa senza una menzione esplicita e verifica che l’agente si risvegli da quel contesto di risposta. - Media in ingresso e messaggi strutturati:
whatsapp-inbound-image-caption,whatsapp-audio-preflight,whatsapp-inbound-structured-messages,whatsapp-group-audio-gating,whatsapp-inbound-reaction-no-trigger. Questi inviano veri eventi WhatsApp di immagine, audio, documento, posizione, contatto, sticker e reazione tramite il driver. - Probe dirette del contratto 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. Queste aggirano intenzionalmente il prompting del modello e provano contratti deterministici Gateway/canalesend,pollemessage.action. - Copertura del controllo di accesso:
whatsapp-access-control-dm-open,whatsapp-access-control-dm-disabled,whatsapp-access-control-group-open,whatsapp-access-control-group-disabled,whatsapp-group-allowlist-block. - Approvazioni native:
whatsapp-approval-exec-deny-native,whatsapp-approval-exec-native,whatsapp-approval-exec-reaction-native,whatsapp-approval-exec-group-reaction-native,whatsapp-approval-plugin-native. - Reazioni di stato:
whatsapp-status-reactions,whatsapp-status-reaction-lifecycle.
live-frontier è
mantenuta piccola con 10 scenari per una copertura smoke rapida. La lane predefinita
mock-openai esegue 44 scenari deterministici tramite il vero trasporto WhatsApp
simulando solo l’output del modello. Gli scenari di approvazione e alcuni controlli più pesanti/bloccanti
restano espliciti per id scenario.
Il driver QA WhatsApp osserva eventi live strutturati (text, media,
location, reaction e poll) e può inviare attivamente media, sondaggi,
contatti, posizioni e sticker. QA Lab importa quel driver tramite la superficie
del pacchetto @openclaw/whatsapp/api.js invece di accedere a file runtime
WhatsApp privati. Per le osservazioni di gruppo, fromJid è il JID del gruppo mentre
participantJid e fromPhoneE164 identificano il mittente partecipante. Il contenuto
dei messaggi è redatto per impostazione predefinita. Le probe dirette Gateway
per poll, upload-file, media, poll di gruppo, media di gruppo e forma della risposta sono controlli del contratto trasporto/API;
non sono trattate come prova che un prompt utente abbia fatto scegliere
all’agente la stessa azione. La prova delle azioni sul percorso utente proviene da scenari come
whatsapp-agent-message-action-react e
whatsapp-group-agent-message-action-react, in cui il driver invia un normale
messaggio WhatsApp e QA Lab osserva l’artefatto WhatsApp nativo risultante.
I report WhatsApp includono la postura di ciascuno scenario (user-path, direct-gateway,
o native-approval) così che le prove non possano essere scambiate per un contratto più forte
di quanto dimostrino realmente.
Artefatti di output:
whatsapp-qa-report.mdqa-evidence.json- voci di prova per i controlli del trasporto live.whatsapp-qa-observed-messages.json- corpi redatti salvoOPENCLAW_QA_WHATSAPP_CAPTURE_CONTENT=1.
Pool di credenziali Convex
Le lane Telegram, Discord, Slack e WhatsApp possono prendere credenziali in lease da un pool Convex condiviso invece di leggere le variabili env sopra. Passa--credential-source convex (o imposta OPENCLAW_QA_CREDENTIAL_SOURCE=convex); QA Lab acquisisce un lease esclusivo, invia Heartbeat per tutta la durata dell’esecuzione e lo rilascia allo spegnimento. I tipi del pool sono "telegram", "discord", "slack" e "whatsapp".
Strutture dei payload che il broker valida su admin/add:
- Telegram (
kind: "telegram"):{ groupId: string, driverToken: string, sutToken: string }-groupIddeve essere una stringa chat-id numerica. - Utente reale 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 }- solo proof Mantis Telegram Desktop. Le lane QA Lab generiche non devono acquisire questo 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 }- i numeri di telefono devono essere stringhe E.164 distinte.
telegram-user esclusivo sia per il driver CLI TDLib sia per il witness Telegram Desktop,
poi lo rilascia dopo la pubblicazione della proof.
Quando una PR richiede un diff visivo deterministico, Mantis può usare la stessa risposta
del modello mock su main e sulla head della PR mentre cambia il formatter Telegram o il layer
di consegna. I valori predefiniti di acquisizione sono ottimizzati per i commenti delle PR: classe Crabbox
standard, registrazione desktop a 24 fps, GIF di movimento a 24 fps e larghezza anteprima di 1920 px.
I commenti prima/dopo devono pubblicare un bundle pulito che contenga solo le
GIF previste.
Anche le lane Slack possono usare il pool. I controlli della forma del payload Slack al momento si trovano nel runner QA Slack anziché nel broker; usa { channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string }, con un id canale Slack come Cxxxxxxxxxx. Vedi Configurazione del workspace Slack per il provisioning di app e scope.
Le variabili d’ambiente operative e il contratto dell’endpoint broker Convex si trovano in Testing → Credenziali Telegram condivise tramite Convex (il nome della sezione precede il pool multi-canale; la semantica dei lease è condivisa tra i tipi).
Seed basati sul repo
Gli asset seed si trovano inqa/:
qa/scenarios/index.yamlqa/scenarios/<theme>/*.yaml
qa-lab deve restare un runner generico di scenari YAML. Ogni file YAML di scenario è
la fonte di verità per una singola esecuzione di test e deve definire:
titledi primo livello- metadati
scenario - metadati opzionali di categoria, capability, lane e rischio in
scenario - riferimenti a documentazione e codice in
scenario - requisiti Plugin opzionali in
scenario - patch opzionale della configurazione Gateway in
scenario floweseguibile di primo livello per gli scenari di flow, oppurescenario.execution.kind/scenario.execution.pathper scenari Vitest e Playwright
flow può rimanere generica
e trasversale. Per esempio, gli scenari YAML possono combinare helper lato trasporto
con helper lato browser che pilotano la Control UI incorporata attraverso il seam
Gateway browser.request senza aggiungere un runner con caso speciale.
I file di scenario devono essere raggruppati per capability di prodotto anziché per cartella
dell’albero sorgente. Mantieni stabili gli ID degli scenari quando i file vengono spostati; usa docsRefs e codeRefs
per la tracciabilità dell’implementazione.
L’elenco baseline deve restare abbastanza ampio da coprire:
- chat DM e canale
- comportamento dei thread
- ciclo di vita delle azioni sui messaggi
- callback cron
- richiamo della memoria
- cambio modello
- handoff a subagent
- lettura del repo e lettura della documentazione
- una piccola attività di build come Lobster Invaders
Lane mock provider
qa suite ha due lane mock provider locali:
mock-openaiè il mock OpenClaw consapevole dello scenario. Rimane la lane mock deterministica predefinita per QA basata sul repo e gate di parità.aimockavvia un server provider basato su AIMock per copertura sperimentale di protocollo, fixture, record/replay e chaos. È additivo e non sostituisce il dispatcher di scenarimock-openai.
extensions/qa-lab/src/providers/.
Ogni provider possiede i propri valori predefiniti, l’avvio del server locale, la configurazione modello del gateway,
le esigenze di staging del profilo auth e i flag di capability live/mock. Il codice condiviso della suite e del
gateway deve passare attraverso il registry provider invece di ramificare sui
nomi dei provider.
Adapter di trasporto
qa-lab possiede un seam di trasporto generico per gli scenari QA YAML. qa-channel è
il default sintetico. crabline avvia server locali con forma provider ed esegue
i normali plugin canale di OpenClaw contro di essi. live è riservato a
credenziali provider reali e canali esterni.
A livello architetturale, la divisione è:
qa-labpossiede esecuzione generica degli scenari, concorrenza worker, scrittura artefatti e reportistica.- L’adapter di trasporto possiede configurazione gateway, readiness, osservazione inbound e outbound, azioni di trasporto e stato di trasporto normalizzato.
- I file di scenario YAML sotto
qa/scenarios/definiscono l’esecuzione del test;qa-labfornisce la superficie runtime riutilizzabile che li esegue.
Aggiungere un canale
Aggiungere un canale al sistema QA YAML richiede l’implementazione del canale più un pacchetto di scenari che eserciti il contratto del canale. Per copertura smoke CI, aggiungi il server provider locale Crabline corrispondente ed esponilo tramite il drivercrabline.
Non aggiungere una nuova radice di comando QA di primo livello quando l’host condiviso qa-lab può possedere il flow.
qa-lab possiede la meccanica dell’host condiviso:
- la radice comando
openclaw qa - avvio e teardown della suite
- concorrenza worker
- scrittura degli artefatti
- generazione report
- esecuzione degli scenari
- alias di compatibilità per scenari
qa-channelpiù vecchi
- come
openclaw qa <runner>viene montato sotto la radice condivisaqa - come il gateway viene configurato per quel trasporto
- come viene controllata la readiness
- come vengono iniettati gli eventi inbound
- come vengono osservati i messaggi outbound
- come vengono esposti transcript e stato di trasporto normalizzato
- come vengono eseguite le azioni basate sul trasporto
- come viene gestito il reset o la pulizia specifica del trasporto
- Mantieni
qa-labcome owner della radice condivisaqa. - Implementa il runner di trasporto sul seam host condiviso
qa-lab. - Mantieni la meccanica specifica del trasporto dentro il plugin runner o l’harness canale.
- Monta il runner come
openclaw qa <runner>invece di registrare un comando root concorrente. I plugin runner devono dichiarareqaRunnersinopenclaw.plugin.jsoned esportare un arrayqaRunnerCliRegistrationscorrispondente daruntime-api.ts. Mantieniruntime-api.tsleggero; la CLI lazy e l’esecuzione runner devono restare dietro entrypoint separati. - Crea o adatta scenari YAML sotto le directory tematiche
qa/scenarios/. - Usa gli helper di scenario generici per i nuovi scenari.
- Mantieni funzionanti gli alias di compatibilità esistenti, a meno che il repo non stia eseguendo una migrazione intenzionale.
- Se un comportamento può essere espresso una volta in
qa-lab, mettilo inqa-lab. - Se un comportamento dipende da un trasporto canale, tienilo in quel plugin runner o harness plugin.
- Se uno scenario richiede una nuova capability che può essere usata da più di un canale, aggiungi un helper generico invece di un ramo specifico del canale in
suite.ts. - Se un comportamento ha senso solo per un trasporto, mantieni lo scenario specifico del trasporto e rendilo esplicito nel contratto dello scenario.
Nomi degli helper di scenario
Helper generici preferiti per i nuovi scenari:waitForTransportReadywaitForChannelReadyinjectInboundMessageinjectOutboundMessagewaitForTransportOutboundMessagewaitForChannelOutboundMessagewaitForNoTransportOutboundgetTransportSnapshotreadTransportMessagereadTransportTranscriptformatTransportTranscriptresetTransport
waitForQaChannelReady, waitForOutboundMessage, waitForNoOutbound, formatConversationTranscript, resetBus - ma la creazione di nuovi scenari deve usare i nomi generici. Gli alias esistono per evitare una migrazione flag-day, non come modello futuro.
Reportistica
qa-lab esporta un report di protocollo Markdown dalla timeline bus osservata.
Il report deve rispondere a:
- Cosa ha funzionato
- Cosa non ha funzionato
- Cosa è rimasto bloccato
- Quali scenari di follow-up vale la pena aggiungere
pnpm openclaw qa coverage (aggiungi --json per output leggibile da macchina).
Quando scegli una proof mirata per un comportamento o percorso file modificato, esegui pnpm openclaw qa coverage --match <query>.
Il report di match cerca nei metadati degli scenari, nei riferimenti alla documentazione, nei riferimenti al codice, negli ID di copertura, nei plugin e nei requisiti provider, poi stampa i target qa suite --scenario ... corrispondenti.
Ogni esecuzione di qa suite scrive gli artefatti di primo livello qa-evidence.json,
qa-suite-summary.json e qa-suite-report.md per l’insieme di scenari selezionato.
Gli scenari che dichiarano execution.kind: vitest o
execution.kind: playwright eseguono il percorso di test corrispondente e scrivono anche
log per scenario. Gli scenari che dichiarano execution.kind: script eseguono il
producer di evidenza in execution.path tramite node --import tsx (con
${outputDir} e ${scenarioId} espansi in execution.args); il producer
scrive il proprio qa-evidence.json, le cui voci vengono importate nell’output
della suite e i cui percorsi artefatto sono risolti relativamente a quel
qa-evidence.json del producer. Quando qa suite viene raggiunto tramite
qa run --qa-profile, lo stesso qa-evidence.json include anche il riepilogo
scorecard del profilo per le categorie tassonomiche selezionate.
Trattalo come un aiuto alla scoperta, non come sostituto dei gate; lo scenario selezionato richiede comunque la modalità provider, il trasporto live, Multipass, Testbox o la lane di release corretti per il comportamento sotto test.
Per il contesto della scorecard, vedi Scorecard di maturità.
Per controlli di carattere e stile, esegui lo stesso scenario su più riferimenti modello
live e scrivi un report Markdown valutato:
SOUL.md, quindi eseguire normali turni utente come chat, aiuto nell’area di lavoro e piccole attività sui file. Al modello candidato non dovrebbe essere comunicato che è in valutazione. Il comando conserva ogni trascrizione completa, registra statistiche di esecuzione di base, quindi chiede ai modelli giudice in modalità veloce con ragionamento xhigh dove supportato di classificare le esecuzioni per naturalezza, vibe e umorismo.
Usa --blind-judge-models quando confronti i provider: il prompt del giudice riceve comunque ogni trascrizione e stato di esecuzione, ma i riferimenti dei candidati vengono sostituiti con etichette neutrali come candidate-01; il report riconduce le classifiche ai riferimenti reali dopo il parsing.
Le esecuzioni dei candidati usano per impostazione predefinita il thinking high, con medium per GPT-5.5 e xhigh per i riferimenti di valutazione OpenAI più vecchi che lo supportano. Sovrascrivi uno specifico candidato inline con --model provider/model,thinking=<level>. --thinking <level> imposta ancora un fallback globale, e la forma precedente --model-thinking <provider/model=level> viene mantenuta per compatibilità.
I riferimenti dei candidati OpenAI usano per impostazione predefinita la modalità veloce, così viene usata l’elaborazione prioritaria dove il provider la supporta. Aggiungi ,fast, ,no-fast o ,fast=false inline quando un singolo candidato o giudice richiede una sovrascrittura. Passa --fast solo quando vuoi forzare la modalità veloce per ogni modello candidato. Le durate di candidati e giudici vengono registrate nel report per l’analisi dei benchmark, ma i prompt dei giudici dicono esplicitamente di non classificare in base alla velocità.
Le esecuzioni dei modelli candidati e giudici usano entrambe per impostazione predefinita la concorrenza 16. Abbassa --concurrency o --judge-concurrency quando i limiti del provider o la pressione sul gateway locale rendono un’esecuzione troppo rumorosa.
Quando non viene passato alcun --model candidato, la valutazione dei personaggi usa per impostazione predefinita 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 non viene passato alcun --model.
Quando non viene passato alcun --judge-model, i giudici usano per impostazione predefinita
openai/gpt-5.5,thinking=xhigh,fast e
anthropic/claude-opus-4-8,thinking=high.