From 54cb02151fd281624dbd59cc72b1e4f53bccf0f4 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 2 Aug 2026 19:54:38 +0800 Subject: [PATCH] test(qa): enforce live voice model --- .../src/scenario-catalog.openai-live.test.ts | 2 ++ ...cenario-flow-runner.voice-talkback.test.ts | 24 +++++++++++++++---- .../media/inbound-voice-talkback-live.yaml | 5 ++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/extensions/qa-lab/src/scenario-catalog.openai-live.test.ts b/extensions/qa-lab/src/scenario-catalog.openai-live.test.ts index 0fbd465a6476..9c133a9732c7 100644 --- a/extensions/qa-lab/src/scenario-catalog.openai-live.test.ts +++ b/extensions/qa-lab/src/scenario-catalog.openai-live.test.ts @@ -66,6 +66,7 @@ describe("qa scenario catalog", () => { | { requiredProviderMode?: string; requiredProvider?: string; + requiredModel?: string; expectedMarker?: string; } | undefined; @@ -90,6 +91,7 @@ describe("qa scenario catalog", () => { }); expect(config?.requiredProviderMode).toBe("live-frontier"); expect(config?.requiredProvider).toBe("openai"); + expect(config?.requiredModel).toBe("gpt-5.4"); expect(config?.expectedMarker).toBe("MATRIX QA VOICE PREFLIGHT OK"); expect(JSON.stringify(scenario.execution.flow)).toContain("./voice-preflight.fixture.js"); expect(JSON.stringify(scenario.execution.flow)).not.toContain("./live-transports/matrix/"); diff --git a/extensions/qa-lab/src/scenario-flow-runner.voice-talkback.test.ts b/extensions/qa-lab/src/scenario-flow-runner.voice-talkback.test.ts index eb8a8eb7c95c..2cc21569e00b 100644 --- a/extensions/qa-lab/src/scenario-flow-runner.voice-talkback.test.ts +++ b/extensions/qa-lab/src/scenario-flow-runner.voice-talkback.test.ts @@ -3,7 +3,26 @@ import { describe, expect, it } from "vitest"; import { createQaBusState } from "./bus-state.js"; import { runLoadedScenarioFlow } from "./scenario-flow-runner.test-support.js"; +function splitModelRef(ref: string) { + const slash = ref.indexOf("/"); + return slash > 0 ? { provider: ref.slice(0, slash), model: ref.slice(slash + 1) } : null; +} + describe("live inbound voice talkback scenario", () => { + it("rejects a live OpenAI model outside the scenario contract", async () => { + await expect( + runLoadedScenarioFlow("inbound-voice-talkback-live", { + api: { + env: { + providerMode: "live-frontier", + primaryModel: "openai/gpt-5.4-mini", + }, + splitModelRef, + }, + }), + ).rejects.toThrow("expected live primary model gpt-5.4, got openai/gpt-5.4-mini"); + }); + it("reuses the spoken WAV fixture and ignores a deleted streaming preview", async () => { const state = createQaBusState(); const expectedReply = "Matrix QA voice pre-flight OK."; @@ -20,10 +39,7 @@ describe("live inbound voice talkback scenario", () => { }, }, }, - splitModelRef: (ref: string) => { - const slash = ref.indexOf("/"); - return slash > 0 ? { provider: ref.slice(0, slash), model: ref.slice(slash + 1) } : null; - }, + splitModelRef, markGatewayLogCursor: () => 0, readGatewayLogs: () => "", resolveQaLiveTurnTimeoutMs: (_env: unknown, timeoutMs: number) => timeoutMs, diff --git a/qa/scenarios/media/inbound-voice-talkback-live.yaml b/qa/scenarios/media/inbound-voice-talkback-live.yaml index b68f6324a841..3696edfcfc34 100644 --- a/qa/scenarios/media/inbound-voice-talkback-live.yaml +++ b/qa/scenarios/media/inbound-voice-talkback-live.yaml @@ -41,6 +41,7 @@ scenario: config: requiredProviderMode: live-frontier requiredProvider: openai + requiredModel: gpt-5.4 conversationId: qa-live-voice-talkback expectedMarker: MATRIX QA VOICE PREFLIGHT OK expectedMarkerNormalized: MATRIXQAVOICEPREFLIGHTOK @@ -59,6 +60,10 @@ flow: expr: "selected?.provider === config.requiredProvider" message: expr: "`expected live primary provider ${config.requiredProvider}, got ${env.primaryModel}`" + - assert: + expr: "selected?.model === config.requiredModel" + message: + expr: "`expected live primary model ${config.requiredModel}, got ${env.primaryModel}`" - assert: expr: "Boolean(env.gateway.runtimeEnv.OPENAI_API_KEY?.trim() || env.gateway.runtimeEnv.OPENCLAW_LIVE_OPENAI_KEY?.trim())" message: live OpenAI API key did not reach the Gateway child