import assert from "node:assert/strict";
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import { afterEach, describe, it } from "node:test";
import { writeSteerRequestToDir } from "../../src/runs/background/control-channel.ts";
import {
SUBAGENT_CHILD_AGENT_ENV,
SUBAGENT_CHILD_INDEX_ENV,
SUBAGENT_FANOUT_CHILD_ENV,
SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV,
SUBAGENT_ORCHESTRATOR_TARGET_ENV,
SUBAGENT_RUN_ID_ENV,
SUBAGENT_STEER_INBOX_ENV,
SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV,
} from "../../src/runs/shared/pi-args.ts";
import { STRUCTURED_OUTPUT_CAPTURE_ENV, STRUCTURED_OUTPUT_SCHEMA_ENV } from "../../src/runs/shared/structured-output.ts";
import { TOOL_BUDGET_ENV } from "../../src/runs/shared/tool-budget.ts";
import registerSubagentPromptRuntime, {
CHILD_FANOUT_BOUNDARY_INSTRUCTIONS,
CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS,
SUBAGENT_INTERCOM_SESSION_NAME_ENV,
rewriteSubagentPrompt,
stripInheritedSkills,
stripParentOnlySubagentMessages,
stripProjectContext,
stripSubagentOrchestrationSkill,
} from "../../src/runs/shared/subagent-prompt-runtime.ts";
const envSnapshot = {
SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT: process.env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT,
SELESAI_SUBAGENT_INHERIT_SKILLS: process.env.SELESAI_SUBAGENT_INHERIT_SKILLS,
SELESAI_SUBAGENT_INTERCOM_SESSION_NAME: process.env.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME,
SELESAI_SUBAGENT_FANOUT_CHILD: process.env.SELESAI_SUBAGENT_FANOUT_CHILD,
SELESAI_SUBAGENT_STEER_INBOX: process.env.SELESAI_SUBAGENT_STEER_INBOX,
SELESAI_SUBAGENT_STRUCTURED_OUTPUT_CAPTURE: process.env.SELESAI_SUBAGENT_STRUCTURED_OUTPUT_CAPTURE,
SELESAI_SUBAGENT_STRUCTURED_OUTPUT_SCHEMA: process.env.SELESAI_SUBAGENT_STRUCTURED_OUTPUT_SCHEMA,
SELESAI_SUBAGENT_TOOL_BUDGET: process.env.SELESAI_SUBAGENT_TOOL_BUDGET,
SELESAI_SUBAGENT_ORCHESTRATOR_TARGET: process.env.SELESAI_SUBAGENT_ORCHESTRATOR_TARGET,
SELESAI_SUBAGENT_ORCHESTRATOR_SESSION_ID: process.env.SELESAI_SUBAGENT_ORCHESTRATOR_SESSION_ID,
SELESAI_SUBAGENT_SUPERVISOR_CHANNEL_DIR: process.env.SELESAI_SUBAGENT_SUPERVISOR_CHANNEL_DIR,
SELESAI_SUBAGENT_RUN_ID: process.env.SELESAI_SUBAGENT_RUN_ID,
SELESAI_SUBAGENT_CHILD_AGENT: process.env.SELESAI_SUBAGENT_CHILD_AGENT,
SELESAI_SUBAGENT_CHILD_INDEX: process.env.SELESAI_SUBAGENT_CHILD_INDEX,
};
const SKILLS_SECTION = "\n\nThe following skills provide specialized instructions for specific tasks.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n\n \n safe-bash\n desc\n /tmp/SKILL.md\n \n \n pi-subagents\n delegate to subagents\n /tmp/pi-subagents/SKILL.md\n \n";
const BASE_PROMPT = [
"You are a subagent.",
"\n\n# Project Context\n\nProject-specific instructions and guidelines:\n\n## /repo/AGENTS.md\n\nProject rules\n\n",
SKILLS_SECTION,
"\nCurrent date: 2026-04-16",
"\nCurrent working directory: /repo",
].join("");
const PROMPT_WITH_EXPLICIT_SKILL = [
"You are a subagent.\n\n\nKeep this section\n",
"\n\n# Project Context\n\nProject-specific instructions and guidelines:\n\n## /repo/AGENTS.md\n\nProject rules\n\n",
SKILLS_SECTION,
"\nCurrent date: 2026-04-16",
].join("");
const CONFIGURED_SKILLS_SECTION = "\n\nThe following configured skills are available to this subagent.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n\n \n configured-skill\n explicit agent skill\n /tmp/configured-skill/SKILL.md\n \n";
afterEach(() => {
if (envSnapshot.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT === undefined) delete process.env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT;
else process.env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT = envSnapshot.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT;
if (envSnapshot.SELESAI_SUBAGENT_INHERIT_SKILLS === undefined) delete process.env.SELESAI_SUBAGENT_INHERIT_SKILLS;
else process.env.SELESAI_SUBAGENT_INHERIT_SKILLS = envSnapshot.SELESAI_SUBAGENT_INHERIT_SKILLS;
if (envSnapshot.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME === undefined) delete process.env.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME;
else process.env.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME = envSnapshot.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME;
if (envSnapshot.SELESAI_SUBAGENT_FANOUT_CHILD === undefined) delete process.env.SELESAI_SUBAGENT_FANOUT_CHILD;
else process.env.SELESAI_SUBAGENT_FANOUT_CHILD = envSnapshot.SELESAI_SUBAGENT_FANOUT_CHILD;
if (envSnapshot.SELESAI_SUBAGENT_STEER_INBOX === undefined) delete process.env[SUBAGENT_STEER_INBOX_ENV];
else process.env[SUBAGENT_STEER_INBOX_ENV] = envSnapshot.SELESAI_SUBAGENT_STEER_INBOX;
if (envSnapshot.SELESAI_SUBAGENT_STRUCTURED_OUTPUT_CAPTURE === undefined) delete process.env[STRUCTURED_OUTPUT_CAPTURE_ENV];
else process.env[STRUCTURED_OUTPUT_CAPTURE_ENV] = envSnapshot.SELESAI_SUBAGENT_STRUCTURED_OUTPUT_CAPTURE;
if (envSnapshot.SELESAI_SUBAGENT_STRUCTURED_OUTPUT_SCHEMA === undefined) delete process.env[STRUCTURED_OUTPUT_SCHEMA_ENV];
else process.env[STRUCTURED_OUTPUT_SCHEMA_ENV] = envSnapshot.SELESAI_SUBAGENT_STRUCTURED_OUTPUT_SCHEMA;
if (envSnapshot.SELESAI_SUBAGENT_TOOL_BUDGET === undefined) delete process.env[TOOL_BUDGET_ENV];
else process.env[TOOL_BUDGET_ENV] = envSnapshot.SELESAI_SUBAGENT_TOOL_BUDGET;
if (envSnapshot.SELESAI_SUBAGENT_ORCHESTRATOR_TARGET === undefined) delete process.env[SUBAGENT_ORCHESTRATOR_TARGET_ENV];
else process.env[SUBAGENT_ORCHESTRATOR_TARGET_ENV] = envSnapshot.SELESAI_SUBAGENT_ORCHESTRATOR_TARGET;
if (envSnapshot.SELESAI_SUBAGENT_ORCHESTRATOR_SESSION_ID === undefined) delete process.env[SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV];
else process.env[SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV] = envSnapshot.SELESAI_SUBAGENT_ORCHESTRATOR_SESSION_ID;
if (envSnapshot.SELESAI_SUBAGENT_SUPERVISOR_CHANNEL_DIR === undefined) delete process.env[SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV];
else process.env[SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV] = envSnapshot.SELESAI_SUBAGENT_SUPERVISOR_CHANNEL_DIR;
if (envSnapshot.SELESAI_SUBAGENT_RUN_ID === undefined) delete process.env[SUBAGENT_RUN_ID_ENV];
else process.env[SUBAGENT_RUN_ID_ENV] = envSnapshot.SELESAI_SUBAGENT_RUN_ID;
if (envSnapshot.SELESAI_SUBAGENT_CHILD_AGENT === undefined) delete process.env[SUBAGENT_CHILD_AGENT_ENV];
else process.env[SUBAGENT_CHILD_AGENT_ENV] = envSnapshot.SELESAI_SUBAGENT_CHILD_AGENT;
if (envSnapshot.SELESAI_SUBAGENT_CHILD_INDEX === undefined) delete process.env[SUBAGENT_CHILD_INDEX_ENV];
else process.env[SUBAGENT_CHILD_INDEX_ENV] = envSnapshot.SELESAI_SUBAGENT_CHILD_INDEX;
});
function setSupervisorEnv(): void {
process.env[SUBAGENT_ORCHESTRATOR_TARGET_ENV] = "subagent-chat-parent";
process.env[SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV] = "session-parent";
process.env[SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV] = path.join(os.tmpdir(), "subagent-supervisor-runtime-test");
process.env[SUBAGENT_RUN_ID_ENV] = "run-123";
process.env[SUBAGENT_CHILD_AGENT_ENV] = "worker";
process.env[SUBAGENT_CHILD_INDEX_ENV] = "0";
}
describe("subagent prompt runtime", () => {
it("nudges after the tool budget soft limit and blocks configured tools after hard", () => {
const handlers = new Map unknown>();
const sent: string[] = [];
process.env[TOOL_BUDGET_ENV] = JSON.stringify({ soft: 2, hard: 2, block: ["read"] });
registerSubagentPromptRuntime({
on(event: string, handler: (payload: { toolName?: string }) => unknown) {
handlers.set(event, handler);
},
sendUserMessage(content: string) {
sent.push(content);
},
} as { on(event: string, handler: (payload: { toolName?: string }) => unknown): void; sendUserMessage(content: string): void });
const toolCall = handlers.get("tool_call");
assert.ok(toolCall, "tool_call handler should be registered");
assert.equal(toolCall({ toolName: "grep" }), undefined);
assert.equal(toolCall({ toolName: "grep" }), undefined);
assert.equal(sent.length, 1);
assert.match(sent[0] ?? "", /soft limit reached/);
assert.deepEqual(toolCall({ toolName: "read" }), {
block: true,
reason: "Tool budget hard limit reached after 3 tool calls (hard 2). The 'read' tool is blocked so you can finalize from the context you already have.",
});
assert.equal(toolCall({ toolName: "write" }), undefined);
});
it("delivers steering inbox requests as mid-run user messages", () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "subagent-steering-runtime-"));
try {
const inbox = path.join(dir, "steer");
process.env[SUBAGENT_STEER_INBOX_ENV] = inbox;
const handlers = new Map unknown>();
const sent: Array<{ content: string; options: { deliverAs: string } }> = [];
registerSubagentPromptRuntime({
on(event: string, handler: (payload?: unknown) => unknown) {
handlers.set(event, handler);
},
sendUserMessage(content: string, options: { deliverAs: string }) {
sent.push({ content, options });
},
} as { on(event: string, handler: (payload?: unknown) => unknown): void; sendUserMessage(content: string, options: { deliverAs: string }): void });
writeSteerRequestToDir(inbox, { type: "steer", id: "steer-1", ts: 1, message: "Focus on tests." });
handlers.get("message_start")?.({});
handlers.get("session_shutdown")?.({});
assert.equal(sent.length, 1);
assert.equal(sent[0]?.options.deliverAs, "steer");
assert.match(sent[0]?.content ?? "", /Mid-run steering/);
assert.match(sent[0]?.content ?? "", /Focus on tests\./);
assert.deepEqual(fs.readdirSync(inbox).filter((entry) => entry.endsWith(".json")), []);
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}
});
it("registered structured_output tool accepts valid schema output and writes the capture file", async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "subagent-structured-runtime-"));
try {
const schemaPath = path.join(dir, "schema.json");
const outputPath = path.join(dir, "output.json");
fs.writeFileSync(schemaPath, JSON.stringify({ type: "object", required: ["ok"], properties: { ok: { type: "boolean" } } }), "utf-8");
process.env[STRUCTURED_OUTPUT_SCHEMA_ENV] = schemaPath;
process.env[STRUCTURED_OUTPUT_CAPTURE_ENV] = outputPath;
let execute: ((_id: string, params: { value: unknown }) => Promise<{ terminate?: boolean }>) | undefined;
registerSubagentPromptRuntime({
registerTool(tool: { name: string; execute: (_id: string, params: { value: unknown }) => Promise<{ terminate?: boolean }> }) {
if (tool.name === "structured_output") execute = tool.execute;
},
on() {},
} as { registerTool(tool: { name: string; execute: (_id: string, params: { value: unknown }) => Promise<{ terminate?: boolean }> }): void; on(): void });
assert.ok(execute, "structured_output tool should be registered");
const result = await execute("tool-1", { value: { ok: true } });
assert.equal(result.terminate, true);
assert.deepEqual(JSON.parse(fs.readFileSync(outputPath, "utf-8")), { ok: true });
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}
});
it("strips only the project context block", () => {
const rewritten = stripProjectContext(BASE_PROMPT);
assert.ok(!rewritten.includes("# Project Context"));
assert.ok(rewritten.includes("The following skills provide specialized instructions for specific tasks."));
assert.ok(rewritten.includes("Current date: 2026-04-16"));
});
it("strips only the inherited skills block", () => {
const rewritten = stripInheritedSkills(BASE_PROMPT);
assert.ok(rewritten.includes("# Project Context"));
assert.ok(!rewritten.includes(""));
assert.ok(rewritten.includes("Current date: 2026-04-16"));
});
it("can strip both inherited sections together", () => {
const rewritten = rewriteSubagentPrompt(BASE_PROMPT, {
inheritProjectContext: false,
inheritSkills: false,
});
assert.ok(!rewritten.includes("# Project Context"));
assert.ok(!rewritten.includes(""));
assert.ok(rewritten.includes("Current working directory: /repo"));
});
it("injects a child-only boundary that forbids proposing or running subagents", () => {
const rewritten = rewriteSubagentPrompt(BASE_PROMPT, {
inheritProjectContext: true,
inheritSkills: true,
});
assert.ok(rewritten.startsWith(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS));
assert.ok(rewritten.includes("Do not propose or run subagents."));
assert.ok(rewritten.includes("If you need to edit files, use the available editing tools."));
assert.ok(!rewritten.includes("call the actual edit/write tools"));
assert.ok(rewritten.includes("Do not print tool-call syntax, patches, or pseudo-tool calls as text."));
assert.equal(rewriteSubagentPrompt(rewritten, { inheritProjectContext: true, inheritSkills: true }).indexOf(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS), 0);
assert.equal(rewriteSubagentPrompt(rewritten, { inheritProjectContext: true, inheritSkills: true }).lastIndexOf(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS), 0);
});
it("replaces inherited child boundaries with the fanout boundary when authorized", () => {
const strictPrompt = `${CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS}\n\n${BASE_PROMPT}`;
const rewritten = rewriteSubagentPrompt(strictPrompt, {
inheritProjectContext: true,
inheritSkills: true,
fanoutChild: true,
});
assert.ok(rewritten.startsWith(CHILD_FANOUT_BOUNDARY_INSTRUCTIONS));
assert.ok(rewritten.includes("You may use the `subagent` tool only for the fanout work explicitly requested in this task."));
assert.ok(rewritten.includes("If you need to edit files, use the available editing tools."));
assert.ok(!rewritten.includes("call the actual edit/write tools"));
assert.ok(!rewritten.includes("Do not propose or run subagents."));
assert.equal(rewritten.lastIndexOf(CHILD_FANOUT_BOUNDARY_INSTRUCTIONS), 0);
});
it("replaces inherited fanout boundaries with the strict boundary when fanout is not authorized", () => {
const fanoutPrompt = `${CHILD_FANOUT_BOUNDARY_INSTRUCTIONS}\n\n${BASE_PROMPT}`;
const rewritten = rewriteSubagentPrompt(fanoutPrompt, {
inheritProjectContext: true,
inheritSkills: true,
});
assert.ok(rewritten.startsWith(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS));
assert.ok(!rewritten.includes("explicit fanout responsibility"));
assert.equal(rewritten.lastIndexOf(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS), 0);
});
it("keeps explicitly injected skill content when inherited skills are stripped", () => {
const rewritten = rewriteSubagentPrompt(PROMPT_WITH_EXPLICIT_SKILL, {
inheritProjectContext: false,
inheritSkills: false,
});
assert.ok(rewritten.includes(""));
assert.ok(!rewritten.includes(""));
assert.ok(!rewritten.includes("# Project Context"));
});
it("keeps configured lazy skill references when inherited skills are stripped", () => {
const prompt = [
"You are a subagent.",
CONFIGURED_SKILLS_SECTION,
"\n\n# Project Context\n\nProject-specific instructions and guidelines:\n\n## /repo/AGENTS.md\n\nProject rules\n\n",
SKILLS_SECTION,
"\nCurrent date: 2026-04-16",
].join("");
const rewritten = rewriteSubagentPrompt(prompt, {
inheritProjectContext: false,
inheritSkills: false,
});
assert.ok(rewritten.includes("configured-skill"));
assert.ok(rewritten.includes("/tmp/configured-skill/SKILL.md"));
assert.ok(!rewritten.includes("safe-bash"));
assert.ok(!rewritten.includes("# Project Context"));
});
it("strips the subagent orchestration skill even when inherited skills remain", () => {
const rewritten = rewriteSubagentPrompt(BASE_PROMPT, {
inheritProjectContext: true,
inheritSkills: true,
});
assert.ok(rewritten.includes("safe-bash"));
assert.ok(!rewritten.includes("pi-subagents"));
assert.ok(!rewritten.includes("delegate to subagents"));
});
it("strips explicit pi-subagents skill injection from child prompts", () => {
const prompt = "Before\n\n\nDo not keep this.\n\n\n\nKeep this.\n\nAfter";
const rewritten = stripSubagentOrchestrationSkill(prompt);
assert.ok(!rewritten.includes("Do not keep this"));
assert.ok(rewritten.includes(""));
});
it("strips parent-only subagent custom messages from forked child context", () => {
const user = { role: "user", content: "Task" };
const instruction = { role: "custom", customType: "subagent-orchestration-instructions", content: "Subagent orchestration is enabled." };
const slashResult = { role: "custom", customType: "subagent-slash-result", content: "## Orchestration" };
const slashTextResult = { role: "custom", customType: "subagent-slash-text-result", content: "Subagent profiles" };
const notify = { role: "custom", customType: "subagent-notify", content: "Background task completed" };
const control = { role: "custom", customType: "subagent_control_notice", content: "needs attention" };
const otherCustom = { role: "custom", customType: "other", content: "keep" };
assert.deepEqual(stripParentOnlySubagentMessages([user, instruction, slashResult, slashTextResult, notify, control, otherCustom]), [user, otherCustom]);
});
it("strips prior parent subagent tool calls and results from forked child context", () => {
const user = { role: "user", content: "Task" };
const subagentResult = { role: "toolResult", toolName: "subagent", content: "subagent results" };
const readResult = { role: "toolResult", toolName: "read", content: "file contents" };
const mixedAssistant = {
role: "assistant",
content: [
{ type: "text", text: "I will inspect the repo." },
{ type: "toolCall", name: "subagent", input: { agent: "worker" } },
{ type: "toolCall", name: "read", input: { path: "README.md" } },
],
};
const pureSubagentCall = {
role: "assistant",
content: [{ type: "toolCall", name: "subagent", input: { agent: "reviewer" } }],
};
assert.deepEqual(
stripParentOnlySubagentMessages([user, subagentResult, readResult, mixedAssistant, pureSubagentCall]),
[
user,
readResult,
{
role: "assistant",
content: [
{ type: "text", text: "I will inspect the repo." },
{ type: "toolCall", name: "read", input: { path: "README.md" } },
],
},
],
);
});
it("preserves live nested subagent calls and results in fanout child context", () => {
const user = { role: "user", content: "Task" };
const subagentResult = { role: "toolResult", toolName: "subagent", content: "OK" };
const subagentCall = { role: "assistant", content: [{ type: "toolCall", name: "subagent", input: { agent: "delegate" } }] };
const instruction = { role: "custom", customType: "subagent-orchestration-instructions", content: "Subagent orchestration is enabled." };
process.env[SUBAGENT_FANOUT_CHILD_ENV] = "1";
assert.deepEqual(stripParentOnlySubagentMessages([user, subagentCall, subagentResult, instruction]), [user, subagentCall, subagentResult]);
});
it("defers native supervisor registration until runtime events and respects installed pi-intercom tools", async () => {
setSupervisorEnv();
const handlers = new Map unknown>();
const registered: string[] = [];
registerSubagentPromptRuntime({
on(event: string, handler: (payload?: unknown) => unknown) {
handlers.set(event, handler);
},
getAllTools: () => [{ name: "intercom" }, { name: "contact_supervisor" }],
registerTool(tool: { name: string }) {
registered.push(tool.name);
},
} as { on(event: string, handler: (payload?: unknown) => unknown): void; getAllTools(): Array<{ name: string }>; registerTool(tool: { name: string }): void });
assert.deepEqual(registered, []);
handlers.get("session_start")?.({});
await handlers.get("before_agent_start")?.({ systemPrompt: BASE_PROMPT });
assert.deepEqual(registered, []);
});
it("keeps installed pi-intercom while filling only a missing child contact_supervisor tool", async () => {
setSupervisorEnv();
const handlers = new Map unknown>();
const registered: string[] = [];
registerSubagentPromptRuntime({
on(event: string, handler: (payload?: unknown) => unknown) {
handlers.set(event, handler);
},
getAllTools: () => [{ name: "intercom" }, ...registered.map((name) => ({ name }))],
registerTool(tool: { name: string }) {
registered.push(tool.name);
},
} as { on(event: string, handler: (payload?: unknown) => unknown): void; getAllTools(): Array<{ name: string }>; registerTool(tool: { name: string }): void });
handlers.get("session_start")?.({});
await handlers.get("before_agent_start")?.({ systemPrompt: BASE_PROMPT });
assert.deepEqual(registered, ["contact_supervisor"]);
});
it("registers native supervisor tools at runtime when pi-intercom is absent", async () => {
setSupervisorEnv();
const handlers = new Map unknown>();
const registered: string[] = [];
registerSubagentPromptRuntime({
on(event: string, handler: (payload?: unknown) => unknown) {
handlers.set(event, handler);
},
getAllTools: () => registered.map((name) => ({ name })),
registerTool(tool: { name: string }) {
registered.push(tool.name);
},
} as { on(event: string, handler: (payload?: unknown) => unknown): void; getAllTools(): Array<{ name: string }>; registerTool(tool: { name: string }): void });
handlers.get("session_start")?.({});
assert.deepEqual(registered, ["contact_supervisor"]);
await handlers.get("before_agent_start")?.({ systemPrompt: BASE_PROMPT });
assert.deepEqual(registered, ["contact_supervisor", "intercom"]);
});
it("sets the child intercom session name from env during agent startup", async () => {
let sessionName: string | undefined;
let beforeAgentStart: ((event: { systemPrompt: string }) => Promise<{ systemPrompt: string } | undefined>) | undefined;
process.env[SUBAGENT_INTERCOM_SESSION_NAME_ENV] = "subagent-worker-78f659a3";
registerSubagentPromptRuntime({
on(event: string, handler: (payload: { systemPrompt: string }) => Promise<{ systemPrompt: string } | undefined>) {
if (event === "before_agent_start") beforeAgentStart = handler;
},
setSessionName(name: string) {
sessionName = name;
},
} as { on(event: string, handler: (payload: { systemPrompt: string }) => Promise<{ systemPrompt: string } | undefined>): void; setSessionName(name: string): void });
await beforeAgentStart?.({ systemPrompt: BASE_PROMPT });
assert.equal(sessionName, "subagent-worker-78f659a3");
});
it("rewrites the final child-visible prompt through before_agent_start", async () => {
let beforeAgentStart: ((event: { systemPrompt: string }) => Promise<{ systemPrompt: string } | undefined>) | undefined;
registerSubagentPromptRuntime({
on(event: string, handler: (payload: { systemPrompt: string }) => Promise<{ systemPrompt: string } | undefined>) {
if (event === "before_agent_start") beforeAgentStart = handler;
},
} as { on(event: string, handler: (payload: { systemPrompt: string }) => Promise<{ systemPrompt: string } | undefined>): void });
assert.ok(beforeAgentStart, "expected before_agent_start handler");
process.env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT = "0";
process.env.SELESAI_SUBAGENT_INHERIT_SKILLS = "0";
const rewritten = await beforeAgentStart?.({ systemPrompt: BASE_PROMPT });
assert.ok(rewritten);
assert.ok(!rewritten.systemPrompt.includes("# Project Context"));
assert.ok(!rewritten.systemPrompt.includes(""));
assert.ok(rewritten.systemPrompt.includes("Current date: 2026-04-16"));
});
it("uses the fanout boundary through before_agent_start when fanout env is set", async () => {
let beforeAgentStart: ((event: { systemPrompt: string }) => Promise<{ systemPrompt: string } | undefined>) | undefined;
registerSubagentPromptRuntime({
on(event: string, handler: (payload: { systemPrompt: string }) => Promise<{ systemPrompt: string } | undefined>) {
if (event === "before_agent_start") beforeAgentStart = handler;
},
} as { on(event: string, handler: (payload: { systemPrompt: string }) => Promise<{ systemPrompt: string } | undefined>): void });
process.env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT = "1";
process.env.SELESAI_SUBAGENT_INHERIT_SKILLS = "1";
process.env[SUBAGENT_FANOUT_CHILD_ENV] = "1";
const rewritten = await beforeAgentStart?.({ systemPrompt: BASE_PROMPT });
assert.ok(rewritten);
assert.ok(rewritten.systemPrompt.startsWith(CHILD_FANOUT_BOUNDARY_INSTRUCTIONS));
});
it("filters parent-only artifacts from polluted fork context while preserving ordinary history", () => {
let contextHandler: ((event: { messages: unknown[] }) => { messages: unknown[] } | undefined) | undefined;
registerSubagentPromptRuntime({
on(event: string, handler: (payload: { messages: unknown[] }) => { messages: unknown[] } | undefined) {
if (event === "context") contextHandler = handler;
},
} as { on(event: string, handler: (payload: { messages: unknown[] }) => { messages: unknown[] } | undefined): void });
const priorParentTurn = { role: "user", content: "Earlier we said planner → worker → reviewers → worker." };
const currentTask = { role: "user", content: "Now implement only the assigned fix." };
const instruction = { role: "custom", customType: "subagent-orchestration-instructions", content: "Subagent orchestration is enabled." };
const slashResult = { role: "custom", customType: "subagent-slash-result", content: "## Orchestration" };
const subagentResult = { role: "toolResult", toolName: "subagent", content: "subagent results" };
const subagentCall = { role: "assistant", content: [{ type: "toolCall", name: "subagent", input: { agent: "worker" } }] };
const otherCustom = { role: "custom", customType: "other", content: "keep" };
assert.deepEqual(contextHandler?.({ messages: [priorParentTurn, instruction, slashResult, subagentCall, subagentResult, otherCustom, currentTask] }), {
messages: [priorParentTurn, otherCustom, currentTask],
});
});
it("does not rewrite child context when no parent-only artifacts are present", () => {
let contextHandler: ((event: { messages: unknown[] }) => { messages: unknown[] } | undefined) | undefined;
registerSubagentPromptRuntime({
on(event: string, handler: (payload: { messages: unknown[] }) => { messages: unknown[] } | undefined) {
if (event === "context") contextHandler = handler;
},
} as { on(event: string, handler: (payload: { messages: unknown[] }) => { messages: unknown[] } | undefined): void });
const messages = [
{ role: "user", content: "Task" },
{ role: "toolResult", toolName: "read", content: "file" },
{ role: "assistant", content: [{ type: "toolCall", name: "read", input: { path: "README.md" } }] },
];
assert.equal(contextHandler?.({ messages }), undefined);
});
});