From ba2799a1d9c27540e71abcbc80bb7ec206ff3b2d Mon Sep 17 00:00:00 2001 From: wassname <1103714+wassname@users.noreply.github.com> Date: Mon, 7 Sep 2026 19:35:05 +0800 Subject: [PATCH] Pair supervisors before starting their model Co-Authored-By: PI[Kimi K3] <288921227+claudypoo@users.noreply.github.com> --- src/herdr.ts | 1 - src/supervisor-session.ts | 24 +++++++++--------------- test/herdr.test.ts | 3 ++- test/supervisor-session.test.ts | 18 +++++++++++------- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/herdr.ts b/src/herdr.ts index e014ead..6c0ac65 100644 --- a/src/herdr.ts +++ b/src/herdr.ts @@ -63,7 +63,6 @@ export function supervisorCommand(input: LaunchSupervisorInput): string { "--name", `goals-supervisor-${input.workerSessionId.slice(0, 8)}`, ]; if (input.model) args.push("--model", input.model); - args.push("Initialize supervision startup."); return `env ${[...env, ...args].map(shellQuote).join(" ")}`; } diff --git a/src/supervisor-session.ts b/src/supervisor-session.ts index 0e344d0..e42266e 100644 --- a/src/supervisor-session.ts +++ b/src/supervisor-session.ts @@ -80,34 +80,28 @@ export function registerVisibleSupervisor(pi: ExtensionAPI): void { let compacting = false; let bootstrapping = false; - pi.on("before_agent_start", async (_event, ctx) => { - await bootstrap(ctx); - return { systemPrompt: `${ctx.getSystemPrompt()}\n\n${supervisorPrompt(settings)}` }; - }); - const bootstrap = async (ctx: ExtensionContext): Promise => { if (bootstrapping) return; const entries = ctx.sessionManager.getEntries(); if (entries.some((entry: { type?: string; customType?: string }) => entry.type === "custom" && entry.customType === BOOTSTRAPPED)) return; bootstrapping = true; - compacting = true; try { - await new Promise((resolve, reject) => { - ctx.compact({ - customInstructions: `Preserve the user's decisions, preferences, and high-level objective from planning. Preserve unresolved risks and the plan path ${settings.planPath}. Remove implementation chatter. This summary is for a read-only supervisor that will judge and steer another Pi session.`, - onComplete: () => resolve(), - onError: reject, - }); - }); await pairWithPiSupervise(pi, settings.workerIntercomId, settings.planPath); pi.appendEntry(BOOTSTRAPPED, { version: 1, workerSessionId: settings.workerSessionId, planPath: settings.planPath }); + pi.sendUserMessage("Supervision is paired. Inspect the worker and give its next concrete instruction."); } catch (error) { ctx.ui.notify(`Supervisor startup failed: ${error instanceof Error ? error.message : String(error)}`, "error"); - } finally { - compacting = false; } }; + pi.on("session_start", async (_event, ctx) => { + setImmediate(() => { void bootstrap(ctx); }); + }); + + pi.on("before_agent_start", async (_event, ctx) => { + return { systemPrompt: `${ctx.getSystemPrompt()}\n\n${supervisorPrompt(settings)}` }; + }); + pi.on("agent_settled", async (_event, ctx) => { if (compacting || (ctx.getContextUsage()?.tokens ?? 0) < COMPACT_AT_TOKENS) return; compacting = true; diff --git a/test/herdr.test.ts b/test/herdr.test.ts index 0b3fe37..7c91ae5 100644 --- a/test/herdr.test.ts +++ b/test/herdr.test.ts @@ -26,7 +26,8 @@ describe("supervisor pane command", () => { expect(command).toContain("'PI_GOALS_WORKER_INTERCOM_ID=intercom-12345678'"); expect(command).toContain("'pi' '--no-extensions' '-e' 'npm:pi-intercom' '-e' 'npm:@wassname2/pi-supervise@0.0.4' '-e' '/repo/src/index.ts'"); expect(command).toContain("'--fork' '/sessions/worker.jsonl'"); - expect(command).toContain("'--model' 'provider/supervisor' 'Initialize supervision startup.'"); + expect(command).toContain("'--model' 'provider/supervisor'"); + expect(command).not.toContain("Initialize supervision startup."); expect(command).not.toContain("pi-subagents"); }); diff --git a/test/supervisor-session.test.ts b/test/supervisor-session.test.ts index 1a544d9..5bfdc07 100644 --- a/test/supervisor-session.test.ts +++ b/test/supervisor-session.test.ts @@ -17,6 +17,7 @@ function setup(cwd: string, planPath: string) { const tools = new Map(); const entries: any[] = []; const paired: Array<{ workerIntercomId: string; goal: string }> = []; + const messages: string[] = []; let branch: any[] = []; const ctx = { cwd, @@ -42,34 +43,37 @@ function setup(cwd: string, planPath: string) { on: (name: string, handler: any) => hooks.set(name, handler), registerTool: (tool: any) => tools.set(tool.name, tool), appendEntry: (customType: string, data: unknown) => entries.push({ type: "custom", customType, data }), + sendUserMessage: (message: string) => messages.push(message), }; registerVisibleSupervisor(pi as unknown as ExtensionAPI); - return { branch: (value: any[]) => { branch = value; }, ctx, entries, hooks, paired, tools }; + return { branch: (value: any[]) => { branch = value; }, ctx, entries, hooks, messages, paired, tools }; } afterEach(() => vi.unstubAllEnvs()); describe("visible supervisor session", () => { - it("compacts the fork before pairing it with the worker", async () => { + it("pairs from session startup before asking the supervisor to work", async () => { const cwd = mkdtempSync(join(tmpdir(), "pi-goals-supervisor-")); try { const runtime = setup(cwd, join(cwd, ".pi/plan/worker-v1.md")); - await runtime.hooks.get("before_agent_start")({}, runtime.ctx); - expect(runtime.ctx.compact).toHaveBeenCalledOnce(); + await runtime.hooks.get("session_start")({}, runtime.ctx); + await new Promise((resolve) => setImmediate(resolve)); + expect(runtime.ctx.compact).not.toHaveBeenCalled(); expect(runtime.entries.at(-1)).toMatchObject({ customType: "pi-goals-visible-supervisor-v1" }); expect(runtime.paired).toEqual([{ workerIntercomId: "worker-intercom", goal: join(cwd, ".pi/plan/worker-v1.md") }]); + expect(runtime.messages).toEqual(["Supervision is paired. Inspect the worker and give its next concrete instruction."]); } finally { rmSync(cwd, { recursive: true, force: true }); } }); - it("does not pair twice when startup reaches a second worker turn", async () => { + it("does not pair twice across session startup and later turns", async () => { const cwd = mkdtempSync(join(tmpdir(), "pi-goals-supervisor-")); try { const runtime = setup(cwd, join(cwd, ".pi/plan/worker-v1.md")); + await runtime.hooks.get("session_start")({}, runtime.ctx); + await new Promise((resolve) => setImmediate(resolve)); await runtime.hooks.get("before_agent_start")({}, runtime.ctx); - await runtime.hooks.get("before_agent_start")({}, runtime.ctx); - expect(runtime.ctx.compact).toHaveBeenCalledOnce(); expect(runtime.paired).toHaveLength(1); } finally { rmSync(cwd, { recursive: true, force: true });