Compact the supervisor fork before work

Co-Authored-By: PI[gpt-5.6-sol] <288921227+claudypoo@users.noreply.github.com>
This commit is contained in:
wassnameandPI[gpt-5.6-sol] committed 2026-09-05 21:31:46 +08:00
1 parent 3eaaec9f5a
commit 6cfeaf44ee
8 files changed
+117 -27

No files matched your search

+5 -5
View File
@@ -187,7 +187,7 @@ export default function piGoalsExtension(pi: ExtensionAPI): void {
}
}
async function startOrResumeWorker(ctx: ExtensionContext, task: string, signal?: AbortSignal): Promise<string> {
async function startOrResumeWorker(ctx: ExtensionContext, task: string, compactPlanning: boolean, signal?: AbortSignal): Promise<string> {
if (workerLaunchPending) throw new Error("A goal-worker launch is already in progress.");
if (!workerRegistration) setupWorker(ctx);
if (!workerRegistration) throw new Error(`Goal worker unavailable: ${workerRegistrationError ?? "pi-subagents is not ready"}.`);
@@ -196,7 +196,7 @@ export default function piGoalsExtension(pi: ExtensionAPI): void {
try {
const runId = state.workerRunId
? await resumeGoalSupervisor(pi.events, state.workerRunId, task, signal)
: await startGoalSupervisor(pi.events, ctx.cwd, task, signal);
: await startGoalSupervisor(pi.events, ctx.cwd, task, compactPlanning, signal);
rememberWorkerRun(runId);
return runId;
} finally {
@@ -238,7 +238,7 @@ export default function piGoalsExtension(pi: ExtensionAPI): void {
return `${instruction}\n\nYou are the retained goal-supervisor. Here is the complete current plan; inspect its exact goal blocks and cited evidence before directing or approving work.\nPlan path: ${planPath(ctx)}\nApproval ID: ${state.approvalId}\nNested worker model: ${state.workerModel ?? "pi-subagents default"}\nPass the exact approval ID to ApproveGoal. Keep checkpoint paths and the approval ID from the nested worker.\nPrivate approval checkpoints, one per current goal:\n${checkpoints || "(no open goals)"}\n\n${plan}`;
}
async function directSupervisor(ctx: ExtensionContext, instruction: string, signal?: AbortSignal): Promise<string> {
async function directSupervisor(ctx: ExtensionContext, instruction: string, signal?: AbortSignal, compactPlanning = false): Promise<string> {
beginReview(ctx);
const task = supervisorTask(ctx, instruction);
if (state.workerPending && state.workerRunId) {
@@ -251,7 +251,7 @@ export default function piGoalsExtension(pi: ExtensionAPI): void {
persist();
}
}
return startOrResumeWorker(ctx, task, signal);
return startOrResumeWorker(ctx, task, compactPlanning, signal);
}
function wakeSupervisor(ctx: ExtensionContext, reason: string): void {
@@ -518,7 +518,7 @@ export default function piGoalsExtension(pi: ExtensionAPI): void {
persist();
updateWidget(ctx);
try {
await directSupervisor(ctx, "Start by launching or resuming the nested goal-worker. Then supervise the current plan.");
await directSupervisor(ctx, "Start by launching or resuming the nested goal-worker. Then supervise the current plan.", undefined, choice === "Ready (compact)");
scheduleSupervisorCheck(ctx);
return true;
} catch (error) {
+57 -1
View File
@@ -7,6 +7,7 @@ import { isSupervisorReadOnlyCommand } from "./index.js";
import { processWorkState } from "./worker.js";
const NESTED_STATE = "pi-goals-nested-worker";
const COMPACTED_STATE = "pi-goals-supervisor-compacted";
interface NestedState {
runId: string | null;
@@ -22,8 +23,17 @@ function targetRun(input: Record<string, unknown>): string | null {
return typeof value === "string" && value ? value : null;
}
function compactPlanningRequested(): boolean {
const raw = process.env.PI_SUBAGENT_EXTENSION_BINDINGS;
if (!raw) return false;
const bindings = JSON.parse(raw) as { "pi-goals/1"?: { compactPlanning?: unknown } };
return bindings["pi-goals/1"]?.compactPlanning === true;
}
export default function goalSupervisorRuntime(pi: ExtensionAPI): void {
let nested: NestedState = { runId: null, pending: false };
let compacting = false;
let compactionDone = Promise.resolve();
const persist = () => pi.appendEntry<NestedState>(NESTED_STATE, nested);
pi.events.on("subagent:async-started", (raw) => {
@@ -41,11 +51,46 @@ export default function goalSupervisorRuntime(pi: ExtensionAPI): void {
pi.events.on("subagent:async-complete", completeNested);
pi.events.on("subagent:process-terminal", completeNested);
pi.on("session_before_compact", async (event) => {
if (!compacting) return;
const branchEntries = event.branchEntries as Array<{ id?: string; type?: string; message?: { role?: string } }>;
const latestMessage = [...branchEntries].reverse().find((entry) => entry.type === "message" && ["user", "assistant"].includes(entry.message?.role ?? ""));
return {
compaction: {
summary: "Planning is complete. The latest retained goal-supervisor task contains the current plan and approval paths; use it as the source of truth. -- PI[gpt-5.6-sol]",
firstKeptEntryId: latestMessage?.id ?? event.preparation.firstKeptEntryId,
tokensBefore: event.preparation.tokensBefore,
details: { source: "pi-goals-plan-handoff" },
},
};
});
pi.on("session_start", async (_event, ctx) => {
const last = ctx.sessionManager.getEntries()
const entries = ctx.sessionManager.getEntries();
const last = entries
.filter((entry: { type?: string; customType?: string }) => entry.type === "custom" && entry.customType === NESTED_STATE)
.pop() as { data?: NestedState } | undefined;
nested = last?.data ?? nested;
if (!compactPlanningRequested()) return;
if (entries.some((entry: { type?: string; customType?: string }) => entry.type === "custom" && entry.customType === COMPACTED_STATE)) return;
compacting = true;
compactionDone = new Promise<void>((resolvePromise, reject) => {
ctx.compact({
onComplete: () => {
compacting = false;
pi.appendEntry(COMPACTED_STATE, { version: 1 });
resolvePromise();
},
onError: (error) => {
compacting = false;
reject(error);
},
});
});
});
pi.on("before_agent_start", async () => {
await compactionDone;
});
pi.on("tool_call", async (event) => {
@@ -68,6 +113,17 @@ export default function goalSupervisorRuntime(pi: ExtensionAPI): void {
return { block: true, reason: "The supervisor may inspect or control only its retained goal-worker." };
});
pi.registerTool({
name: "CheckWorkerState",
label: "Check retained worker",
description: "Return concise retained-worker state after a needs-attention notice or scheduled review. This does not return transcript text.",
parameters: Type.Object({}),
async execute() {
const state = nested.runId ? (nested.pending ? "active" : "terminal") : "not-started";
return result(`retained-worker=${state}${nested.runId ? `; run=${nested.runId}` : ""}`);
},
});
pi.registerTool({
name: "ApproveGoal",
label: "Approve goal",
+8 -6
View File
@@ -39,8 +39,9 @@ interface AsyncSnapshot {
export type WorkState = "active" | "idle" | "unknown";
export const supervisorSystemPrompt = `You are the retained goal supervisor. The main Pi session only coordinates with the human.
Launch one goal-worker, then rely on native progress and completion updates. Do not poll status, wait, or repeatedly
steer an active worker. Read the current plan, repository, cited evidence, and saved verification output yourself after
Your forked planning history is compacted before your first turn. Launch one goal-worker, then rely on native progress
and completion updates. Do not poll status, wait, or repeatedly steer an active worker. Use CheckWorkerState once only
after a needs-attention notice or a scheduled review. Read the current plan, repository, cited evidence, and saved verification output yourself after
the worker finishes. Do not edit project files. Use read/search and standard verification commands only. The worker must
commit its changes before approval. When no nested work is active, HEAD is committed, the worktree is clean, and the
evidence proves the discriminator, call ApproveGoal with the current approval ID. Otherwise give the retained worker
@@ -54,7 +55,7 @@ export function registerGoalSupervisor(events: EventBus, model: string | null):
definition: {
description: "Read-only supervisor that owns a nested retained implementation worker.",
systemPrompt: supervisorSystemPrompt,
tools: ["read", "grep", "find", "ls", "bash", "subagent", "ApproveGoal"],
tools: ["read", "grep", "find", "ls", "bash", "subagent", "CheckWorkerState", "ApproveGoal"],
allowNestedSubagents: true,
subagentOnlyExtensions: [supervisorRuntime],
...(model ? { model } : {}),
@@ -63,7 +64,7 @@ export function registerGoalSupervisor(events: EventBus, model: string | null):
inheritProjectContext: false,
inheritGlobalContext: false,
inheritSkills: false,
defaultContext: "fresh",
defaultContext: "fork",
defaultAsync: true,
defaultProgress: true,
},
@@ -112,14 +113,15 @@ function asyncRunId(data: RpcData): string {
return runId;
}
export async function startGoalSupervisor(events: EventBus, cwd: string, task: string, signal?: AbortSignal): Promise<string> {
export async function startGoalSupervisor(events: EventBus, cwd: string, task: string, compactPlanning: boolean, signal?: AbortSignal): Promise<string> {
const data = await rpc(events, "spawn", {
agent: SUPERVISOR_AGENT,
task,
cwd,
context: "fresh",
context: "fork",
async: true,
mission: false,
extensionBindings: { "pi-goals/1": { compactPlanning } },
}, signal);
return asyncRunId(data);
}