test: harden release validation smokes

This commit is contained in:
Peter Steinberger
2026-04-27 16:28:39 +01:00
parent 5ccf179a34
commit 32bbb5b18f
5 changed files with 128 additions and 40 deletions

View File

@@ -155,8 +155,11 @@ describeLive("buildOpenAIProvider live", () => {
const response = await client.responses.create({
model: normalized?.id ?? liveCase.modelId,
input: "Reply with exactly OK.",
max_output_tokens: 16,
instructions: "Return exactly OK and no other text.",
input: "Return exactly OK.",
max_output_tokens: 64,
reasoning: { effort: "none" },
text: { verbosity: "low" },
});
expect(response.output_text.trim()).toMatch(/^OK[.!]?$/);

View File

@@ -223,8 +223,11 @@ describeLive("openai plugin live", () => {
});
const response = await client.responses.create({
model: normalized?.id ?? LIVE_MODEL_ID,
input: "Reply with exactly OK.",
max_output_tokens: 16,
instructions: "Return exactly OK and no other text.",
input: "Return exactly OK.",
max_output_tokens: 64,
reasoning: { effort: "none" },
text: { verbosity: "low" },
});
expect(response.output_text.trim()).toMatch(/^OK[.!]?$/);
@@ -274,7 +277,7 @@ describeLive("openai plugin live", () => {
const ttsConfig = createLiveTtsConfig();
const synthesized = await speechProvider.synthesize({
text: "OpenClaw integration test OK.",
text: "Open claw. Open claw. Integration test OK.",
cfg,
providerConfig: ttsConfig.providerConfigs.openai ?? {},
target: "audio-file",

View File

@@ -1377,6 +1377,80 @@ describe("qa mock openai server", () => {
});
});
it("does not let fanout completion state hijack child worker replies", async () => {
const server = await startQaMockOpenAiServer({
host: "127.0.0.1",
port: 0,
});
cleanups.push(async () => {
await server.stop();
});
const prompt =
"Subagent fanout synthesis check: delegate two bounded subagents sequentially, then report both results together.";
const spawn = await fetch(`${server.baseUrl}/v1/responses`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
stream: true,
tools: [SESSIONS_SPAWN_TOOL],
input: [{ role: "user", content: [{ type: "input_text", text: prompt }] }],
}),
});
expect(spawn.status).toBe(200);
expect(await spawn.text()).toContain('\\"label\\":\\"qa-fanout-alpha\\"');
const secondSpawn = await fetch(`${server.baseUrl}/v1/responses`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
stream: true,
tools: [SESSIONS_SPAWN_TOOL],
input: [
{ role: "user", content: [{ type: "input_text", text: prompt }] },
{
type: "function_call_output",
output:
'{"status":"accepted","childSessionKey":"agent:qa:subagent:alpha","note":"ALPHA-OK"}',
},
],
}),
});
expect(secondSpawn.status).toBe(200);
expect(await secondSpawn.text()).toContain('\\"label\\":\\"qa-fanout-beta\\"');
const childReply = await fetch(`${server.baseUrl}/v1/responses`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
stream: false,
input: [
{
role: "user",
content: [
{
type: "input_text",
text: "Fanout worker alpha: inspect the QA workspace and finish with exactly ALPHA-OK.",
},
],
},
],
}),
});
expect(childReply.status).toBe(200);
expect(await childReply.json()).toMatchObject({
output: [
{
content: [
{
text: "ALPHA-OK",
},
],
},
],
});
});
it("keeps subagent fanout state isolated per mock server instance", async () => {
const serverA = await startQaMockOpenAiServer({
host: "127.0.0.1",

View File

@@ -795,7 +795,9 @@ function buildAssistantText(
return "FORKED-CONTEXT-ALPHA";
}
const fanoutCompleteReply = "subagent-1: ok\nsubagent-2: ok";
if (scenarioState.subagentFanoutPhase === 2 && prompt) {
const isFanoutCompletionTurn =
/subagent fanout synthesis check/i.test(allInputText) || /^continue\.?$/i.test(prompt.trim());
if (scenarioState.subagentFanoutPhase === 2 && prompt && isFanoutCompletionTurn) {
scenarioState.subagentFanoutPhase = 3;
return fanoutCompleteReply;
}
@@ -1191,6 +1193,12 @@ async function buildResponsesPayload(
if (isHeartbeatPrompt(prompt)) {
return buildAssistantEvents("HEARTBEAT_OK");
}
if (/fanout worker alpha/i.test(prompt)) {
return buildAssistantEvents("ALPHA-OK");
}
if (/fanout worker beta/i.test(prompt)) {
return buildAssistantEvents("BETA-OK");
}
if (QA_REASONING_ONLY_RECOVERY_PROMPT_RE.test(allInputText)) {
if (!toolOutput) {
return buildToolCallEventsWithArgs("read", { path: "QA_KICKOFF_TASK.md" });