{"version":3,"file":"loop-CocC9qO1.mjs","names":["writeJson"],"sources":["../../core/src/lease.ts","../../core/src/metrics.ts","../../core/src/controller.ts","../../core/src/loop.ts"],"sourcesContent":["import { mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\"\nimport { homedir, hostname } from \"node:os\"\nimport { join } from \"node:path\"\n\ninterface LeaseData {\n\trunId: string\n\trepoId: string\n\tbranch: string\n\tpid: number\n\thostname: string\n\tstartedAt: string\n}\n\nfunction sanitize(value: string): string {\n\treturn value.replace(/[^a-zA-Z0-9._-]+/g, \"_\")\n}\n\nfunction processAlive(pid: number): boolean {\n\tif (!Number.isFinite(pid) || pid <= 0) return false\n\ttry {\n\t\tprocess.kill(pid, 0)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\nexport function acquireRepoLease(runId: string, repoId: string, branch: string): { path: string; release: () => void } {\n\tconst locksDir = join(homedir(), \".pi-town\", \"locks\")\n\tmkdirSync(locksDir, { recursive: true })\n\n\tconst leasePath = join(locksDir, `pi-town-${sanitize(repoId)}-${sanitize(branch)}.json`)\n\tconst nextData: LeaseData = {\n\t\trunId,\n\t\trepoId,\n\t\tbranch,\n\t\tpid: process.pid,\n\t\thostname: hostname(),\n\t\tstartedAt: new Date().toISOString(),\n\t}\n\n\ttry {\n\t\tconst current = JSON.parse(readFileSync(leasePath, \"utf-8\")) as LeaseData\n\t\tif (processAlive(current.pid)) {\n\t\t\tthrow new Error(`Pi Town lease already held by pid ${current.pid} on ${current.hostname} for run ${current.runId}.`)\n\t\t}\n\t\trmSync(leasePath, { force: true })\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n\t\t\tif (error instanceof Error && error.message.startsWith(\"Pi Town lease already held\")) throw error\n\t\t}\n\t}\n\n\twriteFileSync(leasePath, `${JSON.stringify(nextData, null, 2)}\\n`, \"utf-8\")\n\n\treturn {\n\t\tpath: leasePath,\n\t\trelease: () => {\n\t\t\ttry {\n\t\t\t\tconst current = JSON.parse(readFileSync(leasePath, \"utf-8\")) as LeaseData\n\t\t\t\tif (current.runId === runId) rmSync(leasePath, { force: true })\n\t\t\t} catch {\n\t\t\t\t// ignore cleanup failures\n\t\t\t}\n\t\t},\n\t}\n}\n","import type { FeedbackCycle, InterruptRecord, MetricsSnapshot, TaskAttempt } from \"./types.js\"\n\nfunction round(value: number): number {\n\treturn Math.round(value * 1000) / 1000\n}\n\nfunction diffHours(start: string, end: string): number {\n\treturn (Date.parse(end) - Date.parse(start)) / 3_600_000\n}\n\nfunction average(values: number[]): number | null {\n\tif (values.length === 0) return null\n\treturn values.reduce((sum, value) => sum + value, 0) / values.length\n}\n\nexport function computeInterruptRate(interrupts: InterruptRecord[], taskAttempts: TaskAttempt[]): number {\n\tif (taskAttempts.length === 0) return 0\n\treturn round(interrupts.length / taskAttempts.length)\n}\n\nexport function computeAutonomousCompletionRate(taskAttempts: TaskAttempt[]): number {\n\tconst completed = taskAttempts.filter((task) => task.status === \"completed\")\n\tif (completed.length === 0) return 0\n\tconst autonomous = completed.filter((task) => !task.interrupted)\n\treturn round(autonomous.length / completed.length)\n}\n\nexport function computeContextCoverageScore(interrupts: InterruptRecord[]): number {\n\tconst observed = new Set(interrupts.map((interrupt) => interrupt.category))\n\tif (observed.size === 0) return 0\n\n\tconst covered = new Set(\n\t\tinterrupts.filter((interrupt) => interrupt.fixType).map((interrupt) => interrupt.category),\n\t)\n\n\treturn round(covered.size / observed.size)\n}\n\nexport function computeMeanTimeToCorrect(interrupts: InterruptRecord[]): number | null {\n\tconst resolved = interrupts.filter((interrupt) => interrupt.resolvedAt)\n\tconst hours = resolved.map((interrupt) => diffHours(interrupt.createdAt, interrupt.resolvedAt!))\n\tconst value = average(hours)\n\treturn value === null ? null : round(value)\n}\n\nexport function computeFeedbackToDemoCycleTime(feedbackCycles: FeedbackCycle[]): number | null {\n\tconst hours = feedbackCycles.map((cycle) => diffHours(cycle.feedbackAt, cycle.demoReadyAt))\n\tconst value = average(hours)\n\treturn value === null ? null : round(value)\n}\n\nexport function computeMetrics(input: {\n\ttaskAttempts: TaskAttempt[]\n\tinterrupts: InterruptRecord[]\n\tfeedbackCycles?: FeedbackCycle[]\n}): MetricsSnapshot {\n\tconst observedCategories = new Set(input.interrupts.map((interrupt) => interrupt.category))\n\tconst coveredCategories = new Set(\n\t\tinput.interrupts.filter((interrupt) => interrupt.fixType).map((interrupt) => interrupt.category),\n\t)\n\tconst completedTasks = input.taskAttempts.filter((task) => task.status === \"completed\").length\n\n\treturn {\n\t\tinterruptRate: computeInterruptRate(input.interrupts, input.taskAttempts),\n\t\tautonomousCompletionRate: computeAutonomousCompletionRate(input.taskAttempts),\n\t\tcontextCoverageScore: computeContextCoverageScore(input.interrupts),\n\t\tmeanTimeToCorrectHours: computeMeanTimeToCorrect(input.interrupts),\n\t\tfeedbackToDemoCycleTimeHours: computeFeedbackToDemoCycleTime(input.feedbackCycles ?? []),\n\t\ttotals: {\n\t\t\ttaskAttempts: input.taskAttempts.length,\n\t\t\tcompletedTasks,\n\t\t\tinterrupts: input.interrupts.length,\n\t\t\tobservedInterruptCategories: observedCategories.size,\n\t\t\tcoveredInterruptCategories: coveredCategories.size,\n\t\t},\n\t}\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport {\n\tcreateAgentSessionRecord,\n\tcreateAgentState,\n\tgetAgentSessionsDir,\n\tgetLatestAgentSession,\n\treadAgentState,\n\twriteAgentState,\n} from \"./agents.js\"\nimport { appendJsonl } from \"./events.js\"\nimport { acquireRepoLease } from \"./lease.js\"\nimport { computeMetrics } from \"./metrics.js\"\nimport { createPiAuthHelpMessage, detectPiAuthFailure } from \"./pi.js\"\nimport { createRepoSlug, getCurrentBranch, getRepoIdentity, getRepoRoot } from \"./repo.js\"\nimport { assertCommandAvailable, runCommandSync } from \"./shell.js\"\nimport type { ControllerRunResult, PiInvocationRecord, RunManifest, RunOptions, RunSummary } from \"./types.js\"\n\nfunction createRunId(): string {\n\treturn `run-${new Date().toISOString().replace(/[:.]/g, \"-\")}`\n}\n\nfunction createPiInvocationArgs(input: {\n\tsessionDir?: string | null\n\tsessionPath?: string | null\n\tprompt: string\n\tappendedSystemPrompt?: string | null | undefined\n\textensionPath?: string | null | undefined\n}) {\n\tconst args: string[] = []\n\n\tif (input.extensionPath) args.push(\"--extension\", input.extensionPath)\n\tif (input.appendedSystemPrompt) args.push(\"--append-system-prompt\", input.appendedSystemPrompt)\n\tif (input.sessionPath) args.push(\"--session\", input.sessionPath)\n\telse if (input.sessionDir) args.push(\"--session-dir\", input.sessionDir)\n\telse throw new Error(\"Pi invocation requires a session path or session directory\")\n\targs.push(\"-p\", input.prompt)\n\n\treturn args\n}\n\nfunction writeJson(path: string, value: unknown) {\n\twriteFileSync(path, `${JSON.stringify(value, null, 2)}\\n`, \"utf-8\")\n}\n\nfunction writeText(path: string, value: string) {\n\twriteFileSync(path, value, \"utf-8\")\n}\n\nfunction createPiPrompt(input: {\n\trepoRoot: string\n\tplanPath: string | null\n\tgoal: string | null\n\trecommendedPlanDir: string | null\n}): string {\n\tconst goal = input.goal ?? \"continue from current scaffold state\"\n\n\tif (input.planPath) {\n\t\treturn [\n\t\t\t\"You are the Pi Town mayor agent for this repository.\",\n\t\t\t\"Coordinate the next bounded unit of work, keep updates concise, and leave a durable artifact trail.\",\n\t\t\t\"\",\n\t\t\t\"Read the private plans in:\",\n\t\t\t`- ${input.planPath}`,\n\t\t\t\"\",\n\t\t\t\"and the current code in:\",\n\t\t\t`- ${input.repoRoot}`,\n\t\t\t\"\",\n\t\t\t`Goal: ${goal}`,\n\t\t\t\"Continue from the current scaffold state.\",\n\t\t\t\"Keep any persisted run artifacts high-signal and avoid copying private plan contents into them.\",\n\t\t].join(\"\\n\")\n\t}\n\n\treturn [\n\t\t\"You are the Pi Town mayor agent for this repository.\",\n\t\t\"Coordinate the next bounded unit of work, keep updates concise, and leave a durable artifact trail.\",\n\t\t\"\",\n\t\t`Work in the repository at: ${input.repoRoot}`,\n\t\t`Goal: ${goal}`,\n\t\t\"No private plan path is configured for this run.\",\n\t\tinput.recommendedPlanDir\n\t\t\t? `If you need private plans, use a user-owned location such as: ${input.recommendedPlanDir}`\n\t\t\t: \"If you need private plans, keep them in a user-owned location outside the repo.\",\n\t\t\"Continue from the current scaffold state.\",\n\t].join(\"\\n\")\n}\n\nfunction assertPiRuntimeAvailable(piCommand: string) {\n\ttry {\n\t\tassertCommandAvailable(piCommand)\n\t} catch (error) {\n\t\tif (piCommand === \"pi\") {\n\t\t\tthrow new Error(\n\t\t\t\t[\n\t\t\t\t\t\"Pi Town requires the `pi` CLI to run `pitown run`.\",\n\t\t\t\t\t\"Install Pi: npm install -g @mariozechner/pi-coding-agent\",\n\t\t\t\t\t\"Then authenticate Pi and verify it works: pi -p \\\"hello\\\"\",\n\t\t\t\t\t`Details: ${(error as Error).message}`,\n\t\t\t\t].join(\"\\n\"),\n\t\t\t)\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t[\n\t\t\t\t`Pi Town could not execute the configured Pi command: ${piCommand}`,\n\t\t\t\t\"Make sure the command exists on PATH or points to an executable file.\",\n\t\t\t\t`Details: ${(error as Error).message}`,\n\t\t\t].join(\"\\n\"),\n\t\t)\n\t}\n}\n\nfunction createManifest(input: {\n\trunId: string\n\trepoId: string\n\trepoSlug: string\n\trepoRoot: string\n\tbranch: string\n\tgoal: string | null\n\tplanPath: string | null\n\trecommendedPlanDir: string | null\n\tmode: \"single-pi\"\n\tleasePath: string\n}): RunManifest {\n\treturn {\n\t\trunId: input.runId,\n\t\trepoId: input.repoId,\n\t\trepoSlug: input.repoSlug,\n\t\trepoRoot: input.repoRoot,\n\t\tbranch: input.branch,\n\t\tgoal: input.goal,\n\t\tplanPath: input.planPath,\n\t\trecommendedPlanDir: input.recommendedPlanDir,\n\t\tmode: input.mode,\n\t\tstartedAt: new Date().toISOString(),\n\t\tendedAt: null,\n\t\tstopReason: null,\n\t\tleasePath: input.leasePath,\n\t\tpiExitCode: null,\n\t\tcompletedTaskCount: 0,\n\t\tblockedTaskCount: 0,\n\t\tskippedTaskCount: 0,\n\t\ttotalCostUsd: 0,\n\t}\n}\n\nfunction createSummary(input: {\n\trunId: string\n\tmode: \"single-pi\"\n\texitCode: number\n\tstdout: string\n\tstderr: string\n\trecommendedPlanDir: string | null\n}): RunSummary {\n\tconst success = input.exitCode === 0\n\tconst recommendation =\n\t\tinput.recommendedPlanDir === null\n\t\t\t? \"\"\n\t\t\t: ` No plan path was configured. Recommended private plans location: ${input.recommendedPlanDir}.`\n\tconst authHelp =\n\t\tsuccess || !detectPiAuthFailure(input.stderr, input.stdout) ? \"\" : ` ${createPiAuthHelpMessage()}`\n\n\treturn {\n\t\trunId: input.runId,\n\t\tmode: input.mode,\n\t\tcreatedAt: new Date().toISOString(),\n\t\tsuccess,\n\t\tmessage: success\n\t\t\t? `Pi invocation completed.${recommendation}`\n\t\t\t: `Pi invocation failed.${authHelp}${recommendation}`,\n\t\tpiExitCode: input.exitCode,\n\t\trecommendedPlanDir: input.recommendedPlanDir,\n\t}\n}\n\nexport function runController(options: RunOptions): ControllerRunResult {\n\tconst cwd = options.cwd ?? process.cwd()\n\tconst artifactsDir = options.artifactsDir\n\tconst repoRoot = getRepoRoot(cwd)\n\tconst repoId = getRepoIdentity(repoRoot)\n\tconst repoSlug = createRepoSlug(repoId, repoRoot)\n\tconst branch = options.branch ?? getCurrentBranch(repoRoot) ?? \"workspace\"\n\tconst goal = options.goal ?? null\n\tconst planPath = options.planPath ?? null\n\tconst recommendedPlanDir = planPath ? null : (options.recommendedPlanDir ?? null)\n\tconst mode = options.mode ?? \"single-pi\"\n\tconst piCommand = options.piCommand ?? \"pi\"\n\tconst runId = createRunId()\n\tconst runDir = join(artifactsDir, \"runs\", runId)\n\tconst latestDir = join(artifactsDir, \"latest\")\n\tconst stdoutPath = join(runDir, \"stdout.txt\")\n\tconst stderrPath = join(runDir, \"stderr.txt\")\n\tconst prompt = createPiPrompt({ repoRoot, planPath, goal, recommendedPlanDir })\n\tconst existingMayorState = readAgentState(artifactsDir, \"mayor\")\n\tconst existingMayorSession =\n\t\texistingMayorState?.session.sessionPath || existingMayorState?.session.sessionDir\n\t\t\t? existingMayorState.session\n\t\t\t: getLatestAgentSession(artifactsDir, \"mayor\")\n\tconst mayorSessionDir = existingMayorSession.sessionDir ?? getAgentSessionsDir(artifactsDir, \"mayor\")\n\tconst mayorState = createAgentState({\n\t\tagentId: \"mayor\",\n\t\trole: \"mayor\",\n\t\tstatus: \"starting\",\n\t\ttask: goal,\n\t\tbranch,\n\t\tlastMessage: goal ? `Starting mayor run for goal: ${goal}` : \"Starting mayor run\",\n\t\trunId,\n\t\tsession: createAgentSessionRecord({\n\t\t\tsessionDir: mayorSessionDir,\n\t\t\tsessionId: existingMayorSession.sessionId,\n\t\t\tsessionPath: existingMayorSession.sessionPath,\n\t\t}),\n\t})\n\n\tassertPiRuntimeAvailable(piCommand)\n\n\tmkdirSync(runDir, { recursive: true })\n\tmkdirSync(latestDir, { recursive: true })\n\n\twriteText(join(runDir, \"questions.jsonl\"), \"\")\n\twriteText(join(runDir, \"interventions.jsonl\"), \"\")\n\twriteJson(join(runDir, \"agent-state.json\"), {\n\t\tstatus: \"starting\",\n\t\tupdatedAt: new Date().toISOString(),\n\t})\n\twriteAgentState(artifactsDir, mayorState)\n\n\tconst lease = acquireRepoLease(runId, repoId, branch)\n\n\ttry {\n\t\tconst manifest = createManifest({\n\t\t\trunId,\n\t\t\trepoId,\n\t\t\trepoSlug,\n\t\t\trepoRoot,\n\t\t\tbranch,\n\t\t\tgoal,\n\t\t\tplanPath,\n\t\t\trecommendedPlanDir,\n\t\t\tmode,\n\t\t\tleasePath: lease.path,\n\t\t})\n\n\t\tappendJsonl(join(runDir, \"events.jsonl\"), {\n\t\t\ttype: \"run_started\",\n\t\t\trunId,\n\t\t\trepoId,\n\t\t\trepoSlug,\n\t\t\tbranch,\n\t\t\tcreatedAt: manifest.startedAt,\n\t\t})\n\n\t\tconst piStartedAt = new Date().toISOString()\n\t\tappendJsonl(join(runDir, \"events.jsonl\"), {\n\t\t\ttype: \"pi_invocation_started\",\n\t\t\trunId,\n\t\t\tcommand: piCommand,\n\t\t\tcreatedAt: piStartedAt,\n\t\t})\n\n\t\twriteAgentState(\n\t\t\tartifactsDir,\n\t\t\tcreateAgentState({\n\t\t\t\t...mayorState,\n\t\t\t\tstatus: \"running\",\n\t\t\t\tlastMessage: goal ? `Mayor working on: ${goal}` : \"Mayor working\",\n\t\t\t}),\n\t\t)\n\n\t\tconst piArgs = createPiInvocationArgs({\n\t\t\tsessionDir: mayorState.session.sessionPath === null ? mayorSessionDir : null,\n\t\t\tsessionPath: mayorState.session.sessionPath,\n\t\t\tprompt,\n\t\t\tappendedSystemPrompt: options.appendedSystemPrompt,\n\t\t\textensionPath: options.extensionPath,\n\t\t})\n\t\tconst piResult = runCommandSync(piCommand, piArgs, {\n\t\t\tcwd: repoRoot,\n\t\t\tenv: process.env,\n\t\t})\n\t\tconst piEndedAt = new Date().toISOString()\n\t\tconst latestMayorSession = getLatestAgentSession(artifactsDir, \"mayor\")\n\n\t\twriteText(stdoutPath, piResult.stdout)\n\t\twriteText(stderrPath, piResult.stderr)\n\n\t\tconst piInvocation: PiInvocationRecord = {\n\t\t\tcommand: piCommand,\n\t\t\tcwd: repoRoot,\n\t\t\trepoRoot,\n\t\t\tplanPath,\n\t\t\tgoal,\n\t\t\tsessionDir: latestMayorSession.sessionDir,\n\t\t\tsessionId: latestMayorSession.sessionId,\n\t\t\tsessionPath: latestMayorSession.sessionPath,\n\t\t\tstartedAt: piStartedAt,\n\t\t\tendedAt: piEndedAt,\n\t\t\texitCode: piResult.exitCode,\n\t\t\tstdoutPath,\n\t\t\tstderrPath,\n\t\t\tpromptSummary: planPath\n\t\t\t\t? \"Read private plan path and continue from current scaffold state.\"\n\t\t\t\t: \"Continue from current scaffold state without a configured private plan path.\",\n\t\t}\n\t\twriteJson(join(runDir, \"pi-invocation.json\"), piInvocation)\n\n\t\tappendJsonl(join(runDir, \"events.jsonl\"), {\n\t\t\ttype: \"pi_invocation_finished\",\n\t\t\trunId,\n\t\t\tcommand: piCommand,\n\t\t\texitCode: piInvocation.exitCode,\n\t\t\tcreatedAt: piEndedAt,\n\t\t})\n\n\t\tconst metrics = computeMetrics({\n\t\t\ttaskAttempts: [],\n\t\t\tinterrupts: [],\n\t\t})\n\t\tconst summary = createSummary({\n\t\t\trunId,\n\t\t\tmode,\n\t\t\texitCode: piInvocation.exitCode,\n\t\t\tstdout: piResult.stdout,\n\t\t\tstderr: piResult.stderr,\n\t\t\trecommendedPlanDir,\n\t\t})\n\t\tconst finalManifest: RunManifest = {\n\t\t\t...manifest,\n\t\t\tendedAt: piEndedAt,\n\t\t\tstopReason:\n\t\t\t\tpiInvocation.exitCode === 0\n\t\t\t\t\t? \"pi invocation completed\"\n\t\t\t\t\t: `pi invocation exited with code ${piInvocation.exitCode}`,\n\t\t\tpiExitCode: piInvocation.exitCode,\n\t\t}\n\n\t\twriteJson(join(runDir, \"manifest.json\"), finalManifest)\n\t\twriteJson(join(runDir, \"metrics.json\"), metrics)\n\t\twriteJson(join(runDir, \"run-summary.json\"), summary)\n\t\twriteJson(join(runDir, \"agent-state.json\"), {\n\t\t\tstatus: summary.success ? \"completed\" : \"failed\",\n\t\t\tupdatedAt: piEndedAt,\n\t\t\texitCode: piInvocation.exitCode,\n\t\t})\n\t\twriteJson(join(latestDir, \"manifest.json\"), finalManifest)\n\t\twriteJson(join(latestDir, \"metrics.json\"), metrics)\n\t\twriteJson(join(latestDir, \"run-summary.json\"), summary)\n\t\twriteAgentState(\n\t\t\tartifactsDir,\n\t\t\tcreateAgentState({\n\t\t\t\t...mayorState,\n\t\t\t\t\tstatus: piInvocation.exitCode === 0 ? \"idle\" : \"blocked\",\n\t\t\t\t\tlastMessage:\n\t\t\t\t\t\tpiInvocation.exitCode === 0\n\t\t\t\t\t\t\t? \"Mayor run completed and is ready for the next instruction\"\n\t\t\t\t\t\t\t: `Mayor run stopped with exit code ${piInvocation.exitCode}`,\n\t\t\t\t\tblocked: piInvocation.exitCode !== 0,\n\t\t\t\t\twaitingOn: piInvocation.exitCode === 0 ? null : \"human-or-follow-up-run\",\n\t\t\t\t\tsession: createAgentSessionRecord({\n\t\t\t\t\t\tsessionDir: latestMayorSession.sessionDir,\n\t\t\t\t\t\tsessionId: latestMayorSession.sessionId,\n\t\t\t\t\t\tsessionPath: latestMayorSession.sessionPath,\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t)\n\n\t\tappendJsonl(join(runDir, \"events.jsonl\"), {\n\t\t\ttype: \"run_finished\",\n\t\t\trunId,\n\t\t\tcreatedAt: finalManifest.endedAt,\n\t\t\tstopReason: finalManifest.stopReason,\n\t\t\tmetrics,\n\t\t})\n\n\t\treturn {\n\t\t\trunId,\n\t\t\trunDir,\n\t\t\tlatestDir,\n\t\t\tmanifest: finalManifest,\n\t\t\tmetrics,\n\t\t\tsummary,\n\t\t\tpiInvocation,\n\t\t}\n\t} finally {\n\t\tlease.release()\n\t}\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { listAgentStates } from \"./agents.js\"\nimport { runController } from \"./controller.js\"\nimport { appendJsonl } from \"./events.js\"\nimport { computeMetrics } from \"./metrics.js\"\nimport { listTaskRecords } from \"./tasks.js\"\nimport type {\n\tBoardSnapshot,\n\tControllerRunResult,\n\tLoopIterationResult,\n\tLoopOptions,\n\tLoopRunResult,\n\tLoopStopReason,\n\tMetricsSnapshot,\n} from \"./types.js\"\n\nconst DEFAULT_MAX_ITERATIONS = 10\nconst DEFAULT_MAX_WALL_TIME_MS = 3_600_000\nconst DEFAULT_BACKGROUND_POLL_MS = 250\n\nfunction createLoopId(): string {\n\treturn `loop-${new Date().toISOString().replace(/[:.]/g, \"-\")}`\n}\n\nfunction writeJson(path: string, value: unknown) {\n\twriteFileSync(path, `${JSON.stringify(value, null, 2)}\\n`, \"utf-8\")\n}\n\nfunction sleepMs(ms: number) {\n\tAtomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms)\n}\n\nfunction hasBackgroundWork(board: BoardSnapshot): boolean {\n\treturn (\n\t\tboard.agents.some(\n\t\t\t(agent) =>\n\t\t\t\tagent.agentId !== \"mayor\" &&\n\t\t\t\t(agent.status === \"queued\" || agent.status === \"running\" || agent.status === \"starting\"),\n\t\t) || board.tasks.some((task) => task.status === \"queued\" || task.status === \"running\")\n\t)\n}\n\nfunction waitForBackgroundWorkToSettle(input: {\n\tartifactsDir: string\n\tmaxWallTimeMs: number\n\tloopStartedAt: number\n\tpollIntervalMs?: number\n}): { timedOut: boolean; board: BoardSnapshot } {\n\tconst pollIntervalMs = input.pollIntervalMs ?? DEFAULT_BACKGROUND_POLL_MS\n\tlet board = snapshotBoard(input.artifactsDir)\n\n\twhile (hasBackgroundWork(board)) {\n\t\tif (Date.now() - input.loopStartedAt >= input.maxWallTimeMs) {\n\t\t\treturn { timedOut: true, board }\n\t\t}\n\n\t\tsleepMs(pollIntervalMs)\n\t\tboard = snapshotBoard(input.artifactsDir)\n\t}\n\n\treturn { timedOut: false, board }\n}\n\nexport function snapshotBoard(artifactsDir: string): BoardSnapshot {\n\tconst tasks = listTaskRecords(artifactsDir)\n\tconst agents = listAgentStates(artifactsDir)\n\n\tconst taskEntries = tasks.map((task) => ({ taskId: task.taskId, status: task.status }))\n\tconst agentEntries = agents.map((agent) => ({\n\t\tagentId: agent.agentId,\n\t\tstatus: agent.status,\n\t\tblocked: agent.blocked,\n\t}))\n\n\tconst allTasksCompleted = tasks.length > 0 && tasks.every((task) => task.status === \"completed\")\n\tconst allRemainingTasksBlocked =\n\t\ttasks.length > 0 && tasks.every((task) => task.status === \"completed\" || task.status === \"blocked\" || task.status === \"aborted\")\n\n\tconst mayor = agents.find((agent) => agent.agentId === \"mayor\")\n\tconst mayorBlocked = mayor?.blocked === true\n\n\tconst hasQueuedOrRunningWork =\n\t\tagents.some((agent) => agent.status === \"queued\" || agent.status === \"running\" || agent.status === \"starting\") ||\n\t\ttasks.some((task) => task.status === \"queued\" || task.status === \"running\")\n\n\treturn {\n\t\ttasks: taskEntries,\n\t\tagents: agentEntries,\n\t\tallTasksCompleted,\n\t\tallRemainingTasksBlocked,\n\t\tmayorBlocked,\n\t\thasQueuedOrRunningWork,\n\t}\n}\n\nexport function evaluateStopCondition(input: {\n\titeration: number\n\tmaxIterations: number\n\telapsedMs: number\n\tmaxWallTimeMs: number\n\tpiExitCode: number\n\tstopOnPiFailure: boolean\n\tstopOnMayorIdleNoWork: boolean\n\tboard: BoardSnapshot\n\tmetrics: MetricsSnapshot\n\tinterruptRateThreshold: number | null\n}): { stopReason: LoopStopReason | null; continueReason: string | null } {\n\tif (input.iteration >= input.maxIterations) {\n\t\treturn { stopReason: \"max-iterations-reached\", continueReason: null }\n\t}\n\n\tif (input.elapsedMs >= input.maxWallTimeMs) {\n\t\treturn { stopReason: \"max-wall-time-reached\", continueReason: null }\n\t}\n\n\tif (input.stopOnPiFailure && input.piExitCode !== 0) {\n\t\treturn { stopReason: \"pi-exit-nonzero\", continueReason: null }\n\t}\n\n\tif (input.board.allTasksCompleted) {\n\t\treturn { stopReason: \"all-tasks-completed\", continueReason: null }\n\t}\n\n\tif (input.board.mayorBlocked) {\n\t\treturn { stopReason: \"mayor-blocked\", continueReason: null }\n\t}\n\n\tconst mayor = input.board.agents.find((agent) => agent.agentId === \"mayor\")\n\tif (input.stopOnMayorIdleNoWork && mayor && !input.board.hasQueuedOrRunningWork && input.board.tasks.length === 0 && mayor.status === \"idle\") {\n\t\treturn { stopReason: \"mayor-idle-no-work\", continueReason: null }\n\t}\n\n\tif (input.board.allRemainingTasksBlocked) {\n\t\treturn { stopReason: \"all-remaining-tasks-blocked\", continueReason: null }\n\t}\n\n\tif (\n\t\tinput.interruptRateThreshold !== null &&\n\t\tinput.metrics.interruptRate > input.interruptRateThreshold\n\t) {\n\t\treturn { stopReason: \"high-interrupt-rate\", continueReason: null }\n\t}\n\n\tconst reasons: string[] = []\n\tif (input.board.hasQueuedOrRunningWork) reasons.push(\"queued or running work remains\")\n\tif (input.board.tasks.length === 0) reasons.push(\"no tasks tracked yet\")\n\tif (reasons.length === 0) reasons.push(\"mayor idle, no stop condition met\")\n\n\treturn { stopReason: null, continueReason: reasons.join(\"; \") }\n}\n\nfunction aggregateMetrics(iterations: LoopIterationResult[]): MetricsSnapshot {\n\tif (iterations.length === 0) {\n\t\treturn computeMetrics({ taskAttempts: [], interrupts: [] })\n\t}\n\n\tlet totalTaskAttempts = 0\n\tlet totalCompletedTasks = 0\n\tlet totalInterrupts = 0\n\tlet totalObservedInterruptCategories = 0\n\tlet totalCoveredInterruptCategories = 0\n\tlet interruptRateSum = 0\n\tlet autonomousCompletionRateSum = 0\n\tlet contextCoverageScoreSum = 0\n\tlet mttcValues: number[] = []\n\tlet ftdValues: number[] = []\n\n\tfor (const iter of iterations) {\n\t\tconst m = iter.metrics\n\t\ttotalTaskAttempts += m.totals.taskAttempts\n\t\ttotalCompletedTasks += m.totals.completedTasks\n\t\ttotalInterrupts += m.totals.interrupts\n\t\ttotalObservedInterruptCategories += m.totals.observedInterruptCategories\n\t\ttotalCoveredInterruptCategories += m.totals.coveredInterruptCategories\n\t\tinterruptRateSum += m.interruptRate\n\t\tautonomousCompletionRateSum += m.autonomousCompletionRate\n\t\tcontextCoverageScoreSum += m.contextCoverageScore\n\t\tif (m.meanTimeToCorrectHours !== null) mttcValues.push(m.meanTimeToCorrectHours)\n\t\tif (m.feedbackToDemoCycleTimeHours !== null) ftdValues.push(m.feedbackToDemoCycleTimeHours)\n\t}\n\n\tconst count = iterations.length\n\tconst round = (v: number) => Math.round(v * 1000) / 1000\n\tconst avg = (values: number[]) => (values.length === 0 ? null : round(values.reduce((s, v) => s + v, 0) / values.length))\n\n\treturn {\n\t\tinterruptRate: round(interruptRateSum / count),\n\t\tautonomousCompletionRate: round(autonomousCompletionRateSum / count),\n\t\tcontextCoverageScore: round(contextCoverageScoreSum / count),\n\t\tmeanTimeToCorrectHours: avg(mttcValues),\n\t\tfeedbackToDemoCycleTimeHours: avg(ftdValues),\n\t\ttotals: {\n\t\t\ttaskAttempts: totalTaskAttempts,\n\t\t\tcompletedTasks: totalCompletedTasks,\n\t\t\tinterrupts: totalInterrupts,\n\t\t\tobservedInterruptCategories: totalObservedInterruptCategories,\n\t\t\tcoveredInterruptCategories: totalCoveredInterruptCategories,\n\t\t},\n\t}\n}\n\nexport function runLoop(options: LoopOptions): LoopRunResult {\n\tconst maxIterations = options.maxIterations ?? DEFAULT_MAX_ITERATIONS\n\tconst maxWallTimeMs = options.maxWallTimeMs ?? DEFAULT_MAX_WALL_TIME_MS\n\tconst stopOnPiFailure = options.stopOnPiFailure ?? true\n\tconst stopOnMayorIdleNoWork = options.stopOnMayorIdleNoWork ?? false\n\tconst interruptRateThreshold = options.interruptRateThreshold ?? null\n\tconst loopId = createLoopId()\n\tconst artifactsDir = options.runOptions.artifactsDir\n\tconst loopDir = join(artifactsDir, \"loops\", loopId)\n\n\tmkdirSync(loopDir, { recursive: true })\n\n\tconst loopStartedAt = Date.now()\n\tconst iterations: LoopIterationResult[] = []\n\tlet finalStopReason: LoopStopReason = \"max-iterations-reached\"\n\tlet needsMayorFollowUp = false\n\n\tappendJsonl(join(loopDir, \"events.jsonl\"), {\n\t\ttype: \"loop_started\",\n\t\tloopId,\n\t\tmaxIterations,\n\t\tmaxWallTimeMs,\n\t\tstopOnPiFailure,\n\t\tcreatedAt: new Date().toISOString(),\n\t})\n\n\tfor (let iteration = 1; iteration <= maxIterations; iteration++) {\n\t\tif (needsMayorFollowUp) {\n\t\t\tconst settled = waitForBackgroundWorkToSettle({\n\t\t\t\tartifactsDir,\n\t\t\t\tmaxWallTimeMs,\n\t\t\t\tloopStartedAt,\n\t\t\t})\n\n\t\t\tappendJsonl(join(loopDir, \"events.jsonl\"), {\n\t\t\t\ttype: \"loop_background_work_settled\",\n\t\t\t\tloopId,\n\t\t\t\titeration,\n\t\t\t\ttimedOut: settled.timedOut,\n\t\t\t\tboardSnapshot: settled.board,\n\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t})\n\n\t\t\tif (settled.timedOut) {\n\t\t\t\tfinalStopReason = \"max-wall-time-reached\"\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tneedsMayorFollowUp = false\n\t\t}\n\n\t\tconst iterationStart = Date.now()\n\n\t\tlet controllerResult: ControllerRunResult\n\t\ttry {\n\t\t\tcontrollerResult = runController(options.runOptions)\n\t\t} catch (error) {\n\t\t\t// If controller fails to run (e.g. lease issue), record and stop\n\t\t\tappendJsonl(join(loopDir, \"events.jsonl\"), {\n\t\t\t\ttype: \"loop_iteration_error\",\n\t\t\t\tloopId,\n\t\t\t\titeration,\n\t\t\t\terror: (error as Error).message,\n\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t})\n\t\t\tfinalStopReason = \"pi-exit-nonzero\"\n\t\t\tbreak\n\t\t}\n\n\t\tconst iterationElapsedMs = Date.now() - iterationStart\n\t\tconst totalElapsedMs = Date.now() - loopStartedAt\n\t\tconst board = snapshotBoard(artifactsDir)\n\t\tconst metrics = controllerResult.metrics\n\n\t\tconst { stopReason, continueReason } = evaluateStopCondition({\n\t\t\titeration,\n\t\t\tmaxIterations,\n\t\t\telapsedMs: totalElapsedMs,\n\t\t\tmaxWallTimeMs,\n\t\t\tpiExitCode: controllerResult.piInvocation.exitCode,\n\t\t\tstopOnPiFailure,\n\t\t\tstopOnMayorIdleNoWork,\n\t\t\tboard,\n\t\t\tmetrics,\n\t\t\tinterruptRateThreshold,\n\t\t})\n\n\t\tconst iterationResult: LoopIterationResult = {\n\t\t\titeration,\n\t\t\tcontrollerResult,\n\t\t\tboardSnapshot: board,\n\t\t\tmetrics,\n\t\t\telapsedMs: iterationElapsedMs,\n\t\t\tcontinueReason,\n\t\t\tstopReason,\n\t\t}\n\n\t\titerations.push(iterationResult)\n\n\t\twriteJson(join(loopDir, `iteration-${iteration}.json`), {\n\t\t\titeration,\n\t\t\trunId: controllerResult.runId,\n\t\t\tboardSnapshot: board,\n\t\t\tmetrics,\n\t\t\telapsedMs: iterationElapsedMs,\n\t\t\tcontinueReason,\n\t\t\tstopReason,\n\t\t})\n\n\t\tappendJsonl(join(loopDir, \"events.jsonl\"), {\n\t\t\ttype: \"loop_iteration_completed\",\n\t\t\tloopId,\n\t\t\titeration,\n\t\t\trunId: controllerResult.runId,\n\t\t\tpiExitCode: controllerResult.piInvocation.exitCode,\n\t\t\tstopReason,\n\t\t\tcontinueReason,\n\t\t\tcreatedAt: new Date().toISOString(),\n\t\t})\n\n\t\tif (options.onIterationComplete) {\n\t\t\toptions.onIterationComplete(iterationResult)\n\t\t}\n\n\t\tif (stopReason !== null) {\n\t\t\tfinalStopReason = stopReason\n\t\t\tbreak\n\t\t}\n\n\t\tneedsMayorFollowUp = hasBackgroundWork(board)\n\t}\n\n\tconst totalElapsedMs = Date.now() - loopStartedAt\n\tconst lastIteration = iterations.at(-1)\n\tconst finalBoard = lastIteration ? lastIteration.boardSnapshot : snapshotBoard(artifactsDir)\n\tconst aggregate = aggregateMetrics(iterations)\n\n\tconst loopResult: LoopRunResult = {\n\t\tloopId,\n\t\titerations,\n\t\tstopReason: finalStopReason,\n\t\ttotalIterations: iterations.length,\n\t\ttotalElapsedMs,\n\t\tfinalBoardSnapshot: finalBoard,\n\t\taggregateMetrics: aggregate,\n\t}\n\n\twriteJson(join(loopDir, \"loop-summary.json\"), {\n\t\tloopId,\n\t\tstopReason: finalStopReason,\n\t\ttotalIterations: iterations.length,\n\t\ttotalElapsedMs,\n\t\tfinalBoardSnapshot: finalBoard,\n\t\taggregateMetrics: aggregate,\n\t})\n\n\tappendJsonl(join(loopDir, \"events.jsonl\"), {\n\t\ttype: \"loop_finished\",\n\t\tloopId,\n\t\tstopReason: finalStopReason,\n\t\ttotalIterations: iterations.length,\n\t\ttotalElapsedMs,\n\t\tcreatedAt: new Date().toISOString(),\n\t})\n\n\treturn loopResult\n}\n"],"mappings":"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"}