import { spawn as spawnChild } from "node:child_process"; import { createHash } from "node:crypto"; import { access, readFile } from "node:fs/promises"; import { constants } from "node:fs"; import { delimiter, isAbsolute, join, normalize, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import type { ExtensionContext } from "@earendil-works/pi-coding-agent"; import type { FleetAgentRecord, FleetWorkerDetails } from "../integration/fleet-view.js"; import { openLaunchPreview, type LaunchPreviewModelOptions, } from "../integration/launch-preview.js"; import { WorkerCompletionNotifier, type WorkerNotice, } from "../integration/worker-completion-notifier.js"; import { limited, UNLIMITED } from "../workflow/budget.js"; import { describeCurrentPiSessionFork } from "../workflow/pi-session-fork.js"; import { ensureRunArtifactDirectory, withRunArtifactContext, } from "../workflow/run-artifacts.js"; import { confirmCleanupDeletion, WorkflowRunCleanup, } from "../workflow/run-cleanup.js"; import { effectiveWorkerContract, WorkflowRunStore, } from "../workflow/run-store.js"; import { SystemProcessIdentityInspector } from "../workflow/system-process-inspector.js"; import { WorkflowDoctor } from "../workflow/workflow-doctor.js"; import { reportMatchesSchema } from "../workflow/worker-gate.js"; import { parseJsonCandidate } from "../workflow/json-candidate.js"; import { buildWorkerModelGuidance, floorAuditorModel, selectWorkerModel, type LiveWorkerModel, } from "../workflow/worker-model-catalog.js"; import { buildWorkerPrompt } from "../workflow/worker-prompt-capsule.js"; import { WorkerRolePresetCatalog, workerRoleContract, type WorkerRolePreset, } from "../workflow/worker-role-presets.js"; import { LaunchPreviewCoordinator, loadConfirmSpawnsPolicy, } from "../workflow/spawn-confirmation.js"; import { projectWorkerLifecycle, type WorkerLifecycleProjectionV1 } from "../workflow/lifecycle-projection.js"; import { NodePiProcessFactory, WorkerProcessSupervisor, } from "../workflow/worker-process-supervisor.js"; import { WorkflowLeaseManager, type ProcessIdentity, type ProcessIdentityInspector, type WorkflowLeaseOwnerV1, } from "../workflow/workflow-lease.js"; import type { BudgetLimit, RunProjectionV2, ModelSpec, WorkerContract, WorkerId, WorkerProjection, WorkerRequest, } from "../workflow/workflow-types.js"; import { defaultPiStateDirectory, workflowNamespaceDirectory, workflowWorkspaceId, } from "../workflow/workspace-paths.js"; import type { CancelWorkerToolParameters, CollectWorkerToolParameters, CleanupRunsToolParameters, ListWorkersToolParameters, ReviseContractToolParameters, SpawnWorkerToolParameters, SteerWorkerToolParameters, WorkerToolProvider, } from "./worker-tools.js"; const DRIVER_DOCTRINE = [ "## Supervised Workers (pi-amq)", "You are the driver: delegate bounded evidence-producing work, retain final synthesis and acceptance authority, and collect before concluding.", "Use spawn_worker/list_workers/collect/cancel/steer/revise_contract only. A collected candidate is not done until every declared Gate fact passes.", "Stall facts are observations only; never infer permission to nudge, retry, or cancel.", ].join("\n"); const CAPABILITY_TOOLS: Readonly> = { "repo.read": ["read", "grep", "find", "ls"], "repo.write": ["read", "grep", "find", "ls", "write", "edit"], shell: ["bash"], message_worker: ["message_worker"], }; const WORKER_RUNTIME_REGISTRY_SYMBOL = Symbol.for("pi-amq.worker-runtime-registry.v1"); interface WorkerRuntimeCoreV1 { readonly schema: 1; readonly key: string; readonly workspacePath: string; readonly workspaceId: string; readonly namespaceDirectory: string; readonly processIdentity: ProcessIdentity; readonly supervisorGeneration: string; readonly leaseManager: WorkflowLeaseManager; readonly store: WorkflowRunStore; readonly supervisor: WorkerProcessSupervisor; readonly cleanup: WorkflowRunCleanup; readonly doctor: WorkflowDoctor; readonly artifactDirectory: string; readonly requestKey: string; } interface WorkerRuntimeRegistryV1 { readonly schema: 1; readonly entries: Map; } interface WorkerRuntimeAttachment { readonly core: WorkerRuntimeCoreV1; readonly notifier: WorkerCompletionNotifier; active: boolean; unsubscribe: () => void; } export class PiWorkerRuntime implements WorkerToolProvider { readonly #publishFleet: (records: readonly FleetAgentRecord[]) => void; readonly #unlimitedDeclaration: () => unknown; readonly #publishLifecycle: (projection: WorkerLifecycleProjectionV1) => Promise; readonly #publishNotice: (notice: WorkerNotice) => void; readonly #launchPreview = new LaunchPreviewCoordinator(); readonly #previewAuditFloors = new Map(); readonly #lifecycleStates = new Map(); #cwd: string | undefined; #store: WorkflowRunStore | undefined; #supervisor: WorkerProcessSupervisor | undefined; #cleanup: WorkflowRunCleanup | undefined; #doctor: WorkflowDoctor | undefined; #artifactDirectory: string | undefined; #requestKey: string | undefined; #error: string | undefined; #guidance = DRIVER_DOCTRINE; #attachment: WorkerRuntimeAttachment | undefined; constructor( publishFleet: (records: readonly FleetAgentRecord[]) => void = () => {}, unlimitedDeclaration: () => unknown = () => undefined, publishLifecycle: (projection: WorkerLifecycleProjectionV1) => Promise = async () => {}, publishNotice: (notice: WorkerNotice) => void = () => {}, ) { this.#publishFleet = publishFleet; this.#unlimitedDeclaration = unlimitedDeclaration; this.#publishLifecycle = publishLifecycle; this.#publishNotice = publishNotice; } async start(ctx: ExtensionContext): Promise { this.#detach(); await this.refreshGuidance(ctx); try { const workspacePath = canonicalWorkerWorkspace(ctx.cwd); const workspaceId = workflowWorkspaceId(workspacePath); const namespaceDirectory = workflowNamespaceDirectory(defaultPiStateDirectory(), workspacePath); const key = workerRuntimeRegistryKey(namespaceDirectory, workspaceId); const registry = processWorkerRuntimeRegistry(); const inspector = new SystemProcessIdentityInspector(); const leaseManager = new WorkflowLeaseManager({ namespaceDirectory, workspaceId, inspector, }); const registered = registry.entries.get(key); if (registered !== undefined) { const existing = parseWorkerRuntimeCore(registered, key); await validateRuntimeAdoption(existing, { workspacePath, workspaceId, namespaceDirectory, inspector, leaseManager, }); existing.supervisor.updateLaunchAuthority(await launchAuthority(ctx)); const current = await requiredRun(existing.store, existing.requestKey); this.#attach(existing, current); this.#error = undefined; return; } const runBudget = await confirmedRunBudget(ctx, this.#unlimitedDeclaration()); const authority = await launchAuthority(ctx); const acquired = await leaseManager.acquireSupervisor(); if (acquired.kind !== "acquired") { throw new Error( acquired.kind === "held" ? `worker supervisor is held by PID ${acquired.owner.pid}; fully restart Pi without deleting the supervisor lease` : acquired.diagnostic, ); } const store = new WorkflowRunStore({ namespaceDirectory, leaseManager, supervisorGeneration: acquired.owner.generation, }); const sessionIdentity = ctx.sessionManager.getSessionFile() ?? `process:${process.pid}`; const requestKey = `pi-session:${hash(`${workspacePath}\0${sessionIdentity}`)}`; await store.startRun({ requestKey, source: { kind: "interactive", amqMessageId: null, driverSessionId: sessionIdentity, }, objective: { schema: 1, goal: "Supervise bounded workers for the current pi session", acceptance: ["Every accepted worker outcome passes its declared Gate facts"], constraints: ["Workers stay within explicit capability and workspace grants"], permissions: Object.keys(CAPABILITY_TOOLS), budget: runBudget, }, }); const artifactDirectory = await ensureRunArtifactDirectory(namespaceDirectory, requestKey); const supervisor = new WorkerProcessSupervisor({ namespaceDirectory, store, leaseManager, supervisorGeneration: acquired.owner.generation, inspector, processFactory: new NodePiProcessFactory(), launchAuthority: authority, }); const cleanup = new WorkflowRunCleanup({ namespaceDirectory, store, leaseManager, supervisorGeneration: acquired.owner.generation, }); const doctor = new WorkflowDoctor({ namespaceDirectory, runs: store, leases: leaseManager, inspector, }); const reconciled = await supervisor.reconcileRun(requestKey); const core: WorkerRuntimeCoreV1 = { schema: 1, key, workspacePath, workspaceId, namespaceDirectory, processIdentity: processIdentityFromOwner(acquired.owner), supervisorGeneration: acquired.owner.generation, leaseManager, store, supervisor, cleanup, doctor, artifactDirectory, requestKey, }; registry.entries.set(key, core); this.#attach(core, reconciled); this.#error = undefined; } catch (error) { this.#detach(); this.#error = toError(error).message; } } async shutdown(): Promise { // Workers own a parent-liveness descriptor. Session changes do not imply cancellation, // so only this extension instance's advisory subscribers are detached. The process-global // core and its supervisor lease remain intact for a replacement extension instance. this.#detach(); } async refreshGuidance(ctx: ExtensionContext): Promise { try { const current = currentLiveModel(ctx); if (!current) { this.#guidance = DRIVER_DOCTRINE; return; } const guidance = await buildWorkerModelGuidance({ available: availableLiveModels(ctx), current, globalNotesPath: join(defaultPiStateDirectory(), "pi-amq", "model-notes.md"), projectNotesPath: join(ctx.cwd, ".pi", "pi-amq", "model-notes.md"), projectTrusted: ctx.isProjectTrusted(), }); this.#guidance = `${DRIVER_DOCTRINE}\n\n${guidance.text}${ guidance.notices.length > 0 ? `\n${guidance.notices.join("\n")}` : "" }`; if (this.#cwd === canonicalWorkerWorkspace(ctx.cwd)) { this.#supervisor?.updateLaunchAuthority(await launchAuthority(ctx)); } } catch (error) { this.#guidance = `${DRIVER_DOCTRINE}\n\nWorker catalog unavailable: ${toError(error).message}`; } } appendGuidance(systemPrompt: string): string { return `${systemPrompt}\n\n${this.#guidance}`; } async spawn( params: SpawnWorkerToolParameters, signal: AbortSignal | undefined, ctx: ExtensionContext, ): Promise { const runtime = this.#required(); await this.refreshGuidance(ctx); const roles = await WorkerRolePresetCatalog.load({ projectDirectory: ctx.cwd, projectTrusted: ctx.isProjectTrusted(), }); const requestedRole = params.role ?? "worker"; const preset = roles.resolve(requestedRole); let auditFloor: LiveWorkerModel | undefined; if (requestedRole.trim().toLowerCase() === "auditor" && !params.audits_worker_id) { throw new Error("An auditor must name audits_worker_id"); } if (params.audits_worker_id) { const run = await requiredRun(runtime.store, runtime.requestKey); const audited = effectiveWorkerContract( requiredWorker(run, params.audits_worker_id as WorkerId), ).model; auditFloor = availableLiveModels(ctx).find( (model) => model.provider === audited.provider && model.id === audited.id, ); if (!auditFloor) throw new Error("Audited implementer model is not in the live catalog"); } const run = await requiredRun(runtime.store, runtime.requestKey); const request = withRunArtifactContext( this.#workerRequest(params, ctx, auditFloor, preset, run), runtime.artifactDirectory, ); const policy = await loadConfirmSpawnsPolicy({ projectDirectory: ctx.cwd, projectTrusted: ctx.isProjectTrusted(), }); if (auditFloor) this.#previewAuditFloors.set(request.requestKey, auditFloor); try { const gated = await this.#launchPreview.submit({ groupKey: `${ctx.cwd}\0${ctx.sessionManager.getSessionId()}`, policy, tui: ctx.mode === "tui" && ctx.hasUI, request, ...(signal ? { signal } : {}), preview: async (requests) => openLaunchPreview( ctx, this.#launchPreviewOptions(requests, roles, ctx), ), launch: async (accepted) => { const result = await runtime.supervisor.spawnWorker(runtime.requestKey, { request: accepted, prompt: buildWorkerPrompt(accepted), depth: 1, ...(params.continue_worker_id === undefined ? {} : { continueWorkerId: params.continue_worker_id as WorkerId }), }); const current = await requiredRun(runtime.store, runtime.requestKey); this.#publish(current); if (result.kind === "started") { void result.settlement.then((projection) => this.#publish(projection)).catch(() => {}); } return { kind: result.kind, worker: projectWorkerForTools(result.worker), attempt: result.attempt, }; }, }); return gated.kind === "cancelled" ? gated : gated.value; } finally { this.#previewAuditFloors.delete(request.requestKey); } } async list(params: ListWorkersToolParameters, _ctx: ExtensionContext): Promise { const runtime = this.#required(); let run = await runtime.store.readRun(runtime.requestKey); if (!run) throw new Error("Current worker run is missing"); for (const worker of Object.values(run.workers)) { if (isTerminal(worker.state) || worker.stall.silent.detected) continue; try { run = await runtime.store.recordSilentStall(runtime.requestKey, { workerId: worker.workerId }); } catch { // Silence has not crossed its budget-derived cadence. } } this.#publish(run); return Object.values(run.workers).slice(0, params.limit ?? 50).map(projectWorkerForTools); } async collect( params: CollectWorkerToolParameters, signal: AbortSignal | undefined, ctx: ExtensionContext, ): Promise { const runtime = this.#required(); const collected: unknown[] = []; for (const rawWorkerId of params.worker_ids) { if (signal?.aborted) throw signal.reason ?? new Error("collect aborted"); const workerId = rawWorkerId as WorkerId; let run = await requiredRun(runtime.store, runtime.requestKey); let worker = requiredWorker(run, workerId); const contract = effectiveWorkerContract(worker); const candidate = worker.attempts.at(-1)?.candidateOutcome.valueOrRef ?? null; const report = params.structured_reports?.[workerId] ?? parseJsonCandidate(candidate); if (report !== undefined) { run = await runtime.store.recordCollectObservation(runtime.requestKey, { workerId, structuredPayload: report, consecutiveRounds: 3, }); worker = requiredWorker(run, workerId); } const reportMatches = contract.report_schema ? reportMatchesSchema(contract.report_schema, report) : null; const acceptanceCheckExitCode = contract.acceptance_check ? await runAcceptanceCheck(contract, signal) : null; const humanApproved = contract.requires_human_approval === true ? await requestHumanApproval(ctx, worker) : null; run = await runtime.store.recordGateEvaluation(runtime.requestKey, { workerId, reportMatches, acceptanceCheckExitCode, humanApproved, evidenceExists: report !== undefined || candidate !== null, }); collected.push(projectWorkerForTools(requiredWorker(run, workerId))); this.#publish(run); } return collected; } async cancel( params: CancelWorkerToolParameters, _signal: AbortSignal | undefined, _ctx: ExtensionContext, ): Promise { const runtime = this.#required(); const result = await runtime.supervisor.cancelWorker(runtime.requestKey, { workerId: params.worker_id as WorkerId, reason: params.reason, }); this.#publish(result.projection); return result; } async steer( params: SteerWorkerToolParameters, _signal: AbortSignal | undefined, _ctx: ExtensionContext, ): Promise { const runtime = this.#required(); const projection = await runtime.supervisor.steerWorker(runtime.requestKey, { workerId: params.worker_id as WorkerId, message: params.message, ...(params.correlation === undefined ? {} : { correlation: params.correlation }), }); this.#publish(projection); return projectWorkerForTools(requiredWorker(projection, params.worker_id as WorkerId)); } async reviseContract( params: ReviseContractToolParameters, _signal: AbortSignal | undefined, _ctx: ExtensionContext, ): Promise { const runtime = this.#required(); const projection = await runtime.supervisor.reviseWorkerContract(runtime.requestKey, { workerId: params.worker_id as WorkerId, ...(params.correlation === undefined ? {} : { correlation: params.correlation }), ...(params.goal === undefined ? {} : { goal: params.goal }), ...(params.acceptance === undefined ? {} : { acceptance: params.acceptance }), ...(params.constraints === undefined ? {} : { constraints: params.constraints }), ...(params.report_schema === undefined ? {} : { report_schema: params.report_schema }), ...(params.report_schema_policy === undefined ? {} : { report_schema_policy: params.report_schema_policy }), ...(params.requires_human_approval === undefined ? {} : { requires_human_approval: params.requires_human_approval }), ...(params.acceptance_check === undefined ? {} : { acceptance_check: params.acceptance_check }), }); this.#publish(projection); return projectWorkerForTools(requiredWorker(projection, params.worker_id as WorkerId)); } async cleanupRuns( params: CleanupRunsToolParameters, _signal: AbortSignal | undefined, ctx: Pick, ): Promise { const runtime = this.#required(); const dryRun = params.dry_run !== false; if (dryRun) return runtime.cleanup.plan(params.older_than_ms); const confirmed = await confirmCleanupDeletion({ dryRun, yes: params.yes === true, tui: ctx.mode === "tui" && ctx.hasUI, ...(ctx.mode === "tui" && ctx.hasUI ? { confirm: () => ctx.ui.confirm( "Delete old pi-amq workflow runs?", "This permanently removes the listed terminal runs, worker session files, and artifacts.", ), } : {}), }); return runtime.cleanup.execute({ olderThanMs: params.older_than_ms, confirmed }); } async doctorWorkflow( _signal: AbortSignal | undefined, _ctx: Pick, ): Promise { return this.#required().doctor.inspect(); } async canReplaceSession(): Promise { if (!this.#store || !this.#requestKey) return true; try { const run = await requiredRun(this.#store, this.#requestKey); return canReplaceWorkerRun(run); } catch { return false; } } async steerFromFleet(workerId: string, generation: string, message: string): Promise { const runtime = this.#required(); const run = await requiredRun(runtime.store, runtime.requestKey); const worker = requiredWorker(run, workerId as WorkerId); const attempt = worker.attempts.at(-1); if (!attempt || attempt.workerAttemptGeneration !== generation) { throw new Error("Fleet steer refused: worker generation is stale"); } if (effectiveWorkerContract(worker).channel !== "rpc") { throw new Error("one-shot worker, cannot steer"); } const activeWait = worker.waits.filter((wait) => wait.status === "waiting" && wait.attemptId === attempt.attemptId && wait.workerAttemptGeneration === generation).at(-1); await runtime.supervisor.steerWorker(runtime.requestKey, { workerId: worker.workerId, message, ...(activeWait ? { correlation: activeWait.correlation } : {}), }); } async cancelFromFleet(workerId: string, generation: string): Promise { const runtime = this.#required(); const run = await requiredRun(runtime.store, runtime.requestKey); const worker = requiredWorker(run, workerId as WorkerId); const attempt = worker.attempts.at(-1); if (!attempt || attempt.workerAttemptGeneration !== generation) { throw new Error("Fleet cancel refused: worker generation is stale"); } await runtime.supervisor.cancelWorker(runtime.requestKey, { workerId: worker.workerId, reason: "operator requested stop from FleetView", }); } #workerRequest( params: SpawnWorkerToolParameters, ctx: ExtensionContext, auditFloor: LiveWorkerModel | undefined, preset: WorkerRolePreset, run: RunProjectionV2, ): WorkerRequest { if (params.context === "fork" && params.continue_worker_id !== undefined) { throw new TypeError("context=fork and continue_worker_id are mutually exclusive"); } const current = currentLiveModel(ctx); if (!current) throw new Error("Current pi model is unavailable"); const available = availableLiveModels(ctx); const scoped = scopedLiveModels(ctx); const difficulty = params.difficulty ?? preset.difficulty; let selected = params.model ? available.find((model) => model.provider === params.model?.provider && model.id === params.model.id) : selectWorkerModel({ difficulty, available, scoped, current, }).model; if (!selected) throw new Error(`Requested model is not in the live catalog`); if (auditFloor && preset.name === "reviewer") selected = floorAuditorModel(selected, auditFloor); const thinkingLevel = params.model?.thinking_level ?? selected.thinkingLevel ?? (selected.provider === current.provider && selected.id === current.id ? ctx.thinkingLevel : undefined) ?? (selected.reasoning ? "medium" : "off"); const modelFallbacks = (params.fallback_models ?? []).map((fallback): ModelSpec => { const live = available.find((model) => model.provider === fallback.provider && model.id === fallback.id); if (!live) throw new Error(`Fallback model is not in the live catalog: ${fallback.provider}/${fallback.id}`); return { provider: live.provider, id: live.id, thinkingLevel: fallback.thinking_level ?? live.thinkingLevel ?? (live.reasoning ? "medium" : "off"), }; }); const modelKeys = [ `${selected.provider}/${selected.id}`, ...modelFallbacks.map((model) => `${model.provider}/${model.id}`), ]; if (new Set(modelKeys).size !== modelKeys.length) { throw new TypeError("Primary and fallback model chain entries must be unique"); } const context = params.context ?? "fresh"; const budget = params.budget ?? defaultWorkerBudget(run); const forkSource = context === "fork" ? describeCurrentPiSessionFork(ctx.sessionManager) : undefined; return { schema: 1, requestKey: params.request_key, difficulty, role: workerRoleContract(preset), context, ...(forkSource ? { forkSource } : {}), goal: params.goal, acceptance: params.acceptance, constraints: params.constraints, budget: { maxAttempts: budget.max_attempts, maxWallClockMs: budget.max_wall_clock_ms, maxTokens: budget.max_tokens, maxCostUsd: budget.max_cost_usd, maxOutputBytes: budget.max_output_bytes, }, model: { provider: selected.provider, id: selected.id, thinkingLevel }, ...(modelFallbacks.length > 0 ? { modelFallbacks } : {}), capabilities: params.capabilities ?? preset.capabilities, workspace: { path: params.workspace.path, mode: params.workspace.mode, ...(params.workspace.worktree_path === undefined ? {} : { worktreePath: params.workspace.worktree_path }), }, contextRefs: params.context_refs, channel: params.channel, sideEffectPolicy: params.side_effect_policy, ...(params.report_schema === undefined ? {} : { report_schema: params.report_schema }), ...(params.report_schema_policy === undefined ? {} : { report_schema_policy: params.report_schema_policy }), ...(params.requires_human_approval === undefined ? {} : { requires_human_approval: params.requires_human_approval }), ...(params.acceptance_check === undefined ? {} : { acceptance_check: params.acceptance_check }), }; } #launchPreviewOptions( requests: readonly WorkerRequest[], roles: WorkerRolePresetCatalog, ctx: ExtensionContext, ): LaunchPreviewModelOptions { const current = currentLiveModel(ctx); if (!current) throw new Error("Current pi model is unavailable"); const available = availableLiveModels(ctx); const scoped = scopedLiveModels(ctx); const defaultFor = (difficulty: "easy" | "medium" | "hard"): ModelSpec => toModelSpec( selectWorkerModel({ difficulty, available, scoped, current }).model, ctx, ); const normalizeModel = (requestKey: string, roleName: string, model: ModelSpec): ModelSpec => { const auditFloor = this.#previewAuditFloors.get(requestKey); if (roleName !== "reviewer" || !auditFloor) return model; const selected = available.find( (candidate) => candidate.provider === model.provider && candidate.id === model.id, ); if (!selected) throw new Error("Preview model is not in the live catalog"); return toModelSpec(floorAuditorModel(selected, auditFloor), ctx); }; return { requests, roles: roles.presets().map((role) => ({ preset: role, defaultModel: defaultFor(role.difficulty), })), models: available.map((model) => toModelSpec(model, ctx)), difficultyModels: { easy: defaultFor("easy"), medium: defaultFor("medium"), hard: defaultFor("hard"), }, normalizeModel, }; } #required(): { readonly store: WorkflowRunStore; readonly supervisor: WorkerProcessSupervisor; readonly cleanup: WorkflowRunCleanup; readonly doctor: WorkflowDoctor; readonly artifactDirectory: string; readonly requestKey: string; } { if (!this.#store || !this.#supervisor || !this.#cleanup || !this.#doctor || !this.#artifactDirectory || !this.#requestKey) { throw new Error(`worker runtime is unavailable${this.#error ? `: ${this.#error}` : ""}`); } return { store: this.#store, supervisor: this.#supervisor, cleanup: this.#cleanup, doctor: this.#doctor, artifactDirectory: this.#artifactDirectory, requestKey: this.#requestKey, }; } #attach(core: WorkerRuntimeCoreV1, projection: RunProjectionV2): void { this.#detach(); this.#cwd = core.workspacePath; this.#store = core.store; this.#supervisor = core.supervisor; this.#cleanup = core.cleanup; this.#doctor = core.doctor; this.#artifactDirectory = core.artifactDirectory; this.#requestKey = core.requestKey; this.#lifecycleStates.clear(); this.#baselineLifecycle(projection); const notifier = new WorkerCompletionNotifier({ publish: this.#publishNotice }); notifier.baseline(projection); const attachment: WorkerRuntimeAttachment = { core, notifier, active: true, unsubscribe: () => {}, }; this.#attachment = attachment; attachment.unsubscribe = core.store.subscribe((run) => { if (!this.#isAttached(attachment)) return; this.#publish(run); void this.#publishWithConversation(run, attachment); void this.#publishLifecycleChanges(run, attachment).catch(() => {}); notifier.observe(run); }); this.#publish(projection); void this.#publishWithConversation(projection, attachment); } #detach(): void { const attachment = this.#attachment; this.#attachment = undefined; if (attachment) { attachment.active = false; attachment.unsubscribe(); attachment.notifier.dispose(); } this.#lifecycleStates.clear(); this.#cwd = undefined; this.#store = undefined; this.#supervisor = undefined; this.#cleanup = undefined; this.#doctor = undefined; this.#artifactDirectory = undefined; this.#requestKey = undefined; } #isAttached(attachment: WorkerRuntimeAttachment): boolean { return attachment.active && this.#attachment === attachment; } #publish(run: RunProjectionV2): void { this.#publishFleet(projectFleetRecords(run)); } async #publishWithConversation( run: RunProjectionV2, attachment: WorkerRuntimeAttachment, ): Promise { const records = await Promise.all(Object.values(run.workers).map(async (worker): Promise => { const attempt = worker.attempts.at(-1); const contract = effectiveWorkerContract(worker); const selectedModel = attempt?.modelSelection?.model ?? contract.model; const conversation = attempt?.session.file ? await readConversationTail(attempt.session.file) : []; return { id: worker.workerId, handle: worker.workerId, role: contract.role?.name ?? "worker", model: `${selectedModel.provider}/${selectedModel.id}`, state: fleetStateForWorker(worker), spend: attempt?.usage.costUsd ?? null, lastActivity: worker.lastLedgerAt, mode: contract.channel === "rpc" ? "rpc" : "json", ...(attempt ? { generation: attempt.workerAttemptGeneration } : {}), details: projectFleetWorkerDetails(worker), conversation: conversation.length > 0 ? conversation : ["No conversation projection available."], }; })); if (this.#isAttached(attachment) && attachment.core.requestKey === run.requestKey) { this.#publishFleet(records); } } #baselineLifecycle(run: RunProjectionV2): void { for (const worker of Object.values(run.workers)) { this.#lifecycleStates.set(`${run.requestKey}\0${worker.workerId}`, worker.state); } } async #publishLifecycleChanges( run: RunProjectionV2, attachment: WorkerRuntimeAttachment, ): Promise { for (const worker of Object.values(run.workers)) { if (!this.#isAttached(attachment)) return; const key = `${run.requestKey}\0${worker.workerId}`; if (this.#lifecycleStates.get(key) === worker.state) continue; this.#lifecycleStates.set(key, worker.state); if (!this.#isAttached(attachment)) return; await this.#publishLifecycle(projectWorkerLifecycle(worker.workerId, worker.state)).catch(() => {}); } } } function processWorkerRuntimeRegistry(): WorkerRuntimeRegistryV1 { const existing = Reflect.get(globalThis, WORKER_RUNTIME_REGISTRY_SYMBOL) as unknown; if (existing === undefined) { const created: WorkerRuntimeRegistryV1 = { schema: 1, entries: new Map() }; Reflect.set(globalThis, WORKER_RUNTIME_REGISTRY_SYMBOL, created); return created; } try { if (!isRecord(existing) || existing["schema"] !== 1 || !(existing["entries"] instanceof Map)) { throw new Error("registry envelope is invalid"); } const registry = existing as unknown as WorkerRuntimeRegistryV1; for (const [key, value] of registry.entries) { if (typeof key !== "string" || key.length === 0) throw new Error("registry key is invalid"); parseWorkerRuntimeCore(value, key); } return registry; } catch (error) { throw reloadAdoptionRefused(`process-global registry is corrupt: ${toError(error).message}`); } } function parseWorkerRuntimeCore(value: unknown, expectedKey: string): WorkerRuntimeCoreV1 { if (!isRecord(value) || value["schema"] !== 1) { throw reloadAdoptionRefused("process-global registry entry is corrupt"); } const core = value as unknown as WorkerRuntimeCoreV1; if (core.key !== expectedKey || !nonEmptyString(core.workspacePath) || !nonEmptyString(core.workspaceId) || !nonEmptyString(core.namespaceDirectory) || !nonEmptyString(core.supervisorGeneration) || !nonEmptyString(core.artifactDirectory) || !nonEmptyString(core.requestKey) || !runtimeProcessIdentity(core.processIdentity) || !hasMethods(core.leaseManager, ["inspectSupervisor"]) || !hasMethods(core.store, ["readRun", "subscribe"]) || !hasMethods(core.supervisor, ["updateLaunchAuthority", "steerWorker", "cancelWorker"]) || !hasMethods(core.cleanup, ["plan", "execute"]) || !hasMethods(core.doctor, ["inspect"])) { throw reloadAdoptionRefused("process-global registry entry is corrupt"); } return core; } async function validateRuntimeAdoption( core: WorkerRuntimeCoreV1, expected: { readonly workspacePath: string; readonly workspaceId: string; readonly namespaceDirectory: string; readonly inspector: ProcessIdentityInspector; readonly leaseManager: WorkflowLeaseManager; }, ): Promise { if (core.workspacePath !== expected.workspacePath || core.workspaceId !== expected.workspaceId || core.namespaceDirectory !== expected.namespaceDirectory || core.key !== workerRuntimeRegistryKey(expected.namespaceDirectory, expected.workspaceId)) { throw reloadAdoptionRefused("workspace or namespace identity changed"); } const current = await expected.inspector.current(); if (!sameProcessIdentity(core.processIdentity, current)) { throw reloadAdoptionRefused("process-start identity changed"); } const lease = await expected.leaseManager.inspectSupervisor(); if (lease.kind !== "owned") { throw reloadAdoptionRefused( lease.kind === "corrupt" ? `supervisor lease is corrupt: ${lease.diagnostic}` : "supervisor lease is missing", ); } if (lease.owner.kind !== "supervisor" || lease.owner.workspaceId !== expected.workspaceId || lease.owner.generation !== core.supervisorGeneration) { throw reloadAdoptionRefused("supervisor generation or workspace does not match the registry"); } const leaseIdentity = processIdentityFromOwner(lease.owner); if (!sameProcessIdentity(leaseIdentity, current) || !sameProcessIdentity(leaseIdentity, core.processIdentity)) { throw reloadAdoptionRefused("supervisor lease process identity does not match the registry"); } } function canonicalWorkerWorkspace(workspacePath: string): string { if (!isAbsolute(workspacePath)) throw new TypeError("Worker workspace must be absolute"); return normalize(resolve(workspacePath)); } function workerRuntimeRegistryKey(namespaceDirectory: string, workspaceId: string): string { return `${normalize(resolve(namespaceDirectory))}\0${workspaceId}`; } function processIdentityFromOwner(owner: WorkflowLeaseOwnerV1): ProcessIdentity { return { pid: owner.pid, processStartIdentity: owner.processStartIdentity, bootIdentity: owner.bootIdentity, executable: owner.executable, hostname: owner.hostname, }; } function sameProcessIdentity(left: ProcessIdentity, right: ProcessIdentity): boolean { return left.pid === right.pid && left.processStartIdentity === right.processStartIdentity && left.bootIdentity === right.bootIdentity && normalize(left.executable) === normalize(right.executable) && left.hostname === right.hostname; } function runtimeProcessIdentity(value: unknown): value is ProcessIdentity { return isRecord(value) && Number.isSafeInteger(value["pid"]) && (value["pid"] as number) > 0 && nonEmptyString(value["processStartIdentity"]) && (value["bootIdentity"] === null || nonEmptyString(value["bootIdentity"])) && nonEmptyString(value["executable"]) && isAbsolute(value["executable"] as string) && nonEmptyString(value["hostname"]); } function hasMethods(value: unknown, methods: readonly string[]): boolean { return isRecord(value) && methods.every((method) => typeof value[method] === "function"); } function nonEmptyString(value: unknown): value is string { return typeof value === "string" && value.length > 0; } function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null && !Array.isArray(value); } function reloadAdoptionRefused(reason: string): Error { return new Error( `worker runtime reload adoption refused: ${reason}; fully restart Pi without deleting the supervisor lease`, ); } export function projectFleetRecords(run: RunProjectionV2): readonly FleetAgentRecord[] { return Object.values(run.workers).map((worker): FleetAgentRecord => { const attempt = worker.attempts.at(-1); const contract = effectiveWorkerContract(worker); const selectedModel = attempt?.modelSelection?.model ?? contract.model; return { id: worker.workerId, handle: worker.workerId, role: contract.role?.name ?? "worker", model: `${selectedModel.provider}/${selectedModel.id}`, state: fleetStateForWorker(worker), spend: attempt?.usage.costUsd ?? null, lastActivity: worker.lastLedgerAt, mode: contract.channel === "rpc" ? "rpc" : "json", ...(attempt ? { generation: attempt.workerAttemptGeneration } : {}), details: projectFleetWorkerDetails(worker), conversation: ["Conversation projection pending."], }; }); } function projectFleetWorkerDetails( worker: RunProjectionV2["workers"][string], ): FleetWorkerDetails { const attempt = worker.attempts.at(-1); const activeWait = worker.waits.filter((wait) => wait.status === "waiting").at(-1); const awaitingReportReview = isAwaitingReportReview(worker); return { attemptState: attempt?.state ?? "none", tierDegraded: worker.attempts.some((candidate) => Boolean(candidate.modelSelection?.fallbackReason)), peerPending: worker.peerMessages.filter((message) => message.status === "pending").length, waitReason: activeWait?.reason ?? null, waitCorrelation: activeWait?.correlation ?? null, silentStall: worker.stall.silent.detected, noProgressStall: worker.stall.noProgress.detected, blockers: [...worker.gate.blockers], awaitingReportReview, }; } export function canReplaceWorkerRun(run: RunProjectionV2): boolean { if (run.state === "ambiguous" || run.state === "needs-attention") return false; return Object.values(run.workers).every((worker) => { const attempt = worker.attempts.at(-1); if (!attempt) return true; if (attempt.control.status === "detached" || attempt.sideEffects.status === "uncertain") { return false; } return isTerminal(worker.state); }); } async function readConversationTail(path: string): Promise { try { const raw = await readFile(path, "utf8"); const bounded = raw.slice(-128 * 1024); const lines: string[] = []; for (const line of bounded.split("\n").filter(Boolean).slice(-80)) { try { const value = JSON.parse(line) as Record; const message = value["message"]; if (typeof message !== "object" || message === null) continue; const role = (message as Record)["role"]; const content = (message as Record)["content"]; const text = typeof content === "string" ? content : Array.isArray(content) ? content.flatMap((part) => typeof part === "object" && part !== null && typeof (part as Record)["text"] === "string" ? [(part as Record)["text"] as string] : []).join(" ") : ""; if (text) lines.push(`${typeof role === "string" ? role : "message"}: ${text.slice(0, 2_000)}`); } catch { // Session tails may begin in the middle of a JSONL line. } } return lines.slice(-24); } catch { return []; } } const RUN_BUDGET_DIMENSIONS = [ "workers", "concurrency", "depth", "attempts", "wall-clock", "tokens", "cost", "output", ] as const; type RunBudgetDimension = (typeof RUN_BUDGET_DIMENSIONS)[number]; export function parseUnlimitedBudgetDimensions(value: unknown): readonly RunBudgetDimension[] { if (value === undefined || value === false || value === "") return []; if (typeof value !== "string") throw new TypeError("--worker-unlimited must be a comma-separated string"); const requested = value.split(",").map((item) => item.trim()).filter(Boolean); if (requested.includes("all")) { if (requested.length !== 1) throw new TypeError("--worker-unlimited=all cannot be combined with dimensions"); return RUN_BUDGET_DIMENSIONS; } const allowed = new Set(RUN_BUDGET_DIMENSIONS); for (const dimension of requested) { if (!allowed.has(dimension)) throw new TypeError(`Unknown unlimited budget dimension: ${dimension}`); } return [...new Set(requested)] as RunBudgetDimension[]; } export async function confirmedRunBudget( ctx: ExtensionContext, declaration: unknown, ): Promise { const unlimited = parseUnlimitedBudgetDimensions(declaration); if (unlimited.length > 0) { if (ctx.mode !== "tui" || !ctx.hasUI) { throw new Error("Unlimited worker budgets require explicit TUI confirmation before run creation"); } const confirmed = await ctx.ui.confirm( "Confirm unlimited worker budget", `Unlimited dimensions: ${unlimited.join(", ")}. Worker contracts must re-declare each dimension.`, ); if (!confirmed) throw new Error("Unlimited worker budget was not confirmed; no run was created"); } const selected = new Set(unlimited); const limit = (dimension: RunBudgetDimension, value: number) => selected.has(dimension) ? UNLIMITED : limited(value); return { maxWorkers: limit("workers", 8), maxConcurrency: limit("concurrency", 4), maxDepth: limit("depth", 3), maxAttempts: limit("attempts", 16), maxWallClockMs: limit("wall-clock", 3_600_000), maxTokens: limit("tokens", 500_000), maxCostUsd: limit("cost", 50), maxOutputBytes: limit("output", 67_108_864), }; } export function defaultWorkerBudget( run: RunProjectionV2, nowMs: number = Date.now(), ): NonNullable { const runWallClockMs = run.budget.limits.maxWallClockMs; const elapsedMs = Math.max(0, nowMs - Date.parse(run.createdAt)); const remainingWallClockMs = runWallClockMs.kind === "limited" ? limited(Math.max(1, runWallClockMs.value - elapsedMs)) : UNLIMITED; return { max_attempts: limited(16), max_wall_clock_ms: remainingWallClockMs, max_tokens: defaultAdditiveWorkerLimit(run.budget.remaining.tokens, 500_000, true), max_cost_usd: defaultAdditiveWorkerLimit(run.budget.remaining.costUsd, 50, false), max_output_bytes: defaultAdditiveWorkerLimit(run.budget.remaining.outputBytes, 67_108_864, true), }; } function defaultAdditiveWorkerLimit( remaining: BudgetLimit, unlimitedFallback: number, integer: boolean, ): BudgetLimit { if (remaining.kind === "unlimited") return limited(unlimitedFallback); return limited(integer ? Math.max(1, Math.floor(remaining.value)) : Math.max(Number.MIN_VALUE, remaining.value)); } async function launchAuthority(ctx: ExtensionContext) { const models = availablePiModels(ctx); return { piExecutable: await resolvePiExecutable(), childExtensionPath: await resolveChildExtensionPath(), grantedCapabilities: Object.keys(CAPABILITY_TOOLS), capabilityTools: CAPABILITY_TOOLS, availableModels: models.map((model) => { const defaultLevel = defaultThinkingLevel(model, ctx); const thinkingLevels = supportedThinkingLevels(model, defaultLevel); return { provider: model.provider, id: model.id, thinkingLevels, defaultThinkingLevel: defaultLevel, }; }), projectTrust: ctx.isProjectTrusted() ? "trusted" as const : "untrusted" as const, requiresProjectResources: true, inheritedEnvironment: process.env, }; } async function resolvePiExecutable(): Promise { const configured = process.env.PI_AMQ_PI_EXECUTABLE; if (configured !== undefined) { if (!isAbsolute(configured)) throw new Error("PI_AMQ_PI_EXECUTABLE must be absolute"); await access(configured, constants.X_OK); return configured; } const argvExecutable = process.argv[1]; if (argvExecutable && isAbsolute(argvExecutable)) { try { await access(argvExecutable, constants.X_OK); return argvExecutable; } catch {} } for (const directory of (process.env.PATH ?? "").split(delimiter)) { if (!directory) continue; const candidate = join(directory, "pi"); try { await access(candidate, constants.X_OK); return candidate; } catch {} } throw new Error("pi executable was not found; set PI_AMQ_PI_EXECUTABLE"); } async function resolveChildExtensionPath(): Promise { const candidates = [ fileURLToPath(new URL("../workflow/worker-child-extension.js", import.meta.url)), fileURLToPath(new URL("../workflow/worker-child-extension.ts", import.meta.url)), ]; for (const candidate of candidates) { try { await access(candidate, constants.R_OK); return candidate; } catch {} } throw new Error("worker child extension is missing from the package"); } interface PiModelLike { readonly provider: string; readonly id: string; readonly name: string; readonly reasoning: boolean; readonly contextWindow: number; readonly maxTokens: number; readonly cost: { readonly input: number; readonly output: number }; readonly thinkingLevelMap?: Readonly>; } function availablePiModels(ctx: ExtensionContext): readonly PiModelLike[] { return ctx.modelRegistry.getAvailable(); } function availableLiveModels(ctx: ExtensionContext): readonly LiveWorkerModel[] { return availablePiModels(ctx).map((model) => toLiveModel(model)); } function scopedLiveModels(ctx: ExtensionContext): readonly LiveWorkerModel[] { return ctx.scopedModels.map((scoped) => ({ ...toLiveModel(scoped.model), ...(scoped.thinkingLevel === undefined ? {} : { thinkingLevel: scoped.thinkingLevel }), })); } function currentLiveModel(ctx: ExtensionContext): LiveWorkerModel | undefined { return ctx.model ? { ...toLiveModel(ctx.model), ...(ctx.thinkingLevel === undefined ? {} : { thinkingLevel: ctx.thinkingLevel }), } : undefined; } function toLiveModel(model: PiModelLike): LiveWorkerModel { return { provider: model.provider, id: model.id, name: model.name, cost: model.cost.input + model.cost.output, contextWindow: model.contextWindow, maxTokens: model.maxTokens, reasoning: model.reasoning, }; } function supportedThinkingLevels(model: PiModelLike, defaultLevel: string): readonly string[] { const levels = ["off", "minimal", "low", "medium", "high", "xhigh"] .filter((level) => model.thinkingLevelMap?.[level] !== null); return levels.includes(defaultLevel) ? levels : [...levels, defaultLevel]; } function defaultThinkingLevel(model: PiModelLike, ctx: ExtensionContext): string { if (ctx.model?.provider === model.provider && ctx.model.id === model.id && ctx.thinkingLevel) { return ctx.thinkingLevel; } const scoped = ctx.scopedModels.find( (candidate) => candidate.model.provider === model.provider && candidate.model.id === model.id, ); return scoped?.thinkingLevel ?? (model.reasoning ? "medium" : "off"); } function toModelSpec(model: LiveWorkerModel, ctx: ExtensionContext): ModelSpec { const catalogModel = availablePiModels(ctx).find( (candidate) => candidate.provider === model.provider && candidate.id === model.id, ); if (!catalogModel) throw new Error("Preview model is not in the live catalog"); return { provider: model.provider, id: model.id, thinkingLevel: model.thinkingLevel ?? defaultThinkingLevel(catalogModel, ctx), }; } async function runAcceptanceCheck( contract: WorkerContract, signal: AbortSignal | undefined, ): Promise { const check = contract.acceptance_check; if (!check) return null; if (signal?.aborted) throw signal.reason ?? new Error("acceptance check aborted"); return new Promise((resolve, reject) => { const child = spawnChild(check.command, [...check.args], { cwd: contract.workspace.worktreePath ?? contract.workspace.path, shell: false, stdio: "ignore", }); const onAbort = (): void => { child.kill("SIGTERM"); }; signal?.addEventListener("abort", onAbort, { once: true }); child.once("error", (error) => { signal?.removeEventListener("abort", onAbort); reject(error); }); child.once("exit", (code) => { signal?.removeEventListener("abort", onAbort); resolve(code); }); }); } async function requestHumanApproval( ctx: ExtensionContext, worker: ReturnType, ): Promise { if (ctx.mode !== "tui" || !ctx.hasUI) return null; return ctx.ui.confirm( "Accept worker outcome?", `${worker.workerId}: ${effectiveWorkerContract(worker).goal}`, ); } export function projectWorkerForTools(worker: WorkerProjection): unknown { const attempt = worker.attempts.at(-1); const contract = effectiveWorkerContract(worker); return { worker_id: worker.workerId, role: contract.role ? { name: contract.role.name, tier: contract.role.tier, preset_source: contract.role.presetSource, } : null, proposal: contract.proposal ?? null, context: contract.context, fork_source: contract.forkSource ?? null, attempted_models: worker.attempts.map((candidate) => ({ model: candidate.modelSelection?.model ?? candidate.launchContract?.model ?? contract.model, fallback_reason: candidate.modelSelection?.fallbackReason ?? null, })), tier_degraded: worker.attempts.some((candidate) => candidate.modelSelection?.fallbackReason), peer_messages: worker.peerMessages, waits: worker.waits, continuation: worker.continuation, context_refs: contract.contextRefs, state: worker.state, attempt: attempt ? { attempt_id: attempt.attemptId, state: attempt.state, candidate: attempt.candidateOutcome, usage: attempt.usage, side_effects: attempt.sideEffects, } : null, gate: worker.gate, stall: worker.stall, contract_revisions: worker.contractRevisions.map((revision) => ({ revision_id: revision.revisionId, revision: revision.revision, status: revision.status, correlation: revision.correlation, requested_at: revision.requestedAt, delivered_at: revision.deliveredAt, })), }; } function requiredWorker(run: RunProjectionV2, workerId: WorkerId) { const worker = run.workers[workerId]; if (!worker) throw new Error(`Unknown worker ${workerId}`); return worker; } async function requiredRun(store: WorkflowRunStore, requestKey: string): Promise { const run = await store.readRun(requestKey); if (!run) throw new Error(`Unknown run ${requestKey}`); return run; } function isTerminal(state: string): boolean { return state === "done" || state === "failed" || state === "cancelled"; } function fleetStateForWorker(worker: RunProjectionV2["workers"][string]): FleetAgentRecord["state"] { if (isAwaitingReportReview(worker)) return "review"; return fleetState(worker.state); } function isAwaitingReportReview(worker: RunProjectionV2["workers"][string]): boolean { const attempt = worker.attempts.at(-1); if (!attempt || attempt.state !== "running" || attempt.pidStartEvidence?.observedExitAt == null) return false; const hasCandidate = attempt.candidateOutcome.valueOrRef !== null || attempt.candidateOutcome.hash !== null; return hasCandidate && worker.gate.blockers.includes("report.matches(report_schema)"); } function fleetState(state: string): FleetAgentRecord["state"] { switch (state) { case "pending": return "idle"; case "running": return "busy"; case "blocked": return "paused"; case "ambiguous": return "ambiguous"; case "done": return "done"; case "failed": return "failed"; case "cancelled": return "cancelled"; default: return "ambiguous"; } } function hash(value: string): string { return createHash("sha256").update(value).digest("hex"); } function toError(error: unknown): Error { return error instanceof Error ? error : new Error(String(error)); }