Files
oh-my-pi/packages/coding-agent/test/task/coordination-advisory.test.ts
can1357 3de8c3a476 Merge PR #7344: fix(agent): stop leaking scout into prompts when it is disabled (@szavadsky)
# Conflicts:
#	packages/coding-agent/src/prompts/system/system-prompt.md
2026-08-02 20:52:56 +02:00

111 lines
3.5 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import { buildCoordinationAdvisory, composeSpawnAdvisory } from "@oh-my-pi/pi-coding-agent/task";
import type { TaskItem } from "@oh-my-pi/pi-coding-agent/task/types";
// Contract: a multi-sibling spawn with spawn capacity and IRC available draws
// a proactive coordinate-via-irc suggestion.
const item = (): TaskItem => ({ task: "do the thing" });
describe("buildCoordinationAdvisory", () => {
it("suggests hub coordination for >=2 siblings with capacity and hub messaging enabled", () => {
const advice = buildCoordinationAdvisory([item(), item()], true, true);
expect(advice).toBeDefined();
expect(advice).toContain("`hub`");
});
it("stays silent for a single spawn", () => {
expect(buildCoordinationAdvisory([item()], true, true)).toBeUndefined();
});
it("stays silent when irc is unavailable", () => {
expect(buildCoordinationAdvisory([item(), item()], true, false)).toBeUndefined();
});
it("stays silent at max depth (no spawn capacity)", () => {
expect(buildCoordinationAdvisory([item(), item()], false, true)).toBeUndefined();
});
});
// Contract: TaskTool.execute composes the specialization nudge with the
// coordination suggestion, gating the latter to the async path (sync siblings
// have already finished). composeSpawnAdvisory is the seam that decision flows
// through, so the gating is pinned here rather than only inside the builders.
describe("composeSpawnAdvisory", () => {
const worker = (): TaskItem => ({ task: "x" });
it("joins the specialization tip and the irc coordination suggestion for an async generic fanout", () => {
const advisory = composeSpawnAdvisory({
agents: ["task", "task"],
items: [worker(), worker()],
depthCapacity: true,
ircEnabled: true,
willRunAsync: true,
});
expect(advisory).toContain("generic");
expect(advisory).toContain('`agent: "scout"`');
expect(advisory).toContain("Coordinate:");
});
it("drops the scout example from the specialization tip when scout is unavailable", () => {
const advisory = composeSpawnAdvisory({
agents: ["task", "task"],
items: [worker(), worker()],
depthCapacity: true,
ircEnabled: true,
willRunAsync: true,
scoutAvailable: false,
});
expect(advisory).toContain("generic");
expect(advisory).not.toContain("scout");
expect(advisory).toContain("Coordinate:");
});
it("drops the coordination suggestion on the sync path but keeps the specialization tip", () => {
const advisory = composeSpawnAdvisory({
agents: ["task", "task"],
items: [worker(), worker()],
depthCapacity: true,
ircEnabled: true,
willRunAsync: false,
});
expect(advisory).toContain("generic");
expect(advisory).not.toContain("Coordinate:");
});
it("omits coordination when irc is unavailable, even async", () => {
const advisory = composeSpawnAdvisory({
agents: ["task", "task"],
items: [worker(), worker()],
depthCapacity: true,
ircEnabled: false,
willRunAsync: true,
});
expect(advisory).toContain("generic");
expect(advisory).not.toContain("Coordinate:");
});
it("returns undefined for a single non-generic spawn", () => {
expect(
composeSpawnAdvisory({
agents: ["reviewer"],
items: [worker()],
depthCapacity: true,
ircEnabled: true,
willRunAsync: true,
}),
).toBeUndefined();
});
it("returns undefined at max depth (no spawn capacity)", () => {
expect(
composeSpawnAdvisory({
agents: ["task", "task"],
items: [worker(), worker()],
depthCapacity: false,
ircEnabled: true,
willRunAsync: true,
}),
).toBeUndefined();
});
});