Files
oh-my-pi/packages/coding-agent/test/task/executor-warnings.test.ts
T
can1357 ecd1554eba feat: renamed subagent handoff flow to use yield instead of submit_result
- Renamed subagent completion flow from `submit_result` to `yield` across SDK tools, prompts, and docs.
- Updated executor/task handling to require and parse `yield` calls, replacing legacy submit-result extraction and state flags.
- Added `subagent-yield-reminder` and updated system prompts to require `yield` with `result.data` or `result.error`.
- Renamed hidden-tool and registration plumbing to `yield`, including discovery helpers and renderer/test surface.
2026-04-26 00:29:52 +02:00

135 lines
4.1 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import {
finalizeSubprocessOutput,
SUBAGENT_WARNING_MISSING_YIELD,
SUBAGENT_WARNING_NULL_YIELD,
} from "../../src/task/executor";
describe("subagent warning injection", () => {
it("injects null-data warning when yield is success without data", () => {
const result = finalizeSubprocessOutput({
rawOutput: "partial output",
exitCode: 0,
stderr: "",
doneAborted: false,
signalAborted: false,
yieldItems: [{ status: "success" }],
outputSchema: undefined,
});
expect(result.rawOutput).toBe(`${SUBAGENT_WARNING_NULL_YIELD}\n\npartial output`);
expect(result.hasYield).toBe(true);
});
it("injects missing-submit warning when subagent exits cleanly without yield", () => {
const result = finalizeSubprocessOutput({
rawOutput: "",
exitCode: 0,
stderr: "",
doneAborted: false,
signalAborted: false,
yieldItems: undefined,
outputSchema: { properties: { ok: { type: "boolean" } } },
});
expect(result.rawOutput).toBe(SUBAGENT_WARNING_MISSING_YIELD);
expect(result.hasYield).toBe(false);
});
it("does not inject missing-submit warning when fallback completion is recoverable", () => {
const result = finalizeSubprocessOutput({
rawOutput: '{"data":{"ok":true}}',
exitCode: 0,
stderr: "",
doneAborted: false,
signalAborted: false,
yieldItems: undefined,
outputSchema: { type: "object", properties: { ok: { type: "boolean" } }, required: ["ok"] },
});
expect(result.rawOutput).toBe('{\n "ok": true\n}');
expect(result.rawOutput.includes("SYSTEM WARNING")).toBe(false);
});
it("prefixes missing-submit warning on stop outputs", () => {
const result = finalizeSubprocessOutput({
rawOutput: "agent stopped after writing analysis",
exitCode: 0,
stderr: "",
doneAborted: false,
signalAborted: false,
yieldItems: undefined,
outputSchema: { type: "object", properties: { ok: { type: "boolean" } }, required: ["ok"] },
});
expect(result.rawOutput).toBe(`${SUBAGENT_WARNING_MISSING_YIELD}\n\nagent stopped after writing analysis`);
});
it("does not inject missing-submit warning when execution exits non-zero", () => {
const result = finalizeSubprocessOutput({
rawOutput: "",
exitCode: 1,
stderr: "subagent terminated",
doneAborted: true,
signalAborted: false,
yieldItems: undefined,
outputSchema: { type: "object", properties: { ok: { type: "boolean" } }, required: ["ok"] },
});
expect(result.rawOutput).toBe("");
expect(result.stderr).toBe("subagent terminated");
expect(result.exitCode).toBe(1);
});
it("normalizes explicit aborted yield into aborted payload", () => {
const result = finalizeSubprocessOutput({
rawOutput: "partial output",
exitCode: 1,
stderr: "old error",
doneAborted: false,
signalAborted: false,
yieldItems: [{ status: "aborted", error: "blocked by permissions" }],
outputSchema: undefined,
});
expect(result.abortedViaYield).toBe(true);
expect(result.exitCode).toBe(0);
expect(result.stderr).toBe("blocked by permissions");
expect(result.rawOutput).toContain('"aborted": true');
expect(result.rawOutput).toContain('"blocked by permissions"');
});
it("accepts successful yield data without warning", () => {
const result = finalizeSubprocessOutput({
rawOutput: "should be replaced",
exitCode: 1,
stderr: "should clear",
doneAborted: false,
signalAborted: false,
yieldItems: [{ status: "success", data: { ok: true } }],
outputSchema: undefined,
});
expect(result.rawOutput).toBe('{\n "ok": true\n}');
expect(result.exitCode).toBe(0);
expect(result.stderr).toBe("");
expect(result.rawOutput.includes("SYSTEM WARNING")).toBe(false);
});
it("does not inject missing-submit warning when no schema and raw text exists", () => {
const result = finalizeSubprocessOutput({
rawOutput: "plain text notes",
exitCode: 0,
stderr: "",
doneAborted: false,
signalAborted: false,
yieldItems: undefined,
outputSchema: undefined,
});
expect(result.rawOutput).toBe("plain text notes");
expect(result.rawOutput.includes("SYSTEM WARNING")).toBe(false);
expect(result.exitCode).toBe(0);
});
});