@neotx/core 0.1.0-alpha.2 → 0.1.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/agents/loader.ts","../src/agents/schema.ts","../src/agents/registry.ts","../src/agents/resolver.ts","../src/concurrency/queue.ts","../src/concurrency/semaphore.ts","../src/config.ts","../src/paths.ts","../src/cost/journal.ts","../src/events/emitter.ts","../src/events/journal.ts","../src/events/webhook.ts","../src/isolation/git.ts","../src/isolation/git-mutex.ts","../src/isolation/sandbox.ts","../src/isolation/worktree.ts","../src/middleware/audit-log.ts","../src/middleware/budget-guard.ts","../src/middleware/chain.ts","../src/middleware/loop-detection.ts","../src/orchestrator.ts","../src/runner/output-parser.ts","../src/runner/session.ts","../src/runner/recovery.ts","../src/workflows/registry.ts","../src/workflows/loader.ts","../src/supervisor/schemas.ts","../src/supervisor/activity-log.ts","../src/supervisor/daemon.ts","../src/supervisor/event-queue.ts","../src/supervisor/heartbeat.ts","../src/supervisor/memory.ts","../src/supervisor/prompt-builder.ts","../src/supervisor/webhook-server.ts","../src/index.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport type { AgentConfig } from \"@/agents/schema\";\nimport { agentConfigSchema } from \"@/agents/schema\";\n\n/**\n * Load a single agent definition from a YAML file.\n * If the `prompt` field points to a .md file, resolve it relative\n * to the YAML file's directory and read its content.\n */\nexport async function loadAgentFile(filePath: string): Promise<AgentConfig> {\n let raw: string;\n try {\n raw = await readFile(filePath, \"utf-8\");\n } catch {\n throw new Error(`Agent file not found: ${filePath}`);\n }\n\n let parsed: unknown;\n try {\n parsed = parseYaml(raw);\n } catch (err) {\n throw new Error(\n `Invalid YAML in agent file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n const result = agentConfigSchema.safeParse(parsed);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` - ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid agent config in ${filePath}:\\n${issues}`);\n }\n\n const config = result.data;\n\n // If prompt points to a .md file, read it\n if (config.prompt?.endsWith(\".md\")) {\n const promptPath = path.resolve(path.dirname(filePath), config.prompt);\n try {\n config.prompt = await readFile(promptPath, \"utf-8\");\n } catch {\n throw new Error(`Prompt file not found: ${promptPath} (referenced in ${filePath})`);\n }\n }\n\n return config;\n}\n","import { z } from \"zod\";\n\n// ─── Agent model enum ────────────────────────────────────\n\nexport const agentModelSchema = z.enum([\"opus\", \"sonnet\", \"haiku\"]);\n\n// ─── Agent tool enum ─────────────────────────────────────\n\nexport const agentToolSchema = z.enum([\n \"Read\",\n \"Write\",\n \"Edit\",\n \"Bash\",\n \"Glob\",\n \"Grep\",\n \"Agent\",\n \"WebSearch\",\n \"WebFetch\",\n \"NotebookEdit\",\n]);\n\n// ─── Agent tool entry (tool or $inherited token) ─────────\n\nexport const agentToolEntrySchema = z.union([agentToolSchema, z.literal(\"$inherited\")]);\n\n// ─── Agent sandbox enum ──────────────────────────────────\n\nexport const agentSandboxSchema = z.enum([\"writable\", \"readonly\"]);\n\n// ─── AgentConfig schema (from YAML) ─────────────────────\n\nexport const agentConfigSchema = z.object({\n name: z.string(),\n extends: z.string().optional(),\n description: z.string().optional(),\n model: agentModelSchema.optional(),\n tools: z.array(agentToolEntrySchema).optional(),\n prompt: z.string().optional(),\n promptAppend: z.string().optional(),\n sandbox: agentSandboxSchema.optional(),\n maxTurns: z.number().optional(),\n mcpServers: z.array(z.string()).optional(),\n});\n\n// ─── Derived types ───────────────────────────────────────\n\nexport type AgentConfig = z.infer<typeof agentConfigSchema>;\nexport type AgentModel = z.infer<typeof agentModelSchema>;\nexport type AgentTool = z.infer<typeof agentToolSchema>;\nexport type AgentToolEntry = z.infer<typeof agentToolEntrySchema>;\n","import { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { loadAgentFile } from \"@/agents/loader\";\nimport { resolveAgent } from \"@/agents/resolver\";\nimport type { AgentConfig } from \"@/agents/schema\";\nimport type { ResolvedAgent } from \"@/types\";\n\nexport class AgentRegistry {\n private readonly builtInDir: string;\n private readonly customDir: string | undefined;\n private agents = new Map<string, ResolvedAgent>();\n\n constructor(builtInDir: string, customDir?: string) {\n this.builtInDir = builtInDir;\n this.customDir = customDir;\n }\n\n async load(): Promise<void> {\n this.agents.clear();\n\n // Load built-in agents\n const builtInConfigs = await loadAgentsFromDir(this.builtInDir);\n const builtInMap = new Map<string, AgentConfig>();\n for (const config of builtInConfigs) {\n builtInMap.set(config.name, config);\n }\n\n // Resolve built-in agents\n for (const config of builtInConfigs) {\n const resolved = resolveAgent(config, builtInMap);\n // Force built-in source for agents loaded from the built-in dir\n this.agents.set(config.name, { ...resolved, source: \"built-in\" });\n }\n\n // Load custom agents (if directory exists)\n if (this.customDir) {\n let customConfigs: AgentConfig[];\n try {\n customConfigs = await loadAgentsFromDir(this.customDir);\n } catch {\n // Custom dir doesn't exist — that's fine\n customConfigs = [];\n }\n\n for (const config of customConfigs) {\n const resolved = resolveAgent(config, builtInMap);\n this.agents.set(config.name, resolved);\n }\n }\n }\n\n get(name: string): ResolvedAgent | undefined {\n return this.agents.get(name);\n }\n\n list(): ResolvedAgent[] {\n return [...this.agents.values()];\n }\n\n has(name: string): boolean {\n return this.agents.has(name);\n }\n}\n\nasync function loadAgentsFromDir(dir: string): Promise<AgentConfig[]> {\n const entries = await readdir(dir);\n const ymlFiles = entries.filter((f) => f.endsWith(\".yml\") || f.endsWith(\".yaml\"));\n\n const configs: AgentConfig[] = [];\n for (const file of ymlFiles) {\n const config = await loadAgentFile(path.join(dir, file));\n configs.push(config);\n }\n return configs;\n}\n","import type { AgentConfig, AgentTool } from \"@/agents/schema\";\nimport type { AgentDefinition, ResolvedAgent } from \"@/types\";\n\n/**\n * Resolve an agent config into a fully-merged ResolvedAgent.\n *\n * Resolution rules:\n * 1. No `extends` → agent must define all required fields\n * 2. With `extends: \"developer\"` → start from built-in, apply overrides\n * 3. Same name as built-in without `extends:` → treated as `extends: <name>` implicitly\n */\nexport function resolveAgent(\n config: AgentConfig,\n builtIns: Map<string, AgentConfig>,\n): ResolvedAgent {\n const extendsName =\n config.extends ??\n (builtIns.has(config.name) && config.extends === undefined ? config.name : undefined);\n const isExtending = extendsName !== undefined;\n\n if (isExtending) {\n const base = builtIns.get(extendsName);\n if (!base) {\n throw new Error(\n `Agent \"${config.name}\" extends \"${extendsName}\", but no built-in agent with that name exists.`,\n );\n }\n\n // Merge tools\n let tools: string[];\n if (config.tools) {\n if (config.tools.includes(\"$inherited\")) {\n // Keep inherited tools + add new ones\n const baseTols = base.tools ?? [];\n const newTools = config.tools.filter((t) => t !== \"$inherited\");\n tools = [...baseTols, ...newTools] as string[];\n } else {\n // Full replacement\n tools = config.tools as string[];\n }\n } else {\n tools = (base.tools ?? []) as string[];\n }\n\n // Merge prompt\n let prompt: string;\n if (config.prompt) {\n prompt = config.prompt;\n } else {\n prompt = base.prompt ?? \"\";\n }\n if (config.promptAppend) {\n prompt = `${prompt}\\n\\n${config.promptAppend}`;\n }\n\n const definition: AgentDefinition = {\n description: config.description ?? base.description ?? \"\",\n prompt,\n tools,\n model: config.model ?? base.model ?? \"sonnet\",\n };\n\n return {\n name: config.name,\n definition,\n sandbox: config.sandbox ?? base.sandbox ?? \"readonly\",\n ...(config.maxTurns !== undefined\n ? { maxTurns: config.maxTurns }\n : base.maxTurns !== undefined\n ? { maxTurns: base.maxTurns }\n : {}),\n source: config.name === extendsName && !config.extends ? \"built-in\" : \"extended\",\n };\n }\n\n // No extends — fully custom agent\n if (!config.description) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"description\". Add a 'description' field to the agent YAML.`,\n );\n }\n if (!config.model) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"model\". Add a 'model' field (e.g., 'claude-sonnet-4-20250514').`,\n );\n }\n if (!config.tools) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"tools\". Add a 'tools' array to the agent YAML.`,\n );\n }\n if (!config.sandbox) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"sandbox\". Add a 'sandbox' field ('full' or 'permissive').`,\n );\n }\n if (!config.prompt) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"prompt\". Add a 'prompt' field or 'promptFile' reference.`,\n );\n }\n\n // Filter out $inherited from tools (shouldn't be there without extends, but be safe)\n const tools = config.tools.filter((t): t is AgentTool => t !== \"$inherited\");\n\n let prompt = config.prompt;\n if (config.promptAppend) {\n prompt = `${prompt}\\n\\n${config.promptAppend}`;\n }\n\n const definition: AgentDefinition = {\n description: config.description,\n prompt,\n tools,\n model: config.model,\n };\n\n return {\n name: config.name,\n definition,\n sandbox: config.sandbox,\n ...(config.maxTurns !== undefined ? { maxTurns: config.maxTurns } : {}),\n source: \"custom\",\n };\n}\n","import type { Priority } from \"@/types\";\n\nconst PRIORITY_ORDER: Record<Priority, number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n};\n\ninterface QueueItem<T> {\n value: T;\n priority: Priority;\n insertionOrder: number;\n}\n\n/**\n * FIFO priority queue. Items with higher priority (critical > high > medium > low)\n * are dequeued first. Within the same priority level, FIFO order is maintained.\n */\nexport class PriorityQueue<T> {\n private readonly items: QueueItem<T>[] = [];\n private readonly maxSize: number;\n private insertionCounter = 0;\n\n constructor(maxSize: number) {\n this.maxSize = maxSize;\n }\n\n enqueue(value: T, priority: Priority): void {\n // Reset counter when queue is empty to prevent overflow after prolonged use\n if (this.items.length === 0) {\n this.insertionCounter = 0;\n }\n\n if (this.items.length >= this.maxSize) {\n throw new Error(`Queue full (${this.maxSize} items). Cannot enqueue.`);\n }\n\n const item: QueueItem<T> = {\n value,\n priority,\n insertionOrder: this.insertionCounter++,\n };\n\n // Insert in sorted position (binary search would be overkill for queue sizes ≤ 50)\n let inserted = false;\n for (let i = 0; i < this.items.length; i++) {\n const existing = this.items[i];\n if (existing && this.comparePriority(item, existing) < 0) {\n this.items.splice(i, 0, item);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n this.items.push(item);\n }\n }\n\n dequeue(): T | undefined {\n const item = this.items.shift();\n return item?.value;\n }\n\n peek(): T | undefined {\n return this.items[0]?.value;\n }\n\n get size(): number {\n return this.items.length;\n }\n\n get isEmpty(): boolean {\n return this.items.length === 0;\n }\n\n remove(predicate: (item: T) => boolean): boolean {\n const index = this.items.findIndex((entry) => predicate(entry.value));\n if (index === -1) return false;\n this.items.splice(index, 1);\n return true;\n }\n\n /** Dequeue the first item matching the predicate (respects priority order). */\n dequeueWhere(predicate: (item: T) => boolean): T | undefined {\n const index = this.items.findIndex((entry) => predicate(entry.value));\n if (index === -1) return undefined;\n const removed = this.items.splice(index, 1)[0];\n if (!removed) return undefined;\n return removed.value;\n }\n\n /** Compare by priority first, then by insertion order (FIFO within same priority). */\n private comparePriority(a: QueueItem<T>, b: QueueItem<T>): number {\n const priorityDiff = PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority];\n if (priorityDiff !== 0) return priorityDiff;\n return a.insertionOrder - b.insertionOrder;\n }\n}\n","import { PriorityQueue } from \"@/concurrency/queue\";\nimport type { Priority } from \"@/types\";\n\nexport interface SemaphoreConfig {\n maxSessions: number;\n maxPerRepo: number;\n queueMax?: number;\n}\n\nexport interface SemaphoreCallbacks {\n onEnqueue?: (sessionId: string, repo: string, position: number) => void;\n onDequeue?: (sessionId: string, repo: string, waitedMs: number) => void;\n}\n\ninterface WaitingEntry {\n sessionId: string;\n repo: string;\n resolve: () => void;\n reject: (reason: unknown) => void;\n enqueuedAt: number;\n _cleanupAbort?: () => void;\n}\n\n/**\n * Concurrency semaphore with global + per-repo limits and a priority queue.\n * When at capacity, `acquire()` blocks until a slot is available.\n */\nexport class Semaphore {\n private readonly maxSessions: number;\n private readonly maxPerRepo: number;\n private readonly queue: PriorityQueue<WaitingEntry>;\n private readonly callbacks: SemaphoreCallbacks;\n\n // sessionId → repo\n private readonly activeSessions = new Map<string, string>();\n // repo → count\n private readonly repoCounts = new Map<string, number>();\n\n constructor(config: SemaphoreConfig, callbacks: SemaphoreCallbacks = {}) {\n this.maxSessions = config.maxSessions;\n this.maxPerRepo = config.maxPerRepo;\n this.queue = new PriorityQueue<WaitingEntry>(config.queueMax ?? 50);\n this.callbacks = callbacks;\n }\n\n /**\n * Acquire a slot. Blocks (via promise) if at capacity.\n * Throws if the queue is full.\n */\n async acquire(\n repo: string,\n sessionId: string,\n priority: Priority = \"medium\",\n signal?: AbortSignal,\n ): Promise<void> {\n if (signal?.aborted) {\n throw signal.reason ?? new DOMException(\"The operation was aborted.\", \"AbortError\");\n }\n\n if (this.canAcquire(repo)) {\n this.allocate(repo, sessionId);\n return;\n }\n\n return new Promise<void>((resolve, reject) => {\n const entry: WaitingEntry = {\n sessionId,\n repo,\n resolve,\n reject,\n enqueuedAt: Date.now(),\n };\n\n this.queue.enqueue(entry, priority);\n this.callbacks.onEnqueue?.(sessionId, repo, this.queue.size);\n\n if (signal) {\n const onAbort = () => {\n this.queue.remove((e) => e === entry);\n reject(signal.reason ?? new DOMException(\"The operation was aborted.\", \"AbortError\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n\n // Store cleanup so we can remove the listener on normal dequeue\n entry._cleanupAbort = () => signal.removeEventListener(\"abort\", onAbort);\n }\n });\n }\n\n /** Release a slot and process the next waiting entry. */\n release(sessionId: string): void {\n const repo = this.activeSessions.get(sessionId);\n if (!repo) return;\n\n this.activeSessions.delete(sessionId);\n const count = this.repoCounts.get(repo) ?? 0;\n if (count <= 1) {\n this.repoCounts.delete(repo);\n } else {\n this.repoCounts.set(repo, count - 1);\n }\n\n this.processQueue();\n }\n\n /** Non-blocking attempt to acquire a slot. Returns true if successful. */\n tryAcquire(repo: string, sessionId: string): boolean {\n if (!this.canAcquire(repo)) return false;\n this.allocate(repo, sessionId);\n return true;\n }\n\n /** Total number of active slots. */\n activeCount(): number {\n return this.activeSessions.size;\n }\n\n /** Number of active slots for a specific repo. */\n activeCountForRepo(repo: string): number {\n return this.repoCounts.get(repo) ?? 0;\n }\n\n /** Can a slot be acquired for this repo without blocking? */\n isAvailable(repo: string): boolean {\n return this.canAcquire(repo);\n }\n\n /** Current queue depth. */\n queueDepth(): number {\n return this.queue.size;\n }\n\n private canAcquire(repo: string): boolean {\n if (this.activeSessions.size >= this.maxSessions) return false;\n const repoCount = this.repoCounts.get(repo) ?? 0;\n return repoCount < this.maxPerRepo;\n }\n\n private allocate(repo: string, sessionId: string): void {\n this.activeSessions.set(sessionId, repo);\n this.repoCounts.set(repo, (this.repoCounts.get(repo) ?? 0) + 1);\n }\n\n private processQueue(): void {\n // Find the highest-priority entry whose repo has capacity\n const entry = this.queue.dequeueWhere((e) => this.canAcquire(e.repo));\n if (!entry) return;\n\n this.allocate(entry.repo, entry.sessionId);\n entry._cleanupAbort?.();\n const waitedMs = Date.now() - entry.enqueuedAt;\n this.callbacks.onDequeue?.(entry.sessionId, entry.repo, waitedMs);\n entry.resolve();\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport { getDataDir, toRepoSlug } from \"@/paths\";\n\n// ─── McpServerConfig schemas ─────────────────────────────\n\nconst httpMcpServerSchema = z.object({\n type: z.literal(\"http\"),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n});\n\nconst stdioMcpServerSchema = z.object({\n type: z.literal(\"stdio\"),\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n});\n\nexport const mcpServerConfigSchema = z.discriminatedUnion(\"type\", [\n httpMcpServerSchema,\n stdioMcpServerSchema,\n]);\n\n// ─── RepoConfig schema (single repo entry) ──────────────\n\nexport const repoConfigSchema = z.object({\n path: z.string(),\n name: z.string().optional(),\n defaultBranch: z.string().default(\"main\"),\n branchPrefix: z.string().default(\"feat\"),\n pushRemote: z.string().default(\"origin\"),\n autoCreatePr: z.boolean().default(false),\n prBaseBranch: z.string().optional(),\n});\n\n// ─── Global config schema (~/.neo/config.yml) ───────────\n// This is now the single source of truth — repos are registered here.\n\nexport const globalConfigSchema = z.object({\n repos: z.array(repoConfigSchema).default([]),\n\n concurrency: z\n .object({\n maxSessions: z.number().default(5),\n maxPerRepo: z.number().default(2),\n queueMax: z.number().default(50),\n })\n .default({ maxSessions: 5, maxPerRepo: 2, queueMax: 50 }),\n\n budget: z\n .object({\n dailyCapUsd: z.number().default(500),\n alertThresholdPct: z.number().default(80),\n })\n .default({ dailyCapUsd: 500, alertThresholdPct: 80 }),\n\n recovery: z\n .object({\n maxRetries: z.number().default(3),\n backoffBaseMs: z.number().default(30_000),\n })\n .default({ maxRetries: 3, backoffBaseMs: 30_000 }),\n\n sessions: z\n .object({\n initTimeoutMs: z.number().default(120_000),\n maxDurationMs: z.number().default(3_600_000),\n })\n .default({ initTimeoutMs: 120_000, maxDurationMs: 3_600_000 }),\n\n webhooks: z\n .array(\n z.object({\n url: z.string().url(),\n events: z.array(z.string()).optional(),\n secret: z.string().optional(),\n timeoutMs: z.number().default(5000),\n }),\n )\n .default([]),\n\n supervisor: z\n .object({\n port: z.number().default(7777),\n secret: z.string().optional(),\n idleIntervalMs: z.number().default(60_000),\n idleSkipMax: z.number().default(20),\n heartbeatTimeoutMs: z.number().default(300_000),\n maxConsecutiveFailures: z.number().default(3),\n maxEventsPerSec: z.number().default(10),\n dailyCapUsd: z.number().default(50),\n instructions: z.string().optional(),\n })\n .default({\n port: 7777,\n idleIntervalMs: 60_000,\n idleSkipMax: 20,\n heartbeatTimeoutMs: 300_000,\n maxConsecutiveFailures: 3,\n maxEventsPerSec: 10,\n dailyCapUsd: 50,\n }),\n\n mcpServers: z.record(z.string(), mcpServerConfigSchema).optional(),\n claudeCodePath: z.string().optional(),\n\n idempotency: z\n .object({\n enabled: z.boolean().default(true),\n key: z.enum([\"metadata\", \"prompt\"]).default(\"metadata\"),\n ttlMs: z.number().default(3_600_000),\n })\n .optional(),\n});\n\n// ─── NeoConfig = GlobalConfig (single schema now) ────────\n\nexport const neoConfigSchema = globalConfigSchema;\n\n// ─── Derived types ───────────────────────────────────────\n\nexport type NeoConfig = z.infer<typeof neoConfigSchema>;\nexport type GlobalConfig = NeoConfig;\nexport type RepoConfig = z.infer<typeof repoConfigSchema>;\nexport type RepoConfigInput = z.input<typeof repoConfigSchema>;\nexport type McpServerConfig = z.infer<typeof mcpServerConfigSchema>;\n\n// ─── Default global config ──────────────────────────────\n\nconst DEFAULT_GLOBAL_CONFIG = {\n repos: [],\n concurrency: {\n maxSessions: 5,\n maxPerRepo: 2,\n queueMax: 50,\n },\n budget: {\n dailyCapUsd: 500,\n alertThresholdPct: 80,\n },\n};\n\n// ─── YAML loader helper ─────────────────────────────────\n\nfunction parseYamlFile(raw: string, filePath: string): unknown {\n try {\n return parseYaml(raw);\n } catch (err) {\n throw new Error(\n `Invalid YAML in ${filePath}: ${err instanceof Error ? err.message : String(err)}. Check YAML syntax at the indicated line.`,\n );\n }\n}\n\nfunction formatZodErrors(issues: z.ZodIssue[], filePath: string): string {\n const formatted = issues.map((i) => ` - ${i.path.join(\".\")}: ${i.message}`).join(\"\\n\");\n return `Invalid config in ${filePath}:\\n${formatted}`;\n}\n\n// ─── Config loaders ─────────────────────────────────────\n\n/**\n * Load NeoConfig from a single file (legacy compatibility).\n */\nexport async function loadConfig(configPath: string): Promise<NeoConfig> {\n let raw: string;\n try {\n raw = await readFile(configPath, \"utf-8\");\n } catch {\n throw new Error(`Config file not found: ${configPath}. Run 'neo init' to get started.`);\n }\n\n const parsed = parseYamlFile(raw, configPath);\n\n const result = neoConfigSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(formatZodErrors(result.error.issues, configPath));\n }\n\n return result.data;\n}\n\n/**\n * Load the global config from ~/.neo/config.yml.\n * Creates the file with defaults if it does not exist.\n */\nexport async function loadGlobalConfig(): Promise<NeoConfig> {\n const configPath = path.join(getDataDir(), \"config.yml\");\n\n if (!existsSync(configPath)) {\n await mkdir(getDataDir(), { recursive: true });\n await writeFile(configPath, stringifyYaml(DEFAULT_GLOBAL_CONFIG), \"utf-8\");\n return globalConfigSchema.parse(DEFAULT_GLOBAL_CONFIG);\n }\n\n const raw = await readFile(configPath, \"utf-8\");\n const parsed = parseYamlFile(raw, configPath);\n\n const result = globalConfigSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(formatZodErrors(result.error.issues, configPath));\n }\n\n return result.data;\n}\n\n// ─── Repo CRUD operations ───────────────────────────────\n\n/**\n * Add a repo to ~/.neo/config.yml. Deduplicates by resolved path.\n */\nexport async function addRepoToGlobalConfig(repo: RepoConfigInput): Promise<void> {\n const config = await loadGlobalConfig();\n const resolvedPath = path.resolve(repo.path);\n const parsed = repoConfigSchema.parse({ ...repo, path: resolvedPath });\n\n const existing = config.repos.findIndex((r) => path.resolve(r.path) === resolvedPath);\n if (existing >= 0) {\n config.repos[existing] = parsed;\n } else {\n config.repos.push(parsed);\n }\n\n const configPath = path.join(getDataDir(), \"config.yml\");\n await writeFile(configPath, stringifyYaml(config), \"utf-8\");\n}\n\n/**\n * Remove a repo from ~/.neo/config.yml by path, name, or slug.\n */\nexport async function removeRepoFromGlobalConfig(pathOrName: string): Promise<boolean> {\n const config = await loadGlobalConfig();\n const resolvedPath = path.resolve(pathOrName);\n const initialLength = config.repos.length;\n\n config.repos = config.repos.filter(\n (r) =>\n path.resolve(r.path) !== resolvedPath &&\n r.name !== pathOrName &&\n toRepoSlug(r) !== pathOrName,\n );\n\n if (config.repos.length === initialLength) return false;\n\n const configPath = path.join(getDataDir(), \"config.yml\");\n await writeFile(configPath, stringifyYaml(config), \"utf-8\");\n return true;\n}\n\n/**\n * List all registered repos from ~/.neo/config.yml.\n */\nexport async function listReposFromGlobalConfig(): Promise<RepoConfig[]> {\n const config = await loadGlobalConfig();\n return config.repos;\n}\n","import { homedir } from \"node:os\";\nimport path from \"node:path\";\n\n/**\n * Global data directory for runtime artifacts (journals, runs).\n * Located at ~/.neo, similar to how Claude Code uses ~/.claude.\n */\nexport function getDataDir(): string {\n return path.join(homedir(), \".neo\");\n}\n\nexport function getJournalsDir(): string {\n return path.join(getDataDir(), \"journals\");\n}\n\nexport function getRunsDir(): string {\n return path.join(getDataDir(), \"runs\");\n}\n\n/**\n * Derive a filesystem-safe slug from a repo config.\n * Uses `name` if present, otherwise `basename(path)`.\n */\nexport function toRepoSlug(repo: { name?: string | undefined; path: string }): string {\n const raw = repo.name ?? path.basename(repo.path);\n return raw\n .toLowerCase()\n .replace(/[^a-z0-9._-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\n/**\n * Runs directory for a specific repo: ~/.neo/runs/<slug>/\n */\nexport function getRepoRunsDir(repoSlug: string): string {\n return path.join(getRunsDir(), repoSlug);\n}\n\n/**\n * Path to the dispatch request file for a detached run.\n */\nexport function getRunDispatchPath(repoSlug: string, runId: string): string {\n return path.join(getRepoRunsDir(repoSlug), `${runId}.dispatch.json`);\n}\n\n/**\n * Path to the log file for a detached run.\n */\nexport function getRunLogPath(repoSlug: string, runId: string): string {\n return path.join(getRepoRunsDir(repoSlug), `${runId}.log`);\n}\n\n/**\n * Directory for all supervisor instances: ~/.neo/supervisors/\n */\nexport function getSupervisorsDir(): string {\n return path.join(getDataDir(), \"supervisors\");\n}\n\n/**\n * Directory for a specific supervisor instance: ~/.neo/supervisors/<name>/\n */\nexport function getSupervisorDir(name: string): string {\n return path.join(getSupervisorsDir(), name);\n}\n\n/**\n * Path to a supervisor state file: ~/.neo/supervisors/<name>/state.json\n */\nexport function getSupervisorStatePath(name: string): string {\n return path.join(getSupervisorDir(name), \"state.json\");\n}\n\nexport function getSupervisorMemoryPath(name: string): string {\n return path.join(getSupervisorDir(name), \"memory.md\");\n}\n\nexport function getSupervisorActivityPath(name: string): string {\n return path.join(getSupervisorDir(name), \"activity.jsonl\");\n}\n\nexport function getSupervisorInboxPath(name: string): string {\n return path.join(getSupervisorDir(name), \"inbox.jsonl\");\n}\n\nexport function getSupervisorEventsPath(name: string): string {\n return path.join(getSupervisorDir(name), \"events.jsonl\");\n}\n\nexport function getSupervisorLockPath(name: string): string {\n return path.join(getSupervisorDir(name), \"daemon.lock\");\n}\n","import { appendFile, mkdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { CostEntry } from \"@/types\";\n\n/**\n * Append-only JSONL journal for cost tracking.\n * Monthly file rotation: cost-YYYY-MM.jsonl\n */\nexport class CostJournal {\n private readonly dir: string;\n private dirCreated = false;\n private dayCache: { key: string; total: number } | null = null;\n\n constructor(options: { dir: string }) {\n this.dir = options.dir;\n }\n\n async append(entry: CostEntry): Promise<void> {\n await this.ensureDir();\n const file = this.fileForDate(new Date(entry.timestamp));\n await appendFile(file, `${JSON.stringify(entry)}\\n`, \"utf-8\");\n // Invalidate cache — the day total may have changed\n this.dayCache = null;\n }\n\n async getDayTotal(date?: Date): Promise<number> {\n const d = date ?? new Date();\n const dayKey = toDateKey(d);\n\n if (this.dayCache?.key === dayKey) {\n return this.dayCache.total;\n }\n\n const file = this.fileForDate(d);\n let total = 0;\n\n try {\n const content = await readFile(file, \"utf-8\");\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n const entry = JSON.parse(line) as CostEntry;\n if (toDateKey(new Date(entry.timestamp)) === dayKey) {\n total += entry.costUsd;\n }\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n // File doesn't exist yet — total is 0\n }\n\n this.dayCache = { key: dayKey, total };\n return total;\n }\n\n private fileForDate(date: Date): string {\n const yyyy = date.getUTCFullYear();\n const mm = String(date.getUTCMonth() + 1).padStart(2, \"0\");\n return path.join(this.dir, `cost-${yyyy}-${mm}.jsonl`);\n }\n\n private async ensureDir(): Promise<void> {\n if (this.dirCreated) return;\n await mkdir(this.dir, { recursive: true });\n this.dirCreated = true;\n }\n}\n\nfunction toDateKey(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n","import { EventEmitter } from \"node:events\";\nimport type { NeoEvent } from \"@/types\";\n\n/**\n * Safe EventEmitter wrapper (ADR-022).\n *\n * - Catches listener errors to prevent cascading crashes\n * - Emits on both the specific event type and the wildcard \"*\" channel\n * - Swallows errors from the error handler itself to guarantee stability\n */\nexport class NeoEventEmitter {\n private readonly emitter = new EventEmitter();\n\n emit(event: NeoEvent): void {\n this.safeEmit(event.type, event);\n this.safeEmit(\"*\", event);\n }\n\n on(eventType: string, listener: (event: NeoEvent) => void): this {\n this.emitter.on(eventType, listener);\n return this;\n }\n\n off(eventType: string, listener: (event: NeoEvent) => void): this {\n this.emitter.off(eventType, listener);\n return this;\n }\n\n once(eventType: string, listener: (event: NeoEvent) => void): this {\n this.emitter.once(eventType, listener);\n return this;\n }\n\n removeAllListeners(eventType?: string): this {\n this.emitter.removeAllListeners(eventType);\n return this;\n }\n\n private safeEmit(eventType: string, event: NeoEvent): void {\n try {\n this.emitter.emit(eventType, event);\n } catch (error) {\n if (eventType !== \"error\") {\n try {\n this.emitter.emit(\"error\", error);\n } catch {\n // Swallow — prevent crash even if error handler throws\n }\n }\n }\n }\n}\n","import { appendFile, mkdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { NeoEvent } from \"@/types\";\n\n/**\n * Append-only JSONL journal for events.\n * Monthly file rotation: events-YYYY-MM.jsonl\n * Write-only for v0.1 — read API comes in v0.2.\n */\nexport class EventJournal {\n private readonly dir: string;\n private dirCreated = false;\n\n constructor(options: { dir: string }) {\n this.dir = options.dir;\n }\n\n async append(event: NeoEvent): Promise<void> {\n await this.ensureDir();\n const file = this.fileForDate(new Date(event.timestamp));\n await appendFile(file, `${JSON.stringify(event)}\\n`, \"utf-8\");\n }\n\n private fileForDate(date: Date): string {\n const yyyy = date.getUTCFullYear();\n const mm = String(date.getUTCMonth() + 1).padStart(2, \"0\");\n return path.join(this.dir, `events-${yyyy}-${mm}.jsonl`);\n }\n\n private async ensureDir(): Promise<void> {\n if (this.dirCreated) return;\n await mkdir(this.dir, { recursive: true });\n this.dirCreated = true;\n }\n}\n","import { createHmac } from \"node:crypto\";\nimport type { NeoConfig } from \"@/config\";\nimport type { NeoEvent } from \"@/types\";\n\ntype WebhookConfig = NeoConfig[\"webhooks\"][number];\n\ninterface WebhookPayload {\n version: 1;\n event: Record<string, unknown>;\n source: \"neo\";\n deliveredAt: string;\n}\n\n/**\n * Fire-and-forget webhook dispatcher for NeoEvents.\n *\n * - Matches events against per-webhook filters (exact or wildcard like \"session:*\")\n * - Excludes gate:waiting events (contain non-serializable callbacks)\n * - Signs payloads with HMAC-SHA256 when a secret is configured\n * - Never throws — errors are silently swallowed (consistent with EventJournal)\n */\nexport class WebhookDispatcher {\n private readonly webhooks: WebhookConfig[];\n\n constructor(webhooks: WebhookConfig[]) {\n this.webhooks = webhooks;\n }\n\n dispatch(event: NeoEvent): void {\n // gate:waiting contains non-serializable callbacks (approve/reject)\n if (event.type === \"gate:waiting\") return;\n\n for (const webhook of this.webhooks) {\n if (!matchesFilter(event.type, webhook.events)) continue;\n\n const payload: WebhookPayload = {\n version: 1,\n event: toSerializable(event),\n source: \"neo\",\n deliveredAt: new Date().toISOString(),\n };\n\n const body = JSON.stringify(payload);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n if (webhook.secret) {\n headers[\"X-Neo-Signature\"] = sign(body, webhook.secret);\n }\n\n // Fire-and-forget — never awaited, errors swallowed\n fetch(webhook.url, {\n method: \"POST\",\n headers,\n body,\n signal: AbortSignal.timeout(webhook.timeoutMs),\n }).catch(() => {});\n }\n }\n}\n\n/**\n * Check if an event type matches a filter list.\n * Supports exact matches and wildcard prefixes (e.g. \"session:*\").\n * No filter (undefined) means all events match.\n */\nexport function matchesFilter(eventType: string, filters?: string[]): boolean {\n if (!filters || filters.length === 0) return true;\n return filters.some((f) => {\n if (f.endsWith(\":*\")) return eventType.startsWith(f.slice(0, -1));\n return f === eventType;\n });\n}\n\nfunction sign(body: string, secret: string): string {\n return createHmac(\"sha256\", secret).update(body).digest(\"hex\");\n}\n\nfunction toSerializable(event: NeoEvent): Record<string, unknown> {\n const obj: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(event)) {\n if (typeof value !== \"function\") {\n obj[key] = value;\n }\n }\n return obj;\n}\n","import { execFile } from \"node:child_process\";\nimport { resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport type { RepoConfig } from \"@/config\";\nimport { withGitLock } from \"@/isolation/git-mutex\";\n\nconst execFileAsync = promisify(execFile);\nconst GIT_TIMEOUT = 60_000;\n\n/**\n * Run a git command with execFile (no shell — prevents injection).\n * All callers should go through the public API which acquires the mutex.\n */\nasync function git(repoPath: string, args: string[]): Promise<string> {\n const { stdout } = await execFileAsync(\"git\", args, {\n cwd: resolve(repoPath),\n timeout: GIT_TIMEOUT,\n });\n return stdout.trim();\n}\n\nexport async function createBranch(\n repoPath: string,\n branch: string,\n baseBranch: string,\n): Promise<void> {\n await withGitLock(repoPath, () => git(repoPath, [\"branch\", branch, baseBranch]));\n}\n\nexport async function pushBranch(repoPath: string, branch: string, remote: string): Promise<void> {\n await withGitLock(repoPath, () => git(repoPath, [\"push\", remote, branch]));\n}\n\nexport async function fetchRemote(repoPath: string, remote: string): Promise<void> {\n await withGitLock(repoPath, () => git(repoPath, [\"fetch\", remote]));\n}\n\nexport async function deleteBranch(repoPath: string, branch: string): Promise<void> {\n await withGitLock(repoPath, () => git(repoPath, [\"branch\", \"-D\", branch]));\n}\n\nexport async function getCurrentBranch(repoPath: string): Promise<string> {\n return withGitLock(repoPath, () => git(repoPath, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]));\n}\n\n/**\n * Generate a deterministic branch name for a run.\n * Uses the repo's branchPrefix (default \"feat\") and the runId.\n */\nexport function getBranchName(config: RepoConfig, runId: string): string {\n const prefix = config.branchPrefix ?? \"feat\";\n const sanitized = runId.toLowerCase().replace(/[^a-z0-9-]/g, \"-\");\n return `${prefix}/run-${sanitized}`;\n}\n\n/**\n * Check if a worktree has uncommitted changes (staged or unstaged).\n */\nexport async function hasUncommittedChanges(worktreePath: string): Promise<boolean> {\n const status = await withGitLock(worktreePath, () =>\n git(worktreePath, [\"status\", \"--porcelain\"]),\n );\n return status.length > 0;\n}\n\n/**\n * Auto-commit all changes in a worktree. Used as a safety net after agent\n * sessions to prevent losing work when the worktree is cleaned up.\n */\nexport async function autoCommitChanges(worktreePath: string, runId: string): Promise<boolean> {\n const hasChanges = await hasUncommittedChanges(worktreePath);\n if (!hasChanges) return false;\n\n await withGitLock(worktreePath, async () => {\n await git(worktreePath, [\"add\", \"-A\"]);\n await git(worktreePath, [\n \"commit\",\n \"-m\",\n `chore: auto-commit uncommitted changes from run ${runId}`,\n ]);\n });\n\n return true;\n}\n\n/**\n * Push a branch from a worktree to a remote. Silently succeeds if\n * the branch has no new commits to push.\n */\nexport async function pushWorktreeBranch(\n worktreePath: string,\n branch: string,\n remote: string,\n): Promise<void> {\n await withGitLock(worktreePath, () => git(worktreePath, [\"push\", \"-u\", remote, branch]));\n}\n","/**\n * Per-repository in-memory mutex to serialise git operations.\n * Concurrent git commands on the same repo corrupt the index — this prevents that.\n */\n\nconst locks = new Map<string, Promise<void>>();\n\n/**\n * Execute `fn` while holding an exclusive lock for `repoPath`.\n * Concurrent calls for the same repo are queued and executed serially.\n * Operations on different repos run in parallel.\n */\nexport async function withGitLock<T>(repoPath: string, fn: () => Promise<T>): Promise<T> {\n const previous = locks.get(repoPath) ?? Promise.resolve();\n\n let releaseLock: (() => void) | undefined;\n const current = new Promise<void>((resolve) => {\n releaseLock = resolve;\n });\n locks.set(repoPath, current);\n\n await previous;\n\n try {\n return await fn();\n } finally {\n releaseLock?.();\n if (locks.get(repoPath) === current) {\n locks.delete(repoPath);\n }\n }\n}\n","import { resolve } from \"node:path\";\nimport type { ResolvedAgent } from \"@/types\";\n\n/**\n * SDK-compatible sandbox configuration.\n * Controls which tools an agent can use and which paths it can access.\n */\nexport interface SandboxConfig {\n /** Tools the agent is allowed to use */\n allowedTools: string[];\n /** Directories the agent can read from */\n readablePaths: string[];\n /** Directories the agent can write to (empty for readonly agents) */\n writablePaths: string[];\n /** Whether the agent has write access */\n writable: boolean;\n}\n\n/** Tools that modify the filesystem */\nconst WRITE_TOOLS = new Set([\"Write\", \"Edit\", \"NotebookEdit\"]);\n\n/**\n * Build an SDK-compatible sandbox configuration for an agent.\n *\n * - Writable agents: all their tools are allowed, write paths include the worktree\n * - Readonly agents: write tools are filtered out, no writable paths\n */\nexport function buildSandboxConfig(agent: ResolvedAgent, worktreePath?: string): SandboxConfig {\n const isWritable = agent.sandbox === \"writable\";\n const absWorktree = worktreePath ? resolve(worktreePath) : undefined;\n\n const allowedTools = isWritable\n ? agent.definition.tools\n : agent.definition.tools.filter((t) => !WRITE_TOOLS.has(t));\n\n const readablePaths = absWorktree ? [absWorktree] : [];\n const writablePaths = isWritable && absWorktree ? [absWorktree] : [];\n\n return {\n allowedTools,\n readablePaths,\n writablePaths,\n writable: isWritable,\n };\n}\n","import { execFile } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { readdir, rm } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { withGitLock } from \"@/isolation/git-mutex\";\n\nconst execFileAsync = promisify(execFile);\nconst GIT_TIMEOUT = 60_000;\n\nexport interface WorktreeInfo {\n path: string;\n branch: string;\n repoPath: string;\n}\n\n/**\n * Create a new git worktree with an associated branch.\n * Creates the branch from baseBranch, then adds the worktree at worktreeDir.\n */\nexport async function createWorktree(options: {\n repoPath: string;\n branch: string;\n baseBranch: string;\n worktreeDir: string;\n}): Promise<WorktreeInfo> {\n const repoPath = resolve(options.repoPath);\n const worktreeDir = resolve(options.worktreeDir);\n\n await withGitLock(repoPath, async () => {\n await execFileAsync(\n \"git\",\n [\"worktree\", \"add\", \"-b\", options.branch, worktreeDir, options.baseBranch],\n { cwd: repoPath, timeout: GIT_TIMEOUT },\n );\n });\n\n // Disable git hooks in the worktree — pre-commit hooks (husky, lint-staged)\n // fail because node_modules are not available in worktrees.\n await execFileAsync(\"git\", [\"config\", \"core.hooksPath\", \"/dev/null\"], {\n cwd: worktreeDir,\n timeout: GIT_TIMEOUT,\n });\n\n return { path: worktreeDir, branch: options.branch, repoPath };\n}\n\n/**\n * Remove a worktree. Does NOT delete the branch (branch stays for the PR).\n * Idempotent — does not throw if the worktree is already gone.\n */\nexport async function removeWorktree(worktreePath: string): Promise<void> {\n const absPath = resolve(worktreePath);\n\n if (!existsSync(absPath)) {\n return;\n }\n\n // We need the repo path to acquire the lock.\n // Read the .git file in the worktree to find the main repo.\n const repoPath = await findRepoForWorktree(absPath);\n\n if (repoPath) {\n await withGitLock(repoPath, async () => {\n try {\n await execFileAsync(\"git\", [\"worktree\", \"remove\", absPath, \"--force\"], {\n cwd: repoPath,\n timeout: GIT_TIMEOUT,\n });\n } catch {\n // Worktree reference may be broken — force cleanup\n await rm(absPath, { recursive: true, force: true });\n await execFileAsync(\"git\", [\"worktree\", \"prune\"], {\n cwd: repoPath,\n timeout: GIT_TIMEOUT,\n }).catch(() => {});\n }\n\n // Refresh the main repo's index stat cache to prevent phantom modifications.\n // Worktree operations can desync timestamps causing `git status` to show\n // files as modified when they are not.\n await execFileAsync(\"git\", [\"update-index\", \"--refresh\"], {\n cwd: repoPath,\n timeout: GIT_TIMEOUT,\n }).catch(() => {});\n });\n } else {\n // No repo found — just remove the directory\n await rm(absPath, { recursive: true, force: true });\n }\n}\n\n/**\n * List all worktrees for a repository.\n */\nexport async function listWorktrees(repoPath: string): Promise<WorktreeInfo[]> {\n const absRepoPath = resolve(repoPath);\n\n const { stdout } = await execFileAsync(\"git\", [\"worktree\", \"list\", \"--porcelain\"], {\n cwd: absRepoPath,\n timeout: GIT_TIMEOUT,\n });\n\n const worktrees: WorktreeInfo[] = [];\n let current: { path: string; branch: string } | undefined;\n\n for (const line of stdout.split(\"\\n\")) {\n if (line.startsWith(\"worktree \")) {\n if (current) {\n worktrees.push({ ...current, repoPath: absRepoPath });\n }\n current = { path: line.slice(9), branch: \"\" };\n } else if (line.startsWith(\"branch \") && current) {\n // \"branch refs/heads/feat/run-abc\" → \"feat/run-abc\"\n current.branch = line.slice(7).replace(\"refs/heads/\", \"\");\n }\n }\n if (current) {\n worktrees.push({ ...current, repoPath: absRepoPath });\n }\n\n return worktrees;\n}\n\n/**\n * Clean up worktrees under worktreeBaseDir that no longer have a matching run.\n * Removes any subdirectory that is a git worktree.\n */\nexport async function cleanupOrphanedWorktrees(worktreeBaseDir: string): Promise<void> {\n const absBase = resolve(worktreeBaseDir);\n\n if (!existsSync(absBase)) {\n return;\n }\n\n const entries = await readdir(absBase, { withFileTypes: true });\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const worktreePath = resolve(absBase, entry.name);\n await removeWorktree(worktreePath);\n }\n}\n\n/**\n * Find the main repository path for a worktree by reading its .git file.\n * Worktrees have a .git *file* (not directory) that points to the main repo.\n */\nasync function findRepoForWorktree(worktreePath: string): Promise<string | undefined> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"--git-common-dir\"], {\n cwd: worktreePath,\n timeout: GIT_TIMEOUT,\n });\n // Returns something like \"/path/to/repo/.git\" — we want the parent\n const gitCommonDir = resolve(worktreePath, stdout.trim());\n return resolve(gitCommonDir, \"..\");\n } catch {\n return undefined;\n }\n}\n","import { appendFile, mkdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Middleware } from \"@/types\";\n\nconst DEFAULT_FLUSH_INTERVAL_MS = 500;\nconst DEFAULT_FLUSH_SIZE = 20;\n\n/**\n * Audit log middleware.\n *\n * Buffers JSONL entries in memory and flushes to disk either when\n * the buffer reaches `flushSize` entries or every `flushIntervalMs`.\n * File per session. Uses `{ decision: \"async\" }` so it never blocks the chain.\n *\n * Call `flush()` to force-write remaining entries (e.g. on shutdown).\n */\nexport interface AuditLogMiddleware extends Middleware {\n flush: () => Promise<void>;\n}\n\nexport function auditLog(options: {\n dir: string;\n includeInput?: boolean;\n includeOutput?: boolean;\n flushIntervalMs?: number;\n flushSize?: number;\n}): AuditLogMiddleware {\n const {\n dir,\n includeInput = true,\n includeOutput = false,\n flushIntervalMs = DEFAULT_FLUSH_INTERVAL_MS,\n flushSize = DEFAULT_FLUSH_SIZE,\n } = options;\n\n let dirCreated = false;\n // sessionId → buffered lines\n const buffers = new Map<string, string[]>();\n let flushTimer: ReturnType<typeof setInterval> | undefined;\n\n async function ensureDir(): Promise<void> {\n if (!dirCreated) {\n await mkdir(dir, { recursive: true });\n dirCreated = true;\n }\n }\n\n async function flushAll(): Promise<void> {\n if (buffers.size === 0) return;\n await ensureDir();\n\n const writes: Promise<void>[] = [];\n for (const [sessionId, lines] of buffers) {\n const filePath = path.join(dir, `${sessionId}.jsonl`);\n writes.push(appendFile(filePath, lines.join(\"\"), \"utf-8\"));\n }\n buffers.clear();\n await Promise.all(writes);\n }\n\n async function flushSession(sessionId: string): Promise<void> {\n const lines = buffers.get(sessionId);\n if (!lines || lines.length === 0) return;\n await ensureDir();\n\n const filePath = path.join(dir, `${sessionId}.jsonl`);\n await appendFile(filePath, lines.join(\"\"), \"utf-8\");\n buffers.delete(sessionId);\n }\n\n return {\n name: \"audit-log\",\n on: \"PostToolUse\",\n async flush() {\n await flushAll();\n if (flushTimer !== undefined) {\n clearInterval(flushTimer);\n flushTimer = undefined;\n }\n },\n async handler(event, context) {\n const entry: Record<string, unknown> = {\n timestamp: new Date().toISOString(),\n sessionId: event.sessionId,\n agent: context.agent,\n toolName: event.toolName,\n };\n\n if (includeInput && event.input !== undefined) {\n entry.input = event.input;\n }\n\n if (includeOutput && event.output !== undefined) {\n entry.output = event.output;\n }\n\n const sessionId = event.sessionId;\n let lines = buffers.get(sessionId);\n if (!lines) {\n lines = [];\n buffers.set(sessionId, lines);\n }\n lines.push(`${JSON.stringify(entry)}\\n`);\n\n // Flush when buffer is full\n if (lines.length >= flushSize) {\n await flushSession(sessionId);\n }\n\n // Start periodic flush timer if not already running\n if (flushTimer === undefined && flushIntervalMs > 0) {\n flushTimer = setInterval(() => {\n void flushAll();\n }, flushIntervalMs);\n // Unref so it doesn't keep the process alive\n if (typeof flushTimer === \"object\" && \"unref\" in flushTimer) {\n flushTimer.unref();\n }\n }\n\n return { decision: \"async\", asyncTimeout: 5_000 };\n },\n };\n}\n","import type { Middleware } from \"@/types\";\n\n/**\n * Budget guard middleware.\n *\n * Checks daily cost against budget cap on every tool call.\n * If over budget, blocks with reason \"Daily budget exceeded\".\n * Uses the middleware context's `get(\"costToday\")` and `get(\"budgetCapUsd\")`.\n */\nexport function budgetGuard(): Middleware {\n return {\n name: \"budget-guard\",\n on: \"PreToolUse\",\n async handler(_event, context) {\n const costToday = context.get(\"costToday\");\n const budgetCapUsd = context.get(\"budgetCapUsd\");\n\n if (costToday !== undefined && budgetCapUsd !== undefined && costToday >= budgetCapUsd) {\n return {\n decision: \"block\",\n reason: \"Daily budget exceeded\",\n };\n }\n\n return { decision: \"pass\" };\n },\n };\n}\n","import type {\n HookCallback,\n HookCallbackMatcher,\n HookInput,\n HookJSONOutput,\n HookEvent as SDKHookEvent,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport type {\n HookEvent,\n Middleware,\n MiddlewareContext,\n MiddlewareEvent,\n MiddlewareResult,\n} from \"@/types\";\n\nexport interface MiddlewareChain {\n execute(event: MiddlewareEvent, context: MiddlewareContext): Promise<MiddlewareResult>;\n}\n\nfunction matchesTool(match: string | string[] | undefined, toolName: string | undefined): boolean {\n if (match === undefined) return true;\n if (toolName === undefined) return false;\n if (Array.isArray(match)) return match.includes(toolName);\n return match === toolName;\n}\n\nexport function buildMiddlewareChain(middleware: Middleware[]): MiddlewareChain {\n return {\n async execute(event: MiddlewareEvent, context: MiddlewareContext): Promise<MiddlewareResult> {\n let lastAsync: MiddlewareResult | undefined;\n\n for (const mw of middleware) {\n // Hook event matching\n if (mw.on !== event.hookEvent) continue;\n\n // Tool name matching\n if (!matchesTool(mw.match, event.toolName)) continue;\n\n const result = await mw.handler(event, context);\n\n switch (result.decision) {\n case \"block\":\n return result;\n case \"async\":\n lastAsync = result;\n break;\n case \"pass\":\n break;\n }\n }\n\n return lastAsync ?? { decision: \"pass\" };\n },\n };\n}\n\n/**\n * SDK hooks type — maps hook event names to callback matchers.\n */\nexport type SDKHooks = Partial<Record<SDKHookEvent, HookCallbackMatcher[]>>;\n\n/**\n * Convert a middleware chain to Agent SDK hooks format.\n *\n * Creates one HookCallbackMatcher per supported event (PreToolUse, PostToolUse, Notification).\n * The matcher delegates to the chain's execute method, translating SDK input to our\n * MiddlewareEvent format.\n */\nexport function buildSDKHooks(\n chain: MiddlewareChain,\n context: MiddlewareContext,\n middleware: Middleware[] = [],\n): SDKHooks {\n function makeCallback(hookEvent: HookEvent): HookCallback {\n return async (input: HookInput): Promise<HookJSONOutput> => {\n const event: MiddlewareEvent = {\n hookEvent,\n sessionId: input.session_id,\n toolName: \"tool_name\" in input ? (input.tool_name as string) : undefined,\n input: \"tool_input\" in input ? (input.tool_input as Record<string, unknown>) : undefined,\n output: \"tool_response\" in input ? String(input.tool_response) : undefined,\n message: \"message\" in input ? (input.message as string) : undefined,\n };\n\n const result = await chain.execute(event, context);\n\n switch (result.decision) {\n case \"block\":\n return { decision: \"block\", reason: result.reason };\n case \"async\":\n return { async: true, asyncTimeout: result.asyncTimeout };\n case \"pass\":\n return {};\n }\n };\n }\n\n // Only register hooks for events that have at least one middleware listener\n const usedEvents = new Set(middleware.map((mw) => mw.on));\n const allEvents: HookEvent[] = [\"PreToolUse\", \"PostToolUse\", \"Notification\"];\n\n const hooks: SDKHooks = {};\n for (const hookEvent of allEvents) {\n // When no middleware list is provided, register all events (backward-compatible)\n if (middleware.length === 0 || usedEvents.has(hookEvent)) {\n hooks[hookEvent] = [{ hooks: [makeCallback(hookEvent)] }];\n }\n }\n\n return hooks;\n}\n","import type { Middleware } from \"@/types\";\n\n/**\n * Loop detection middleware.\n *\n * Tracks Bash commands per session. If the same command appears\n * `threshold` times, blocks it and tells the agent to escalate.\n *\n * Call `cleanup(sessionId)` when a session ends to prevent memory leaks.\n */\nexport interface LoopDetectionMiddleware extends Middleware {\n cleanup: (sessionId: string) => void;\n}\n\nexport function loopDetection(options: {\n threshold: number;\n scope?: \"session\";\n}): LoopDetectionMiddleware {\n const { threshold } = options;\n const commandHistory = new Map<string, Map<string, number>>();\n\n return {\n name: \"loop-detection\",\n on: \"PreToolUse\",\n match: \"Bash\",\n cleanup(sessionId: string) {\n commandHistory.delete(sessionId);\n },\n async handler(event) {\n const sessionId = event.sessionId;\n const command =\n event.input && typeof event.input === \"object\" && \"command\" in event.input\n ? String(event.input.command)\n : \"\";\n\n if (!command) return { decision: \"pass\" };\n\n if (!commandHistory.has(sessionId)) {\n commandHistory.set(sessionId, new Map());\n }\n\n const sessionHistory = commandHistory.get(sessionId) ?? new Map<string, number>();\n const count = (sessionHistory.get(command) ?? 0) + 1;\n sessionHistory.set(command, count);\n\n if (count >= threshold) {\n return {\n decision: \"block\",\n reason: `Loop detected: you have run this exact command ${String(count)} times. STOP and escalate — do not retry the same approach.`,\n };\n }\n\n return { decision: \"pass\" };\n },\n };\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Semaphore } from \"@/concurrency/semaphore\";\nimport type { NeoConfig, RepoConfig } from \"@/config\";\nimport { CostJournal } from \"@/cost/journal\";\nimport { NeoEventEmitter } from \"@/events\";\nimport { EventJournal } from \"@/events/journal\";\nimport { WebhookDispatcher } from \"@/events/webhook\";\nimport { getBranchName, pushWorktreeBranch } from \"@/isolation/git\";\nimport { buildSandboxConfig } from \"@/isolation/sandbox\";\nimport { cleanupOrphanedWorktrees, createWorktree, removeWorktree } from \"@/isolation/worktree\";\nimport { auditLog } from \"@/middleware/audit-log\";\nimport { budgetGuard } from \"@/middleware/budget-guard\";\nimport { buildMiddlewareChain, buildSDKHooks } from \"@/middleware/chain\";\nimport { loopDetection } from \"@/middleware/loop-detection\";\nimport { getJournalsDir, getRepoRunsDir, getRunsDir, toRepoSlug } from \"@/paths\";\nimport { parseOutput } from \"@/runner/output-parser\";\nimport { runWithRecovery } from \"@/runner/recovery\";\nimport type {\n ActiveSession,\n CostEntry,\n DispatchInput,\n Middleware,\n MiddlewareContext,\n NeoEvent,\n OrchestratorStatus,\n PersistedRun,\n ResolvedAgent,\n StepResult,\n TaskResult,\n WorkflowDefinition,\n WorkflowStepDef,\n} from \"@/types\";\nimport { WorkflowRegistry } from \"@/workflows/registry\";\n\n// ─── Constants ─────────────────────────────────────────\n\nconst MAX_PROMPT_SIZE = 100 * 1024; // 100 KB\nconst MAX_METADATA_DEPTH = 5;\nconst SHUTDOWN_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\nconst WORKTREES_DIR = \".neo/worktrees\";\nconst textEncoder = new TextEncoder();\n\n// ─── Options ───────────────────────────────────────────\n\nexport interface OrchestratorOptions {\n middleware?: Middleware[] | undefined;\n journalDir?: string | undefined;\n builtInWorkflowDir?: string | undefined;\n customWorkflowDir?: string | undefined;\n}\n\n// ─── Internal dispatch context ─────────────────────────\n\ninterface DispatchContext {\n input: DispatchInput;\n runId: string;\n sessionId: string;\n startedAt: number;\n stepName: string;\n stepDef: WorkflowStepDef;\n agent: ResolvedAgent;\n repoConfig: RepoConfig;\n activeSession: ActiveSession;\n}\n\n// ─── Idempotency ───────────────────────────────────────\n\ninterface IdempotencyEntry {\n result: TaskResult;\n expiresAt: number;\n}\n\n// ─── Orchestrator ──────────────────────────────────────\n\nexport class Orchestrator extends NeoEventEmitter {\n private readonly config: NeoConfig;\n private readonly semaphore: Semaphore;\n private readonly userMiddleware: Middleware[];\n private readonly workflows = new Map<string, WorkflowDefinition>();\n private readonly registeredAgents = new Map<string, ResolvedAgent>();\n private readonly _activeSessions = new Map<string, ActiveSession>();\n private readonly idempotencyCache = new Map<string, IdempotencyEntry>();\n private readonly abortControllers = new Map<string, AbortController>();\n private readonly repoIndex = new Map<string, RepoConfig>();\n private readonly createdRunDirs = new Set<string>();\n private readonly journalDir: string;\n private readonly builtInWorkflowDir: string | undefined;\n private readonly customWorkflowDir: string | undefined;\n private costJournal: CostJournal | null = null;\n private eventJournal: EventJournal | null = null;\n private webhookDispatcher: WebhookDispatcher | null = null;\n private _paused = false;\n private _costToday = 0;\n private _startedAt = 0;\n private _drainResolve: (() => void) | null = null;\n\n constructor(config: NeoConfig, options: OrchestratorOptions = {}) {\n super();\n this.config = config;\n this.userMiddleware = options.middleware ?? [];\n this.journalDir = options.journalDir ?? getJournalsDir();\n this.builtInWorkflowDir = options.builtInWorkflowDir;\n this.customWorkflowDir = options.customWorkflowDir;\n for (const repo of config.repos) {\n const resolvedPath = path.resolve(repo.path);\n const normalizedRepo = { ...repo, path: resolvedPath };\n this.repoIndex.set(resolvedPath, normalizedRepo);\n }\n this.semaphore = new Semaphore(\n {\n maxSessions: config.concurrency.maxSessions,\n maxPerRepo: config.concurrency.maxPerRepo,\n queueMax: config.concurrency.queueMax,\n },\n {\n onEnqueue: (sessionId, repo, position) => {\n this.emit({\n type: \"queue:enqueue\",\n sessionId,\n repo,\n position,\n timestamp: new Date().toISOString(),\n });\n },\n onDequeue: (sessionId, repo, waitedMs) => {\n this.emit({\n type: \"queue:dequeue\",\n sessionId,\n repo,\n waitedMs,\n timestamp: new Date().toISOString(),\n });\n },\n },\n );\n }\n\n // ─── Registration ──────────────────────────────────────\n\n registerWorkflow(definition: WorkflowDefinition): void {\n this.workflows.set(definition.name, definition);\n }\n\n registerAgent(agent: ResolvedAgent): void {\n this.registeredAgents.set(agent.name, agent);\n }\n\n // ─── Dispatch ──────────────────────────────────────────\n\n async dispatch(input: DispatchInput): Promise<TaskResult> {\n const idempotencyKey = this.preDispatchChecks(input);\n const ctx = this.buildDispatchContext(input);\n\n // Acquire semaphore (blocks if at capacity)\n const abortController = new AbortController();\n this.abortControllers.set(ctx.sessionId, abortController);\n await this.semaphore.acquire(\n input.repo,\n ctx.sessionId,\n input.priority ?? \"medium\",\n abortController.signal,\n );\n ctx.activeSession.status = \"running\";\n\n const stepResult = await this.executeStep(ctx);\n return this.finalizeDispatch(ctx, stepResult, idempotencyKey);\n }\n\n // ─── Control ───────────────────────────────────────────\n\n pause(): void {\n this._paused = true;\n }\n\n resume(): void {\n this._paused = false;\n }\n\n async kill(sessionId: string): Promise<void> {\n const controller = this.abortControllers.get(sessionId);\n if (controller) {\n controller.abort(new Error(\"Session killed\"));\n }\n\n this._activeSessions.delete(sessionId);\n this.abortControllers.delete(sessionId);\n this.semaphore.release(sessionId);\n }\n\n async drain(): Promise<void> {\n this._paused = true;\n if (this._activeSessions.size === 0) return;\n return new Promise<void>((resolve) => {\n this._drainResolve = resolve;\n });\n }\n\n // ─── Getters ───────────────────────────────────────────\n\n get status(): OrchestratorStatus {\n return {\n paused: this._paused,\n activeSessions: [...this._activeSessions.values()],\n queueDepth: this.semaphore.queueDepth(),\n costToday: this._costToday,\n budgetCapUsd: this.config.budget.dailyCapUsd,\n budgetRemainingPct: this.computeBudgetRemainingPct(),\n uptime: this._startedAt > 0 ? Date.now() - this._startedAt : 0,\n };\n }\n\n get activeSessions(): ActiveSession[] {\n return [...this._activeSessions.values()];\n }\n\n // ─── Lifecycle ─────────────────────────────────────────\n\n async start(): Promise<void> {\n this._startedAt = Date.now();\n\n // Initialize journals\n this.costJournal = new CostJournal({ dir: this.journalDir });\n this.eventJournal = new EventJournal({ dir: this.journalDir });\n\n // Initialize webhook dispatcher if webhooks are configured\n if (this.config.webhooks.length > 0) {\n this.webhookDispatcher = new WebhookDispatcher(this.config.webhooks);\n }\n\n // Restore today's cost from journal\n this._costToday = await this.costJournal.getDayTotal();\n\n // Load workflows from registry if dirs are configured\n if (this.builtInWorkflowDir) {\n const registry = new WorkflowRegistry(this.builtInWorkflowDir, this.customWorkflowDir);\n await registry.load();\n for (const workflow of registry.list()) {\n this.registerWorkflow(workflow);\n }\n }\n\n await this.recoverOrphanedRuns();\n\n for (const repo of this.config.repos) {\n const worktreeBase = path.join(repo.path, WORKTREES_DIR);\n await cleanupOrphanedWorktrees(worktreeBase).catch(() => {});\n }\n }\n\n async shutdown(): Promise<void> {\n this._paused = true;\n\n if (this._activeSessions.size > 0) {\n await Promise.race([\n this.drain(),\n new Promise<void>((resolve) => setTimeout(resolve, SHUTDOWN_TIMEOUT_MS)),\n ]);\n }\n\n for (const mw of this.userMiddleware) {\n if (\"flush\" in mw && typeof mw.flush === \"function\") {\n await (mw as { flush: () => Promise<void> }).flush();\n }\n if (\"cleanup\" in mw && typeof mw.cleanup === \"function\") {\n for (const session of this._activeSessions.values()) {\n (mw as { cleanup: (id: string) => void }).cleanup(session.sessionId);\n }\n }\n }\n\n this.emit({\n type: \"orchestrator:shutdown\",\n timestamp: new Date().toISOString(),\n });\n }\n\n // ─── Emit override (journal events) ───────────────────\n\n override emit(event: NeoEvent): void {\n super.emit(event);\n // Fire-and-forget event journal append\n if (this.eventJournal) {\n this.eventJournal.append(event).catch(() => {});\n }\n // Fire-and-forget webhook dispatch\n if (this.webhookDispatcher) {\n this.webhookDispatcher.dispatch(event);\n }\n }\n\n // ─── Static middleware factories ───────────────────────\n\n static middleware = {\n loopDetection: (options: { threshold: number; scope?: \"session\" }) => loopDetection(options),\n auditLog: (options: {\n dir: string;\n includeInput?: boolean;\n includeOutput?: boolean;\n flushIntervalMs?: number;\n flushSize?: number;\n }) => auditLog(options),\n budgetGuard: () => budgetGuard(),\n };\n\n // ─── Private: Dispatch phases ──────────────────────────\n\n private preDispatchChecks(input: DispatchInput): string | null {\n this.validateInput(input);\n\n const idempotencyKey = this.computeIdempotencyKey(input);\n if (idempotencyKey) {\n this.evictExpiredIdempotencyEntries();\n const cached = this.idempotencyCache.get(idempotencyKey);\n if (cached && cached.expiresAt > Date.now()) {\n throw new Error(\n `Duplicate dispatch rejected: runId '${input.runId ?? \"auto-generated\"}' already exists. Each dispatch must use a unique runId.`,\n );\n }\n }\n\n if (this._paused) {\n throw new Error(\n \"Dispatch rejected: orchestrator is paused. Call orchestrator.resume() before dispatching.\",\n );\n }\n\n return idempotencyKey;\n }\n\n private buildDispatchContext(input: DispatchInput): DispatchContext {\n const runId = input.runId ?? randomUUID();\n const sessionId = randomUUID();\n const workflow = this.workflows.get(input.workflow);\n if (!workflow) {\n const available = [...this.workflows.keys()].join(\", \") || \"none\";\n throw new Error(\n `Workflow \"${input.workflow}\" not found. Available workflows: ${available}. Check the workflow name or register it first.`,\n );\n }\n const [stepName, stepDef] = this.getFirstStep(workflow, input);\n const agent = this.resolveStepAgent(stepDef, workflow.name);\n const repoConfig = this.resolveRepo(input.repo);\n\n const activeSession: ActiveSession = {\n sessionId,\n runId,\n workflow: input.workflow,\n step: stepName,\n agent: agent.name,\n repo: input.repo,\n status: \"queued\",\n startedAt: new Date().toISOString(),\n };\n this._activeSessions.set(sessionId, activeSession);\n\n return {\n input,\n runId,\n sessionId,\n startedAt: Date.now(),\n stepName,\n stepDef,\n agent,\n repoConfig,\n activeSession,\n };\n }\n\n private async executeStep(ctx: DispatchContext): Promise<StepResult> {\n const { input, runId, sessionId, startedAt, agent, repoConfig, activeSession } = ctx;\n let worktreePath: string | undefined;\n\n try {\n // Create worktree if writable agent\n if (agent.sandbox === \"writable\") {\n const branchName = getBranchName(repoConfig, runId);\n const worktreeDir = path.join(input.repo, WORKTREES_DIR, runId);\n const info = await createWorktree({\n repoPath: input.repo,\n branch: branchName,\n baseBranch: repoConfig.defaultBranch,\n worktreeDir,\n });\n worktreePath = info.path;\n activeSession.worktreePath = worktreePath;\n }\n\n const stepResult = await this.runAgentSession(ctx, worktreePath);\n this.emitCostEvents(sessionId, stepResult.costUsd, ctx);\n this.emitSessionComplete(ctx, stepResult);\n return stepResult;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.emitSessionFail(ctx, errorMsg);\n\n return {\n status: \"failure\",\n sessionId,\n costUsd: 0,\n durationMs: Date.now() - startedAt,\n agent: agent.name,\n startedAt: activeSession.startedAt,\n completedAt: new Date().toISOString(),\n error: errorMsg,\n attempt: 1,\n };\n } finally {\n // Auto-commit, push, and cleanup worktree\n if (worktreePath) {\n await this.finalizeWorktree(worktreePath, ctx);\n }\n\n this.semaphore.release(sessionId);\n this._activeSessions.delete(sessionId);\n this.abortControllers.delete(sessionId);\n\n if (this._activeSessions.size === 0 && this._drainResolve) {\n this._drainResolve();\n this._drainResolve = null;\n }\n }\n }\n\n /**\n * Push the branch, then remove the worktree.\n * Runs in `finally` so it executes on both success and failure.\n */\n private async finalizeWorktree(worktreePath: string, ctx: DispatchContext): Promise<void> {\n const { runId, repoConfig } = ctx;\n const branch = getBranchName(repoConfig, runId);\n const remote = repoConfig.pushRemote ?? \"origin\";\n\n try {\n await pushWorktreeBranch(worktreePath, branch, remote).catch(() => {\n // Push may fail (no remote, auth, etc.) — not critical\n });\n } catch {\n // Best-effort — don't let finalization errors mask the real result\n }\n\n try {\n await removeWorktree(worktreePath);\n } catch {\n // Worktree cleanup is best-effort\n }\n }\n\n private async runAgentSession(\n ctx: DispatchContext,\n worktreePath: string | undefined,\n ): Promise<StepResult> {\n const { input, runId, sessionId, stepName, stepDef, agent, activeSession } = ctx;\n\n const sandboxConfig = buildSandboxConfig(agent, worktreePath);\n const chain = buildMiddlewareChain(this.userMiddleware);\n const middlewareContext = this.buildMiddlewareContext(\n runId,\n input.workflow,\n stepName,\n agent.name,\n input.repo,\n );\n const hooks = buildSDKHooks(chain, middlewareContext, this.userMiddleware);\n\n this.emit({\n type: \"session:start\",\n sessionId,\n runId,\n workflow: input.workflow,\n step: stepName,\n agent: agent.name,\n repo: input.repo,\n metadata: input.metadata,\n timestamp: new Date().toISOString(),\n });\n\n const recoveryOpts = stepDef.recovery;\n const sessionResult = await runWithRecovery({\n agent,\n prompt: stepDef.prompt ?? input.prompt,\n repoPath: input.repo,\n sandboxConfig,\n hooks,\n initTimeoutMs: this.config.sessions.initTimeoutMs,\n maxDurationMs: this.config.sessions.maxDurationMs,\n maxRetries: recoveryOpts?.maxRetries ?? this.config.recovery.maxRetries,\n backoffBaseMs: this.config.recovery.backoffBaseMs,\n ...(worktreePath ? { worktreePath } : {}),\n ...(recoveryOpts?.nonRetryable ? { nonRetryable: recoveryOpts.nonRetryable } : {}),\n onAttempt: (attempt, strategy) => {\n if (attempt > 1) {\n this.emit({\n type: \"session:fail\",\n sessionId,\n runId,\n error: `Retrying with strategy: ${strategy}`,\n attempt: attempt - 1,\n maxRetries: recoveryOpts?.maxRetries ?? this.config.recovery.maxRetries,\n willRetry: true,\n metadata: input.metadata,\n timestamp: new Date().toISOString(),\n });\n }\n },\n });\n\n const parsed = parseOutput(sessionResult.output);\n\n return {\n status: \"success\",\n sessionId: sessionResult.sessionId,\n output: parsed.output ?? parsed.rawOutput,\n rawOutput: sessionResult.output,\n costUsd: sessionResult.costUsd,\n durationMs: sessionResult.durationMs,\n agent: agent.name,\n startedAt: activeSession.startedAt,\n completedAt: new Date().toISOString(),\n attempt: 1,\n };\n }\n\n private async finalizeDispatch(\n ctx: DispatchContext,\n stepResult: StepResult,\n idempotencyKey: string | null,\n ): Promise<TaskResult> {\n const { input, runId, stepName, repoConfig, activeSession } = ctx;\n\n const taskResult: TaskResult = {\n runId,\n workflow: input.workflow,\n repo: input.repo,\n status: stepResult.status === \"success\" ? \"success\" : \"failure\",\n steps: { [stepName]: stepResult },\n branch:\n stepResult.status === \"success\" && activeSession.worktreePath\n ? getBranchName(repoConfig, runId)\n : undefined,\n costUsd: stepResult.costUsd,\n durationMs: Date.now() - ctx.startedAt,\n timestamp: new Date().toISOString(),\n metadata: input.metadata,\n };\n\n await this.persistRun({\n version: 1,\n runId,\n workflow: input.workflow,\n repo: input.repo,\n prompt: input.prompt,\n branch: taskResult.branch,\n status: taskResult.status === \"success\" ? \"completed\" : \"failed\",\n steps: taskResult.steps,\n createdAt: activeSession.startedAt,\n updatedAt: new Date().toISOString(),\n metadata: input.metadata,\n });\n\n if (idempotencyKey) {\n const ttl = this.config.idempotency?.ttlMs ?? 3_600_000;\n this.idempotencyCache.set(idempotencyKey, {\n result: taskResult,\n expiresAt: Date.now() + ttl,\n });\n }\n\n return taskResult;\n }\n\n // ─── Private: Event helpers ────────────────────────────\n\n private emitCostEvents(sessionId: string, sessionCost: number, ctx: DispatchContext): void {\n this._costToday += sessionCost;\n\n // Persist cost entry to journal (fire-and-forget)\n if (this.costJournal) {\n const costEntry: CostEntry = {\n timestamp: new Date().toISOString(),\n runId: ctx.runId,\n workflow: ctx.input.workflow,\n step: ctx.stepName,\n sessionId,\n agent: ctx.agent.name,\n costUsd: sessionCost,\n models: {},\n durationMs: Date.now() - ctx.startedAt,\n repo: ctx.input.repo,\n };\n this.costJournal.append(costEntry).catch(() => {});\n }\n\n this.emit({\n type: \"cost:update\",\n sessionId,\n sessionCost,\n todayTotal: this._costToday,\n budgetRemainingPct: this.computeBudgetRemainingPct(),\n timestamp: new Date().toISOString(),\n });\n\n const utilizationPct = (this._costToday / this.config.budget.dailyCapUsd) * 100;\n if (utilizationPct >= this.config.budget.alertThresholdPct) {\n this.emit({\n type: \"budget:alert\",\n todayTotal: this._costToday,\n capUsd: this.config.budget.dailyCapUsd,\n utilizationPct,\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n private emitSessionComplete(ctx: DispatchContext, stepResult: StepResult): void {\n this.emit({\n type: \"session:complete\",\n sessionId: ctx.sessionId,\n runId: ctx.runId,\n status: \"success\",\n costUsd: stepResult.costUsd,\n durationMs: stepResult.durationMs,\n output: stepResult.output,\n metadata: ctx.input.metadata,\n timestamp: new Date().toISOString(),\n });\n }\n\n private emitSessionFail(ctx: DispatchContext, errorMsg: string): void {\n this.emit({\n type: \"session:fail\",\n sessionId: ctx.sessionId,\n runId: ctx.runId,\n error: errorMsg,\n attempt: 1,\n maxRetries: this.config.recovery.maxRetries,\n willRetry: false,\n metadata: ctx.input.metadata,\n timestamp: new Date().toISOString(),\n });\n }\n\n // ─── Private: Input validation ─────────────────────────\n\n private validateInput(input: DispatchInput): void {\n if (!input.prompt || input.prompt.trim().length === 0) {\n throw new Error(\"Validation error: prompt must be a non-empty string\");\n }\n if (textEncoder.encode(input.prompt).length > MAX_PROMPT_SIZE) {\n throw new Error(\n `Validation error: prompt exceeds maximum size of ${String(MAX_PROMPT_SIZE)} bytes`,\n );\n }\n\n if (!existsSync(input.repo)) {\n throw new Error(`Validation error: repo path does not exist: ${input.repo}`);\n }\n\n if (!this.workflows.has(input.workflow)) {\n throw new Error(`Validation error: workflow \"${input.workflow}\" not found in registry`);\n }\n\n if (input.metadata !== undefined) {\n if (!isPlainObject(input.metadata)) {\n throw new Error(\"Validation error: metadata must be a plain object\");\n }\n if (objectDepth(input.metadata) > MAX_METADATA_DEPTH) {\n throw new Error(\n `Validation error: metadata exceeds maximum nesting depth of ${String(MAX_METADATA_DEPTH)}`,\n );\n }\n }\n\n const resumeOptions = [input.step, input.from, input.retry].filter(Boolean);\n if (resumeOptions.length > 1) {\n throw new Error(\"Validation error: step, from, and retry are mutually exclusive\");\n }\n }\n\n // ─── Private: Helpers ──────────────────────────────────\n\n private evictExpiredIdempotencyEntries(): void {\n const now = Date.now();\n for (const [key, entry] of this.idempotencyCache) {\n if (entry.expiresAt <= now) {\n this.idempotencyCache.delete(key);\n }\n }\n }\n\n private computeIdempotencyKey(input: DispatchInput): string | null {\n const idempotency = this.config.idempotency;\n if (!idempotency?.enabled) return null;\n\n const key = idempotency.key ?? \"metadata\";\n if (key === \"prompt\") {\n return `${input.workflow}:${input.repo}:${input.prompt}`;\n }\n return `${input.workflow}:${input.repo}:${JSON.stringify(input.metadata ?? {})}`;\n }\n\n private getFirstStep(\n workflow: WorkflowDefinition,\n input: DispatchInput,\n ): [string, WorkflowStepDef] {\n if (input.step) {\n const step = workflow.steps[input.step];\n if (!step || step.type === \"gate\") {\n throw new Error(\n `Step \"${input.step}\" not found in workflow \"${workflow.name}\" or is a gate step. Check the step name in the workflow definition.`,\n );\n }\n return [input.step, step as WorkflowStepDef];\n }\n\n for (const [name, step] of Object.entries(workflow.steps)) {\n if (step.type === \"gate\") continue;\n const stepDef = step as WorkflowStepDef;\n if (!stepDef.dependsOn || stepDef.dependsOn.length === 0) {\n return [name, stepDef];\n }\n }\n\n const entries = Object.entries(workflow.steps);\n const first = entries[0];\n if (!first) {\n throw new Error(`Workflow \"${workflow.name}\" has no steps`);\n }\n return [first[0], first[1] as WorkflowStepDef];\n }\n\n private resolveStepAgent(step: WorkflowStepDef, workflowName: string): ResolvedAgent {\n const agent = this.registeredAgents.get(step.agent);\n if (!agent) {\n throw new Error(\n `Agent \"${step.agent}\" required by workflow \"${workflowName}\" not found in registry. Register the agent or check the workflow definition.`,\n );\n }\n return agent;\n }\n\n private resolveRepo(repoPath: string): RepoConfig {\n const repo = this.repoIndex.get(path.resolve(repoPath));\n if (repo) return repo;\n return {\n path: repoPath,\n defaultBranch: \"main\",\n branchPrefix: \"feat\",\n pushRemote: \"origin\",\n autoCreatePr: false,\n };\n }\n\n private buildMiddlewareContext(\n runId: string,\n workflow: string,\n step: string,\n agent: string,\n repo: string,\n ): MiddlewareContext {\n const store = new Map<string, unknown>();\n return {\n runId,\n workflow,\n step,\n agent,\n repo,\n get: ((key: string) => {\n if (key === \"costToday\") return this._costToday;\n if (key === \"budgetCapUsd\") return this.config.budget.dailyCapUsd;\n return store.get(key);\n }) as MiddlewareContext[\"get\"],\n set: ((key: string, value: unknown) => {\n store.set(key, value);\n }) as MiddlewareContext[\"set\"],\n };\n }\n\n private computeBudgetRemainingPct(): number {\n const cap = this.config.budget.dailyCapUsd;\n if (cap <= 0) return 0;\n return Math.max(0, ((cap - this._costToday) / cap) * 100);\n }\n\n // ─── Private: Run persistence ──────────────────────────\n\n private async persistRun(run: PersistedRun): Promise<void> {\n try {\n const slug = toRepoSlug({ path: run.repo });\n const runsDir = getRepoRunsDir(slug);\n if (!this.createdRunDirs.has(runsDir)) {\n await mkdir(runsDir, { recursive: true });\n this.createdRunDirs.add(runsDir);\n }\n const filePath = path.join(runsDir, `${run.runId}.json`);\n await writeFile(filePath, JSON.stringify(run, null, 2), \"utf-8\");\n } catch {\n // Non-critical — don't fail the dispatch if persistence fails\n }\n }\n\n private async recoverOrphanedRuns(): Promise<void> {\n const runsDir = getRunsDir();\n if (!existsSync(runsDir)) return;\n\n try {\n const entries = await readdir(runsDir, { withFileTypes: true });\n // Scan slug subdirs and legacy flat .json files\n const jsonFiles: string[] = [];\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const subDir = path.join(runsDir, entry.name);\n const subFiles = await readdir(subDir);\n for (const f of subFiles) {\n if (f.endsWith(\".json\")) jsonFiles.push(path.join(subDir, f));\n }\n } else if (entry.name.endsWith(\".json\")) {\n jsonFiles.push(path.join(runsDir, entry.name));\n }\n }\n\n for (const filePath of jsonFiles) {\n const content = await readFile(filePath, \"utf-8\");\n const run = JSON.parse(content) as PersistedRun;\n\n if (run.status === \"running\") {\n run.status = \"failed\";\n run.updatedAt = new Date().toISOString();\n await writeFile(filePath, JSON.stringify(run, null, 2), \"utf-8\");\n }\n }\n } catch {\n // Non-critical\n }\n }\n}\n\n// ─── Utility functions ─────────────────────────────────\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction objectDepth(obj: unknown, current = 0): number {\n if (!isPlainObject(obj)) return current;\n let max = current + 1;\n for (const value of Object.values(obj)) {\n const depth = objectDepth(value, current + 1);\n if (depth > max) max = depth;\n }\n return max;\n}\n","import type { ZodType } from \"zod\";\n\nexport interface ParsedOutput {\n rawOutput: string;\n output?: unknown;\n parseError?: string;\n}\n\n/**\n * Extract JSON from agent output that may be wrapped in markdown code blocks.\n * Tries multiple strategies: raw JSON parse, then markdown code block extraction.\n */\nfunction extractJson(raw: string): unknown | undefined {\n // Strategy 1: Try parsing the entire string as JSON\n try {\n return JSON.parse(raw);\n } catch {\n // Not raw JSON, continue\n }\n\n // Strategy 2: Extract from markdown code blocks (```json ... ``` or ``` ... ```)\n const codeBlockRegex = /```(?:json)?\\s*\\n?([\\s\\S]*?)```/;\n const match = raw.match(codeBlockRegex);\n if (match?.[1]) {\n try {\n return JSON.parse(match[1].trim());\n } catch {\n // Invalid JSON inside code block\n }\n }\n\n return undefined;\n}\n\n/**\n * Parse agent output, optionally validating against a Zod schema.\n *\n * - If no schema: returns rawOutput only\n * - If schema provided: extracts JSON from output, validates with schema\n * - On failure: returns rawOutput + parseError (caller decides whether to retry)\n */\nexport function parseOutput(raw: string, schema?: ZodType): ParsedOutput {\n if (!schema) {\n return { rawOutput: raw };\n }\n\n const extracted = extractJson(raw);\n if (extracted === undefined) {\n return {\n rawOutput: raw,\n parseError: \"Failed to extract JSON from output\",\n };\n }\n\n const result = schema.safeParse(extracted);\n if (!result.success) {\n return {\n rawOutput: raw,\n parseError: `Schema validation failed: ${result.error.message}`,\n };\n }\n\n return {\n rawOutput: raw,\n output: result.data,\n };\n}\n","import type { McpServerConfig } from \"@/config\";\nimport type { SandboxConfig } from \"@/isolation/sandbox\";\nimport type { ResolvedAgent } from \"@/types\";\n\n// ─── Types ──────────────────────────────────────────────\n\nexport interface SessionOptions {\n agent: ResolvedAgent;\n prompt: string;\n repoPath?: string;\n worktreePath?: string;\n sandboxConfig: SandboxConfig;\n hooks?: Record<string, unknown>;\n mcpServers?: McpServerConfig[];\n initTimeoutMs: number;\n maxDurationMs: number;\n resumeSessionId?: string | undefined;\n onEvent?: ((event: SessionEvent) => void) | undefined;\n}\n\nexport interface SessionResult {\n sessionId: string;\n output: string;\n costUsd: number;\n durationMs: number;\n turnCount: number;\n}\n\nexport type SessionEvent =\n | { type: \"session:start\"; sessionId: string }\n | { type: \"session:complete\"; sessionId: string; result: SessionResult }\n | { type: \"session:fail\"; sessionId: string; error: string };\n\n// ─── SDK stream message shapes ──────────────────────────\n\ninterface SDKInitMessage {\n type: \"system\";\n subtype: \"init\";\n session_id: string;\n}\n\ninterface SDKResultMessage {\n type: \"result\";\n subtype: \"success\" | string;\n session_id: string;\n result: string;\n total_cost_usd: number;\n num_turns: number;\n}\n\ninterface SDKStreamMessage {\n type: string;\n subtype?: string;\n}\n\nfunction isInitMessage(msg: SDKStreamMessage): msg is SDKInitMessage {\n return msg.type === \"system\" && msg.subtype === \"init\";\n}\n\nfunction isResultMessage(msg: SDKStreamMessage): msg is SDKResultMessage {\n return msg.type === \"result\";\n}\n\n// ─── Helpers ────────────────────────────────────────────\n\nfunction checkAborted(signal: AbortSignal): void {\n if (signal.aborted) {\n const reason = signal.reason;\n throw reason instanceof Error ? reason : new Error(String(reason));\n }\n}\n\nfunction toSessionError(error: unknown, isTimeout: boolean, sessionId: string): SessionError {\n if (error instanceof SessionError) return error;\n const message = error instanceof Error ? error.message : String(error);\n return new SessionError(message, isTimeout ? \"timeout\" : \"unknown\", sessionId);\n}\n\n// ─── Session Runner ─────────────────────────────────────\n\nexport async function runSession(options: SessionOptions): Promise<SessionResult> {\n const { agent, prompt, worktreePath, sandboxConfig, initTimeoutMs, maxDurationMs, onEvent } =\n options;\n\n const startTime = Date.now();\n let sessionId = \"\";\n\n const abortController = new AbortController();\n const initTimer = setTimeout(() => {\n abortController.abort(new Error(\"Session init timeout exceeded\"));\n }, initTimeoutMs);\n const maxDurationTimer = setTimeout(() => {\n abortController.abort(new Error(\"Session max duration exceeded\"));\n }, maxDurationMs);\n\n try {\n const sdk = await import(\"@anthropic-ai/claude-agent-sdk\");\n\n const queryOptions: Record<string, unknown> = {\n // Always pass cwd: worktree for writable agents, repo root for readonly.\n // Without this, readonly agents default to process.cwd() and may write to main tree.\n cwd: worktreePath ?? options.repoPath,\n maxTurns: agent.maxTurns,\n allowedTools: sandboxConfig.allowedTools,\n };\n\n if (options.resumeSessionId) {\n queryOptions.resume = options.resumeSessionId;\n }\n\n if (options.mcpServers?.length) {\n queryOptions.mcpServers = options.mcpServers;\n }\n\n let output = \"\";\n let costUsd = 0;\n let turnCount = 0;\n\n // Combine agent system prompt with task prompt so the agent\n // receives its full instructions (commit, push, etc.)\n const fullPrompt = agent.definition.prompt\n ? `${agent.definition.prompt}\\n\\n---\\n\\n## Task\\n\\n${prompt}`\n : prompt;\n\n const stream = sdk.query({ prompt: fullPrompt, options: queryOptions as never });\n\n for await (const message of stream) {\n checkAborted(abortController.signal);\n\n const msg = message as SDKStreamMessage;\n\n if (isInitMessage(msg)) {\n sessionId = msg.session_id;\n clearTimeout(initTimer);\n onEvent?.({ type: \"session:start\", sessionId });\n }\n\n if (isResultMessage(msg)) {\n output = msg.result ?? \"\";\n costUsd = msg.total_cost_usd ?? 0;\n turnCount = msg.num_turns ?? 0;\n sessionId = msg.session_id ?? sessionId;\n\n if (msg.subtype !== \"success\") {\n throw new SessionError(\n `Session ended with error: ${msg.subtype}`,\n msg.subtype,\n sessionId,\n );\n }\n }\n }\n\n const sessionResult: SessionResult = {\n sessionId,\n output,\n costUsd,\n durationMs: Date.now() - startTime,\n turnCount,\n };\n\n onEvent?.({ type: \"session:complete\", sessionId, result: sessionResult });\n return sessionResult;\n } catch (error) {\n const errorSessionId = sessionId || \"unknown\";\n const sessionError = toSessionError(error, abortController.signal.aborted, errorSessionId);\n\n onEvent?.({ type: \"session:fail\", sessionId: errorSessionId, error: sessionError.message });\n throw sessionError;\n } finally {\n clearTimeout(initTimer);\n clearTimeout(maxDurationTimer);\n }\n}\n\n// ─── Error class ────────────────────────────────────────\n\nexport class SessionError extends Error {\n constructor(\n message: string,\n public readonly errorType: string,\n public readonly sessionId: string,\n ) {\n super(message);\n this.name = \"SessionError\";\n }\n}\n","import {\n runSession,\n SessionError,\n type SessionOptions,\n type SessionResult,\n} from \"@/runner/session\";\n\n// ─── Types ──────────────────────────────────────────────\n\nexport interface RecoveryOptions extends SessionOptions {\n maxRetries: number;\n backoffBaseMs: number;\n nonRetryable?: string[];\n onAttempt?: (attempt: number, strategy: string) => void;\n}\n\n// ─── Default non-retryable errors ───────────────────────\n\nconst DEFAULT_NON_RETRYABLE = [\"error_max_turns\", \"budget_exceeded\"];\n\n// ─── Recovery strategy names ────────────────────────────\n\nfunction getStrategy(attempt: number): string {\n switch (attempt) {\n case 1:\n return \"normal\";\n case 2:\n return \"resume\";\n default:\n return \"fresh\";\n }\n}\n\n// ─── Sleep utility ──────────────────────────────────────\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// ─── Error handling ─────────────────────────────────────\n\nfunction isNonRetryable(error: unknown, nonRetryable: string[]): boolean {\n return error instanceof SessionError && nonRetryable.includes(error.errorType);\n}\n\nfunction updateSessionId(error: unknown, current: string | undefined): string | undefined {\n if (error instanceof SessionError && error.sessionId !== \"unknown\") {\n return error.sessionId;\n }\n return current;\n}\n\nfunction buildFinalError(error: unknown, maxRetries: number): Error {\n if (error instanceof Error) {\n return new Error(`Recovery failed after ${maxRetries} attempts. Last error: ${error.message}`, {\n cause: error,\n });\n }\n return new Error(`Recovery failed after ${maxRetries} attempts`);\n}\n\n/**\n * Run a session with 3-level recovery escalation (ADR-020).\n *\n * Level 1 (attempt 1): Normal execution — new session\n * Level 2 (attempt 2): Resume session — pass resumeSessionId from level 1\n * Level 3 (attempt 3): Fresh session — abandon previous, start clean\n *\n * Non-retryable errors skip to immediate failure.\n * Backoff: backoffBaseMs * attempt between levels.\n */\nexport async function runWithRecovery(options: RecoveryOptions): Promise<SessionResult> {\n const {\n maxRetries,\n backoffBaseMs,\n nonRetryable = DEFAULT_NON_RETRYABLE,\n onAttempt,\n ...rest\n } = options;\n\n let lastSessionId: string | undefined;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n const strategy = getStrategy(attempt);\n onAttempt?.(attempt, strategy);\n\n try {\n const result = await runSession({\n ...rest,\n resumeSessionId: strategy === \"resume\" ? lastSessionId : undefined,\n });\n return result;\n } catch (error) {\n lastSessionId = updateSessionId(error, lastSessionId);\n\n if (isNonRetryable(error, nonRetryable)) throw error;\n if (attempt === maxRetries) throw buildFinalError(error, maxRetries);\n\n // Next attempt will be \"fresh\" — clear session to start clean\n if (getStrategy(attempt + 1) === \"fresh\") {\n lastSessionId = undefined;\n }\n\n await sleep(backoffBaseMs * attempt);\n }\n }\n\n throw new Error(\"Recovery failed: unreachable\");\n}\n","import { existsSync } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { WorkflowDefinition } from \"@/types\";\nimport { loadWorkflow } from \"@/workflows/loader\";\n\n/**\n * Registry for workflow definitions.\n * Loads built-in workflows from a directory and optional custom workflows.\n * Custom workflows with the same name override built-in ones.\n */\nexport class WorkflowRegistry {\n private readonly builtInDir: string;\n private readonly customDir: string | undefined;\n private readonly workflows = new Map<string, WorkflowDefinition>();\n\n constructor(builtInDir: string, customDir?: string) {\n this.builtInDir = builtInDir;\n this.customDir = customDir;\n }\n\n async load(): Promise<void> {\n // Load built-in workflows first\n await this.loadFromDir(this.builtInDir);\n\n // Custom workflows override built-in ones\n if (this.customDir) {\n await this.loadFromDir(this.customDir);\n }\n }\n\n get(name: string): WorkflowDefinition | undefined {\n return this.workflows.get(name);\n }\n\n list(): WorkflowDefinition[] {\n return [...this.workflows.values()];\n }\n\n has(name: string): boolean {\n return this.workflows.has(name);\n }\n\n private async loadFromDir(dir: string): Promise<void> {\n if (!existsSync(dir)) return;\n\n const files = await readdir(dir);\n for (const file of files) {\n if (!file.endsWith(\".yml\") && !file.endsWith(\".yaml\")) continue;\n const filePath = path.join(dir, file);\n const workflow = await loadWorkflow(filePath);\n this.workflows.set(workflow.name, workflow);\n }\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { parse } from \"yaml\";\nimport { z } from \"zod\";\nimport type { WorkflowDefinition, WorkflowGateDef, WorkflowStepDef } from \"@/types\";\n\n// ─── Zod Schemas ────────────────────────────────────────\n\nconst workflowStepDefSchema = z.object({\n type: z.literal(\"step\").optional().default(\"step\"),\n agent: z.string(),\n dependsOn: z.array(z.string()).optional(),\n prompt: z.string().optional(),\n sandbox: z.enum([\"writable\", \"readonly\"]).optional(),\n maxTurns: z.number().int().positive().optional(),\n mcpServers: z.array(z.string()).optional(),\n recovery: z\n .object({\n maxRetries: z.number().int().nonnegative().optional(),\n nonRetryable: z.array(z.string()).optional(),\n })\n .optional(),\n condition: z.string().optional(),\n});\n\nconst workflowGateDefSchema = z.object({\n type: z.literal(\"gate\"),\n dependsOn: z.array(z.string()).optional(),\n description: z.string(),\n timeout: z.string().optional(),\n autoApprove: z.boolean().optional(),\n});\n\nconst workflowHeaderSchema = z.object({\n name: z.string().min(1),\n description: z.string().optional(),\n steps: z.record(z.string(), z.unknown()),\n});\n\n// ─── Helpers ────────────────────────────────────────────\n\nfunction parseStepEntry(\n stepName: string,\n stepValue: unknown,\n): { step: WorkflowStepDef | WorkflowGateDef; errors: string[] } {\n const obj = stepValue as Record<string, unknown>;\n const schema = obj.type === \"gate\" ? workflowGateDefSchema : workflowStepDefSchema;\n const result = schema.safeParse(stepValue);\n\n if (result.success) {\n return { step: result.data as WorkflowStepDef | WorkflowGateDef, errors: [] };\n }\n return {\n step: stepValue as WorkflowStepDef,\n errors: result.error.issues.map(\n (i) => ` - steps.${stepName}.${i.path.join(\".\")}: ${i.message}`,\n ),\n };\n}\n\nfunction parseSteps(\n rawSteps: Record<string, unknown>,\n filePath: string,\n): Record<string, WorkflowStepDef | WorkflowGateDef> {\n if (Object.keys(rawSteps).length === 0) {\n throw new Error(\n `Invalid workflow definition in ${filePath}:\\n - steps: Workflow must have at least one step`,\n );\n }\n\n const steps: Record<string, WorkflowStepDef | WorkflowGateDef> = {};\n const errors: string[] = [];\n\n for (const [name, value] of Object.entries(rawSteps)) {\n const { step, errors: stepErrors } = parseStepEntry(name, value);\n if (stepErrors.length > 0) {\n errors.push(...stepErrors);\n } else {\n steps[name] = step;\n }\n }\n\n if (errors.length > 0) {\n throw new Error(`Invalid workflow definition in ${filePath}:\\n${errors.join(\"\\n\")}`);\n }\n\n return steps;\n}\n\n// ─── Loader ─────────────────────────────────────────────\n\nexport async function loadWorkflow(filePath: string): Promise<WorkflowDefinition> {\n const content = await readFile(filePath, \"utf-8\");\n const raw = parse(content) as unknown;\n\n const headerResult = workflowHeaderSchema.safeParse(raw);\n if (!headerResult.success) {\n const issues = headerResult.error.issues\n .map((i) => ` - ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid workflow definition in ${filePath}:\\n${issues}`);\n }\n\n const { name, description, steps: rawSteps } = headerResult.data;\n const steps = parseSteps(rawSteps, filePath);\n\n return { name, description, steps };\n}\n\nexport { workflowGateDefSchema, workflowStepDefSchema };\n","import { z } from \"zod\";\n\n// ─── Daemon state (persisted in state.json) ──────────────\n\nexport const supervisorDaemonStateSchema = z.object({\n pid: z.number(),\n sessionId: z.string(),\n port: z.number(),\n cwd: z.string(),\n startedAt: z.string(),\n lastHeartbeat: z.string().optional(),\n heartbeatCount: z.number().default(0),\n totalCostUsd: z.number().default(0),\n todayCostUsd: z.number().default(0),\n costResetDate: z.string().optional(),\n idleSkipCount: z.number().default(0),\n status: z.enum([\"running\", \"draining\", \"stopped\"]).default(\"running\"),\n});\n\nexport type SupervisorDaemonState = z.infer<typeof supervisorDaemonStateSchema>;\n\n// ─── Incoming webhook event ──────────────────────────────\n\nexport const webhookIncomingEventSchema = z.object({\n id: z.string().optional(),\n source: z.string().optional(),\n event: z.string().optional(),\n payload: z.record(z.string(), z.unknown()).optional(),\n receivedAt: z.string(),\n processedAt: z.string().optional(),\n});\n\nexport type WebhookIncomingEvent = z.infer<typeof webhookIncomingEventSchema>;\n\n// ─── TUI / external inbox message ───────────────────────\n\nexport const inboxMessageSchema = z.object({\n id: z.string(),\n from: z.enum([\"tui\", \"api\", \"external\"]),\n text: z.string(),\n timestamp: z.string(),\n processedAt: z.string().optional(),\n});\n\nexport type InboxMessage = z.infer<typeof inboxMessageSchema>;\n\n// ─── Activity log entry ─────────────────────────────────\n\nexport const activityEntrySchema = z.object({\n id: z.string(),\n type: z.enum([\n \"heartbeat\",\n \"decision\",\n \"action\",\n \"error\",\n \"event\",\n \"message\",\n \"thinking\",\n \"plan\",\n \"dispatch\",\n \"tool_use\",\n ]),\n summary: z.string(),\n detail: z.unknown().optional(),\n timestamp: z.string(),\n});\n\nexport type ActivityEntry = z.infer<typeof activityEntrySchema>;\n\n// ─── Queued event (union of all event sources) ──────────\n\nexport type QueuedEvent =\n | { kind: \"webhook\"; data: WebhookIncomingEvent }\n | { kind: \"message\"; data: InboxMessage }\n | { kind: \"run_complete\"; runId: string; timestamp: string };\n","import { randomUUID } from \"node:crypto\";\nimport { appendFile, readFile, rename, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { ActivityEntry } from \"./schemas.js\";\n\nconst ACTIVITY_FILE = \"activity.jsonl\";\nconst MAX_SIZE_BYTES = 10 * 1024 * 1024; // 10MB rotation threshold\n\nexport class ActivityLog {\n readonly filePath: string;\n private readonly dir: string;\n\n constructor(dir: string) {\n this.dir = dir;\n this.filePath = path.join(dir, ACTIVITY_FILE);\n }\n\n /**\n * Append a structured entry to the activity log.\n * Rotates the file if it exceeds MAX_SIZE_BYTES.\n */\n async append(entry: ActivityEntry): Promise<void> {\n await this.checkRotation();\n const line = `${JSON.stringify(entry)}\\n`;\n await appendFile(this.filePath, line, \"utf-8\");\n }\n\n /**\n * Create and append a new entry with auto-generated id and timestamp.\n */\n async log(type: ActivityEntry[\"type\"], summary: string, detail?: unknown): Promise<void> {\n await this.append({\n id: randomUUID(),\n type,\n summary,\n detail,\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Read the last N entries from the activity log.\n */\n async tail(n: number): Promise<ActivityEntry[]> {\n let content: string;\n try {\n content = await readFile(this.filePath, \"utf-8\");\n } catch {\n return [];\n }\n\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n const lastLines = lines.slice(-n);\n\n const entries: ActivityEntry[] = [];\n for (const line of lastLines) {\n try {\n entries.push(JSON.parse(line) as ActivityEntry);\n } catch {\n // Skip malformed lines\n }\n }\n return entries;\n }\n\n private async checkRotation(): Promise<void> {\n try {\n const stats = await stat(this.filePath);\n if (stats.size > MAX_SIZE_BYTES) {\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const rotatedPath = path.join(this.dir, `activity-${timestamp}.jsonl`);\n await rename(this.filePath, rotatedPath);\n }\n } catch {\n // File doesn't exist yet — no rotation needed\n }\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport type { GlobalConfig } from \"@/config\";\nimport { getSupervisorDir } from \"@/paths\";\nimport { ActivityLog } from \"./activity-log.js\";\nimport { EventQueue } from \"./event-queue.js\";\nimport { HeartbeatLoop } from \"./heartbeat.js\";\nimport type { SupervisorDaemonState } from \"./schemas.js\";\nimport { WebhookServer } from \"./webhook-server.js\";\n\nexport interface SupervisorDaemonOptions {\n name: string;\n config: GlobalConfig;\n}\n\n/**\n * Orchestrates all supervisor components: webhook server, event queue,\n * heartbeat loop, memory, and activity logging.\n */\nexport class SupervisorDaemon {\n private readonly name: string;\n private readonly config: GlobalConfig;\n private readonly dir: string;\n private webhookServer: WebhookServer | null = null;\n private eventQueue: EventQueue | null = null;\n private heartbeatLoop: HeartbeatLoop | null = null;\n private activityLog: ActivityLog | null = null;\n private sessionId = \"\";\n\n constructor(options: SupervisorDaemonOptions) {\n this.name = options.name;\n this.config = options.config;\n this.dir = getSupervisorDir(options.name);\n }\n\n async start(): Promise<void> {\n // Create supervisor directory\n await mkdir(this.dir, { recursive: true });\n\n // Check lockfile for duplicate daemons\n const lockPath = path.join(this.dir, \"daemon.lock\");\n if (existsSync(lockPath)) {\n const lockPid = await this.readLockPid(lockPath);\n if (lockPid && this.isProcessAlive(lockPid)) {\n throw new Error(\n `Supervisor \"${this.name}\" already running (PID ${lockPid}). Use --kill first.`,\n );\n }\n // Stale lock — clean up\n await rm(lockPath, { force: true });\n }\n\n // Write lockfile atomically\n const tempLock = `${lockPath}.${process.pid}`;\n await writeFile(tempLock, String(process.pid), \"utf-8\");\n const { rename } = await import(\"node:fs/promises\");\n await rename(tempLock, lockPath);\n\n // Recover session ID from previous state or generate new one\n const existingState = await this.readState();\n if (existingState?.sessionId && existingState.status !== \"stopped\") {\n this.sessionId = existingState.sessionId;\n } else {\n this.sessionId = randomUUID();\n }\n\n // Initialize activity log\n this.activityLog = new ActivityLog(this.dir);\n\n // Initialize event queue\n this.eventQueue = new EventQueue({\n maxEventsPerSec: this.config.supervisor.maxEventsPerSec,\n });\n\n // Replay unprocessed events from disk\n const inboxPath = path.join(this.dir, \"inbox.jsonl\");\n const eventsPath = path.join(this.dir, \"events.jsonl\");\n await this.eventQueue.replayUnprocessed(inboxPath, eventsPath);\n\n // Start file watching\n this.eventQueue.startWatching(inboxPath, eventsPath);\n\n // Start webhook server\n this.webhookServer = new WebhookServer({\n port: this.config.supervisor.port,\n secret: this.config.supervisor.secret,\n eventsPath,\n onEvent: (event) => {\n this.eventQueue?.push({ kind: \"webhook\", data: event });\n },\n getHealth: () => this.getHealthInfo(),\n });\n await this.webhookServer.start();\n\n // Write initial state\n await this.writeState({\n pid: process.pid,\n sessionId: this.sessionId,\n port: this.config.supervisor.port,\n cwd: homedir(),\n startedAt: new Date().toISOString(),\n lastHeartbeat: existingState?.lastHeartbeat,\n heartbeatCount: existingState?.heartbeatCount ?? 0,\n totalCostUsd: existingState?.totalCostUsd ?? 0,\n todayCostUsd: existingState?.todayCostUsd ?? 0,\n costResetDate: existingState?.costResetDate,\n idleSkipCount: existingState?.idleSkipCount ?? 0,\n status: \"running\",\n });\n\n // Install signal handlers\n const shutdown = () => {\n this.stop().catch(console.error);\n };\n process.on(\"SIGTERM\", shutdown);\n process.on(\"SIGINT\", shutdown);\n\n await this.activityLog.log(\n \"event\",\n `Supervisor \"${this.name}\" started on port ${this.config.supervisor.port}`,\n );\n\n // Start heartbeat loop (blocks until stopped)\n const statePath = path.join(this.dir, \"state.json\");\n this.heartbeatLoop = new HeartbeatLoop({\n config: this.config,\n supervisorDir: this.dir,\n statePath,\n sessionId: this.sessionId,\n eventQueue: this.eventQueue,\n activityLog: this.activityLog,\n });\n\n await this.heartbeatLoop.start();\n }\n\n async stop(): Promise<void> {\n this.heartbeatLoop?.stop();\n this.eventQueue?.stopWatching();\n\n if (this.webhookServer) {\n await this.webhookServer.stop();\n }\n\n // Update state\n const state = await this.readState();\n if (state) {\n state.status = \"stopped\";\n await this.writeState(state);\n }\n\n // Remove lockfile\n const lockPath = path.join(this.dir, \"daemon.lock\");\n await rm(lockPath, { force: true });\n\n if (this.activityLog) {\n await this.activityLog.log(\"event\", `Supervisor \"${this.name}\" stopped`);\n }\n }\n\n private getHealthInfo(): Record<string, unknown> {\n return {\n status: \"ok\",\n name: this.name,\n pid: process.pid,\n uptime: process.uptime(),\n sessionId: this.sessionId,\n port: this.config.supervisor.port,\n };\n }\n\n private async readState(): Promise<SupervisorDaemonState | null> {\n const statePath = path.join(this.dir, \"state.json\");\n try {\n const raw = await readFile(statePath, \"utf-8\");\n return JSON.parse(raw) as SupervisorDaemonState;\n } catch {\n return null;\n }\n }\n\n private async writeState(state: SupervisorDaemonState): Promise<void> {\n const statePath = path.join(this.dir, \"state.json\");\n await writeFile(statePath, JSON.stringify(state, null, 2), \"utf-8\");\n }\n\n private async readLockPid(lockPath: string): Promise<number | null> {\n try {\n const raw = await readFile(lockPath, \"utf-8\");\n const pid = Number.parseInt(raw.trim(), 10);\n return Number.isNaN(pid) ? null : pid;\n } catch {\n return null;\n }\n }\n\n private isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n }\n}\n","import { type FSWatcher, watch } from \"node:fs\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport type { InboxMessage, QueuedEvent, WebhookIncomingEvent } from \"./schemas.js\";\n\ninterface EventQueueOptions {\n maxEventsPerSec: number;\n}\n\nexport interface GroupedMessage {\n text: string;\n from: string;\n count: number;\n}\n\nexport interface GroupedEvents {\n messages: GroupedMessage[];\n webhooks: QueuedEvent[];\n runCompletions: QueuedEvent[];\n}\n\n/**\n * In-memory event queue with deduplication, rate limiting, and file watching.\n *\n * Accumulates events from 3 sources:\n * - Webhooks (pushed directly by WebhookServer)\n * - Inbox messages (watched from inbox.jsonl)\n * - Run completions (watched from runs directory)\n *\n * The daemon drains this queue at each heartbeat.\n */\nexport class EventQueue {\n private readonly queue: QueuedEvent[] = [];\n private readonly seenIds = new Set<string>();\n private readonly maxSeenIds = 1000;\n private readonly maxEventsPerSec: number;\n private eventCountThisSecond = 0;\n private currentSecond = 0;\n private watchers: FSWatcher[] = [];\n private fileOffsets = new Map<string, number>();\n\n /** Resolve function to wake up the heartbeat loop when an event arrives */\n private wakeUp: (() => void) | null = null;\n\n constructor(options: EventQueueOptions) {\n this.maxEventsPerSec = options.maxEventsPerSec;\n }\n\n /**\n * Push an event into the queue. Applies dedup and rate limiting.\n */\n push(event: QueuedEvent): boolean {\n // Deduplication by event ID\n const id = this.getEventId(event);\n if (id && this.seenIds.has(id)) return false;\n\n // Rate limiting\n const now = Math.floor(Date.now() / 1000);\n if (now !== this.currentSecond) {\n this.currentSecond = now;\n this.eventCountThisSecond = 0;\n }\n if (this.eventCountThisSecond >= this.maxEventsPerSec) return false;\n this.eventCountThisSecond++;\n\n // Track seen IDs (LRU-style: evict oldest when full)\n if (id) {\n this.seenIds.add(id);\n if (this.seenIds.size > this.maxSeenIds) {\n const first = this.seenIds.values().next().value;\n if (first) this.seenIds.delete(first);\n }\n }\n\n this.queue.push(event);\n this.wakeUp?.();\n return true;\n }\n\n /**\n * Drain all queued events and return them. Clears the queue.\n */\n drain(): QueuedEvent[] {\n const events = [...this.queue];\n this.queue.length = 0;\n return events;\n }\n\n /**\n * Drain and group events: deduplicates messages by content,\n * keeps webhooks and run completions separate.\n */\n drainAndGroup(): GroupedEvents {\n const events = this.drain();\n\n const messageMap = new Map<string, GroupedMessage>();\n const webhooks: QueuedEvent[] = [];\n const runCompletions: QueuedEvent[] = [];\n\n for (const event of events) {\n if (event.kind === \"message\") {\n const key = event.data.text.trim().toLowerCase();\n const existing = messageMap.get(key);\n if (existing) {\n existing.count++;\n } else {\n messageMap.set(key, { text: event.data.text, from: event.data.from, count: 1 });\n }\n } else if (event.kind === \"webhook\") {\n webhooks.push(event);\n } else {\n runCompletions.push(event);\n }\n }\n\n return {\n messages: [...messageMap.values()],\n webhooks,\n runCompletions,\n };\n }\n\n size(): number {\n return this.queue.length;\n }\n\n /**\n * Start watching inbox.jsonl and events.jsonl for new entries.\n * New lines are parsed and pushed into the queue.\n */\n startWatching(inboxPath: string, eventsPath: string): void {\n this.watchJsonlFile(inboxPath, \"message\");\n this.watchJsonlFile(eventsPath, \"webhook\");\n }\n\n stopWatching(): void {\n for (const w of this.watchers) w.close();\n this.watchers = [];\n this.fileOffsets.clear();\n }\n\n /**\n * Replay unprocessed events from disk on startup.\n */\n async replayUnprocessed(inboxPath: string, eventsPath: string): Promise<void> {\n await this.replayFile(inboxPath, \"message\");\n await this.replayFile(eventsPath, \"webhook\");\n }\n\n /**\n * Returns a promise that resolves when a new event arrives or timeout is reached.\n */\n waitForEvent(timeoutMs: number): Promise<void> {\n if (this.queue.length > 0) return Promise.resolve();\n return new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n this.wakeUp = null;\n resolve();\n }, timeoutMs);\n\n this.wakeUp = () => {\n clearTimeout(timer);\n this.wakeUp = null;\n resolve();\n };\n });\n }\n\n /**\n * Interrupt any pending waitForEvent — used during shutdown.\n */\n interrupt(): void {\n this.wakeUp?.();\n }\n\n private getEventId(event: QueuedEvent): string | undefined {\n if (event.kind === \"webhook\") return event.data.id;\n if (event.kind === \"message\") return event.data.id;\n if (event.kind === \"run_complete\") return `run:${event.runId}`;\n return undefined;\n }\n\n private watchJsonlFile(filePath: string, kind: \"message\" | \"webhook\"): void {\n try {\n const watcher = watch(filePath, () => {\n this.readNewLines(filePath, kind).catch(() => {});\n });\n this.watchers.push(watcher);\n } catch {\n // File may not exist yet — that's fine\n }\n }\n\n private async readNewLines(filePath: string, kind: \"message\" | \"webhook\"): Promise<void> {\n let content: string;\n try {\n content = await readFile(filePath, \"utf-8\");\n } catch {\n return;\n }\n\n const offset = this.fileOffsets.get(filePath) ?? 0;\n if (content.length <= offset) return;\n\n const newContent = content.slice(offset);\n this.fileOffsets.set(filePath, content.length);\n\n const lines = newContent.trim().split(\"\\n\").filter(Boolean);\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n if (parsed.processedAt) continue; // Already processed\n\n if (kind === \"webhook\") {\n this.push({ kind: \"webhook\", data: parsed as unknown as WebhookIncomingEvent });\n } else {\n this.push({ kind: \"message\", data: parsed as unknown as InboxMessage });\n }\n } catch {\n // Skip malformed lines\n }\n }\n }\n\n private async replayFile(filePath: string, kind: \"message\" | \"webhook\"): Promise<void> {\n let content: string;\n try {\n content = await readFile(filePath, \"utf-8\");\n } catch {\n return;\n }\n\n // Set offset so watcher doesn't re-read\n this.fileOffsets.set(filePath, content.length);\n\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n const unprocessed: string[] = [];\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n if (parsed.processedAt) continue;\n\n if (kind === \"webhook\") {\n this.push({ kind: \"webhook\", data: parsed as unknown as WebhookIncomingEvent });\n } else {\n this.push({ kind: \"message\", data: parsed as unknown as InboxMessage });\n }\n unprocessed.push(line);\n } catch {\n // Skip malformed\n }\n }\n }\n\n /**\n * Mark events as processed by rewriting the source files.\n */\n async markProcessed(inboxPath: string, eventsPath: string, events: QueuedEvent[]): Promise<void> {\n const now = new Date().toISOString();\n\n for (const event of events) {\n if (event.kind === \"webhook\") {\n await this.markInFile(eventsPath, event.data.receivedAt, now);\n } else if (event.kind === \"message\") {\n await this.markInFile(inboxPath, event.data.timestamp, now);\n }\n }\n }\n\n private async markInFile(\n filePath: string,\n matchTimestamp: string,\n processedAt: string,\n ): Promise<void> {\n try {\n const content = await readFile(filePath, \"utf-8\");\n const lines = content.split(\"\\n\");\n let changed = false;\n\n const updated = lines.map((line) => {\n if (!line.trim()) return line;\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n if (\n (parsed.receivedAt === matchTimestamp || parsed.timestamp === matchTimestamp) &&\n !parsed.processedAt\n ) {\n parsed.processedAt = processedAt;\n changed = true;\n return JSON.stringify(parsed);\n }\n } catch {\n // Keep as-is\n }\n return line;\n });\n\n if (changed) {\n await writeFile(filePath, updated.join(\"\\n\"), \"utf-8\");\n this.fileOffsets.set(filePath, updated.join(\"\\n\").length);\n }\n } catch {\n // Non-critical\n }\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { GlobalConfig } from \"@/config\";\nimport { getDataDir } from \"@/paths\";\nimport type { ActivityLog } from \"./activity-log.js\";\nimport type { EventQueue } from \"./event-queue.js\";\nimport {\n checkMemorySize,\n extractKnowledgeFromResponse,\n extractMemoryFromResponse,\n loadKnowledge,\n loadMemory,\n saveKnowledge,\n saveMemory,\n} from \"./memory.js\";\nimport { buildHeartbeatPrompt } from \"./prompt-builder.js\";\nimport type { SupervisorDaemonState } from \"./schemas.js\";\n\n// ─── SDK message shapes (same as runner/session.ts) ──────\n\ninterface SDKStreamMessage {\n type: string;\n subtype?: string;\n [key: string]: unknown;\n}\n\n// ─── HeartbeatLoop ───────────────────────────────────────\n\nexport interface HeartbeatLoopOptions {\n config: GlobalConfig;\n supervisorDir: string;\n statePath: string;\n sessionId: string;\n eventQueue: EventQueue;\n activityLog: ActivityLog;\n}\n\n/**\n * The core autonomous loop. At each iteration:\n * 1. Drain events from the queue\n * 2. Build a prompt with context + memory + events\n * 3. Call sdk.query() for Claude to reason and act\n * 4. Extract and save updated memory\n * 5. Log activity\n * 6. Wait for the next event or idle timeout\n */\nexport class HeartbeatLoop {\n private stopping = false;\n private consecutiveFailures = 0;\n private activeAbort: AbortController | null = null;\n private readonly config: GlobalConfig;\n private readonly supervisorDir: string;\n private readonly statePath: string;\n private sessionId: string;\n private readonly eventQueue: EventQueue;\n private readonly activityLog: ActivityLog;\n\n private customInstructions: string | undefined;\n\n constructor(options: HeartbeatLoopOptions) {\n this.config = options.config;\n this.supervisorDir = options.supervisorDir;\n this.statePath = options.statePath;\n this.sessionId = options.sessionId;\n this.eventQueue = options.eventQueue;\n this.activityLog = options.activityLog;\n }\n\n async start(): Promise<void> {\n this.customInstructions = await this.loadInstructions();\n await this.activityLog.log(\"heartbeat\", \"Supervisor heartbeat loop started\");\n\n while (!this.stopping) {\n try {\n await this.runHeartbeat();\n this.consecutiveFailures = 0;\n } catch (error) {\n this.consecutiveFailures++;\n const msg = error instanceof Error ? error.message : String(error);\n await this.activityLog.log(\"error\", `Heartbeat failed: ${msg}`, { error: msg });\n\n // Circuit breaker: exponential backoff after consecutive failures\n if (this.consecutiveFailures >= this.config.supervisor.maxConsecutiveFailures) {\n const backoffMs = Math.min(\n this.config.supervisor.idleIntervalMs *\n 2 ** (this.consecutiveFailures - this.config.supervisor.maxConsecutiveFailures),\n 15 * 60 * 1000, // max 15 minutes\n );\n await this.activityLog.log(\n \"error\",\n `Circuit breaker: backing off ${Math.round(backoffMs / 1000)}s after ${this.consecutiveFailures} failures`,\n );\n await this.sleep(backoffMs);\n continue;\n }\n }\n\n if (this.stopping) break;\n\n // Wait for next event or idle timeout\n await this.eventQueue.waitForEvent(this.config.supervisor.idleIntervalMs);\n }\n\n await this.activityLog.log(\"heartbeat\", \"Supervisor heartbeat loop stopped\");\n }\n\n stop(): void {\n this.stopping = true;\n this.activeAbort?.abort(new Error(\"Supervisor shutting down\"));\n this.eventQueue.interrupt();\n }\n\n private async runHeartbeat(): Promise<void> {\n const startTime = Date.now();\n const heartbeatId = randomUUID();\n\n // Check supervisor daily budget\n const state = await this.readState();\n const today = new Date().toISOString().slice(0, 10);\n const todayCost = state?.costResetDate === today ? (state.todayCostUsd ?? 0) : 0;\n\n if (todayCost >= this.config.supervisor.dailyCapUsd) {\n await this.activityLog.log(\n \"error\",\n `Supervisor daily budget exceeded ($${todayCost.toFixed(2)} / $${this.config.supervisor.dailyCapUsd}). Skipping heartbeat.`,\n );\n await this.sleep(this.config.supervisor.idleIntervalMs);\n return;\n }\n\n // Drain and group events (deduplicates messages by content)\n const grouped = this.eventQueue.drainAndGroup();\n const totalEventCount =\n grouped.messages.length + grouped.webhooks.length + grouped.runCompletions.length;\n\n // Skip idle heartbeats (no events) unless forced every N skips\n const idleSkipCount = state?.idleSkipCount ?? 0;\n if (totalEventCount === 0 && idleSkipCount < this.config.supervisor.idleSkipMax) {\n await this.updateState({ idleSkipCount: idleSkipCount + 1 });\n await this.activityLog.log(\"heartbeat\", `Idle skip #${idleSkipCount + 1} — no events`);\n return;\n }\n\n // Reset idle skip counter (we're running a real heartbeat)\n if (idleSkipCount > 0) {\n await this.updateState({ idleSkipCount: 0 });\n }\n\n // Load memory + knowledge\n const memory = await loadMemory(this.supervisorDir);\n const knowledge = await loadKnowledge(this.supervisorDir);\n const memoryCheck = checkMemorySize(memory);\n\n // Build prompt\n const mcpServerNames = this.config.mcpServers ? Object.keys(this.config.mcpServers) : [];\n\n const prompt = buildHeartbeatPrompt({\n repos: this.config.repos,\n memory,\n knowledge,\n memorySizeKB: memoryCheck.sizeKB,\n grouped,\n budgetStatus: {\n todayUsd: todayCost,\n capUsd: this.config.supervisor.dailyCapUsd,\n remainingPct:\n ((this.config.supervisor.dailyCapUsd - todayCost) / this.config.supervisor.dailyCapUsd) *\n 100,\n },\n activeRuns: [], // TODO: read from persisted runs\n heartbeatCount: state?.heartbeatCount ?? 0,\n mcpServerNames,\n customInstructions: this.customInstructions,\n });\n\n await this.activityLog.log(\"heartbeat\", `Heartbeat #${state?.heartbeatCount ?? 0} starting`, {\n heartbeatId,\n eventCount: totalEventCount,\n messages: grouped.messages.length,\n webhooks: grouped.webhooks.length,\n runCompletions: grouped.runCompletions.length,\n });\n\n // Call SDK with timeout + shutdown abort\n const abortController = new AbortController();\n this.activeAbort = abortController;\n const timeout = setTimeout(() => {\n abortController.abort(new Error(\"Heartbeat timeout exceeded\"));\n }, this.config.supervisor.heartbeatTimeoutMs);\n\n let output = \"\";\n let costUsd = 0;\n let turnCount = 0;\n\n try {\n const sdk = await import(\"@anthropic-ai/claude-agent-sdk\");\n\n // Build allowed tools list — include MCP tool patterns for configured servers\n const allowedTools: string[] = [\"Bash\", \"Read\", \"mcp__neo__*\"];\n if (this.config.mcpServers) {\n for (const name of Object.keys(this.config.mcpServers)) {\n allowedTools.push(`mcp__${name}__*`);\n }\n }\n\n // Auto-configure internal MCP server for structured reporting\n const mcpInternalPath = path.join(\n path.dirname(fileURLToPath(import.meta.url)),\n \"mcp-internal.js\",\n );\n const mcpServers: Record<string, unknown> = {\n neo: {\n type: \"stdio\",\n command: \"node\",\n args: [mcpInternalPath],\n env: { NEO_ACTIVITY_PATH: this.activityLog.filePath },\n },\n ...(this.config.mcpServers ?? {}),\n };\n\n const queryOptions: Record<string, unknown> = {\n cwd: homedir(),\n maxTurns: 50,\n allowedTools,\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n mcpServers,\n };\n\n const stream = sdk.query({ prompt, options: queryOptions as never });\n\n for await (const message of stream) {\n if (abortController.signal.aborted) break;\n\n const msg = message as SDKStreamMessage;\n\n if (msg.type === \"system\" && msg.subtype === \"init\") {\n this.sessionId = msg.session_id as string;\n }\n\n if (msg.type === \"result\") {\n output = (msg.result as string) ?? \"\";\n costUsd = (msg.total_cost_usd as number) ?? 0;\n turnCount = (msg.num_turns as number) ?? 0;\n }\n\n await this.logStreamMessage(msg, heartbeatId);\n }\n } finally {\n clearTimeout(timeout);\n this.activeAbort = null;\n }\n\n // Extract and save memory + knowledge\n const newMemory = extractMemoryFromResponse(output);\n if (newMemory) {\n await saveMemory(this.supervisorDir, newMemory);\n }\n\n const newKnowledge = extractKnowledgeFromResponse(output);\n if (newKnowledge) {\n await saveKnowledge(this.supervisorDir, newKnowledge);\n }\n\n // Update state\n const durationMs = Date.now() - startTime;\n await this.updateState({\n sessionId: this.sessionId,\n lastHeartbeat: new Date().toISOString(),\n heartbeatCount: (state?.heartbeatCount ?? 0) + 1,\n totalCostUsd: (state?.totalCostUsd ?? 0) + costUsd,\n todayCostUsd: todayCost + costUsd,\n costResetDate: today,\n });\n\n await this.activityLog.log(\n \"heartbeat\",\n `Heartbeat #${(state?.heartbeatCount ?? 0) + 1} complete`,\n {\n heartbeatId,\n costUsd,\n durationMs,\n turnCount,\n memoryUpdated: !!newMemory,\n responseSummary: output,\n },\n );\n }\n\n private async readState(): Promise<SupervisorDaemonState | null> {\n try {\n const raw = await readFile(this.statePath, \"utf-8\");\n return JSON.parse(raw) as SupervisorDaemonState;\n } catch {\n return null;\n }\n }\n\n private async updateState(updates: Partial<SupervisorDaemonState>): Promise<void> {\n try {\n const raw = await readFile(this.statePath, \"utf-8\");\n const state = JSON.parse(raw) as SupervisorDaemonState;\n Object.assign(state, updates);\n await writeFile(this.statePath, JSON.stringify(state, null, 2), \"utf-8\");\n } catch {\n // Non-critical\n }\n }\n\n /**\n * Load custom instructions from SUPERVISOR.md.\n * Resolution order:\n * 1. Explicit path via `supervisor.instructions` in config\n * 2. Default: ~/.neo/SUPERVISOR.md\n */\n private async loadInstructions(): Promise<string | undefined> {\n const candidates: string[] = [];\n\n if (this.config.supervisor.instructions) {\n candidates.push(path.resolve(this.config.supervisor.instructions));\n }\n\n candidates.push(path.join(getDataDir(), \"SUPERVISOR.md\"));\n\n for (const filePath of candidates) {\n try {\n const content = await readFile(filePath, \"utf-8\");\n await this.activityLog.log(\"event\", `Loaded custom instructions from ${filePath}`);\n return content;\n } catch {\n // File not found — try next candidate\n }\n }\n\n return undefined;\n }\n\n /** Route a single SDK stream message to the appropriate log handler. */\n private async logStreamMessage(msg: SDKStreamMessage, heartbeatId: string): Promise<void> {\n if (msg.type !== \"assistant\") return;\n\n if (!msg.subtype) {\n await this.logContentBlocks(msg, heartbeatId);\n } else if (msg.subtype === \"tool_use\") {\n await this.logToolUse(msg, heartbeatId);\n } else if (msg.subtype === \"tool_result\") {\n await this.logToolResult(msg, heartbeatId);\n }\n }\n\n /** Log thinking and plan blocks from assistant content — no truncation. */\n private async logContentBlocks(msg: SDKStreamMessage, heartbeatId: string): Promise<void> {\n const content = (\n msg.message as\n | { content?: Array<{ type: string; thinking?: string; text?: string }> }\n | undefined\n )?.content;\n if (!content) return;\n\n for (const block of content) {\n if (block.type === \"thinking\" && block.thinking) {\n await this.activityLog.log(\"thinking\", block.thinking, { heartbeatId });\n }\n if (block.type === \"text\" && block.text) {\n await this.activityLog.log(\"plan\", block.text, { heartbeatId });\n break; // Only log first text block per message\n }\n }\n }\n\n /** Log tool use events — distinguish MCP tools from built-in tools. */\n private async logToolUse(msg: SDKStreamMessage, heartbeatId: string): Promise<void> {\n const toolName = String(msg.tool ?? \"unknown\");\n const isMcp = toolName.startsWith(\"mcp__\");\n await this.activityLog.log(\n isMcp ? \"tool_use\" : \"action\",\n isMcp ? toolName : `Tool use: ${toolName}`,\n { heartbeatId, tool: toolName, input: msg.input },\n );\n }\n\n /** Detect agent dispatches from bash tool results. */\n private async logToolResult(msg: SDKStreamMessage, heartbeatId: string): Promise<void> {\n const result = String(msg.result ?? \"\");\n const runMatch = /Run\\s+(\\S+)\\s+dispatched/i.exec(result);\n if (runMatch) {\n await this.activityLog.log(\"dispatch\", `Agent dispatched: ${runMatch[1]}`, {\n heartbeatId,\n runId: runMatch[1],\n });\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { appendFile, readFile, rename, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nconst MEMORY_FILE = \"memory.json\";\nconst KNOWLEDGE_FILE = \"knowledge.json\";\nconst ARCHIVE_FILE = \"memory-archive.jsonl\";\nconst LEGACY_FILE = \"memory.md\";\nconst MAX_SIZE_KB = 6;\nconst MAX_DECISIONS = 10;\n\n// ─── Structured memory type ─────────────────────────────\n\nexport interface SupervisorMemory {\n activeWork: string[];\n blockers: string[];\n repoNotes: Record<string, string>;\n recentDecisions: Array<{\n date: string;\n decision: string;\n outcome?: string;\n }>;\n trackerSync: Record<string, string>;\n notes: string;\n}\n\n/**\n * Parse raw memory content into structured format.\n * Tries JSON first, falls back to wrapping raw markdown in { notes }.\n */\nexport function parseStructuredMemory(raw: string): SupervisorMemory {\n if (!raw.trim()) {\n return emptyMemory();\n }\n try {\n const parsed = JSON.parse(raw) as Partial<SupervisorMemory>;\n return {\n activeWork: parsed.activeWork ?? [],\n blockers: parsed.blockers ?? [],\n repoNotes: parsed.repoNotes ?? {},\n recentDecisions: parsed.recentDecisions ?? [],\n trackerSync: parsed.trackerSync ?? {},\n notes: parsed.notes ?? \"\",\n };\n } catch {\n // Legacy markdown format — wrap in notes\n return { ...emptyMemory(), notes: raw };\n }\n}\n\nfunction emptyMemory(): SupervisorMemory {\n return {\n activeWork: [],\n blockers: [],\n repoNotes: {},\n recentDecisions: [],\n trackerSync: {},\n notes: \"\",\n };\n}\n\n// ─── Knowledge (cold/static data) ───────────────────────\n\nexport async function loadKnowledge(dir: string): Promise<string> {\n try {\n return await readFile(path.join(dir, KNOWLEDGE_FILE), \"utf-8\");\n } catch {\n return \"\";\n }\n}\n\nexport async function saveKnowledge(dir: string, content: string): Promise<void> {\n await writeFile(path.join(dir, KNOWLEDGE_FILE), content, \"utf-8\");\n}\n\n// ─── Memory (working/volatile data) ─────────────────────\n\n/**\n * Load the supervisor memory from disk.\n * Migrates from legacy memory.md if needed.\n */\nexport async function loadMemory(dir: string): Promise<string> {\n // Try new format first\n try {\n return await readFile(path.join(dir, MEMORY_FILE), \"utf-8\");\n } catch {\n // Not found — try legacy migration\n }\n\n // Migrate from legacy memory.md\n try {\n const legacy = await readFile(path.join(dir, LEGACY_FILE), \"utf-8\");\n if (legacy.trim()) {\n await writeFile(path.join(dir, MEMORY_FILE), legacy, \"utf-8\");\n await rename(path.join(dir, LEGACY_FILE), path.join(dir, `${LEGACY_FILE}.bak`));\n return legacy;\n }\n } catch {\n // No legacy file either\n }\n\n return \"\";\n}\n\n/**\n * Save the supervisor memory to disk (full overwrite).\n * Automatically compacts if needed.\n */\nexport async function saveMemory(dir: string, content: string): Promise<void> {\n const compacted = await compactMemory(dir, content);\n await writeFile(path.join(dir, MEMORY_FILE), compacted, \"utf-8\");\n}\n\n/**\n * Extract memory content from Claude's response using <memory>...</memory> tags.\n */\nexport function extractMemoryFromResponse(response: string): string | null {\n const match = /<memory>([\\s\\S]*?)<\\/memory>/i.exec(response);\n if (!match?.[1]) return null;\n const content = match[1].trim();\n\n if (content.startsWith(\"{\")) {\n try {\n JSON.parse(content);\n return content;\n } catch {\n // Malformed JSON — still save as raw text\n }\n }\n return content;\n}\n\n/**\n * Extract knowledge updates from Claude's response using <knowledge>...</knowledge> tags.\n */\nexport function extractKnowledgeFromResponse(response: string): string | null {\n const match = /<knowledge>([\\s\\S]*?)<\\/knowledge>/i.exec(response);\n if (!match?.[1]) return null;\n return match[1].trim();\n}\n\n/**\n * Check if memory content exceeds the recommended size limit.\n */\nexport function checkMemorySize(content: string): { ok: boolean; sizeKB: number } {\n const sizeKB = Buffer.byteLength(content, \"utf-8\") / 1024;\n return { ok: sizeKB <= MAX_SIZE_KB, sizeKB: Math.round(sizeKB * 10) / 10 };\n}\n\n// ─── Compaction ─────────────────────────────────────────\n\n/**\n * Compact memory: archive old decisions, trim notes if over size limit.\n * Archived data goes to memory-archive.jsonl (append-only, never lost).\n */\nasync function compactMemory(dir: string, content: string): Promise<string> {\n if (!content.startsWith(\"{\")) return content;\n\n let parsed: SupervisorMemory;\n try {\n parsed = parseStructuredMemory(content);\n } catch {\n return content;\n }\n\n let changed = false;\n\n // Archive old decisions (keep last MAX_DECISIONS)\n if (parsed.recentDecisions.length > MAX_DECISIONS) {\n const toArchive = parsed.recentDecisions.slice(0, -MAX_DECISIONS);\n parsed.recentDecisions = parsed.recentDecisions.slice(-MAX_DECISIONS);\n changed = true;\n\n const archivePath = path.join(dir, ARCHIVE_FILE);\n const entry = {\n type: \"decisions_archived\",\n timestamp: new Date().toISOString(),\n decisions: toArchive,\n };\n await appendFile(archivePath, `${JSON.stringify(entry)}\\n`, \"utf-8\");\n }\n\n // If still over size, trim notes\n const result = changed ? JSON.stringify(parsed, null, 2) : content;\n const sizeKB = Buffer.byteLength(result, \"utf-8\") / 1024;\n\n if (sizeKB > MAX_SIZE_KB && parsed.notes.length > 200) {\n const archivePath = path.join(dir, ARCHIVE_FILE);\n const entry = {\n type: \"notes_archived\",\n timestamp: new Date().toISOString(),\n notes: parsed.notes,\n };\n await appendFile(archivePath, `${JSON.stringify(entry)}\\n`, \"utf-8\");\n\n parsed.notes = \"(archived — see memory-archive.jsonl)\";\n return JSON.stringify(parsed, null, 2);\n }\n\n return result;\n}\n","import type { RepoConfig } from \"@/config\";\nimport type { GroupedEvents } from \"./event-queue.js\";\nimport type { QueuedEvent } from \"./schemas.js\";\n\nexport interface HeartbeatPromptOptions {\n repos: RepoConfig[];\n memory: string;\n knowledge: string;\n memorySizeKB: number;\n grouped: GroupedEvents;\n budgetStatus: {\n todayUsd: number;\n capUsd: number;\n remainingPct: number;\n };\n activeRuns: string[];\n heartbeatCount: number;\n mcpServerNames: string[];\n customInstructions?: string | undefined;\n}\n\n/**\n * Build the prompt sent to Claude at each heartbeat.\n *\n * Includes: role definition, current memory, pending events,\n * budget status, active runs, and available integrations.\n */\nexport function buildHeartbeatPrompt(opts: HeartbeatPromptOptions): string {\n const sections: string[] = [];\n\n // ─── Role ──────────────────────────────────────────────\n sections.push(`You are the neo autonomous supervisor (heartbeat #${opts.heartbeatCount}).\nYou orchestrate developer agents across repositories. You make decisions autonomously.\n\nYour job:\n1. Process any incoming events (webhooks, user messages, run completions)\n2. Decide what actions to take (dispatch agents, check status, respond to users)\n3. Update your memory with relevant context for future heartbeats\n4. If nothing to do, simply acknowledge and wait\n\nAvailable commands (via bash):\n neo run <agent> --prompt \"...\" [--repo <path>] dispatch an agent\n neo runs --short [--all] check recent runs\n neo cost --short [--all] check budget\n neo agents list available agents\n\nIMPORTANT: Always include a <memory>...</memory> block at the end of your response with your updated memory.\n\n## Reporting\nUse the \\`mcp__neo__report_progress\\` tool to log your decisions, actions and blockers.\nAlways report what you're doing and why — these logs are your audit trail.\nTypes: \"decision\" (what you chose), \"action\" (what you did), \"blocker\" (what's stuck), \"progress\" (status update).`);\n\n // ─── Custom instructions (SUPERVISOR.md) ─────────────\n if (opts.customInstructions) {\n sections.push(`## Custom instructions\\n${opts.customInstructions}`);\n }\n\n // ─── Repos ─────────────────────────────────────────────\n if (opts.repos.length > 0) {\n const repoList = opts.repos.map((r) => `- ${r.path} (branch: ${r.defaultBranch})`).join(\"\\n\");\n sections.push(`## Registered repositories\\n${repoList}`);\n } else {\n sections.push(\"## Registered repositories\\n(none — run 'neo init' in a repo to register it)\");\n }\n\n // ─── MCP Integrations ─────────────────────────────────\n if (opts.mcpServerNames.length > 0) {\n const mcpList = opts.mcpServerNames.map((n) => `- ${n}`).join(\"\\n\");\n\n sections.push(\n `## Available integrations (MCP)\\n${mcpList}\\n\\nYou can use these tools directly to query external systems.`,\n );\n }\n\n // ─── Budget ────────────────────────────────────────────\n sections.push(\n `## Budget status\\n- Today: $${opts.budgetStatus.todayUsd.toFixed(2)} / $${opts.budgetStatus.capUsd.toFixed(2)} (${opts.budgetStatus.remainingPct.toFixed(0)}% remaining)`,\n );\n\n // ─── Active runs ───────────────────────────────────────\n if (opts.activeRuns.length > 0) {\n sections.push(`## Active runs\\n${opts.activeRuns.map((r) => `- ${r}`).join(\"\\n\")}`);\n }\n\n // ─── Events ────────────────────────────────────────────\n const { messages, webhooks, runCompletions } = opts.grouped;\n const totalEvents = messages.length + webhooks.length + runCompletions.length;\n\n if (totalEvents > 0) {\n const parts: string[] = [];\n for (const msg of messages) {\n const countSuffix = msg.count > 1 ? ` (×${msg.count})` : \"\";\n parts.push(`**Message from ${msg.from}${countSuffix}**: ${msg.text}`);\n }\n for (const evt of webhooks) {\n parts.push(formatEvent(evt));\n }\n for (const evt of runCompletions) {\n parts.push(formatEvent(evt));\n }\n sections.push(`## Pending events (${totalEvents})\\n${parts.join(\"\\n\\n\")}`);\n } else {\n sections.push(\n \"## Pending events\\nNo new events. This is an idle heartbeat — check on active runs if any, or wait.\",\n );\n }\n\n // ─── Knowledge (read-only reference data) ──────────────\n if (opts.knowledge) {\n sections.push(`## Reference knowledge (read-only)\n${opts.knowledge}\n\nTo update knowledge, output a \\`<knowledge>...</knowledge>\\` block. Only update when reference data changes (API IDs, workspace config, etc.).`);\n }\n\n // ─── Memory ────────────────────────────────────────────\n sections.push(buildMemorySection(opts.memory, opts.memorySizeKB));\n\n return sections.join(\"\\n\\n---\\n\\n\");\n}\n\nfunction buildMemorySection(memory: string, memorySizeKB: number): string {\n const schema = `{\n \"activeWork\": [\"description of current task 1\", ...],\n \"blockers\": [\"what is stuck and why\", ...],\n \"repoNotes\": { \"/path/to/repo\": \"relevant context about this repo\" },\n \"recentDecisions\": [{ \"date\": \"YYYY-MM-DD\", \"decision\": \"what you decided\", \"outcome\": \"result\" }],\n \"trackerSync\": { \"ticket-id\": \"last known status\" },\n \"notes\": \"free-form context that doesn't fit elsewhere\"\n}`;\n\n if (!memory) {\n return `## Your current memory\n(empty — this is your first heartbeat, initialize your memory)\n\nYour memory MUST be a JSON object inside \\`<memory>...</memory>\\` tags:\n\\`\\`\\`\n${schema}\n\\`\\`\\`\nKeep under 8KB. Prune old decisions (keep last 10).`;\n }\n\n const sizeWarning =\n memorySizeKB > 8\n ? \"\\n\\n**Memory is over 8KB — condense it. Remove old decisions, summarize notes.**\"\n : \"\";\n\n return `## Your current memory (${memorySizeKB}KB)${sizeWarning}\n${memory}\n\nRemember: update your memory as a JSON object inside \\`<memory>...</memory>\\` tags.\nSchema: ${schema}`;\n}\n\nfunction formatEvent(event: QueuedEvent): string {\n switch (event.kind) {\n case \"webhook\":\n return `**Webhook** [${event.data.source ?? \"unknown\"}] ${event.data.event ?? \"\"}\n\\`\\`\\`json\n${JSON.stringify(event.data.payload ?? {}, null, 2)}\n\\`\\`\\``;\n\n case \"message\":\n return `**Message from ${event.data.from}**: ${event.data.text}`;\n\n case \"run_complete\":\n return `**Run completed**: ${event.runId} (check with \\`neo runs\\`)`;\n }\n}\n","import { timingSafeEqual } from \"node:crypto\";\nimport { appendFile } from \"node:fs/promises\";\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\nimport type { WebhookIncomingEvent } from \"./schemas.js\";\n\nconst MAX_BODY_SIZE = 1024 * 1024; // 1MB\n\ninterface WebhookServerOptions {\n port: number;\n secret?: string | undefined;\n eventsPath: string;\n onEvent: (event: WebhookIncomingEvent) => void;\n getHealth: () => Record<string, unknown>;\n}\n\n/**\n * Minimal HTTP server for receiving incoming webhooks.\n *\n * Routes:\n * POST /webhook — receive any JSON payload, persist to disk, push to queue\n * GET /health — liveness check with daemon status\n *\n * Uses raw http.createServer — zero external dependencies.\n */\nexport class WebhookServer {\n private server: Server | null = null;\n private readonly port: number;\n private readonly secret: string | undefined;\n private readonly eventsPath: string;\n private readonly onEvent: (event: WebhookIncomingEvent) => void;\n private readonly getHealth: () => Record<string, unknown>;\n\n constructor(options: WebhookServerOptions) {\n this.port = options.port;\n this.secret = options.secret;\n this.eventsPath = options.eventsPath;\n this.onEvent = options.onEvent;\n this.getHealth = options.getHealth;\n }\n\n async start(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.server = createServer((req, res) => {\n this.handleRequest(req, res).catch((err) => {\n this.sendJson(res, 500, { error: \"Internal server error\", detail: String(err) });\n });\n });\n\n this.server.on(\"error\", reject);\n\n this.server.listen(this.port, () => {\n resolve();\n });\n });\n }\n\n async stop(): Promise<void> {\n return new Promise<void>((resolve) => {\n if (!this.server) {\n resolve();\n return;\n }\n this.server.close(() => resolve());\n });\n }\n\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = req.url ?? \"/\";\n\n if (req.method === \"GET\" && url === \"/health\") {\n this.sendJson(res, 200, this.getHealth());\n return;\n }\n\n if (req.method === \"POST\" && url === \"/webhook\") {\n await this.handleWebhook(req, res);\n return;\n }\n\n this.sendJson(res, 404, { error: \"Not found\" });\n }\n\n private async handleWebhook(req: IncomingMessage, res: ServerResponse): Promise<void> {\n // Validate secret if configured\n if (this.secret) {\n const provided = req.headers[\"x-neo-secret\"] as string | undefined;\n if (!provided) {\n this.sendJson(res, 401, { error: \"Missing X-Neo-Secret header\" });\n return;\n }\n\n const expected = Buffer.from(this.secret, \"utf-8\");\n const actual = Buffer.from(provided, \"utf-8\");\n if (expected.length !== actual.length || !timingSafeEqual(expected, actual)) {\n this.sendJson(res, 403, { error: \"Invalid secret\" });\n return;\n }\n }\n\n // Read body with size limit\n const body = await this.readBody(req);\n if (body === null) {\n this.sendJson(res, 413, { error: \"Payload too large (max 1MB)\" });\n return;\n }\n\n // Parse JSON\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(body) as Record<string, unknown>;\n } catch {\n this.sendJson(res, 400, { error: \"Invalid JSON\" });\n return;\n }\n\n const event: WebhookIncomingEvent = {\n id: typeof parsed.id === \"string\" ? parsed.id : undefined,\n source: typeof parsed.source === \"string\" ? parsed.source : undefined,\n event: typeof parsed.event === \"string\" ? parsed.event : undefined,\n payload: (parsed.payload as Record<string, unknown> | undefined) ?? parsed,\n receivedAt: new Date().toISOString(),\n };\n\n // Disk-first: persist before pushing to memory\n await appendFile(this.eventsPath, `${JSON.stringify(event)}\\n`, \"utf-8\");\n\n // Push to in-memory queue\n this.onEvent(event);\n\n this.sendJson(res, 200, { ok: true, id: event.id });\n }\n\n private readBody(req: IncomingMessage): Promise<string | null> {\n return new Promise((resolve) => {\n const chunks: Buffer[] = [];\n let size = 0;\n\n req.on(\"data\", (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY_SIZE) {\n resolve(null);\n req.destroy();\n return;\n }\n chunks.push(chunk);\n });\n\n req.on(\"end\", () => {\n resolve(Buffer.concat(chunks).toString(\"utf-8\"));\n });\n\n req.on(\"error\", () => resolve(null));\n });\n }\n\n private sendJson(res: ServerResponse, status: number, data: unknown): void {\n res.writeHead(status, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(data));\n }\n}\n","export const VERSION = \"0.1.0\";\n\n// ─── Orchestrator (public API) ──────────────────────────\n\nexport { loadAgentFile } from \"@/agents/loader\";\nexport { AgentRegistry } from \"@/agents/registry\";\nexport { resolveAgent } from \"@/agents/resolver\";\nexport {\n agentConfigSchema,\n agentModelSchema,\n agentSandboxSchema,\n agentToolEntrySchema,\n agentToolSchema,\n} from \"@/agents/schema\";\nexport type {\n SemaphoreCallbacks,\n SemaphoreConfig,\n} from \"@/concurrency/semaphore\";\n// ─── Concurrency ────────────────────────────────────────\nexport { Semaphore } from \"@/concurrency/semaphore\";\nexport type {\n GlobalConfig,\n McpServerConfig,\n NeoConfig,\n RepoConfig,\n RepoConfigInput,\n} from \"@/config\";\nexport {\n addRepoToGlobalConfig,\n globalConfigSchema,\n listReposFromGlobalConfig,\n loadConfig,\n loadGlobalConfig,\n mcpServerConfigSchema,\n neoConfigSchema,\n removeRepoFromGlobalConfig,\n repoConfigSchema,\n} from \"@/config\";\n// ─── Cost ──────────────────────────────────────────────\nexport { CostJournal } from \"@/cost/journal\";\nexport { NeoEventEmitter } from \"@/events\";\n// ─── Events ────────────────────────────────────────────\nexport { EventJournal } from \"@/events/journal\";\nexport { matchesFilter, WebhookDispatcher } from \"@/events/webhook\";\nexport {\n createBranch,\n deleteBranch,\n fetchRemote,\n getBranchName,\n getCurrentBranch,\n pushBranch,\n} from \"@/isolation/git\";\n// ─── Isolation ──────────────────────────────────────────\nexport { withGitLock } from \"@/isolation/git-mutex\";\nexport type { SandboxConfig } from \"@/isolation/sandbox\";\nexport { buildSandboxConfig } from \"@/isolation/sandbox\";\nexport type { WorktreeInfo } from \"@/isolation/worktree\";\nexport {\n cleanupOrphanedWorktrees,\n createWorktree,\n listWorktrees,\n removeWorktree,\n} from \"@/isolation/worktree\";\nexport type { AuditLogMiddleware } from \"@/middleware/audit-log\";\n// ─── Middleware ─────────────────────────────────────────\nexport { auditLog } from \"@/middleware/audit-log\";\nexport { budgetGuard } from \"@/middleware/budget-guard\";\nexport type { MiddlewareChain, SDKHooks } from \"@/middleware/chain\";\nexport { buildMiddlewareChain, buildSDKHooks } from \"@/middleware/chain\";\nexport type { LoopDetectionMiddleware } from \"@/middleware/loop-detection\";\nexport { loopDetection } from \"@/middleware/loop-detection\";\nexport type { OrchestratorOptions } from \"@/orchestrator\";\nexport { Orchestrator } from \"@/orchestrator\";\n// ─── Paths ─────────────────────────────────────────────\nexport {\n getDataDir,\n getJournalsDir,\n getRepoRunsDir,\n getRunDispatchPath,\n getRunLogPath,\n getRunsDir,\n getSupervisorActivityPath,\n getSupervisorDir,\n getSupervisorEventsPath,\n getSupervisorInboxPath,\n getSupervisorLockPath,\n getSupervisorMemoryPath,\n getSupervisorStatePath,\n getSupervisorsDir,\n toRepoSlug,\n} from \"@/paths\";\nexport type { ParsedOutput } from \"@/runner/output-parser\";\n// ─── Runner ────────────────────────────────────────────\nexport { parseOutput } from \"@/runner/output-parser\";\nexport type { RecoveryOptions } from \"@/runner/recovery\";\nexport { runWithRecovery } from \"@/runner/recovery\";\nexport type {\n SessionEvent,\n SessionOptions,\n SessionResult,\n} from \"@/runner/session\";\nexport { runSession, SessionError } from \"@/runner/session\";\n// ─── Supervisor (legacy) ──────────────────────────────\nexport type { SupervisorState } from \"@/supervisor\";\nexport { supervisorStateSchema } from \"@/supervisor\";\n// ─── Supervisor (daemon) ──────────────────────────────\nexport type {\n ActivityEntry,\n HeartbeatLoopOptions,\n HeartbeatPromptOptions,\n InboxMessage,\n QueuedEvent,\n SupervisorDaemonOptions,\n SupervisorDaemonState,\n WebhookIncomingEvent,\n} from \"@/supervisor/index\";\nexport {\n ActivityLog,\n activityEntrySchema,\n buildHeartbeatPrompt,\n checkMemorySize,\n EventQueue,\n extractMemoryFromResponse,\n HeartbeatLoop,\n inboxMessageSchema,\n loadMemory,\n SupervisorDaemon,\n saveMemory,\n supervisorDaemonStateSchema,\n WebhookServer,\n webhookIncomingEventSchema,\n} from \"@/supervisor/index\";\nexport * from \"@/types\";\n// ─── Workflows ─────────────────────────────────────────\nexport { loadWorkflow, workflowGateDefSchema, workflowStepDefSchema } from \"@/workflows/loader\";\nexport { WorkflowRegistry } from \"@/workflows/registry\";\n"],"mappings":"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","names":["path","tools","prompt","definition","path","resolve","readFile","path","parseYaml","z","path","z","parseYaml","readFile","path","mkdir","readFile","path","appendFile","mkdir","path","resolve","resolve","execFile","existsSync","readdir","resolve","promisify","execFileAsync","promisify","execFile","GIT_TIMEOUT","resolve","existsSync","readdir","appendFile","mkdir","path","existsSync","mkdir","readdir","readFile","writeFile","path","resolve","existsSync","readdir","path","readFile","z","existsSync","readdir","path","path","resolve","existsSync","mkdir","writeFile","readdir","readFile","z","randomUUID","appendFile","readFile","path","randomUUID","existsSync","mkdir","readFile","rm","writeFile","homedir","path","readFile","writeFile","resolve","randomUUID","readFile","writeFile","homedir","path","appendFile","readFile","rename","writeFile","path","randomUUID","path","homedir","readFile","writeFile","resolve","appendFile","resolve","mkdir","path","existsSync","rm","writeFile","rename","randomUUID","homedir","readFile"]}
1
+ {"version":3,"sources":["../src/agents/loader.ts","../src/agents/schema.ts","../src/agents/registry.ts","../src/agents/resolver.ts","../src/concurrency/queue.ts","../src/concurrency/semaphore.ts","../src/config.ts","../src/paths.ts","../src/cost/journal.ts","../src/shared/date.ts","../src/shared/fs.ts","../src/events/emitter.ts","../src/events/journal.ts","../src/events/webhook.ts","../src/isolation/clone.ts","../src/isolation/git.ts","../src/isolation/sandbox.ts","../src/middleware/audit-log.ts","../src/middleware/budget-guard.ts","../src/middleware/chain.ts","../src/middleware/loop-detection.ts","../src/orchestrator.ts","../src/orchestrator/run-store.ts","../src/shared/process.ts","../src/runner/session-executor.ts","../src/runner/output-parser.ts","../src/sdk-types.ts","../src/runner/session.ts","../src/runner/recovery.ts","../src/supervisor/memory/embedder.ts","../src/supervisor/memory/entry.ts","../src/supervisor/memory/format.ts","../src/supervisor/memory/store.ts","../src/workflows/registry.ts","../src/workflows/loader.ts","../src/supervisor/schemas.ts","../src/supervisor/activity-log.ts","../src/supervisor/daemon.ts","../src/supervisor/event-queue.ts","../src/supervisor/heartbeat.ts","../src/supervisor/log-buffer.ts","../src/supervisor/prompt-builder.ts","../src/supervisor/webhook-server.ts","../src/index.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport type { AgentConfig } from \"@/agents/schema\";\nimport { agentConfigSchema } from \"@/agents/schema\";\n\n/**\n * Load a single agent definition from a YAML file.\n * If the `prompt` field points to a .md file, resolve it relative\n * to the YAML file's directory and read its content.\n */\nexport async function loadAgentFile(filePath: string): Promise<AgentConfig> {\n let raw: string;\n try {\n raw = await readFile(filePath, \"utf-8\");\n } catch {\n throw new Error(`Agent file not found: ${filePath}`);\n }\n\n let parsed: unknown;\n try {\n parsed = parseYaml(raw);\n } catch (err) {\n throw new Error(\n `Invalid YAML in agent file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n const result = agentConfigSchema.safeParse(parsed);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` - ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid agent config in ${filePath}:\\n${issues}`);\n }\n\n const config = result.data;\n\n // If prompt points to a .md file, read it\n if (config.prompt?.endsWith(\".md\")) {\n const promptPath = path.resolve(path.dirname(filePath), config.prompt);\n try {\n config.prompt = await readFile(promptPath, \"utf-8\");\n } catch {\n throw new Error(`Prompt file not found: ${promptPath} (referenced in ${filePath})`);\n }\n }\n\n return config;\n}\n","import { z } from \"zod\";\n\n// ─── Agent model enum ────────────────────────────────────\n\nexport const agentModelSchema = z.enum([\"opus\", \"sonnet\", \"haiku\"]);\n\n// ─── Agent tool enum ─────────────────────────────────────\n\nexport const agentToolSchema = z.enum([\n \"Read\",\n \"Write\",\n \"Edit\",\n \"Bash\",\n \"Glob\",\n \"Grep\",\n \"Agent\",\n \"WebSearch\",\n \"WebFetch\",\n \"NotebookEdit\",\n]);\n\n// ─── Agent tool entry (tool or $inherited token) ─────────\n\nexport const agentToolEntrySchema = z.union([agentToolSchema, z.literal(\"$inherited\")]);\n\n// ─── Agent sandbox enum ──────────────────────────────────\n\nexport const agentSandboxSchema = z.enum([\"writable\", \"readonly\"]);\n\n// ─── AgentConfig schema (from YAML) ─────────────────────\n\nexport const agentConfigSchema = z.object({\n name: z.string(),\n extends: z.string().optional(),\n description: z.string().optional(),\n model: agentModelSchema.optional(),\n tools: z.array(agentToolEntrySchema).optional(),\n prompt: z.string().optional(),\n promptAppend: z.string().optional(),\n sandbox: agentSandboxSchema.optional(),\n maxTurns: z.number().optional(),\n mcpServers: z.array(z.string()).optional(),\n});\n\n// ─── Derived types ───────────────────────────────────────\n\nexport type AgentConfig = z.infer<typeof agentConfigSchema>;\nexport type AgentModel = z.infer<typeof agentModelSchema>;\nexport type AgentTool = z.infer<typeof agentToolSchema>;\nexport type AgentToolEntry = z.infer<typeof agentToolEntrySchema>;\n","import { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { loadAgentFile } from \"@/agents/loader\";\nimport { resolveAgent } from \"@/agents/resolver\";\nimport type { AgentConfig } from \"@/agents/schema\";\nimport type { ResolvedAgent } from \"@/types\";\n\nexport class AgentRegistry {\n private readonly builtInDir: string;\n private readonly customDir: string | undefined;\n private agents = new Map<string, ResolvedAgent>();\n\n constructor(builtInDir: string, customDir?: string) {\n this.builtInDir = builtInDir;\n this.customDir = customDir;\n }\n\n async load(): Promise<void> {\n this.agents.clear();\n\n // Load built-in agents\n const builtInConfigs = await loadAgentsFromDir(this.builtInDir);\n const builtInMap = new Map<string, AgentConfig>();\n for (const config of builtInConfigs) {\n builtInMap.set(config.name, config);\n }\n\n // Resolve built-in agents\n for (const config of builtInConfigs) {\n const resolved = resolveAgent(config, builtInMap);\n // Force built-in source for agents loaded from the built-in dir\n this.agents.set(config.name, { ...resolved, source: \"built-in\" });\n }\n\n // Load custom agents (if directory exists)\n if (this.customDir) {\n let customConfigs: AgentConfig[];\n try {\n customConfigs = await loadAgentsFromDir(this.customDir);\n } catch {\n // Custom dir doesn't exist — that's fine\n customConfigs = [];\n }\n\n for (const config of customConfigs) {\n const resolved = resolveAgent(config, builtInMap);\n this.agents.set(config.name, resolved);\n }\n }\n }\n\n get(name: string): ResolvedAgent | undefined {\n return this.agents.get(name);\n }\n\n list(): ResolvedAgent[] {\n return [...this.agents.values()];\n }\n\n has(name: string): boolean {\n return this.agents.has(name);\n }\n}\n\nasync function loadAgentsFromDir(dir: string): Promise<AgentConfig[]> {\n const entries = await readdir(dir);\n const ymlFiles = entries.filter((f) => f.endsWith(\".yml\") || f.endsWith(\".yaml\"));\n\n const configs: AgentConfig[] = [];\n for (const file of ymlFiles) {\n const config = await loadAgentFile(path.join(dir, file));\n configs.push(config);\n }\n return configs;\n}\n","import type { AgentConfig, AgentTool } from \"@/agents/schema\";\nimport type { AgentDefinition, ResolvedAgent } from \"@/types\";\n\n/**\n * Resolve an agent config into a fully-merged ResolvedAgent.\n *\n * Resolution rules:\n * 1. No `extends` → agent must define all required fields\n * 2. With `extends: \"developer\"` → start from built-in, apply overrides\n * 3. Same name as built-in without `extends:` → treated as `extends: <name>` implicitly\n */\nexport function resolveAgent(\n config: AgentConfig,\n builtIns: Map<string, AgentConfig>,\n): ResolvedAgent {\n const extendsName =\n config.extends ??\n (builtIns.has(config.name) && config.extends === undefined ? config.name : undefined);\n\n if (extendsName !== undefined) {\n return resolveExtendedAgent(config, extendsName, builtIns);\n }\n\n return resolveCustomAgent(config);\n}\n\n// ─── Extended agent (inherits from built-in) ────────────\n\nfunction resolveExtendedAgent(\n config: AgentConfig,\n extendsName: string,\n builtIns: Map<string, AgentConfig>,\n): ResolvedAgent {\n const base = builtIns.get(extendsName);\n\n if (!base) {\n throw new Error(\n `Agent \"${config.name}\" extends \"${extendsName}\", but no built-in agent with that name exists.`,\n );\n }\n\n const tools = mergeTools(config.tools, base.tools);\n const prompt = mergePrompt(config.prompt, config.promptAppend, base.prompt);\n const mcpServers = mergeMcpServerNames(base.mcpServers, config.mcpServers);\n\n const definition: AgentDefinition = {\n description: config.description ?? base.description ?? \"\",\n prompt,\n tools,\n model: config.model ?? base.model ?? \"sonnet\",\n ...(mcpServers.length > 0 ? { mcpServers } : {}),\n };\n\n return {\n name: config.name,\n definition,\n sandbox: config.sandbox ?? base.sandbox ?? \"readonly\",\n ...(config.maxTurns !== undefined\n ? { maxTurns: config.maxTurns }\n : base.maxTurns !== undefined\n ? { maxTurns: base.maxTurns }\n : {}),\n source: config.name === extendsName && !config.extends ? \"built-in\" : \"extended\",\n };\n}\n\n// ─── Custom agent (no inheritance) ──────────────────────\n\nfunction resolveCustomAgent(config: AgentConfig): ResolvedAgent {\n if (!config.description) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"description\". Add a 'description' field to the agent YAML.`,\n );\n }\n if (!config.model) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"model\". Add a 'model' field (e.g., 'claude-sonnet-4-20250514').`,\n );\n }\n if (!config.tools) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"tools\". Add a 'tools' array to the agent YAML.`,\n );\n }\n if (!config.sandbox) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"sandbox\". Add a 'sandbox' field ('full' or 'permissive').`,\n );\n }\n if (!config.prompt) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"prompt\". Add a 'prompt' field or 'promptFile' reference.`,\n );\n }\n\n // Filter out $inherited from tools (shouldn't be there without extends, but be safe)\n const tools = config.tools.filter((t): t is AgentTool => t !== \"$inherited\");\n\n let prompt = config.prompt;\n if (config.promptAppend) {\n prompt = `${prompt}\\n\\n${config.promptAppend}`;\n }\n\n const definition: AgentDefinition = {\n description: config.description,\n prompt,\n tools,\n model: config.model,\n ...(config.mcpServers?.length ? { mcpServers: config.mcpServers } : {}),\n };\n\n return {\n name: config.name,\n definition,\n sandbox: config.sandbox,\n ...(config.maxTurns !== undefined ? { maxTurns: config.maxTurns } : {}),\n source: \"custom\",\n };\n}\n\n// ─── Helpers ────────────────────────────────────────────\n\nfunction mergeTools(configTools: AgentConfig[\"tools\"], baseTools: AgentConfig[\"tools\"]): string[] {\n if (!configTools) return (baseTools ?? []) as string[];\n if (configTools.includes(\"$inherited\")) {\n const newTools = configTools.filter((t) => t !== \"$inherited\");\n return [...(baseTools ?? []), ...newTools] as string[];\n }\n return configTools as string[];\n}\n\nfunction mergePrompt(\n configPrompt: string | undefined,\n promptAppend: string | undefined,\n basePrompt: string | undefined,\n): string {\n let prompt = configPrompt ?? basePrompt ?? \"\";\n if (promptAppend) {\n prompt = `${prompt}\\n\\n${promptAppend}`;\n }\n return prompt;\n}\n\nfunction mergeMcpServerNames(base: string[] | undefined, override: string[] | undefined): string[] {\n if (!base?.length && !override?.length) return [];\n return [...new Set([...(base ?? []), ...(override ?? [])])];\n}\n","import type { Priority } from \"@/types\";\n\nconst PRIORITY_ORDER: Record<Priority, number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n};\n\ninterface QueueItem<T> {\n value: T;\n priority: Priority;\n insertionOrder: number;\n}\n\n/**\n * FIFO priority queue. Items with higher priority (critical > high > medium > low)\n * are dequeued first. Within the same priority level, FIFO order is maintained.\n */\nexport class PriorityQueue<T> {\n private readonly items: QueueItem<T>[] = [];\n private readonly maxSize: number;\n private insertionCounter = 0;\n\n constructor(maxSize: number) {\n this.maxSize = maxSize;\n }\n\n enqueue(value: T, priority: Priority): void {\n // Reset counter when queue is empty to prevent overflow after prolonged use\n if (this.items.length === 0) {\n this.insertionCounter = 0;\n }\n\n if (this.items.length >= this.maxSize) {\n throw new Error(`Queue full (${this.maxSize} items). Cannot enqueue.`);\n }\n\n const item: QueueItem<T> = {\n value,\n priority,\n insertionOrder: this.insertionCounter++,\n };\n\n // Insert in sorted position (binary search would be overkill for queue sizes ≤ 50)\n let inserted = false;\n for (let i = 0; i < this.items.length; i++) {\n const existing = this.items[i];\n if (existing && this.comparePriority(item, existing) < 0) {\n this.items.splice(i, 0, item);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n this.items.push(item);\n }\n }\n\n dequeue(): T | undefined {\n const item = this.items.shift();\n return item?.value;\n }\n\n peek(): T | undefined {\n return this.items[0]?.value;\n }\n\n get size(): number {\n return this.items.length;\n }\n\n get isEmpty(): boolean {\n return this.items.length === 0;\n }\n\n remove(predicate: (item: T) => boolean): boolean {\n const index = this.items.findIndex((entry) => predicate(entry.value));\n if (index === -1) return false;\n this.items.splice(index, 1);\n return true;\n }\n\n /** Dequeue the first item matching the predicate (respects priority order). */\n dequeueWhere(predicate: (item: T) => boolean): T | undefined {\n const index = this.items.findIndex((entry) => predicate(entry.value));\n if (index === -1) return undefined;\n const removed = this.items.splice(index, 1)[0];\n if (!removed) return undefined;\n return removed.value;\n }\n\n /** Compare by priority first, then by insertion order (FIFO within same priority). */\n private comparePriority(a: QueueItem<T>, b: QueueItem<T>): number {\n const priorityDiff = PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority];\n if (priorityDiff !== 0) return priorityDiff;\n return a.insertionOrder - b.insertionOrder;\n }\n}\n","import { PriorityQueue } from \"@/concurrency/queue\";\nimport type { Priority } from \"@/types\";\n\nexport interface SemaphoreConfig {\n maxSessions: number;\n maxPerRepo: number;\n queueMax?: number;\n}\n\nexport interface SemaphoreCallbacks {\n onEnqueue?: (sessionId: string, repo: string, position: number) => void;\n onDequeue?: (sessionId: string, repo: string, waitedMs: number) => void;\n}\n\ninterface WaitingEntry {\n sessionId: string;\n repo: string;\n resolve: () => void;\n reject: (reason: unknown) => void;\n enqueuedAt: number;\n _cleanupAbort?: () => void;\n}\n\n/**\n * Concurrency semaphore with global + per-repo limits and a priority queue.\n * When at capacity, `acquire()` blocks until a slot is available.\n */\nexport class Semaphore {\n private readonly maxSessions: number;\n private readonly maxPerRepo: number;\n private readonly queue: PriorityQueue<WaitingEntry>;\n private readonly callbacks: SemaphoreCallbacks;\n\n // sessionId → repo\n private readonly activeSessions = new Map<string, string>();\n // repo → count\n private readonly repoCounts = new Map<string, number>();\n\n constructor(config: SemaphoreConfig, callbacks: SemaphoreCallbacks = {}) {\n this.maxSessions = config.maxSessions;\n this.maxPerRepo = config.maxPerRepo;\n this.queue = new PriorityQueue<WaitingEntry>(config.queueMax ?? 50);\n this.callbacks = callbacks;\n }\n\n /**\n * Acquire a slot. Blocks (via promise) if at capacity.\n * Throws if the queue is full.\n */\n async acquire(\n repo: string,\n sessionId: string,\n priority: Priority = \"medium\",\n signal?: AbortSignal,\n ): Promise<void> {\n if (signal?.aborted) {\n throw signal.reason ?? new DOMException(\"The operation was aborted.\", \"AbortError\");\n }\n\n if (this.canAcquire(repo)) {\n this.allocate(repo, sessionId);\n return;\n }\n\n return new Promise<void>((resolve, reject) => {\n const entry: WaitingEntry = {\n sessionId,\n repo,\n resolve,\n reject,\n enqueuedAt: Date.now(),\n };\n\n this.queue.enqueue(entry, priority);\n this.callbacks.onEnqueue?.(sessionId, repo, this.queue.size);\n\n if (signal) {\n const onAbort = () => {\n this.queue.remove((e) => e === entry);\n reject(signal.reason ?? new DOMException(\"The operation was aborted.\", \"AbortError\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n\n // Store cleanup so we can remove the listener on normal dequeue\n entry._cleanupAbort = () => signal.removeEventListener(\"abort\", onAbort);\n }\n });\n }\n\n /** Release a slot and process the next waiting entry. */\n release(sessionId: string): void {\n const repo = this.activeSessions.get(sessionId);\n if (!repo) return;\n\n this.activeSessions.delete(sessionId);\n const count = this.repoCounts.get(repo) ?? 0;\n if (count <= 1) {\n this.repoCounts.delete(repo);\n } else {\n this.repoCounts.set(repo, count - 1);\n }\n\n this.processQueue();\n }\n\n /** Non-blocking attempt to acquire a slot. Returns true if successful. */\n tryAcquire(repo: string, sessionId: string): boolean {\n if (!this.canAcquire(repo)) return false;\n this.allocate(repo, sessionId);\n return true;\n }\n\n /** Total number of active slots. */\n activeCount(): number {\n return this.activeSessions.size;\n }\n\n /** Number of active slots for a specific repo. */\n activeCountForRepo(repo: string): number {\n return this.repoCounts.get(repo) ?? 0;\n }\n\n /** Can a slot be acquired for this repo without blocking? */\n isAvailable(repo: string): boolean {\n return this.canAcquire(repo);\n }\n\n /** Current queue depth. */\n queueDepth(): number {\n return this.queue.size;\n }\n\n private canAcquire(repo: string): boolean {\n if (this.activeSessions.size >= this.maxSessions) return false;\n const repoCount = this.repoCounts.get(repo) ?? 0;\n return repoCount < this.maxPerRepo;\n }\n\n private allocate(repo: string, sessionId: string): void {\n this.activeSessions.set(sessionId, repo);\n this.repoCounts.set(repo, (this.repoCounts.get(repo) ?? 0) + 1);\n }\n\n private processQueue(): void {\n // Find the highest-priority entry whose repo has capacity\n const entry = this.queue.dequeueWhere((e) => this.canAcquire(e.repo));\n if (!entry) return;\n\n this.allocate(entry.repo, entry.sessionId);\n entry._cleanupAbort?.();\n const waitedMs = Date.now() - entry.enqueuedAt;\n this.callbacks.onDequeue?.(entry.sessionId, entry.repo, waitedMs);\n entry.resolve();\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport { getDataDir, toRepoSlug } from \"@/paths\";\n\n// ─── McpServerConfig schemas ─────────────────────────────\n\nconst httpMcpServerSchema = z.object({\n type: z.literal(\"http\"),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n});\n\nconst stdioMcpServerSchema = z.object({\n type: z.literal(\"stdio\"),\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n});\n\nexport const mcpServerConfigSchema = z.discriminatedUnion(\"type\", [\n httpMcpServerSchema,\n stdioMcpServerSchema,\n]);\n\n// ─── RepoConfig schema (single repo entry) ──────────────\n\nexport const gitStrategySchema = z.enum([\"pr\", \"branch\"]).default(\"branch\");\n\nexport type GitStrategy = z.infer<typeof gitStrategySchema>;\n\nexport const repoConfigSchema = z.object({\n path: z.string(),\n name: z.string().optional(),\n defaultBranch: z.string().default(\"main\"),\n branchPrefix: z.string().default(\"feat\"),\n pushRemote: z.string().default(\"origin\"),\n gitStrategy: gitStrategySchema,\n});\n\n// ─── Global config schema (~/.neo/config.yml) ───────────\n// This is now the single source of truth — repos are registered here.\n\nexport const globalConfigSchema = z.object({\n repos: z.array(repoConfigSchema).default([]),\n\n concurrency: z\n .object({\n maxSessions: z.number().default(5),\n maxPerRepo: z.number().default(4),\n queueMax: z.number().default(50),\n })\n .default({ maxSessions: 5, maxPerRepo: 4, queueMax: 50 }),\n\n budget: z\n .object({\n dailyCapUsd: z.number().default(500),\n alertThresholdPct: z.number().default(80),\n })\n .default({ dailyCapUsd: 500, alertThresholdPct: 80 }),\n\n recovery: z\n .object({\n maxRetries: z.number().default(3),\n backoffBaseMs: z.number().default(30_000),\n })\n .default({ maxRetries: 3, backoffBaseMs: 30_000 }),\n\n sessions: z\n .object({\n initTimeoutMs: z.number().default(120_000),\n maxDurationMs: z.number().default(3_600_000),\n dir: z.string().default(\"/tmp/neo-sessions\"),\n })\n .default({ initTimeoutMs: 120_000, maxDurationMs: 3_600_000, dir: \"/tmp/neo-sessions\" }),\n\n webhooks: z\n .array(\n z.object({\n url: z.string().url(),\n events: z.array(z.string()).optional(),\n secret: z.string().optional(),\n timeoutMs: z.number().default(5000),\n }),\n )\n .default([]),\n\n supervisor: z\n .object({\n port: z.number().default(7777),\n secret: z.string().optional(),\n heartbeatTimeoutMs: z.number().default(300_000),\n maxConsecutiveFailures: z.number().default(3),\n maxEventsPerSec: z.number().default(10),\n dailyCapUsd: z.number().default(50),\n /** How often consolidation runs (ms) */\n consolidationIntervalMs: z.number().default(300_000),\n /** How often compaction runs (ms) */\n compactionIntervalMs: z.number().default(3_600_000),\n /** Safety timeout for waitForWork (ms) */\n eventTimeoutMs: z.number().default(300_000),\n instructions: z.string().optional(),\n })\n .default({\n port: 7777,\n heartbeatTimeoutMs: 300_000,\n maxConsecutiveFailures: 3,\n maxEventsPerSec: 10,\n dailyCapUsd: 50,\n consolidationIntervalMs: 300_000,\n compactionIntervalMs: 3_600_000,\n eventTimeoutMs: 300_000,\n }),\n\n memory: z\n .object({\n embeddings: z.boolean().default(true),\n })\n .default({ embeddings: true }),\n\n mcpServers: z.record(z.string(), mcpServerConfigSchema).optional(),\n claudeCodePath: z.string().optional(),\n\n idempotency: z\n .object({\n enabled: z.boolean().default(true),\n key: z.enum([\"metadata\", \"prompt\"]).default(\"metadata\"),\n ttlMs: z.number().default(3_600_000),\n })\n .optional(),\n});\n\n// ─── NeoConfig = GlobalConfig (single schema now) ────────\n\nexport const neoConfigSchema = globalConfigSchema;\n\n// ─── Derived types ───────────────────────────────────────\n\nexport type NeoConfig = z.infer<typeof neoConfigSchema>;\nexport type GlobalConfig = NeoConfig;\nexport type RepoConfig = z.infer<typeof repoConfigSchema>;\nexport type RepoConfigInput = z.input<typeof repoConfigSchema>;\nexport type McpServerConfig = z.infer<typeof mcpServerConfigSchema>;\n\n// ─── Default global config ──────────────────────────────\n\nconst DEFAULT_GLOBAL_CONFIG = {\n repos: [],\n concurrency: {\n maxSessions: 5,\n maxPerRepo: 4,\n queueMax: 50,\n },\n budget: {\n dailyCapUsd: 500,\n alertThresholdPct: 80,\n },\n};\n\n// ─── YAML loader helper ─────────────────────────────────\n\nfunction parseYamlFile(raw: string, filePath: string): unknown {\n try {\n return parseYaml(raw);\n } catch (err) {\n throw new Error(\n `Invalid YAML in ${filePath}: ${err instanceof Error ? err.message : String(err)}. Check YAML syntax at the indicated line.`,\n );\n }\n}\n\nfunction formatZodErrors(issues: z.ZodIssue[], filePath: string): string {\n const formatted = issues.map((i) => ` - ${i.path.join(\".\")}: ${i.message}`).join(\"\\n\");\n return `Invalid config in ${filePath}:\\n${formatted}`;\n}\n\n// ─── Config loaders ─────────────────────────────────────\n\n/**\n * Load NeoConfig from a single file (legacy compatibility).\n */\nexport async function loadConfig(configPath: string): Promise<NeoConfig> {\n let raw: string;\n try {\n raw = await readFile(configPath, \"utf-8\");\n } catch {\n throw new Error(`Config file not found: ${configPath}. Run 'neo init' to get started.`);\n }\n\n const parsed = parseYamlFile(raw, configPath);\n\n const result = neoConfigSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(formatZodErrors(result.error.issues, configPath));\n }\n\n return result.data;\n}\n\n/**\n * Load the global config from ~/.neo/config.yml.\n * Creates the file with defaults if it does not exist.\n */\nexport async function loadGlobalConfig(): Promise<NeoConfig> {\n const configPath = path.join(getDataDir(), \"config.yml\");\n\n if (!existsSync(configPath)) {\n await mkdir(getDataDir(), { recursive: true });\n await writeFile(configPath, stringifyYaml(DEFAULT_GLOBAL_CONFIG), \"utf-8\");\n return globalConfigSchema.parse(DEFAULT_GLOBAL_CONFIG);\n }\n\n const raw = await readFile(configPath, \"utf-8\");\n const parsed = parseYamlFile(raw, configPath);\n\n const result = globalConfigSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(formatZodErrors(result.error.issues, configPath));\n }\n\n return result.data;\n}\n\n// ─── Repo CRUD operations ───────────────────────────────\n\n/**\n * Add a repo to ~/.neo/config.yml. Deduplicates by resolved path.\n */\nexport async function addRepoToGlobalConfig(repo: RepoConfigInput): Promise<void> {\n const config = await loadGlobalConfig();\n const resolvedPath = path.resolve(repo.path);\n const parsed = repoConfigSchema.parse({ ...repo, path: resolvedPath });\n\n const existing = config.repos.findIndex((r) => path.resolve(r.path) === resolvedPath);\n if (existing >= 0) {\n config.repos[existing] = parsed;\n } else {\n config.repos.push(parsed);\n }\n\n const configPath = path.join(getDataDir(), \"config.yml\");\n await writeFile(configPath, stringifyYaml(config), \"utf-8\");\n}\n\n/**\n * Remove a repo from ~/.neo/config.yml by path, name, or slug.\n */\nexport async function removeRepoFromGlobalConfig(pathOrName: string): Promise<boolean> {\n const config = await loadGlobalConfig();\n const resolvedPath = path.resolve(pathOrName);\n const initialLength = config.repos.length;\n\n config.repos = config.repos.filter(\n (r) =>\n path.resolve(r.path) !== resolvedPath &&\n r.name !== pathOrName &&\n toRepoSlug(r) !== pathOrName,\n );\n\n if (config.repos.length === initialLength) return false;\n\n const configPath = path.join(getDataDir(), \"config.yml\");\n await writeFile(configPath, stringifyYaml(config), \"utf-8\");\n return true;\n}\n\n/**\n * List all registered repos from ~/.neo/config.yml.\n */\nexport async function listReposFromGlobalConfig(): Promise<RepoConfig[]> {\n const config = await loadGlobalConfig();\n return config.repos;\n}\n","import { homedir } from \"node:os\";\nimport path from \"node:path\";\n\n/**\n * Global data directory for runtime artifacts (journals, runs).\n * Located at ~/.neo, similar to how Claude Code uses ~/.claude.\n */\nexport function getDataDir(): string {\n return path.join(homedir(), \".neo\");\n}\n\nexport function getJournalsDir(): string {\n return path.join(getDataDir(), \"journals\");\n}\n\nexport function getRunsDir(): string {\n return path.join(getDataDir(), \"runs\");\n}\n\n/**\n * Derive a filesystem-safe slug from a repo config.\n * Uses `name` if present, otherwise `basename(path)`.\n */\nexport function toRepoSlug(repo: { name?: string | undefined; path: string }): string {\n const raw = repo.name ?? path.basename(repo.path);\n return raw\n .toLowerCase()\n .replace(/[^a-z0-9._-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\n/**\n * Runs directory for a specific repo: ~/.neo/runs/<slug>/\n */\nexport function getRepoRunsDir(repoSlug: string): string {\n return path.join(getRunsDir(), repoSlug);\n}\n\n/**\n * Path to the dispatch request file for a detached run.\n */\nexport function getRunDispatchPath(repoSlug: string, runId: string): string {\n return path.join(getRepoRunsDir(repoSlug), `${runId}.dispatch.json`);\n}\n\n/**\n * Path to the log file for a detached run.\n */\nexport function getRunLogPath(repoSlug: string, runId: string): string {\n return path.join(getRepoRunsDir(repoSlug), `${runId}.log`);\n}\n\n/**\n * Directory for all supervisor instances: ~/.neo/supervisors/\n */\nexport function getSupervisorsDir(): string {\n return path.join(getDataDir(), \"supervisors\");\n}\n\n/**\n * Directory for a specific supervisor instance: ~/.neo/supervisors/<name>/\n */\nexport function getSupervisorDir(name: string): string {\n return path.join(getSupervisorsDir(), name);\n}\n\n/**\n * Path to a supervisor state file: ~/.neo/supervisors/<name>/state.json\n */\nexport function getSupervisorStatePath(name: string): string {\n return path.join(getSupervisorDir(name), \"state.json\");\n}\n\nexport function getSupervisorActivityPath(name: string): string {\n return path.join(getSupervisorDir(name), \"activity.jsonl\");\n}\n\nexport function getSupervisorInboxPath(name: string): string {\n return path.join(getSupervisorDir(name), \"inbox.jsonl\");\n}\n\nexport function getSupervisorEventsPath(name: string): string {\n return path.join(getSupervisorDir(name), \"events.jsonl\");\n}\n\nexport function getSupervisorLockPath(name: string): string {\n return path.join(getSupervisorDir(name), \"daemon.lock\");\n}\n","import { appendFile, readFile } from \"node:fs/promises\";\nimport { fileForDate, toDateKey } from \"@/shared/date\";\nimport { ensureDir } from \"@/shared/fs\";\nimport type { CostEntry } from \"@/types\";\n\n/**\n * Append-only JSONL journal for cost tracking.\n * Monthly file rotation: cost-YYYY-MM.jsonl\n */\nexport class CostJournal {\n private readonly dir: string;\n private readonly dirCache = new Set<string>();\n private dayCache: { key: string; total: number } | null = null;\n\n constructor(options: { dir: string }) {\n this.dir = options.dir;\n }\n\n async append(entry: CostEntry): Promise<void> {\n await ensureDir(this.dir, this.dirCache);\n const file = fileForDate(new Date(entry.timestamp), \"cost\", this.dir);\n await appendFile(file, `${JSON.stringify(entry)}\\n`, \"utf-8\");\n // Invalidate cache — the day total may have changed\n this.dayCache = null;\n }\n\n async getDayTotal(date?: Date): Promise<number> {\n const d = date ?? new Date();\n const dayKey = toDateKey(d);\n\n if (this.dayCache?.key === dayKey) {\n return this.dayCache.total;\n }\n\n const file = fileForDate(d, \"cost\", this.dir);\n let total = 0;\n\n try {\n const content = await readFile(file, \"utf-8\");\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n const entry = JSON.parse(line) as CostEntry;\n if (toDateKey(new Date(entry.timestamp)) === dayKey) {\n total += entry.costUsd;\n }\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n // File doesn't exist yet — total is 0\n }\n\n this.dayCache = { key: dayKey, total };\n return total;\n }\n}\n","import path from \"node:path\";\n\n/**\n * Converts a Date to a YYYY-MM-DD string in UTC.\n *\n * Uses UTC to ensure consistent date keys regardless of local timezone.\n * This is critical for cost tracking and event journaling where entries\n * must be grouped by calendar day consistently across all environments.\n *\n * @param date - The date to convert.\n * @returns A string in YYYY-MM-DD format (e.g., \"2026-03-14\").\n *\n * @example\n * ```ts\n * import { toDateKey } from \"@/shared/date\";\n *\n * toDateKey(new Date(\"2026-03-14T10:00:00Z\")); // => \"2026-03-14\"\n * toDateKey(new Date(\"2026-03-14T23:59:59Z\")); // => \"2026-03-14\"\n * ```\n */\nexport function toDateKey(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n\n/**\n * Generates a dated file path with monthly rotation.\n *\n * Creates paths in the format: `{dir}/{prefix}-YYYY-MM.jsonl`\n * Uses UTC year/month to ensure consistent file paths across timezones.\n *\n * @param date - The date used to determine the year and month for the file name.\n * @param prefix - The prefix for the file name (e.g., \"cost\", \"events\").\n * @param dir - The directory where the file will be located.\n * @returns The full file path (e.g., \"/data/cost-2026-03.jsonl\").\n *\n * @example\n * ```ts\n * import { fileForDate } from \"@/shared/date\";\n *\n * fileForDate(new Date(\"2026-03-14T10:00:00Z\"), \"cost\", \"/data\");\n * // => \"/data/cost-2026-03.jsonl\"\n *\n * fileForDate(new Date(\"2026-12-31T23:59:59Z\"), \"events\", \"/logs\");\n * // => \"/logs/events-2026-12.jsonl\"\n * ```\n */\nexport function fileForDate(date: Date, prefix: string, dir: string): string {\n const yyyy = date.getUTCFullYear();\n const mm = String(date.getUTCMonth() + 1).padStart(2, \"0\");\n return path.join(dir, `${prefix}-${yyyy}-${mm}.jsonl`);\n}\n","import { mkdir } from \"node:fs/promises\";\n\n/**\n * Ensures a directory exists, creating it recursively if necessary.\n *\n * Uses an optional cache to avoid redundant filesystem calls when the same\n * directory is ensured multiple times. This is useful in hot paths where\n * directory existence is checked frequently.\n *\n * @param dirPath - The absolute or relative path to the directory to ensure.\n * @param cache - Optional Set to track directories that have already been created.\n * When provided, subsequent calls with the same path skip the mkdir call.\n * @returns A promise that resolves when the directory exists.\n *\n * @example\n * ```ts\n * import { ensureDir } from \"@/shared/fs\";\n *\n * // Basic usage - creates directory if it doesn't exist\n * await ensureDir(\"/tmp/my-app/logs\");\n *\n * // With caching - second call skips filesystem\n * const cache = new Set<string>();\n * await ensureDir(\"/tmp/my-app/logs\", cache); // calls mkdir\n * await ensureDir(\"/tmp/my-app/logs\", cache); // returns immediately\n * ```\n */\nexport async function ensureDir(dirPath: string, cache?: Set<string>): Promise<void> {\n if (cache?.has(dirPath)) {\n return;\n }\n\n await mkdir(dirPath, { recursive: true });\n\n cache?.add(dirPath);\n}\n","import { EventEmitter } from \"node:events\";\nimport type { NeoEvent } from \"@/types\";\n\n/**\n * Safe EventEmitter wrapper (ADR-022).\n *\n * - Catches listener errors to prevent cascading crashes\n * - Emits on both the specific event type and the wildcard \"*\" channel\n * - Swallows errors from the error handler itself to guarantee stability\n */\nexport class NeoEventEmitter {\n private readonly emitter = new EventEmitter();\n\n emit(event: NeoEvent): void {\n this.safeEmit(event.type, event);\n this.safeEmit(\"*\", event);\n }\n\n on(eventType: string, listener: (event: NeoEvent) => void): this {\n this.emitter.on(eventType, listener);\n return this;\n }\n\n off(eventType: string, listener: (event: NeoEvent) => void): this {\n this.emitter.off(eventType, listener);\n return this;\n }\n\n once(eventType: string, listener: (event: NeoEvent) => void): this {\n this.emitter.once(eventType, listener);\n return this;\n }\n\n removeAllListeners(eventType?: string): this {\n this.emitter.removeAllListeners(eventType);\n return this;\n }\n\n private safeEmit(eventType: string, event: NeoEvent): void {\n try {\n this.emitter.emit(eventType, event);\n } catch (error) {\n if (eventType !== \"error\") {\n try {\n this.emitter.emit(\"error\", error);\n } catch {\n // Swallow — prevent crash even if error handler throws\n }\n }\n }\n }\n}\n","import { appendFile } from \"node:fs/promises\";\nimport { fileForDate } from \"@/shared/date\";\nimport { ensureDir } from \"@/shared/fs\";\nimport type { NeoEvent } from \"@/types\";\n\n/**\n * Append-only JSONL journal for events.\n * Monthly file rotation: events-YYYY-MM.jsonl\n * Write-only for v0.1 — read API comes in v0.2.\n */\nexport class EventJournal {\n private readonly dir: string;\n private readonly dirCache = new Set<string>();\n\n constructor(options: { dir: string }) {\n this.dir = options.dir;\n }\n\n async append(event: NeoEvent): Promise<void> {\n await ensureDir(this.dir, this.dirCache);\n const file = fileForDate(new Date(event.timestamp), \"events\", this.dir);\n await appendFile(file, `${JSON.stringify(event)}\\n`, \"utf-8\");\n }\n}\n","import { createHmac, randomUUID } from \"node:crypto\";\nimport type { NeoConfig } from \"@/config\";\nimport type { NeoEvent } from \"@/types\";\n\ntype WebhookConfig = NeoConfig[\"webhooks\"][number];\n\ninterface WebhookPayload {\n id: string;\n version: 1;\n event: string;\n payload: Record<string, unknown>;\n source: \"neo\";\n deliveredAt: string;\n}\n\n/** Event types that get retry on failure (terminal events the supervisor must see). */\nconst RETRY_EVENT_TYPES = new Set([\"session:complete\", \"session:fail\", \"budget:alert\"]);\n\nconst RETRY_MAX_ATTEMPTS = 3;\nconst RETRY_BASE_DELAY_MS = 500;\n\n/**\n * Webhook dispatcher for NeoEvents.\n *\n * - Matches events against per-webhook filters (exact or wildcard like \"session:*\")\n * - Excludes gate:waiting events (contain non-serializable callbacks)\n * - Signs payloads with HMAC-SHA256 when a secret is configured\n * - Terminal events (session:complete, session:fail, budget:alert) are retried\n * with exponential backoff on failure\n * - Non-terminal events remain fire-and-forget\n */\nexport class WebhookDispatcher {\n private readonly webhooks: WebhookConfig[];\n private readonly pending: Set<Promise<void>> = new Set();\n\n constructor(webhooks: WebhookConfig[]) {\n this.webhooks = webhooks;\n }\n\n dispatch(event: NeoEvent): void {\n // gate:waiting contains non-serializable callbacks (approve/reject)\n if (event.type === \"gate:waiting\") return;\n\n for (const webhook of this.webhooks) {\n if (!matchesFilter(event.type, webhook.events)) continue;\n\n const payload: WebhookPayload = {\n id: randomUUID(),\n version: 1,\n event: event.type,\n payload: toSerializable(event),\n source: \"neo\",\n deliveredAt: new Date().toISOString(),\n };\n\n const body = JSON.stringify(payload);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n if (webhook.secret) {\n headers[\"X-Neo-Signature\"] = sign(body, webhook.secret);\n }\n\n if (RETRY_EVENT_TYPES.has(event.type)) {\n // Terminal events: retry with exponential backoff, track for flush\n const p = sendWithRetry(webhook.url, headers, body, webhook.timeoutMs)\n .catch(() => {})\n .finally(() => this.pending.delete(p));\n this.pending.add(p);\n } else {\n // Non-terminal: fire-and-forget\n fetch(webhook.url, {\n method: \"POST\",\n headers,\n body,\n signal: AbortSignal.timeout(webhook.timeoutMs),\n }).catch(() => {});\n }\n }\n }\n\n /** Wait for all pending terminal webhook deliveries to complete. */\n async flush(): Promise<void> {\n if (this.pending.size === 0) return;\n await Promise.allSettled([...this.pending]);\n }\n}\n\n/**\n * Send a webhook POST with exponential backoff retry.\n * Retries up to RETRY_MAX_ATTEMPTS times with delays of 500ms, 1s, 2s.\n */\nasync function sendWithRetry(\n url: string,\n headers: Record<string, string>,\n body: string,\n timeoutMs: number,\n): Promise<void> {\n for (let attempt = 1; attempt <= RETRY_MAX_ATTEMPTS; attempt++) {\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (res.ok) return;\n // Non-2xx: treat as failure, retry\n } catch {\n // Network error or timeout: retry\n }\n\n if (attempt < RETRY_MAX_ATTEMPTS) {\n const delay = RETRY_BASE_DELAY_MS * 2 ** (attempt - 1);\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n}\n\n/**\n * Check if an event type matches a filter list.\n * Supports exact matches and wildcard prefixes (e.g. \"session:*\").\n * No filter (undefined) means all events match.\n */\nexport function matchesFilter(eventType: string, filters?: string[]): boolean {\n if (!filters || filters.length === 0) return true;\n return filters.some((f) => {\n if (f.endsWith(\":*\")) return eventType.startsWith(f.slice(0, -1));\n return f === eventType;\n });\n}\n\nfunction sign(body: string, secret: string): string {\n return createHmac(\"sha256\", secret).update(body).digest(\"hex\");\n}\n\nfunction toSerializable(event: NeoEvent): Record<string, unknown> {\n const obj: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(event)) {\n if (typeof value !== \"function\") {\n obj[key] = value;\n }\n }\n return obj;\n}\n","import { execFile } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, rm } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\nconst GIT_TIMEOUT = 60_000;\n\nexport interface SessionCloneInfo {\n path: string;\n branch: string;\n repoPath: string;\n}\n\n/**\n * Create an isolated git clone for an agent session.\n * Uses `git clone --local` to hardlink objects (fast, no network).\n * Then checks out the target branch (existing or new).\n */\nexport async function createSessionClone(options: {\n repoPath: string;\n branch: string;\n baseBranch: string;\n sessionDir: string;\n}): Promise<SessionCloneInfo> {\n const repoPath = resolve(options.repoPath);\n const sessionDir = resolve(options.sessionDir);\n\n await mkdir(dirname(sessionDir), { recursive: true });\n\n // Resolve the real upstream remote URL so the clone is completely\n // independent from the user's local repo. This prevents any git\n // operations in the clone from leaking into the user's working tree.\n const remoteUrl = await execFileAsync(\"git\", [\"config\", \"--get\", \"remote.origin.url\"], {\n cwd: repoPath,\n timeout: GIT_TIMEOUT,\n })\n .then(({ stdout }) => stdout.trim())\n .catch(() => \"\");\n\n // Clone from the real remote (GitHub) instead of the local path.\n // This ensures zero coupling: no hardlinks, no local-path origin,\n // no alternates. Falls back to local clone if no remote is configured.\n const cloneSource = remoteUrl || repoPath;\n await execFileAsync(\"git\", [\"clone\", \"--branch\", options.baseBranch, cloneSource, sessionDir], {\n timeout: GIT_TIMEOUT,\n });\n\n // If branch === baseBranch, we're already on it after clone — nothing to do\n if (options.branch !== options.baseBranch) {\n // Check if the target branch already exists on the remote (e.g. fixer on existing PR)\n const branchExists = await execFileAsync(\n \"git\",\n [\"ls-remote\", \"--heads\", \"origin\", options.branch],\n { cwd: sessionDir, timeout: GIT_TIMEOUT },\n )\n .then(({ stdout }) => stdout.trim().length > 0)\n .catch(() => false);\n\n if (branchExists) {\n // Fetch and checkout the existing branch\n await execFileAsync(\"git\", [\"fetch\", \"origin\", options.branch], {\n cwd: sessionDir,\n timeout: GIT_TIMEOUT,\n });\n await execFileAsync(\"git\", [\"checkout\", \"-b\", options.branch, `origin/${options.branch}`], {\n cwd: sessionDir,\n timeout: GIT_TIMEOUT,\n });\n } else {\n // Create a new branch from baseBranch\n await execFileAsync(\"git\", [\"checkout\", \"-b\", options.branch], {\n cwd: sessionDir,\n timeout: GIT_TIMEOUT,\n });\n }\n }\n\n return { path: sessionDir, branch: options.branch, repoPath };\n}\n\n/**\n * Remove a session clone directory.\n * Idempotent — does not throw if the directory is already gone.\n */\nexport async function removeSessionClone(sessionPath: string): Promise<void> {\n const absPath = resolve(sessionPath);\n\n if (!existsSync(absPath)) {\n return;\n }\n\n await rm(absPath, { recursive: true, force: true });\n}\n\n/**\n * List all session clones under a base directory.\n */\nexport async function listSessionClones(sessionsBaseDir: string): Promise<SessionCloneInfo[]> {\n const absBase = resolve(sessionsBaseDir);\n\n if (!existsSync(absBase)) {\n return [];\n }\n\n const entries = await readdir(absBase, { withFileTypes: true });\n const clones: SessionCloneInfo[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const clonePath = resolve(absBase, entry.name);\n\n try {\n const { stdout: branchOut } = await execFileAsync(\n \"git\",\n [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"],\n {\n cwd: clonePath,\n timeout: GIT_TIMEOUT,\n },\n );\n let repoPath = clonePath;\n try {\n const { stdout: originUrl } = await execFileAsync(\n \"git\",\n [\"config\", \"--get\", \"remote.origin.url\"],\n { cwd: clonePath, timeout: GIT_TIMEOUT },\n );\n const url = originUrl.trim();\n if (url) repoPath = resolve(clonePath, url);\n } catch {\n // No origin or not a clone — keep clonePath as fallback\n }\n clones.push({\n path: clonePath,\n branch: branchOut.trim(),\n repoPath,\n });\n } catch {\n // Not a git repo — skip\n }\n }\n\n return clones;\n}\n","import { execFile } from \"node:child_process\";\nimport { resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport type { RepoConfig } from \"@/config\";\n\nconst execFileAsync = promisify(execFile);\nconst GIT_TIMEOUT = 60_000;\n\n/**\n * Run a git command with execFile (no shell — prevents injection).\n */\nasync function git(repoPath: string, args: string[]): Promise<string> {\n const { stdout } = await execFileAsync(\"git\", args, {\n cwd: resolve(repoPath),\n timeout: GIT_TIMEOUT,\n });\n return stdout.trim();\n}\n\nexport async function createBranch(\n repoPath: string,\n branch: string,\n baseBranch: string,\n): Promise<void> {\n await git(repoPath, [\"branch\", branch, baseBranch]);\n}\n\nexport async function pushBranch(repoPath: string, branch: string, remote: string): Promise<void> {\n await git(repoPath, [\"push\", remote, branch]);\n}\n\nexport async function fetchRemote(repoPath: string, remote: string): Promise<void> {\n await git(repoPath, [\"fetch\", remote]);\n}\n\nexport async function deleteBranch(repoPath: string, branch: string): Promise<void> {\n await git(repoPath, [\"branch\", \"-D\", branch]);\n}\n\nexport async function getCurrentBranch(repoPath: string): Promise<string> {\n return git(repoPath, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n}\n\n/**\n * Resolve the branch name for a run.\n * If an explicit branch is provided, use it as-is.\n * Otherwise, generate a deterministic name from the repo's branchPrefix and runId.\n */\nexport function getBranchName(config: RepoConfig, runId: string, branch?: string): string {\n if (branch) return branch;\n const prefix = config.branchPrefix ?? \"feat\";\n const sanitized = runId.toLowerCase().replace(/[^a-z0-9-]/g, \"-\");\n return `${prefix}/run-${sanitized}`;\n}\n\n/**\n * Check if a session clone has uncommitted changes (staged or unstaged).\n */\nexport async function hasUncommittedChanges(sessionPath: string): Promise<boolean> {\n const status = await git(sessionPath, [\"status\", \"--porcelain\"]);\n return status.length > 0;\n}\n\n/**\n * Auto-commit all changes in a session clone. Used as a safety net after agent\n * sessions to prevent losing work when the clone is cleaned up.\n */\nexport async function autoCommitChanges(sessionPath: string, runId: string): Promise<boolean> {\n const hasChanges = await hasUncommittedChanges(sessionPath);\n if (!hasChanges) return false;\n\n await git(sessionPath, [\"add\", \"-A\"]);\n await git(sessionPath, [\n \"commit\",\n \"-m\",\n `chore: auto-commit uncommitted changes from run ${runId}`,\n ]);\n\n return true;\n}\n\n/**\n * Push a branch from a session clone to a remote. Silently succeeds if\n * the branch has no new commits to push.\n */\nexport async function pushSessionBranch(\n sessionPath: string,\n branch: string,\n remote: string,\n): Promise<void> {\n await git(sessionPath, [\"push\", \"-u\", remote, branch]);\n}\n","import { resolve } from \"node:path\";\nimport type { ResolvedAgent } from \"@/types\";\n\n/**\n * SDK-compatible sandbox configuration.\n * Controls which tools an agent can use and which paths it can access.\n */\nexport interface SandboxConfig {\n /** Tools the agent is allowed to use */\n allowedTools: string[];\n /** Directories the agent can read from */\n readablePaths: string[];\n /** Directories the agent can write to (empty for readonly agents) */\n writablePaths: string[];\n /** Whether the agent has write access */\n writable: boolean;\n}\n\n/** Tools that modify the filesystem */\nconst WRITE_TOOLS = new Set([\"Write\", \"Edit\", \"NotebookEdit\"]);\n\n/**\n * Build an SDK-compatible sandbox configuration for an agent.\n *\n * - Writable agents: all their tools are allowed, write paths include the session clone\n * - Readonly agents: write tools are filtered out, no writable paths\n */\nexport function buildSandboxConfig(agent: ResolvedAgent, sessionPath?: string): SandboxConfig {\n const isWritable = agent.sandbox === \"writable\";\n const absSession = sessionPath ? resolve(sessionPath) : undefined;\n\n const allowedTools = isWritable\n ? agent.definition.tools\n : agent.definition.tools.filter((t) => !WRITE_TOOLS.has(t));\n\n const readablePaths = absSession ? [absSession] : [];\n const writablePaths = isWritable && absSession ? [absSession] : [];\n\n return {\n allowedTools,\n readablePaths,\n writablePaths,\n writable: isWritable,\n };\n}\n","import { appendFile, mkdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Middleware } from \"@/types\";\n\nconst DEFAULT_FLUSH_INTERVAL_MS = 500;\nconst DEFAULT_FLUSH_SIZE = 20;\n\n/**\n * Audit log middleware.\n *\n * Buffers JSONL entries in memory and flushes to disk either when\n * the buffer reaches `flushSize` entries or every `flushIntervalMs`.\n * File per session. Uses `{ decision: \"async\" }` so it never blocks the chain.\n *\n * Call `flush()` to force-write remaining entries (e.g. on shutdown).\n */\nexport interface AuditLogMiddleware extends Middleware {\n flush: () => Promise<void>;\n}\n\nexport function auditLog(options: {\n dir: string;\n includeInput?: boolean;\n includeOutput?: boolean;\n flushIntervalMs?: number;\n flushSize?: number;\n}): AuditLogMiddleware {\n const {\n dir,\n includeInput = true,\n includeOutput = false,\n flushIntervalMs = DEFAULT_FLUSH_INTERVAL_MS,\n flushSize = DEFAULT_FLUSH_SIZE,\n } = options;\n\n let dirCreated = false;\n // sessionId → buffered lines\n const buffers = new Map<string, string[]>();\n let flushTimer: ReturnType<typeof setInterval> | undefined;\n\n async function ensureDir(): Promise<void> {\n if (!dirCreated) {\n await mkdir(dir, { recursive: true });\n dirCreated = true;\n }\n }\n\n async function flushAll(): Promise<void> {\n if (buffers.size === 0) return;\n await ensureDir();\n\n const writes: Promise<void>[] = [];\n for (const [sessionId, lines] of buffers) {\n const filePath = path.join(dir, `${sessionId}.jsonl`);\n writes.push(appendFile(filePath, lines.join(\"\"), \"utf-8\"));\n }\n buffers.clear();\n await Promise.all(writes);\n }\n\n async function flushSession(sessionId: string): Promise<void> {\n const lines = buffers.get(sessionId);\n if (!lines || lines.length === 0) return;\n await ensureDir();\n\n const filePath = path.join(dir, `${sessionId}.jsonl`);\n await appendFile(filePath, lines.join(\"\"), \"utf-8\");\n buffers.delete(sessionId);\n }\n\n return {\n name: \"audit-log\",\n on: \"PostToolUse\",\n async flush() {\n await flushAll();\n if (flushTimer !== undefined) {\n clearInterval(flushTimer);\n flushTimer = undefined;\n }\n },\n async handler(event, context) {\n const entry: Record<string, unknown> = {\n timestamp: new Date().toISOString(),\n sessionId: event.sessionId,\n agent: context.agent,\n toolName: event.toolName,\n };\n\n if (includeInput && event.input !== undefined) {\n entry.input = event.input;\n }\n\n if (includeOutput && event.output !== undefined) {\n entry.output = event.output;\n }\n\n const sessionId = event.sessionId;\n let lines = buffers.get(sessionId);\n if (!lines) {\n lines = [];\n buffers.set(sessionId, lines);\n }\n lines.push(`${JSON.stringify(entry)}\\n`);\n\n // Flush when buffer is full\n if (lines.length >= flushSize) {\n await flushSession(sessionId);\n }\n\n // Start periodic flush timer if not already running\n if (flushTimer === undefined && flushIntervalMs > 0) {\n flushTimer = setInterval(() => {\n void flushAll();\n }, flushIntervalMs);\n // Unref so it doesn't keep the process alive\n if (typeof flushTimer === \"object\" && \"unref\" in flushTimer) {\n flushTimer.unref();\n }\n }\n\n return { decision: \"async\", asyncTimeout: 5_000 };\n },\n };\n}\n","import type { Middleware } from \"@/types\";\n\n/**\n * Budget guard middleware.\n *\n * Checks daily cost against budget cap on every tool call.\n * If over budget, blocks with reason \"Daily budget exceeded\".\n * Uses the middleware context's `get(\"costToday\")` and `get(\"budgetCapUsd\")`.\n */\nexport function budgetGuard(): Middleware {\n return {\n name: \"budget-guard\",\n on: \"PreToolUse\",\n async handler(_event, context) {\n const costToday = context.get(\"costToday\");\n const budgetCapUsd = context.get(\"budgetCapUsd\");\n\n if (costToday !== undefined && budgetCapUsd !== undefined && costToday >= budgetCapUsd) {\n return {\n decision: \"block\",\n reason: \"Daily budget exceeded\",\n };\n }\n\n return { decision: \"pass\" };\n },\n };\n}\n","import type {\n HookCallback,\n HookCallbackMatcher,\n HookInput,\n HookJSONOutput,\n HookEvent as SDKHookEvent,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport type {\n HookEvent,\n Middleware,\n MiddlewareContext,\n MiddlewareEvent,\n MiddlewareResult,\n} from \"@/types\";\n\nexport interface MiddlewareChain {\n execute(event: MiddlewareEvent, context: MiddlewareContext): Promise<MiddlewareResult>;\n}\n\nfunction matchesTool(match: string | string[] | undefined, toolName: string | undefined): boolean {\n if (match === undefined) return true;\n if (toolName === undefined) return false;\n if (Array.isArray(match)) return match.includes(toolName);\n return match === toolName;\n}\n\nexport function buildMiddlewareChain(middleware: Middleware[]): MiddlewareChain {\n return {\n async execute(event: MiddlewareEvent, context: MiddlewareContext): Promise<MiddlewareResult> {\n let lastAsync: MiddlewareResult | undefined;\n\n for (const mw of middleware) {\n // Hook event matching\n if (mw.on !== event.hookEvent) continue;\n\n // Tool name matching\n if (!matchesTool(mw.match, event.toolName)) continue;\n\n const result = await mw.handler(event, context);\n\n switch (result.decision) {\n case \"block\":\n return result;\n case \"async\":\n lastAsync = result;\n break;\n case \"pass\":\n break;\n }\n }\n\n return lastAsync ?? { decision: \"pass\" };\n },\n };\n}\n\n/**\n * SDK hooks type — maps hook event names to callback matchers.\n */\nexport type SDKHooks = Partial<Record<SDKHookEvent, HookCallbackMatcher[]>>;\n\n/**\n * Convert a middleware chain to Agent SDK hooks format.\n *\n * Creates one HookCallbackMatcher per supported event (PreToolUse, PostToolUse, Notification).\n * The matcher delegates to the chain's execute method, translating SDK input to our\n * MiddlewareEvent format.\n */\nexport function buildSDKHooks(\n chain: MiddlewareChain,\n context: MiddlewareContext,\n middleware: Middleware[] = [],\n): SDKHooks {\n function makeCallback(hookEvent: HookEvent): HookCallback {\n return async (input: HookInput): Promise<HookJSONOutput> => {\n const event: MiddlewareEvent = {\n hookEvent,\n sessionId: input.session_id,\n toolName: \"tool_name\" in input ? (input.tool_name as string) : undefined,\n input: \"tool_input\" in input ? (input.tool_input as Record<string, unknown>) : undefined,\n output: \"tool_response\" in input ? String(input.tool_response) : undefined,\n message: \"message\" in input ? (input.message as string) : undefined,\n };\n\n const result = await chain.execute(event, context);\n\n switch (result.decision) {\n case \"block\":\n return { decision: \"block\", reason: result.reason };\n case \"async\":\n return { async: true, asyncTimeout: result.asyncTimeout };\n case \"pass\":\n return {};\n }\n };\n }\n\n // Only register hooks for events that have at least one middleware listener\n const usedEvents = new Set(middleware.map((mw) => mw.on));\n const allEvents: HookEvent[] = [\"PreToolUse\", \"PostToolUse\", \"Notification\"];\n\n const hooks: SDKHooks = {};\n for (const hookEvent of allEvents) {\n // When no middleware list is provided, register all events (backward-compatible)\n if (middleware.length === 0 || usedEvents.has(hookEvent)) {\n hooks[hookEvent] = [{ hooks: [makeCallback(hookEvent)] }];\n }\n }\n\n return hooks;\n}\n","import type { Middleware } from \"@/types\";\n\n/**\n * Loop detection middleware.\n *\n * Tracks Bash commands per session. If the same command appears\n * `threshold` times, blocks it and tells the agent to escalate.\n *\n * Call `cleanup(sessionId)` when a session ends to prevent memory leaks.\n */\nexport interface LoopDetectionMiddleware extends Middleware {\n cleanup: (sessionId: string) => void;\n}\n\nexport function loopDetection(options: {\n threshold: number;\n scope?: \"session\";\n}): LoopDetectionMiddleware {\n const { threshold } = options;\n const commandHistory = new Map<string, Map<string, number>>();\n\n return {\n name: \"loop-detection\",\n on: \"PreToolUse\",\n match: \"Bash\",\n cleanup(sessionId: string) {\n commandHistory.delete(sessionId);\n },\n async handler(event) {\n const sessionId = event.sessionId;\n const command =\n event.input && typeof event.input === \"object\" && \"command\" in event.input\n ? String(event.input.command)\n : \"\";\n\n if (!command) return { decision: \"pass\" };\n\n if (!commandHistory.has(sessionId)) {\n commandHistory.set(sessionId, new Map());\n }\n\n const sessionHistory = commandHistory.get(sessionId) ?? new Map<string, number>();\n const count = (sessionHistory.get(command) ?? 0) + 1;\n sessionHistory.set(command, count);\n\n if (count >= threshold) {\n return {\n decision: \"block\",\n reason: `Loop detected: you have run this exact command ${String(count)} times. STOP and escalate — do not retry the same approach.`,\n };\n }\n\n return { decision: \"pass\" };\n },\n };\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Semaphore } from \"@/concurrency/semaphore\";\nimport type { McpServerConfig, NeoConfig, RepoConfig } from \"@/config\";\nimport { CostJournal } from \"@/cost/journal\";\nimport { NeoEventEmitter } from \"@/events\";\nimport { EventJournal } from \"@/events/journal\";\nimport { WebhookDispatcher } from \"@/events/webhook\";\nimport { createSessionClone, removeSessionClone } from \"@/isolation/clone\";\nimport { pushSessionBranch } from \"@/isolation/git\";\nimport { auditLog } from \"@/middleware/audit-log\";\nimport { budgetGuard } from \"@/middleware/budget-guard\";\nimport { loopDetection } from \"@/middleware/loop-detection\";\nimport { RunStore } from \"@/orchestrator/run-store\";\nimport { getJournalsDir, getSupervisorsDir } from \"@/paths\";\nimport { SessionExecutor } from \"@/runner/session-executor\";\nimport { isProcessAlive } from \"@/shared/process\";\nimport { formatMemoriesForPrompt, MemoryStore } from \"@/supervisor/memory/index.js\";\nimport type {\n ActiveSession,\n CostEntry,\n DispatchInput,\n Middleware,\n NeoEvent,\n OrchestratorStatus,\n PersistedRun,\n ResolvedAgent,\n StepResult,\n TaskResult,\n WorkflowDefinition,\n WorkflowStepDef,\n} from \"@/types\";\nimport { WorkflowRegistry } from \"@/workflows/registry\";\n\n// ─── Constants ─────────────────────────────────────────\n\nconst MAX_PROMPT_SIZE = 100 * 1024; // 100 KB\nconst MAX_METADATA_DEPTH = 5;\nconst SHUTDOWN_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\nconst textEncoder = new TextEncoder();\n\n// ─── Options ───────────────────────────────────────────\n\nexport interface OrchestratorOptions {\n middleware?: Middleware[] | undefined;\n journalDir?: string | undefined;\n builtInWorkflowDir?: string | undefined;\n customWorkflowDir?: string | undefined;\n}\n\n// ─── Internal dispatch context ─────────────────────────\n\ninterface DispatchContext {\n input: DispatchInput;\n runId: string;\n sessionId: string;\n startedAt: number;\n stepName: string;\n stepDef: WorkflowStepDef;\n agent: ResolvedAgent;\n repoConfig: RepoConfig;\n activeSession: ActiveSession;\n}\n\n// ─── Idempotency ───────────────────────────────────────\n\ninterface IdempotencyEntry {\n result: TaskResult;\n expiresAt: number;\n}\n\n// ─── Orchestrator ──────────────────────────────────────\n\nexport class Orchestrator extends NeoEventEmitter {\n private readonly config: NeoConfig;\n private readonly semaphore: Semaphore;\n private readonly userMiddleware: Middleware[];\n private readonly workflows = new Map<string, WorkflowDefinition>();\n private readonly registeredAgents = new Map<string, ResolvedAgent>();\n private readonly _activeSessions = new Map<string, ActiveSession>();\n private readonly idempotencyCache = new Map<string, IdempotencyEntry>();\n private readonly abortControllers = new Map<string, AbortController>();\n private readonly repoIndex = new Map<string, RepoConfig>();\n private readonly runStore = new RunStore();\n private readonly journalDir: string;\n private readonly builtInWorkflowDir: string | undefined;\n private readonly customWorkflowDir: string | undefined;\n private costJournal: CostJournal | null = null;\n private eventJournal: EventJournal | null = null;\n private webhookDispatcher: WebhookDispatcher | null = null;\n private memoryStore: MemoryStore | null = null;\n private _paused = false;\n private _costToday = 0;\n private _startedAt = 0;\n private _drainResolve: (() => void) | null = null;\n\n constructor(config: NeoConfig, options: OrchestratorOptions = {}) {\n super();\n this.config = config;\n this.userMiddleware = options.middleware ?? [];\n this.journalDir = options.journalDir ?? getJournalsDir();\n this.builtInWorkflowDir = options.builtInWorkflowDir;\n this.customWorkflowDir = options.customWorkflowDir;\n for (const repo of config.repos) {\n const resolvedPath = path.resolve(repo.path);\n const normalizedRepo = { ...repo, path: resolvedPath };\n this.repoIndex.set(resolvedPath, normalizedRepo);\n }\n this.semaphore = new Semaphore(\n {\n maxSessions: config.concurrency.maxSessions,\n maxPerRepo: config.concurrency.maxPerRepo,\n queueMax: config.concurrency.queueMax,\n },\n {\n onEnqueue: (sessionId, repo, position) => {\n this.emit({\n type: \"queue:enqueue\",\n sessionId,\n repo,\n position,\n timestamp: new Date().toISOString(),\n });\n },\n onDequeue: (sessionId, repo, waitedMs) => {\n this.emit({\n type: \"queue:dequeue\",\n sessionId,\n repo,\n waitedMs,\n timestamp: new Date().toISOString(),\n });\n },\n },\n );\n }\n\n // ─── Registration ──────────────────────────────────────\n\n registerWorkflow(definition: WorkflowDefinition): void {\n this.workflows.set(definition.name, definition);\n }\n\n registerAgent(agent: ResolvedAgent): void {\n this.registeredAgents.set(agent.name, agent);\n }\n\n // ─── Dispatch ──────────────────────────────────────────\n\n async dispatch(input: DispatchInput): Promise<TaskResult> {\n const idempotencyKey = this.preDispatchChecks(input);\n const ctx = this.buildDispatchContext(input);\n\n // Acquire semaphore (blocks if at capacity)\n const abortController = new AbortController();\n this.abortControllers.set(ctx.sessionId, abortController);\n await this.semaphore.acquire(\n input.repo,\n ctx.sessionId,\n input.priority ?? \"medium\",\n abortController.signal,\n );\n ctx.activeSession.status = \"running\";\n\n const stepResult = await this.executeStep(ctx);\n return this.finalizeDispatch(ctx, stepResult, idempotencyKey);\n }\n\n // ─── Control ───────────────────────────────────────────\n\n pause(): void {\n this._paused = true;\n }\n\n resume(): void {\n this._paused = false;\n }\n\n async kill(sessionId: string): Promise<void> {\n const controller = this.abortControllers.get(sessionId);\n if (controller) {\n controller.abort(new Error(\"Session killed\"));\n }\n\n this._activeSessions.delete(sessionId);\n this.abortControllers.delete(sessionId);\n this.semaphore.release(sessionId);\n }\n\n async drain(): Promise<void> {\n this._paused = true;\n if (this._activeSessions.size === 0) return;\n return new Promise<void>((resolve) => {\n this._drainResolve = resolve;\n });\n }\n\n // ─── Getters ───────────────────────────────────────────\n\n get status(): OrchestratorStatus {\n return {\n paused: this._paused,\n activeSessions: [...this._activeSessions.values()],\n queueDepth: this.semaphore.queueDepth(),\n costToday: this._costToday,\n budgetCapUsd: this.config.budget.dailyCapUsd,\n budgetRemainingPct: this.computeBudgetRemainingPct(),\n uptime: this._startedAt > 0 ? Date.now() - this._startedAt : 0,\n };\n }\n\n get activeSessions(): ActiveSession[] {\n return [...this._activeSessions.values()];\n }\n\n // ─── Lifecycle ─────────────────────────────────────────\n\n async start(): Promise<void> {\n this._startedAt = Date.now();\n\n // Initialize journals\n this.costJournal = new CostJournal({ dir: this.journalDir });\n this.eventJournal = new EventJournal({ dir: this.journalDir });\n\n // Initialize webhook dispatcher with configured webhooks + auto-discovered supervisor webhooks\n const supervisorWebhooks = await this.discoverSupervisorWebhooks();\n\n const allWebhooks = [...this.config.webhooks, ...supervisorWebhooks];\n if (allWebhooks.length > 0) {\n this.webhookDispatcher = new WebhookDispatcher(allWebhooks);\n }\n\n // Log supervisor webhook discovery for debugging connectivity\n if (supervisorWebhooks.length > 0) {\n // biome-ignore lint/suspicious/noConsole: Intentional logging for webhook discovery\n console.log(\n `[neo] Discovered ${supervisorWebhooks.length} supervisor webhook(s): ${supervisorWebhooks.map((w) => w.url).join(\", \")}`,\n );\n }\n\n // Restore today's cost from journal\n this._costToday = await this.costJournal.getDayTotal();\n\n // Load workflows from registry if dirs are configured\n if (this.builtInWorkflowDir) {\n const registry = new WorkflowRegistry(this.builtInWorkflowDir, this.customWorkflowDir);\n await registry.load();\n for (const workflow of registry.list()) {\n this.registerWorkflow(workflow);\n }\n }\n\n await this.recoverOrphanedRuns();\n\n await mkdir(this.config.sessions.dir, { recursive: true });\n }\n\n async shutdown(): Promise<void> {\n this._paused = true;\n\n if (this._activeSessions.size > 0) {\n await Promise.race([\n this.drain(),\n new Promise<void>((resolve) => setTimeout(resolve, SHUTDOWN_TIMEOUT_MS)),\n ]);\n }\n\n for (const mw of this.userMiddleware) {\n if (\"flush\" in mw && typeof mw.flush === \"function\") {\n await (mw as { flush: () => Promise<void> }).flush();\n }\n if (\"cleanup\" in mw && typeof mw.cleanup === \"function\") {\n for (const session of this._activeSessions.values()) {\n (mw as { cleanup: (id: string) => void }).cleanup(session.sessionId);\n }\n }\n }\n\n this.emit({\n type: \"orchestrator:shutdown\",\n timestamp: new Date().toISOString(),\n });\n\n // Flush pending webhook deliveries — ensures terminal events\n // (session:complete/fail) reach the supervisor before process exits\n if (this.webhookDispatcher) {\n await this.webhookDispatcher.flush();\n }\n }\n\n // ─── Emit override (journal events) ───────────────────\n\n override emit(event: NeoEvent): void {\n super.emit(event);\n // Fire-and-forget event journal append\n if (this.eventJournal) {\n this.eventJournal.append(event).catch(() => {});\n }\n // Fire-and-forget webhook dispatch\n if (this.webhookDispatcher) {\n this.webhookDispatcher.dispatch(event);\n }\n }\n\n // ─── Static middleware factories ───────────────────────\n\n static middleware = {\n loopDetection: (options: { threshold: number; scope?: \"session\" }) => loopDetection(options),\n auditLog: (options: {\n dir: string;\n includeInput?: boolean;\n includeOutput?: boolean;\n flushIntervalMs?: number;\n flushSize?: number;\n }) => auditLog(options),\n budgetGuard: () => budgetGuard(),\n };\n\n // ─── Private: Dispatch phases ──────────────────────────\n\n private preDispatchChecks(input: DispatchInput): string | null {\n this.validateInput(input);\n\n const idempotencyKey = this.computeIdempotencyKey(input);\n if (idempotencyKey) {\n this.evictExpiredIdempotencyEntries();\n const cached = this.idempotencyCache.get(idempotencyKey);\n if (cached && cached.expiresAt > Date.now()) {\n throw new Error(\n `Duplicate dispatch rejected: runId '${input.runId ?? \"auto-generated\"}' already exists. Each dispatch must use a unique runId.`,\n );\n }\n }\n\n if (this._paused) {\n throw new Error(\n \"Dispatch rejected: orchestrator is paused. Call orchestrator.resume() before dispatching.\",\n );\n }\n\n return idempotencyKey;\n }\n\n private buildDispatchContext(input: DispatchInput): DispatchContext {\n const runId = input.runId ?? randomUUID();\n const sessionId = randomUUID();\n const workflow = this.workflows.get(input.workflow);\n if (!workflow) {\n const available = [...this.workflows.keys()].join(\", \") || \"none\";\n throw new Error(\n `Workflow \"${input.workflow}\" not found. Available workflows: ${available}. Check the workflow name or register it first.`,\n );\n }\n const [stepName, stepDef] = this.getFirstStep(workflow, input);\n const agent = this.resolveStepAgent(stepDef, workflow.name);\n const repoConfig = this.resolveRepo(input.repo);\n\n const activeSession: ActiveSession = {\n sessionId,\n runId,\n workflow: input.workflow,\n step: stepName,\n agent: agent.name,\n repo: input.repo,\n status: \"queued\",\n startedAt: new Date().toISOString(),\n };\n this._activeSessions.set(sessionId, activeSession);\n\n return {\n input,\n runId,\n sessionId,\n startedAt: Date.now(),\n stepName,\n stepDef,\n agent,\n repoConfig,\n activeSession,\n };\n }\n\n private async executeStep(ctx: DispatchContext): Promise<StepResult> {\n const { input, runId, sessionId, startedAt, agent, repoConfig, activeSession } = ctx;\n let sessionPath: string | undefined;\n\n // Persist initial running state so `neo runs` shows this run immediately\n await this.persistRun({\n version: 1,\n runId,\n workflow: input.workflow,\n repo: input.repo,\n prompt: input.prompt,\n status: \"running\",\n steps: {},\n createdAt: activeSession.startedAt,\n updatedAt: new Date().toISOString(),\n metadata: input.metadata,\n });\n\n try {\n // Create isolated clone for ALL agents.\n // Uses the explicit branch if provided, otherwise falls back to the base branch.\n const branchName = (input.branch as string) || repoConfig.defaultBranch;\n const sessionDir = path.join(this.config.sessions.dir, runId);\n const info = await createSessionClone({\n repoPath: input.repo,\n branch: branchName,\n baseBranch: repoConfig.defaultBranch,\n sessionDir,\n });\n sessionPath = info.path;\n activeSession.sessionPath = sessionPath;\n\n const stepResult = await this.runAgentSession(ctx, sessionPath);\n this.emitCostEvents(sessionId, stepResult.costUsd, ctx);\n this.emitSessionComplete(ctx, stepResult);\n return stepResult;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.emitSessionFail(ctx, errorMsg);\n\n const failResult: StepResult = {\n status: \"failure\",\n sessionId,\n costUsd: 0,\n durationMs: Date.now() - startedAt,\n agent: agent.name,\n startedAt: activeSession.startedAt,\n completedAt: new Date().toISOString(),\n error: errorMsg,\n attempt: 1,\n };\n\n // Write episode to memory store\n try {\n const store = this.getMemoryStore();\n await store.write({\n type: \"episode\",\n scope: input.repo,\n content: `Run ${runId.slice(0, 8)} (${agent.name}): failed${failResult.error ? ` — ${failResult.error.slice(0, 150)}` : \"\"}`,\n source: agent.name,\n outcome: \"failure\",\n runId,\n });\n } catch {\n // Best-effort — don't fail the run if memory write fails\n }\n\n return failResult;\n } finally {\n // Auto-commit, push, and cleanup session clone\n if (sessionPath) {\n await this.finalizeSession(sessionPath, ctx);\n }\n\n this.semaphore.release(sessionId);\n this._activeSessions.delete(sessionId);\n this.abortControllers.delete(sessionId);\n\n if (this._activeSessions.size === 0 && this._drainResolve) {\n this._drainResolve();\n this._drainResolve = null;\n }\n }\n }\n\n /**\n * Push the branch (writable only), then remove the session clone.\n * Runs in `finally` so it executes on both success and failure.\n */\n private async finalizeSession(sessionPath: string, ctx: DispatchContext): Promise<void> {\n // Only push for writable agents — readonly agents have no changes to push\n if (ctx.agent.sandbox === \"writable\") {\n const branch = ctx.input.branch as string;\n const remote = ctx.repoConfig.pushRemote ?? \"origin\";\n try {\n await pushSessionBranch(sessionPath, branch, remote).catch(() => {\n // Push may fail (no remote, auth, etc.) — not critical\n });\n } catch {\n // Best-effort — don't let finalization errors mask the real result\n }\n }\n\n try {\n await removeSessionClone(sessionPath);\n } catch {\n // Session cleanup is best-effort\n }\n }\n\n private async runAgentSession(\n ctx: DispatchContext,\n sessionPath: string | undefined,\n ): Promise<StepResult> {\n const { input, runId, sessionId, stepName, stepDef, agent, repoConfig, activeSession } = ctx;\n\n this.emit({\n type: \"session:start\",\n sessionId,\n runId,\n workflow: input.workflow,\n step: stepName,\n agent: agent.name,\n repo: input.repo,\n metadata: input.metadata,\n timestamp: new Date().toISOString(),\n });\n\n // Create SessionExecutor with config and context value getter\n const executor = new SessionExecutor(\n {\n initTimeoutMs: this.config.sessions.initTimeoutMs,\n maxDurationMs: this.config.sessions.maxDurationMs,\n maxRetries: this.config.recovery.maxRetries,\n backoffBaseMs: this.config.recovery.backoffBaseMs,\n },\n (key: string) => {\n if (key === \"costToday\") return this._costToday;\n if (key === \"budgetCapUsd\") return this.config.budget.dailyCapUsd;\n return undefined;\n },\n );\n\n // Build execution input\n const strategy = input.gitStrategy ?? repoConfig.gitStrategy ?? \"branch\";\n const mcpServers = this.resolveMcpServers(stepDef, agent);\n const memoryContext = this.loadMemoryContext(input.repo);\n const recoveryOpts = stepDef.recovery;\n\n const result = await executor.execute(\n {\n runId,\n sessionId,\n agent,\n stepDef,\n repoConfig,\n repoPath: input.repo,\n prompt: input.prompt,\n branch: input.branch,\n gitStrategy: strategy,\n sessionPath,\n metadata: input.metadata,\n startedAt: activeSession.startedAt,\n },\n {\n middleware: this.userMiddleware,\n mcpServers,\n memoryContext,\n onAttempt: (attempt, strategy) => {\n if (attempt > 1) {\n this.emit({\n type: \"session:fail\",\n sessionId,\n runId,\n error: `Retrying with strategy: ${strategy}`,\n attempt: attempt - 1,\n maxRetries: recoveryOpts?.maxRetries ?? this.config.recovery.maxRetries,\n willRetry: true,\n metadata: input.metadata,\n timestamp: new Date().toISOString(),\n });\n }\n },\n },\n );\n\n // Write episode to memory store\n try {\n const store = this.getMemoryStore();\n const isSuccess = result.status === \"success\";\n await store.write({\n type: \"episode\",\n scope: input.repo,\n content: `Run ${runId.slice(0, 8)} (${agent.name}): ${isSuccess ? \"completed\" : \"failed\"}${result.error ? ` — ${result.error.slice(0, 150)}` : \"\"}`,\n source: agent.name,\n outcome: isSuccess ? \"success\" : \"failure\",\n runId,\n });\n } catch {\n // Best-effort — don't fail the run if memory write fails\n }\n\n return result;\n }\n\n private async finalizeDispatch(\n ctx: DispatchContext,\n stepResult: StepResult,\n idempotencyKey: string | null,\n ): Promise<TaskResult> {\n const { input, runId, stepName, activeSession } = ctx;\n\n const taskResult: TaskResult = {\n runId,\n workflow: input.workflow,\n repo: input.repo,\n status: stepResult.status === \"success\" ? \"success\" : \"failure\",\n steps: { [stepName]: stepResult },\n branch:\n stepResult.status === \"success\" && activeSession.sessionPath ? input.branch : undefined,\n costUsd: stepResult.costUsd,\n durationMs: Date.now() - ctx.startedAt,\n timestamp: new Date().toISOString(),\n metadata: input.metadata,\n };\n\n if (stepResult.prUrl) {\n taskResult.prUrl = stepResult.prUrl;\n }\n if (stepResult.prNumber !== undefined) {\n taskResult.prNumber = stepResult.prNumber;\n }\n\n await this.persistRun({\n version: 1,\n runId,\n workflow: input.workflow,\n repo: input.repo,\n prompt: input.prompt,\n branch: taskResult.branch,\n status: taskResult.status === \"success\" ? \"completed\" : \"failed\",\n steps: taskResult.steps,\n createdAt: activeSession.startedAt,\n updatedAt: new Date().toISOString(),\n metadata: input.metadata,\n });\n\n if (idempotencyKey) {\n const ttl = this.config.idempotency?.ttlMs ?? 3_600_000;\n this.idempotencyCache.set(idempotencyKey, {\n result: taskResult,\n expiresAt: Date.now() + ttl,\n });\n }\n\n return taskResult;\n }\n\n // ─── Private: Memory injection ──────────────────────────\n\n private getMemoryStore(): MemoryStore {\n if (!this.memoryStore) {\n const supervisorDir = path.join(getSupervisorsDir(), \"supervisor\");\n this.memoryStore = new MemoryStore(path.join(supervisorDir, \"memory.sqlite\"));\n }\n return this.memoryStore;\n }\n\n private loadMemoryContext(repoPath: string): string | undefined {\n try {\n const store = this.getMemoryStore();\n const memories = store.query({\n scope: repoPath,\n types: [\"fact\", \"procedure\", \"feedback\"],\n limit: 25,\n sortBy: \"relevance\",\n });\n if (memories.length === 0) return undefined;\n store.markAccessed(memories.map((m) => m.id));\n return formatMemoriesForPrompt(memories);\n } catch {\n return undefined;\n }\n }\n\n // ─── Private: Event helpers ────────────────────────────\n\n private emitCostEvents(sessionId: string, sessionCost: number, ctx: DispatchContext): void {\n this._costToday += sessionCost;\n\n // Persist cost entry to journal (fire-and-forget)\n if (this.costJournal) {\n const costEntry: CostEntry = {\n timestamp: new Date().toISOString(),\n runId: ctx.runId,\n workflow: ctx.input.workflow,\n step: ctx.stepName,\n sessionId,\n agent: ctx.agent.name,\n costUsd: sessionCost,\n models: {},\n durationMs: Date.now() - ctx.startedAt,\n repo: ctx.input.repo,\n };\n this.costJournal.append(costEntry).catch(() => {});\n }\n\n this.emit({\n type: \"cost:update\",\n sessionId,\n sessionCost,\n todayTotal: this._costToday,\n budgetRemainingPct: this.computeBudgetRemainingPct(),\n timestamp: new Date().toISOString(),\n });\n\n const utilizationPct = (this._costToday / this.config.budget.dailyCapUsd) * 100;\n if (utilizationPct >= this.config.budget.alertThresholdPct) {\n this.emit({\n type: \"budget:alert\",\n todayTotal: this._costToday,\n capUsd: this.config.budget.dailyCapUsd,\n utilizationPct,\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n private emitSessionComplete(ctx: DispatchContext, stepResult: StepResult): void {\n this.emit({\n type: \"session:complete\",\n sessionId: ctx.sessionId,\n runId: ctx.runId,\n status: \"success\",\n costUsd: stepResult.costUsd,\n durationMs: stepResult.durationMs,\n output: stepResult.output,\n metadata: ctx.input.metadata,\n timestamp: new Date().toISOString(),\n });\n }\n\n private emitSessionFail(ctx: DispatchContext, errorMsg: string): void {\n this.emit({\n type: \"session:fail\",\n sessionId: ctx.sessionId,\n runId: ctx.runId,\n error: errorMsg,\n attempt: 1,\n maxRetries: this.config.recovery.maxRetries,\n willRetry: false,\n metadata: ctx.input.metadata,\n timestamp: new Date().toISOString(),\n });\n }\n\n // ─── Private: Input validation ─────────────────────────\n\n private validateInput(input: DispatchInput): void {\n if (!input.prompt || input.prompt.trim().length === 0) {\n throw new Error(\"Validation error: prompt must be a non-empty string\");\n }\n if (textEncoder.encode(input.prompt).length > MAX_PROMPT_SIZE) {\n throw new Error(\n `Validation error: prompt exceeds maximum size of ${String(MAX_PROMPT_SIZE)} bytes`,\n );\n }\n\n if (!existsSync(input.repo)) {\n throw new Error(`Validation error: repo path does not exist: ${input.repo}`);\n }\n\n if (!this.workflows.has(input.workflow)) {\n throw new Error(`Validation error: workflow \"${input.workflow}\" not found in registry`);\n }\n\n if (input.metadata !== undefined) {\n if (!isPlainObject(input.metadata)) {\n throw new Error(\"Validation error: metadata must be a plain object\");\n }\n if (objectDepth(input.metadata) > MAX_METADATA_DEPTH) {\n throw new Error(\n `Validation error: metadata exceeds maximum nesting depth of ${String(MAX_METADATA_DEPTH)}`,\n );\n }\n }\n\n const resumeOptions = [input.step, input.from, input.retry].filter(Boolean);\n if (resumeOptions.length > 1) {\n throw new Error(\"Validation error: step, from, and retry are mutually exclusive\");\n }\n }\n\n // ─── Private: Helpers ──────────────────────────────────\n\n private evictExpiredIdempotencyEntries(): void {\n const now = Date.now();\n for (const [key, entry] of this.idempotencyCache) {\n if (entry.expiresAt <= now) {\n this.idempotencyCache.delete(key);\n }\n }\n }\n\n private computeIdempotencyKey(input: DispatchInput): string | null {\n const idempotency = this.config.idempotency;\n if (!idempotency?.enabled) return null;\n\n const key = idempotency.key ?? \"metadata\";\n if (key === \"prompt\") {\n return `${input.workflow}:${input.repo}:${input.prompt}`;\n }\n return `${input.workflow}:${input.repo}:${JSON.stringify(input.metadata ?? {})}`;\n }\n\n private getFirstStep(\n workflow: WorkflowDefinition,\n input: DispatchInput,\n ): [string, WorkflowStepDef] {\n if (input.step) {\n const step = workflow.steps[input.step];\n if (!step || step.type === \"gate\") {\n throw new Error(\n `Step \"${input.step}\" not found in workflow \"${workflow.name}\" or is a gate step. Check the step name in the workflow definition.`,\n );\n }\n return [input.step, step as WorkflowStepDef];\n }\n\n for (const [name, step] of Object.entries(workflow.steps)) {\n if (step.type === \"gate\") continue;\n const stepDef = step as WorkflowStepDef;\n if (!stepDef.dependsOn || stepDef.dependsOn.length === 0) {\n return [name, stepDef];\n }\n }\n\n const entries = Object.entries(workflow.steps);\n const first = entries[0];\n if (!first) {\n throw new Error(`Workflow \"${workflow.name}\" has no steps`);\n }\n return [first[0], first[1] as WorkflowStepDef];\n }\n\n private resolveStepAgent(step: WorkflowStepDef, workflowName: string): ResolvedAgent {\n const agent = this.registeredAgents.get(step.agent);\n if (!agent) {\n throw new Error(\n `Agent \"${step.agent}\" required by workflow \"${workflowName}\" not found in registry. Register the agent or check the workflow definition.`,\n );\n }\n return agent;\n }\n\n private resolveRepo(repoPath: string): RepoConfig {\n const repo = this.repoIndex.get(path.resolve(repoPath));\n if (repo) return repo;\n return {\n path: repoPath,\n defaultBranch: \"main\",\n branchPrefix: \"feat\",\n pushRemote: \"origin\",\n gitStrategy: \"branch\",\n };\n }\n\n private computeBudgetRemainingPct(): number {\n const cap = this.config.budget.dailyCapUsd;\n if (cap <= 0) return 0;\n return Math.max(0, ((cap - this._costToday) / cap) * 100);\n }\n\n // ─── Private: MCP server resolution ────────────────────\n\n private resolveMcpServers(\n stepDef: WorkflowStepDef,\n agent: ResolvedAgent,\n ): Record<string, McpServerConfig> | undefined {\n const configServers = this.config.mcpServers;\n if (!configServers) return undefined;\n\n // Collect unique server names from step definition and agent definition\n const names = new Set<string>();\n if (stepDef.mcpServers) {\n for (const name of stepDef.mcpServers) names.add(name);\n }\n if (agent.definition.mcpServers) {\n for (const name of agent.definition.mcpServers) names.add(name);\n }\n\n if (names.size === 0) return undefined;\n\n const resolved: Record<string, McpServerConfig> = {};\n for (const name of names) {\n const serverConfig = configServers[name];\n if (serverConfig) {\n resolved[name] = serverConfig;\n }\n }\n\n return Object.keys(resolved).length > 0 ? resolved : undefined;\n }\n\n // ─── Private: Supervisor discovery ─────────────────────\n\n /** Discover running supervisor daemons and return webhook configs for their endpoints. */\n private async discoverSupervisorWebhooks(): Promise<NeoConfig[\"webhooks\"]> {\n const { readdir } = await import(\"node:fs/promises\");\n const supervisorsDir = getSupervisorsDir();\n if (!existsSync(supervisorsDir)) return [];\n\n const webhooks: NeoConfig[\"webhooks\"] = [];\n\n try {\n const entries = await readdir(supervisorsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n try {\n const statePath = path.join(supervisorsDir, entry.name, \"state.json\");\n const raw = await readFile(statePath, \"utf-8\");\n const state = JSON.parse(raw) as { status?: string; port?: number; pid?: number };\n\n if (state.status !== \"running\" || !state.port) continue;\n if (state.pid && !isProcessAlive(state.pid)) continue;\n\n webhooks.push({\n url: `http://localhost:${String(state.port)}/webhook`,\n events: [\"session:complete\", \"session:fail\", \"budget:alert\"],\n secret: this.config.supervisor.secret,\n timeoutMs: 5000,\n });\n } catch {\n // State file missing or corrupt — skip\n }\n }\n } catch {\n // Supervisors dir unreadable — skip\n }\n\n return webhooks;\n }\n\n // ─── Private: Run persistence ──────────────────────────\n\n private async persistRun(run: PersistedRun): Promise<void> {\n await this.runStore.persistRun(run);\n }\n\n private async recoverOrphanedRuns(): Promise<void> {\n const orphanedRuns = await this.runStore.recoverOrphanedRuns();\n\n // Emit session:fail for each orphaned run so the supervisor learns about them\n for (const run of orphanedRuns) {\n this.emit({\n type: \"session:fail\",\n sessionId: run.runId,\n runId: run.runId,\n error: \"Orphaned run: process died without completing\",\n attempt: 1,\n maxRetries: this.config.recovery.maxRetries,\n willRetry: false,\n metadata: run.metadata,\n timestamp: new Date().toISOString(),\n });\n }\n }\n}\n\n// ─── Utility functions ─────────────────────────────────\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction objectDepth(obj: unknown, current = 0): number {\n if (!isPlainObject(obj)) return current;\n let max = current + 1;\n for (const value of Object.values(obj)) {\n const depth = objectDepth(value, current + 1);\n if (depth > max) max = depth;\n }\n return max;\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getRepoRunsDir, getRunsDir, toRepoSlug } from \"@/paths\";\nimport { isProcessAlive } from \"@/shared/process\";\nimport type { PersistedRun } from \"@/types\";\n\nexport interface RunStoreOptions {\n runsDir?: string | undefined;\n}\n\n/**\n * Handles persistence and recovery of workflow runs.\n *\n * Runs are stored as JSON files in: ~/.neo/runs/<repo-slug>/<runId>.json\n * This enables cross-process resume and status queries via `neo runs`.\n */\nexport class RunStore {\n private readonly runsDir: string;\n private readonly createdDirs = new Set<string>();\n\n constructor(options: RunStoreOptions = {}) {\n this.runsDir = options.runsDir ?? getRunsDir();\n }\n\n /**\n * Persist a run to disk. Creates the repo subdirectory if needed.\n * Fails silently — run persistence is non-critical.\n */\n async persistRun(run: PersistedRun): Promise<void> {\n try {\n const slug = toRepoSlug({ path: run.repo });\n const repoDir = getRepoRunsDir(slug);\n if (!this.createdDirs.has(repoDir)) {\n await mkdir(repoDir, { recursive: true });\n this.createdDirs.add(repoDir);\n }\n const filePath = path.join(repoDir, `${run.runId}.json`);\n await writeFile(filePath, JSON.stringify(run, null, 2), \"utf-8\");\n } catch {\n // Non-critical — don't fail the dispatch if persistence fails\n }\n }\n\n /**\n * Find all runs that were left in \"running\" state but whose process died.\n * Returns them so the caller can emit failure events and update status.\n */\n async recoverOrphanedRuns(): Promise<PersistedRun[]> {\n if (!existsSync(this.runsDir)) return [];\n\n const orphaned: PersistedRun[] = [];\n\n try {\n const jsonFiles = await this.collectRunFiles();\n for (const filePath of jsonFiles) {\n const run = await this.recoverRunIfOrphaned(filePath);\n if (run) orphaned.push(run);\n }\n } catch {\n // Non-critical\n }\n\n return orphaned;\n }\n\n /**\n * Collect all .json run files from the runs directory tree.\n * Searches both top-level and repo subdirectories.\n */\n async collectRunFiles(): Promise<string[]> {\n const entries = await readdir(this.runsDir, { withFileTypes: true });\n const jsonFiles: string[] = [];\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const subDir = path.join(this.runsDir, entry.name);\n const subFiles = await readdir(subDir);\n for (const f of subFiles) {\n if (f.endsWith(\".json\")) jsonFiles.push(path.join(subDir, f));\n }\n } else if (entry.name.endsWith(\".json\")) {\n jsonFiles.push(path.join(this.runsDir, entry.name));\n }\n }\n\n return jsonFiles;\n }\n\n /**\n * Check if a run file represents an orphaned run.\n * If so, update its status to \"failed\" and return it.\n */\n private async recoverRunIfOrphaned(filePath: string): Promise<PersistedRun | null> {\n const content = await readFile(filePath, \"utf-8\");\n const run = JSON.parse(content) as PersistedRun;\n\n if (run.status !== \"running\") return null;\n // If the run has a PID and the process is still alive, skip it\n if (run.pid && isProcessAlive(run.pid)) return null;\n\n run.status = \"failed\";\n run.updatedAt = new Date().toISOString();\n await writeFile(filePath, JSON.stringify(run, null, 2), \"utf-8\");\n\n return run;\n }\n}\n","/**\n * Checks whether a process with the given PID is currently running.\n *\n * Uses the POSIX signal 0 trick: `process.kill(pid, 0)` doesn't actually\n * send a signal but checks whether the process exists and the current\n * process has permission to signal it. If the process doesn't exist,\n * an ESRCH error is thrown.\n *\n * @param pid - The process ID to check. Must be a positive integer.\n * @returns `true` if the process is alive and accessible, `false` otherwise.\n *\n * @example\n * ```ts\n * import { isProcessAlive } from \"@/shared/process\";\n *\n * // Check if current process is alive (always true)\n * isProcessAlive(process.pid); // => true\n *\n * // Check if a non-existent process is alive\n * isProcessAlive(999999); // => false\n * ```\n */\nexport function isProcessAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) {\n return false;\n }\n\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { GitStrategy, McpServerConfig, RepoConfig } from \"@/config\";\nimport { buildSandboxConfig } from \"@/isolation/sandbox\";\nimport { buildMiddlewareChain, buildSDKHooks } from \"@/middleware/chain\";\nimport { type ParsedOutput, parseOutput } from \"@/runner/output-parser\";\nimport { runWithRecovery } from \"@/runner/recovery\";\nimport type {\n Middleware,\n MiddlewareContext,\n ResolvedAgent,\n StepResult,\n WorkflowStepDef,\n} from \"@/types\";\n\n// ─── Constants ─────────────────────────────────────────\n\nconst INSTRUCTIONS_PATH = \".neo/INSTRUCTIONS.md\";\n\n// ─── Types ─────────────────────────────────────────────\n\nexport interface SessionExecutionInput {\n runId: string;\n sessionId: string;\n agent: ResolvedAgent;\n stepDef: WorkflowStepDef;\n repoConfig: RepoConfig;\n repoPath: string;\n prompt: string;\n branch?: string | undefined;\n gitStrategy: GitStrategy;\n sessionPath?: string | undefined;\n metadata?: Record<string, unknown> | undefined;\n startedAt: string;\n}\n\nexport interface SessionExecutionConfig {\n initTimeoutMs: number;\n maxDurationMs: number;\n maxRetries: number;\n backoffBaseMs: number;\n}\n\nexport interface SessionExecutionDeps {\n middleware: Middleware[];\n mcpServers?: Record<string, McpServerConfig> | undefined;\n memoryContext?: string | undefined;\n onAttempt?: (attempt: number, strategy: string) => void;\n}\n\nexport interface SessionExecutionResult extends StepResult {\n parsed: ParsedOutput;\n}\n\n// ─── Repo instructions loader ──────────────────────────\n\nasync function loadRepoInstructions(repoPath: string): Promise<string | undefined> {\n const filePath = path.join(repoPath, INSTRUCTIONS_PATH);\n try {\n return await readFile(filePath, \"utf-8\");\n } catch {\n return undefined;\n }\n}\n\n// ─── Git strategy prompt builder ───────────────────────\n\nfunction buildGitStrategyInstructions(\n strategy: GitStrategy,\n agent: ResolvedAgent,\n branch: string,\n baseBranch: string,\n remote: string,\n metadata?: Record<string, unknown>,\n): string | null {\n const prNumber = metadata?.prNumber as number | undefined;\n\n // Readonly agents: only inject PR comment instruction if a PR exists\n if (agent.sandbox !== \"writable\") {\n if (prNumber) {\n return `## Pull Request\\n\\nPR #${String(prNumber)} is open for this task. After your review, leave your findings as a comment: \\`gh pr comment ${String(prNumber)} --body \"...\"\\`.`;\n }\n return null;\n }\n\n // Writable agents: inject git workflow context\n if (strategy === \"pr\") {\n if (prNumber) {\n return `## Git workflow\\n\\nYou are on branch \\`${branch}\\`.\\nAn open PR exists: #${String(prNumber)}.\\nAfter committing, push your changes to the branch. The PR will be updated automatically.\\nLeave a review comment on the PR summarizing what you did: \\`gh pr comment ${String(prNumber)} --body \"...\"\\`.`;\n }\n return `## Git workflow\\n\\nYou are on branch \\`${branch}\\` (base: \\`${baseBranch}\\`).\\nAfter committing:\\n1. Push: \\`git push -u ${remote} ${branch}\\`\\n2. Create a PR against \\`${baseBranch}\\` — choose a title and description that reflect the work you completed. End the PR body with: \\`🤖 Generated with [neo](https://neotx.dev)\\`\\n3. Output the PR URL on a dedicated line: \\`PR_URL: <url>\\``;\n }\n\n // strategy === \"branch\"\n return `## Git workflow\\n\\nYou are on branch \\`${branch}\\` (base: \\`${baseBranch}\\`).\\nCommit your changes. The branch will be pushed automatically.`;\n}\n\n// ─── Reporting instructions for agents ──────────────────\n\nfunction buildReportingInstructions(_runId: string): string {\n return `## Reporting & Memory\n\n### Progress reporting (real-time, visible in TUI)\nChain \\`neo log\\` with the command that triggered it — never standalone:\n\\`\\`\\`bash\npnpm test && neo log milestone \"all tests passing\" || neo log blocker \"tests failing\"\ngit push origin HEAD && neo log action \"pushed to branch\"\nneo log decision \"chose JWT over sessions — simpler for MVP\"\n\\`\\`\\`\n\n### Memory (persistent, injected into future agent prompts)\nWrite discoveries so the next agent on this repo starts smarter.\n\n**Be selective** — only write a memory if it would change HOW you or future agents approach work:\n\\`\\`\\`bash\n# GOOD: affects workflow decisions\nneo memory write --type fact --scope $NEO_REPOSITORY \"CI requires pnpm build before push — no auto-rebuild in pipeline\"\nneo memory write --type fact --scope $NEO_REPOSITORY \"Biome enforces complexity max 20 — extract helpers for large functions\"\nneo memory write --type procedure --scope $NEO_REPOSITORY \"Integration tests require DATABASE_URL env var — set before running\"\n\n# BAD: trivial or derivable — do NOT write these\n# \"packages/core has 71 files\" — derivable from ls\n# \"Uses React 19\" — visible in package.json\n# \"apps/web has no test framework\" — derivable from ls/cat\n\\`\\`\\`\n\n**The test**: if \\`cat package.json\\`, \\`ls\\`, or reading the README can answer it, do NOT memorize it. Only memorize truths that affect decisions or non-obvious workflows learned from failure.\n\nWrite at key moments: after resolving a non-obvious issue, after discovering a build/CI quirk, before finishing.`;\n}\n\n// ─── Full prompt assembler ─────────────────────────────\n\nfunction buildFullPrompt(\n agentPrompt: string | undefined,\n repoInstructions: string | undefined,\n gitInstructions: string | null,\n taskPrompt: string,\n memoryContext?: string | undefined,\n cwdInstructions?: string | undefined,\n reportingInstructions?: string | undefined,\n): string {\n const sections: string[] = [];\n\n if (agentPrompt) sections.push(agentPrompt);\n if (cwdInstructions) sections.push(cwdInstructions);\n if (memoryContext) sections.push(memoryContext);\n if (repoInstructions) sections.push(`## Repository instructions\\n\\n${repoInstructions}`);\n if (gitInstructions) sections.push(gitInstructions);\n if (reportingInstructions) sections.push(reportingInstructions);\n sections.push(`## Task\\n\\n${taskPrompt}`);\n\n return sections.join(\"\\n\\n---\\n\\n\");\n}\n\n// ─── Middleware context builder ────────────────────────\n\nfunction buildMiddlewareContext(\n runId: string,\n workflow: string,\n step: string,\n agent: string,\n repo: string,\n getContextValue: (key: string) => unknown,\n): MiddlewareContext {\n const store = new Map<string, unknown>();\n return {\n runId,\n workflow,\n step,\n agent,\n repo,\n get: ((key: string) => {\n const value = getContextValue(key);\n if (value !== undefined) return value;\n return store.get(key);\n }) as MiddlewareContext[\"get\"],\n set: ((key: string, value: unknown) => {\n store.set(key, value);\n }) as MiddlewareContext[\"set\"],\n };\n}\n\n// ─── SessionExecutor ───────────────────────────────────\n\n/**\n * Encapsulates session execution logic: prompt building, SDK calls, and response processing.\n * Extracted from Orchestrator for better testability and separation of concerns.\n */\nexport class SessionExecutor {\n constructor(\n private readonly config: SessionExecutionConfig,\n private readonly getContextValue: (key: string) => unknown,\n ) {}\n\n /**\n * Execute an agent session with the given input and dependencies.\n * Handles prompt building, SDK invocation via recovery wrapper, and output parsing.\n */\n async execute(\n input: SessionExecutionInput,\n deps: SessionExecutionDeps,\n ): Promise<SessionExecutionResult> {\n const {\n runId,\n agent,\n stepDef,\n repoConfig,\n repoPath,\n prompt: taskPrompt,\n branch,\n gitStrategy,\n sessionPath,\n metadata,\n startedAt,\n } = input;\n\n const { middleware, mcpServers, memoryContext, onAttempt } = deps;\n\n // Validate writable agents have a branch\n if (agent.sandbox === \"writable\" && !branch) {\n throw new Error(\n \"Validation error: --branch is required for writable agents. Provide an explicit branch name (e.g. --branch feat/PROJ-42-description).\",\n );\n }\n\n const branchName = agent.sandbox === \"writable\" ? (branch as string) : \"\";\n\n // Build sandbox config for agent\n const sandboxConfig = buildSandboxConfig(agent, sessionPath);\n\n // Build middleware chain and SDK hooks\n const chain = buildMiddlewareChain(middleware);\n const middlewareContext = buildMiddlewareContext(\n runId,\n stepDef.prompt ? \"workflow\" : \"direct\",\n \"execute\",\n agent.name,\n repoPath,\n this.getContextValue,\n );\n const hooks = buildSDKHooks(chain, middlewareContext, middleware);\n\n // Build the full prompt\n const repoInstructions = await loadRepoInstructions(repoPath);\n const gitInstructions = buildGitStrategyInstructions(\n gitStrategy,\n agent,\n branchName,\n repoConfig.defaultBranch,\n repoConfig.pushRemote ?? \"origin\",\n metadata,\n );\n\n const cwdInstructions = sessionPath\n ? `## Working directory\\n\\nYou are working in an isolated clone at: \\`${sessionPath}\\`\\nALWAYS run commands from this directory. NEVER cd to or operate on any other repository.`\n : undefined;\n\n const reportingInstructions = buildReportingInstructions(runId);\n\n const fullPrompt = buildFullPrompt(\n agent.definition.prompt,\n repoInstructions,\n gitInstructions,\n stepDef.prompt ?? taskPrompt,\n memoryContext,\n cwdInstructions,\n reportingInstructions,\n );\n\n // Execute session with recovery\n const recoveryOpts = stepDef.recovery;\n const agentEnv: Record<string, string> = {\n NEO_RUN_ID: runId,\n NEO_AGENT_NAME: agent.name,\n NEO_REPOSITORY: repoPath,\n };\n\n const sessionResult = await runWithRecovery({\n agent,\n prompt: fullPrompt,\n repoPath,\n sandboxConfig,\n hooks,\n env: agentEnv,\n initTimeoutMs: this.config.initTimeoutMs,\n maxDurationMs: this.config.maxDurationMs,\n maxRetries: recoveryOpts?.maxRetries ?? this.config.maxRetries,\n backoffBaseMs: this.config.backoffBaseMs,\n ...(sessionPath ? { sessionPath } : {}),\n ...(mcpServers ? { mcpServers } : {}),\n ...(recoveryOpts?.nonRetryable ? { nonRetryable: recoveryOpts.nonRetryable } : {}),\n ...(onAttempt ? { onAttempt } : {}),\n });\n\n // Parse output\n const parsed = parseOutput(sessionResult.output);\n\n // Build result\n const result: SessionExecutionResult = {\n status: \"success\",\n sessionId: sessionResult.sessionId,\n output: parsed.output ?? parsed.rawOutput,\n rawOutput: sessionResult.output,\n costUsd: sessionResult.costUsd,\n durationMs: sessionResult.durationMs,\n agent: agent.name,\n startedAt,\n completedAt: new Date().toISOString(),\n attempt: 1,\n parsed,\n };\n\n if (parsed.prUrl) {\n result.prUrl = parsed.prUrl;\n }\n if (parsed.prNumber !== undefined) {\n result.prNumber = parsed.prNumber;\n }\n\n return result;\n }\n}\n\n// ─── Standalone prompt builders (re-exported for backward compatibility) ───\n\nexport {\n buildFullPrompt,\n buildGitStrategyInstructions,\n buildReportingInstructions,\n loadRepoInstructions,\n};\n","import type { ZodType } from \"zod\";\n\nexport interface ParsedOutput {\n rawOutput: string;\n output?: unknown;\n parseError?: string;\n prUrl?: string;\n prNumber?: number;\n}\n\n/**\n * Extract JSON from agent output that may be wrapped in markdown code blocks.\n * Tries multiple strategies: raw JSON parse, then markdown code block extraction.\n */\nfunction extractJson(raw: string): unknown | undefined {\n // Strategy 1: Try parsing the entire string as JSON\n try {\n return JSON.parse(raw);\n } catch {\n // Not raw JSON, continue\n }\n\n // Strategy 2: Extract from markdown code blocks (```json ... ``` or ``` ... ```)\n const codeBlockRegex = /```(?:json)?\\s*\\n?([\\s\\S]*?)```/;\n const match = raw.match(codeBlockRegex);\n if (match?.[1]) {\n try {\n return JSON.parse(match[1].trim());\n } catch {\n // Invalid JSON inside code block\n }\n }\n\n return undefined;\n}\n\n// ─── PR URL extraction ──────────────────────────────────\n\nconst PR_URL_REGEX = /^PR_URL:\\s*(https?:\\/\\/\\S+)/m;\n\nexport function extractPrUrl(raw: string): { prUrl: string; prNumber?: number } | undefined {\n const match = raw.match(PR_URL_REGEX);\n if (!match?.[1]) return undefined;\n\n const prUrl = match[1];\n const numberMatch = prUrl.match(/\\/pull\\/(\\d+)/);\n\n if (numberMatch?.[1]) {\n return { prUrl, prNumber: Number.parseInt(numberMatch[1], 10) };\n }\n return { prUrl };\n}\n\n/**\n * Parse agent output, optionally validating against a Zod schema.\n * Also extracts structured markers like PR_URL from the output.\n *\n * - If no schema: returns rawOutput only\n * - If schema provided: extracts JSON from output, validates with schema\n * - On failure: returns rawOutput + parseError (caller decides whether to retry)\n */\nexport function parseOutput(raw: string, schema?: ZodType): ParsedOutput {\n const prInfo = extractPrUrl(raw);\n const base: ParsedOutput = { rawOutput: raw };\n if (prInfo) {\n base.prUrl = prInfo.prUrl;\n if (prInfo.prNumber !== undefined) {\n base.prNumber = prInfo.prNumber;\n }\n }\n\n if (!schema) {\n return base;\n }\n\n const extracted = extractJson(raw);\n if (extracted === undefined) {\n base.parseError = \"Failed to extract JSON from output\";\n return base;\n }\n\n const result = schema.safeParse(extracted);\n if (!result.success) {\n base.parseError = `Schema validation failed: ${result.error.message}`;\n return base;\n }\n\n base.output = result.data;\n return base;\n}\n","// ─── SDK Stream Message Types ────────────────────────────\n// Unified type definitions for Claude Agent SDK stream messages.\n// Both session.ts and heartbeat.ts import from this module.\n\n/**\n * Base SDK stream message shape.\n * All messages from the SDK stream have at least a type field.\n */\nexport interface SDKStreamMessage {\n type: string;\n subtype?: string;\n}\n\n/**\n * Init message emitted when a session starts.\n * Contains the session ID for tracking.\n */\nexport interface SDKInitMessage extends SDKStreamMessage {\n type: \"system\";\n subtype: \"init\";\n session_id: string;\n}\n\n/**\n * Result message emitted when a session completes.\n * Contains the final output, cost, and turn count.\n */\nexport interface SDKResultMessage extends SDKStreamMessage {\n type: \"result\";\n subtype: \"success\" | string;\n session_id: string;\n result: string;\n total_cost_usd: number;\n num_turns: number;\n}\n\n/**\n * Content block in an assistant message.\n */\nexport interface SDKContentBlock {\n type: string;\n thinking?: string;\n text?: string;\n}\n\n/**\n * Assistant message with content blocks.\n */\nexport interface SDKAssistantMessage extends SDKStreamMessage {\n type: \"assistant\";\n message?: {\n content?: SDKContentBlock[];\n };\n}\n\n/**\n * Tool use message from the assistant.\n */\nexport interface SDKToolUseMessage extends SDKStreamMessage {\n type: \"assistant\";\n subtype: \"tool_use\";\n tool: string;\n input?: unknown;\n}\n\n/**\n * Tool result message.\n */\nexport interface SDKToolResultMessage extends SDKStreamMessage {\n type: \"assistant\";\n subtype: \"tool_result\";\n result?: string;\n}\n\n// ─── Type Guards ─────────────────────────────────────────\n\n/**\n * Check if a message is an init message (session started).\n */\nexport function isInitMessage(msg: SDKStreamMessage): msg is SDKInitMessage {\n return msg.type === \"system\" && msg.subtype === \"init\";\n}\n\n/**\n * Check if a message is a result message (session completed).\n */\nexport function isResultMessage(msg: SDKStreamMessage): msg is SDKResultMessage {\n return msg.type === \"result\";\n}\n\n/**\n * Check if a message is an assistant message with content.\n */\nexport function isAssistantMessage(msg: SDKStreamMessage): msg is SDKAssistantMessage {\n return msg.type === \"assistant\" && !msg.subtype;\n}\n\n/**\n * Check if a message is a tool use message.\n */\nexport function isToolUseMessage(msg: SDKStreamMessage): msg is SDKToolUseMessage {\n return msg.type === \"assistant\" && msg.subtype === \"tool_use\";\n}\n\n/**\n * Check if a message is a tool result message.\n */\nexport function isToolResultMessage(msg: SDKStreamMessage): msg is SDKToolResultMessage {\n return msg.type === \"assistant\" && msg.subtype === \"tool_result\";\n}\n","import type { McpServerConfig } from \"@/config\";\nimport type { SandboxConfig } from \"@/isolation/sandbox\";\nimport { isInitMessage, isResultMessage, type SDKStreamMessage } from \"@/sdk-types\";\nimport type { ResolvedAgent } from \"@/types\";\n\n// ─── Types ──────────────────────────────────────────────\n\nexport interface SessionOptions {\n agent: ResolvedAgent;\n prompt: string;\n repoPath?: string;\n sessionPath?: string;\n sandboxConfig: SandboxConfig;\n hooks?: Record<string, unknown>;\n mcpServers?: Record<string, McpServerConfig>;\n env?: Record<string, string>;\n initTimeoutMs: number;\n maxDurationMs: number;\n resumeSessionId?: string | undefined;\n onEvent?: ((event: SessionEvent) => void) | undefined;\n}\n\nexport interface SessionResult {\n sessionId: string;\n output: string;\n costUsd: number;\n durationMs: number;\n turnCount: number;\n}\n\nexport type SessionEvent =\n | { type: \"session:start\"; sessionId: string }\n | { type: \"session:complete\"; sessionId: string; result: SessionResult }\n | { type: \"session:fail\"; sessionId: string; error: string };\n\n// ─── Helpers ────────────────────────────────────────────\n\nfunction checkAborted(signal: AbortSignal): void {\n if (signal.aborted) {\n const reason = signal.reason;\n throw reason instanceof Error ? reason : new Error(String(reason));\n }\n}\n\nfunction toSessionError(error: unknown, isTimeout: boolean, sessionId: string): SessionError {\n if (error instanceof SessionError) return error;\n const message = error instanceof Error ? error.message : String(error);\n return new SessionError(message, isTimeout ? \"timeout\" : \"unknown\", sessionId);\n}\n\n// ─── Query Options Builder ──────────────────────────────\n\nfunction buildQueryOptions(options: SessionOptions): Record<string, unknown> {\n const { sessionPath, sandboxConfig } = options;\n\n const queryOptions: Record<string, unknown> = {\n // Always pass cwd: session clone for writable agents, repo root for readonly.\n // Without this, readonly agents default to process.cwd() and may write to main tree.\n cwd: sessionPath ?? options.repoPath,\n // maxTurns: agent.maxTurns,\n allowedTools: sandboxConfig.allowedTools,\n // Workers run detached without a TTY — bypass interactive permission prompts.\n // Required pair: permissionMode alone is not enough, SDK also needs the flag.\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n // Load project-level CLAUDE.md so agents inherit project rules and conventions.\n settingSources: [\"user\", \"project\", \"local\"],\n // Don't persist agent sessions — they are ephemeral clones.\n persistSession: false,\n };\n\n if (options.resumeSessionId) {\n queryOptions.resume = options.resumeSessionId;\n }\n\n if (options.mcpServers && Object.keys(options.mcpServers).length > 0) {\n queryOptions.mcpServers = options.mcpServers;\n }\n\n if (options.env && Object.keys(options.env).length > 0) {\n // Merge with process.env so PATH, HOME, etc. are preserved.\n // Custom vars override process.env if there's a conflict.\n queryOptions.env = { ...process.env, ...options.env };\n }\n\n return queryOptions;\n}\n\n// ─── Session Runner ─────────────────────────────────────\n\nexport async function runSession(options: SessionOptions): Promise<SessionResult> {\n const { prompt, initTimeoutMs, maxDurationMs, onEvent } = options;\n\n const startTime = Date.now();\n let sessionId = \"\";\n\n const abortController = new AbortController();\n const initTimer = setTimeout(() => {\n abortController.abort(new Error(\"Session init timeout exceeded\"));\n }, initTimeoutMs);\n const maxDurationTimer = setTimeout(() => {\n abortController.abort(new Error(\"Session max duration exceeded\"));\n }, maxDurationMs);\n\n try {\n const sdk = await import(\"@anthropic-ai/claude-agent-sdk\");\n const queryOptions = buildQueryOptions(options);\n\n let output = \"\";\n let costUsd = 0;\n let turnCount = 0;\n\n // The prompt is already assembled by the orchestrator (agent prompt +\n // repo instructions + git strategy context + task). Session just passes it through.\n const stream = sdk.query({ prompt, options: queryOptions as never });\n\n for await (const message of stream) {\n checkAborted(abortController.signal);\n\n const msg = message as SDKStreamMessage;\n\n if (isInitMessage(msg)) {\n sessionId = msg.session_id;\n clearTimeout(initTimer);\n onEvent?.({ type: \"session:start\", sessionId });\n }\n\n if (isResultMessage(msg)) {\n output = msg.result ?? \"\";\n costUsd = msg.total_cost_usd ?? 0;\n turnCount = msg.num_turns ?? 0;\n sessionId = msg.session_id ?? sessionId;\n\n if (msg.subtype !== \"success\") {\n throw new SessionError(\n `Session ended with error: ${msg.subtype}`,\n msg.subtype,\n sessionId,\n );\n }\n }\n }\n\n const sessionResult: SessionResult = {\n sessionId,\n output,\n costUsd,\n durationMs: Date.now() - startTime,\n turnCount,\n };\n\n onEvent?.({ type: \"session:complete\", sessionId, result: sessionResult });\n return sessionResult;\n } catch (error) {\n const errorSessionId = sessionId || \"unknown\";\n const sessionError = toSessionError(error, abortController.signal.aborted, errorSessionId);\n\n onEvent?.({ type: \"session:fail\", sessionId: errorSessionId, error: sessionError.message });\n throw sessionError;\n } finally {\n clearTimeout(initTimer);\n clearTimeout(maxDurationTimer);\n }\n}\n\n// ─── Error class ────────────────────────────────────────\n\nexport class SessionError extends Error {\n constructor(\n message: string,\n public readonly errorType: string,\n public readonly sessionId: string,\n ) {\n super(message);\n this.name = \"SessionError\";\n }\n}\n","import {\n runSession,\n SessionError,\n type SessionOptions,\n type SessionResult,\n} from \"@/runner/session\";\n\n// ─── Types ──────────────────────────────────────────────\n\nexport interface RecoveryOptions extends SessionOptions {\n maxRetries: number;\n backoffBaseMs: number;\n nonRetryable?: string[];\n onAttempt?: (attempt: number, strategy: string) => void;\n}\n\n// ─── Default non-retryable errors ───────────────────────\n\nconst DEFAULT_NON_RETRYABLE = [\"error_max_turns\", \"budget_exceeded\"];\n\n// ─── Recovery strategy names ────────────────────────────\n\nfunction getStrategy(attempt: number): string {\n switch (attempt) {\n case 1:\n return \"normal\";\n case 2:\n return \"resume\";\n default:\n return \"fresh\";\n }\n}\n\n// ─── Sleep utility ──────────────────────────────────────\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// ─── Error handling ─────────────────────────────────────\n\nfunction isNonRetryable(error: unknown, nonRetryable: string[]): boolean {\n return error instanceof SessionError && nonRetryable.includes(error.errorType);\n}\n\nfunction updateSessionId(error: unknown, current: string | undefined): string | undefined {\n if (error instanceof SessionError && error.sessionId !== \"unknown\") {\n return error.sessionId;\n }\n return current;\n}\n\nfunction buildFinalError(error: unknown, maxRetries: number): Error {\n if (error instanceof Error) {\n return new Error(`Recovery failed after ${maxRetries} attempts. Last error: ${error.message}`, {\n cause: error,\n });\n }\n return new Error(`Recovery failed after ${maxRetries} attempts`);\n}\n\n/**\n * Run a session with 3-level recovery escalation (ADR-020).\n *\n * Level 1 (attempt 1): Normal execution — new session\n * Level 2 (attempt 2): Resume session — pass resumeSessionId from level 1\n * Level 3 (attempt 3): Fresh session — abandon previous, start clean\n *\n * Non-retryable errors skip to immediate failure.\n * Backoff: backoffBaseMs * attempt between levels.\n */\nexport async function runWithRecovery(options: RecoveryOptions): Promise<SessionResult> {\n const {\n maxRetries,\n backoffBaseMs,\n nonRetryable = DEFAULT_NON_RETRYABLE,\n onAttempt,\n ...rest\n } = options;\n\n let lastSessionId: string | undefined;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n const strategy = getStrategy(attempt);\n onAttempt?.(attempt, strategy);\n\n try {\n const result = await runSession({\n ...rest,\n resumeSessionId: strategy === \"resume\" ? lastSessionId : undefined,\n });\n return result;\n } catch (error) {\n lastSessionId = updateSessionId(error, lastSessionId);\n\n if (isNonRetryable(error, nonRetryable)) throw error;\n if (attempt === maxRetries) throw buildFinalError(error, maxRetries);\n\n // Next attempt will be \"fresh\" — clear session to start clean\n if (getStrategy(attempt + 1) === \"fresh\") {\n lastSessionId = undefined;\n }\n\n await sleep(backoffBaseMs * attempt);\n }\n }\n\n throw new Error(\"Recovery failed: unreachable\");\n}\n","// ─── Embedder interface ──────────────────────────────────\n\nexport interface Embedder {\n embed(texts: string[]): Promise<number[][]>;\n readonly dimensions: number;\n}\n\n// ─── Local embedder (Transformers.js) ────────────────────\n\nlet extractorPromise: Promise<unknown> | null = null;\n\nfunction getExtractor(): Promise<unknown> {\n if (!extractorPromise) {\n extractorPromise = (async () => {\n const { pipeline } = await import(\"@huggingface/transformers\");\n return pipeline(\"feature-extraction\", \"Xenova/all-MiniLM-L6-v2\", {\n dtype: \"fp32\",\n });\n })();\n }\n return extractorPromise;\n}\n\nexport class LocalEmbedder implements Embedder {\n readonly dimensions = 384;\n\n async embed(texts: string[]): Promise<number[][]> {\n const extractor = (await getExtractor()) as (\n texts: string[],\n opts: { pooling: string; normalize: boolean },\n ) => Promise<{ tolist(): number[][] }>;\n const output = await extractor(texts, { pooling: \"mean\", normalize: true });\n return output.tolist();\n }\n}\n\n// ─── Cosine similarity ──────────────────────────────────\n\nexport function cosineSimilarity(a: number[], b: number[]): number {\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < a.length; i++) {\n dot += (a[i] ?? 0) * (b[i] ?? 0);\n normA += (a[i] ?? 0) * (a[i] ?? 0);\n normB += (b[i] ?? 0) * (b[i] ?? 0);\n }\n const denom = Math.sqrt(normA) * Math.sqrt(normB);\n return denom === 0 ? 0 : dot / denom;\n}\n","import { z } from \"zod\";\n\n// ─── Memory types ────────────────────────────────────────\n\nexport const memoryTypeSchema = z.enum([\n \"fact\",\n \"procedure\",\n \"episode\",\n \"focus\",\n \"feedback\",\n \"task\",\n]);\n\nexport type MemoryType = z.infer<typeof memoryTypeSchema>;\n\n// ─── Memory entry (persisted in SQLite) ──────────────────\n\nexport const memoryEntrySchema = z.object({\n id: z.string(),\n type: memoryTypeSchema,\n scope: z.string(), // \"global\" | repo path\n content: z.string(),\n source: z.string(), // \"developer\" | \"reviewer\" | \"supervisor\" | \"user\"\n tags: z.array(z.string()).default([]),\n\n // Lifecycle\n createdAt: z.string(),\n lastAccessedAt: z.string(),\n accessCount: z.number().default(0),\n\n // Optional per-type fields\n expiresAt: z.string().optional(), // focus TTL\n outcome: z.string().optional(), // episode: success/failure/blocked\n runId: z.string().optional(),\n category: z.string().optional(), // feedback: reviewer issue category\n severity: z.string().optional(),\n supersedes: z.string().optional(), // contradiction resolution\n});\n\nexport type MemoryEntry = z.infer<typeof memoryEntrySchema>;\n\n// ─── Write input (id and timestamps are auto-generated) ──\n\nexport const memoryWriteInputSchema = z.object({\n type: memoryTypeSchema,\n scope: z.string().default(\"global\"),\n content: z.string(),\n source: z.string().default(\"user\"),\n tags: z.array(z.string()).default([]),\n expiresAt: z.string().optional(),\n outcome: z.string().optional(),\n runId: z.string().optional(),\n category: z.string().optional(),\n severity: z.string().optional(),\n supersedes: z.string().optional(),\n});\n\nexport type MemoryWriteInput = z.input<typeof memoryWriteInputSchema>;\n\n// ─── Query options ───────────────────────────────────────\n\nexport interface MemoryQuery {\n scope?: string;\n types?: MemoryType[];\n since?: string; // ISO timestamp\n limit?: number;\n sortBy?: \"relevance\" | \"createdAt\" | \"accessCount\";\n tags?: string[];\n}\n\n// ─── Stats ───────────────────────────────────────────────\n\nexport interface MemoryStats {\n total: number;\n byType: Record<string, number>;\n byScope: Record<string, number>;\n}\n","import type { MemoryEntry } from \"./entry.js\";\n\nconst TYPE_LABELS: Record<string, string> = {\n fact: \"Fact\",\n procedure: \"How-to\",\n episode: \"Past run\",\n focus: \"Current focus\",\n feedback: \"Recurring issue\",\n};\n\nconst TYPE_ICONS: Record<string, string> = {\n fact: \"·\",\n procedure: \"→\",\n episode: \"◇\",\n focus: \"★\",\n feedback: \"⚠\",\n};\n\n/**\n * Format a list of memories for injection into an agent or supervisor prompt.\n * Groups by type, renders as concise markdown.\n */\nexport function formatMemoriesForPrompt(memories: MemoryEntry[]): string {\n if (memories.length === 0) return \"\";\n\n const grouped = new Map<string, MemoryEntry[]>();\n for (const m of memories) {\n const group = grouped.get(m.type) ?? [];\n group.push(m);\n grouped.set(m.type, group);\n }\n\n const sections: string[] = [];\n\n for (const [type, entries] of grouped) {\n const label = TYPE_LABELS[type] ?? type;\n const icon = TYPE_ICONS[type] ?? \"·\";\n const lines = entries.map((e) => {\n const confidence = e.accessCount >= 3 ? \"\" : \" (unconfirmed)\";\n return `${icon} ${e.content}${confidence}`;\n });\n sections.push(`### ${label}s\\n${lines.join(\"\\n\")}`);\n }\n\n return `## Known context for this repository\\n\\n${sections.join(\"\\n\\n\")}`;\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport path from \"node:path\";\nimport type { Embedder } from \"./embedder.js\";\nimport type { MemoryEntry, MemoryQuery, MemoryStats, MemoryWriteInput } from \"./entry.js\";\n\nconst esmRequire = createRequire(import.meta.url);\n\n// ─── MemoryStore ─────────────────────────────────────────\n\nexport class MemoryStore {\n private db: import(\"better-sqlite3\").Database;\n private embedder: Embedder | null;\n private hasVec: boolean;\n\n constructor(dbPath: string, embedder?: Embedder | null) {\n const dir = path.dirname(dbPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // better-sqlite3 is synchronous — import at module level would break ESM lazy loading\n const Database = esmRequire(\"better-sqlite3\");\n this.db = new Database(dbPath);\n this.db.pragma(\"journal_mode = WAL\");\n this.db.pragma(\"foreign_keys = ON\");\n\n this.embedder = embedder ?? null;\n this.hasVec = false;\n\n this.initSchema();\n }\n\n // ─── Schema initialization ───────────────────────────\n\n private initSchema(): void {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS memories (\n id TEXT PRIMARY KEY,\n type TEXT NOT NULL CHECK(type IN ('fact','procedure','episode','focus','feedback','task')),\n scope TEXT NOT NULL,\n content TEXT NOT NULL,\n source TEXT NOT NULL,\n tags TEXT DEFAULT '[]',\n created_at TEXT NOT NULL,\n last_accessed_at TEXT NOT NULL,\n access_count INTEGER DEFAULT 0,\n expires_at TEXT,\n outcome TEXT,\n run_id TEXT,\n category TEXT,\n severity TEXT,\n supersedes TEXT\n );\n\n CREATE INDEX IF NOT EXISTS idx_mem_type_scope ON memories(type, scope);\n CREATE INDEX IF NOT EXISTS idx_mem_created ON memories(created_at);\n `);\n\n // Migrate CHECK constraint if table predates 'task' type\n this.migrateCheckConstraint();\n\n // FTS5 for full-text search\n this.db.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(\n content,\n content='memories',\n content_rowid='rowid',\n tokenize='porter'\n );\n `);\n\n // Triggers to keep FTS in sync\n this.db.exec(`\n CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN\n INSERT INTO memories_fts(rowid, content) VALUES (new.rowid, new.content);\n END;\n CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN\n INSERT INTO memories_fts(memories_fts, rowid, content) VALUES('delete', old.rowid, old.content);\n END;\n CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN\n INSERT INTO memories_fts(memories_fts, rowid, content) VALUES('delete', old.rowid, old.content);\n INSERT INTO memories_fts(rowid, content) VALUES (new.rowid, new.content);\n END;\n `);\n\n // sqlite-vec for vector search (optional — may not be installed)\n if (this.embedder) {\n try {\n const sqliteVec = esmRequire(\"sqlite-vec\");\n sqliteVec.load(this.db);\n this.db.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS memories_vec USING vec0(\n memory_id TEXT,\n embedding float[${this.embedder.dimensions}]\n );\n `);\n this.hasVec = true;\n } catch {\n // sqlite-vec not available — fall back to FTS\n this.hasVec = false;\n }\n }\n }\n\n /**\n * Migrate existing tables whose CHECK constraint predates the 'task' type.\n * SQLite doesn't allow ALTER CHECK, so we recreate the table if needed.\n */\n private migrateCheckConstraint(): void {\n const tableInfo = this.db\n .prepare(\"SELECT sql FROM sqlite_master WHERE type='table' AND name='memories'\")\n .get() as { sql: string } | undefined;\n if (!tableInfo || tableInfo.sql.includes(\"'task'\")) return;\n\n this.db.exec(`\n ALTER TABLE memories RENAME TO memories_old;\n\n CREATE TABLE memories (\n id TEXT PRIMARY KEY,\n type TEXT NOT NULL CHECK(type IN ('fact','procedure','episode','focus','feedback','task')),\n scope TEXT NOT NULL,\n content TEXT NOT NULL,\n source TEXT NOT NULL,\n tags TEXT DEFAULT '[]',\n created_at TEXT NOT NULL,\n last_accessed_at TEXT NOT NULL,\n access_count INTEGER DEFAULT 0,\n expires_at TEXT,\n outcome TEXT,\n run_id TEXT,\n category TEXT,\n severity TEXT,\n supersedes TEXT\n );\n\n INSERT INTO memories SELECT * FROM memories_old;\n DROP TABLE memories_old;\n `);\n }\n\n // ─── Write ───────────────────────────────────────────\n\n async write(input: MemoryWriteInput): Promise<string> {\n const id = `mem_${randomUUID().slice(0, 12)}`;\n const now = new Date().toISOString();\n\n this.db\n .prepare(\n `INSERT INTO memories (id, type, scope, content, source, tags, created_at, last_accessed_at, access_count, expires_at, outcome, run_id, category, severity, supersedes)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n id,\n input.type,\n input.scope ?? \"global\",\n input.content,\n input.source ?? \"user\",\n JSON.stringify(input.tags ?? []),\n now,\n now,\n input.expiresAt ?? null,\n input.outcome ?? null,\n input.runId ?? null,\n input.category ?? null,\n input.severity ?? null,\n input.supersedes ?? null,\n );\n\n // Embed and store vector\n if (this.embedder && this.hasVec) {\n try {\n const [vector] = await this.embedder.embed([input.content]);\n const rowid = this.db.prepare(\"SELECT rowid FROM memories WHERE id = ?\").get(id) as\n | { rowid: number }\n | undefined;\n if (rowid && vector) {\n this.db\n .prepare(\"INSERT INTO memories_vec (rowid, memory_id, embedding) VALUES (?, ?, ?)\")\n .run(rowid.rowid, id, new Float32Array(vector));\n }\n } catch {\n // Embedding failed — entry still saved without vector\n }\n }\n\n return id;\n }\n\n // ─── Update ──────────────────────────────────────────\n\n update(id: string, content: string): void {\n this.db.prepare(\"UPDATE memories SET content = ? WHERE id = ?\").run(content, id);\n\n // Re-embedding happens lazily on next search if needed\n // For now, remove stale vector\n if (this.hasVec) {\n const row = this.db.prepare(\"SELECT rowid FROM memories WHERE id = ?\").get(id) as\n | { rowid: number }\n | undefined;\n if (row) {\n this.db.prepare(\"DELETE FROM memories_vec WHERE rowid = ?\").run(row.rowid);\n }\n }\n }\n\n // ─── Update fields ───────────────────────────────────\n\n updateFields(id: string, fields: { content?: string; outcome?: string; runId?: string }): void {\n const sets: string[] = [];\n const params: unknown[] = [];\n if (fields.content !== undefined) {\n sets.push(\"content = ?\");\n params.push(fields.content);\n }\n if (fields.outcome !== undefined) {\n sets.push(\"outcome = ?\");\n params.push(fields.outcome);\n }\n if (fields.runId !== undefined) {\n sets.push(\"run_id = ?\");\n params.push(fields.runId);\n }\n if (sets.length === 0) return;\n params.push(id);\n this.db.prepare(`UPDATE memories SET ${sets.join(\", \")} WHERE id = ?`).run(...params);\n }\n\n // ─── Forget ──────────────────────────────────────────\n\n forget(id: string): void {\n const row = this.db.prepare(\"SELECT rowid FROM memories WHERE id = ?\").get(id) as\n | { rowid: number }\n | undefined;\n if (row && this.hasVec) {\n this.db.prepare(\"DELETE FROM memories_vec WHERE rowid = ?\").run(row.rowid);\n }\n this.db.prepare(\"DELETE FROM memories WHERE id = ?\").run(id);\n }\n\n // ─── Query (synchronous — structured filters) ───────\n\n query(opts: MemoryQuery = {}): MemoryEntry[] {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (opts.scope) {\n conditions.push(\"(scope = ? OR scope = 'global')\");\n params.push(opts.scope);\n }\n\n if (opts.types && opts.types.length > 0) {\n const placeholders = opts.types.map(() => \"?\").join(\",\");\n conditions.push(`type IN (${placeholders})`);\n params.push(...opts.types);\n }\n\n if (opts.since) {\n conditions.push(\"created_at > ?\");\n params.push(opts.since);\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(\" AND \")}` : \"\";\n\n let orderBy: string;\n switch (opts.sortBy) {\n case \"accessCount\":\n orderBy = \"ORDER BY access_count DESC\";\n break;\n case \"createdAt\":\n orderBy = \"ORDER BY created_at DESC\";\n break;\n case \"relevance\":\n default:\n orderBy =\n \"ORDER BY (access_count * MAX(0, 1.0 - (julianday('now') - julianday(last_accessed_at)) / 60.0)) DESC\";\n break;\n }\n\n const limit = opts.limit ? `LIMIT ${opts.limit}` : \"LIMIT 50\";\n\n const rows = this.db\n .prepare(`SELECT * FROM memories ${where} ${orderBy} ${limit}`)\n .all(...params) as RawMemoryRow[];\n\n return rows.map(rowToEntry);\n }\n\n // ─── Search (async — semantic or FTS) ────────────────\n\n async search(text: string, opts: MemoryQuery = {}): Promise<MemoryEntry[]> {\n // Try vector search first\n if (this.embedder && this.hasVec) {\n try {\n const [queryVec] = await this.embedder.embed([text]);\n const limit = opts.limit ?? 20;\n\n // Build scope/type filter for post-filtering\n const candidates = this.db\n .prepare(\n `SELECT m.*, v.distance\n FROM memories_vec v\n JOIN memories m ON m.rowid = v.rowid\n WHERE v.embedding MATCH ?\n ORDER BY v.distance\n LIMIT ?`,\n )\n .all(new Float32Array(queryVec as number[]), limit * 3) as (RawMemoryRow & {\n distance: number;\n })[];\n\n // Post-filter by scope and type\n const filtered = candidates.filter((row) => {\n if (opts.scope && row.scope !== opts.scope && row.scope !== \"global\") return false;\n if (\n opts.types &&\n opts.types.length > 0 &&\n !opts.types.includes(row.type as MemoryEntry[\"type\"])\n )\n return false;\n return true;\n });\n\n return filtered.slice(0, limit).map((row) => rowToEntry(row));\n } catch {\n // Fall through to FTS\n }\n }\n\n // Fallback: FTS5 full-text search\n const limit = opts.limit ?? 20;\n const ftsQuery = text\n .split(/\\s+/)\n .filter(Boolean)\n .map((w) => `\"${w}\"`)\n .join(\" OR \");\n\n if (!ftsQuery) return this.query(opts);\n\n try {\n const rows = this.db\n .prepare(\n `SELECT m.*, rank\n FROM memories_fts fts\n JOIN memories m ON m.rowid = fts.rowid\n WHERE memories_fts MATCH ?\n ORDER BY rank\n LIMIT ?`,\n )\n .all(ftsQuery, limit) as RawMemoryRow[];\n\n const filtered = rows.filter((row) => {\n if (opts.scope && row.scope !== opts.scope && row.scope !== \"global\") return false;\n if (\n opts.types &&\n opts.types.length > 0 &&\n !opts.types.includes(row.type as MemoryEntry[\"type\"])\n )\n return false;\n return true;\n });\n\n return filtered.map(rowToEntry);\n } catch {\n // FTS query syntax error — fall back to LIKE\n return this.query(opts);\n }\n }\n\n // ─── Lifecycle ───────────────────────────────────────\n\n markAccessed(ids: string[]): void {\n if (ids.length === 0) return;\n const now = new Date().toISOString();\n const stmt = this.db.prepare(\n \"UPDATE memories SET access_count = access_count + 1, last_accessed_at = ? WHERE id = ?\",\n );\n const transaction = this.db.transaction(() => {\n for (const id of ids) {\n stmt.run(now, id);\n }\n });\n transaction();\n }\n\n decay(maxAgeDays = 30, minAccessCount = 3): number {\n // Delete stale low-access memories\n const staleResult = this.db\n .prepare(\n `DELETE FROM memories\n WHERE access_count < ?\n AND julianday('now') - julianday(last_accessed_at) > ?\n AND type NOT IN ('focus', 'task')`,\n )\n .run(minAccessCount, maxAgeDays);\n\n // Delete completed tasks older than 7 days\n const taskResult = this.db\n .prepare(\n `DELETE FROM memories\n WHERE type = 'task'\n AND outcome = 'done'\n AND julianday('now') - julianday(last_accessed_at) > 7`,\n )\n .run();\n\n return staleResult.changes + taskResult.changes;\n }\n\n expireEphemeral(): number {\n const result = this.db\n .prepare(\n `DELETE FROM memories\n WHERE type = 'focus'\n AND expires_at IS NOT NULL\n AND expires_at < ?`,\n )\n .run(new Date().toISOString());\n return result.changes;\n }\n\n // ─── Stats ───────────────────────────────────────────\n\n stats(): MemoryStats {\n const total = (\n this.db.prepare(\"SELECT COUNT(*) as count FROM memories\").get() as { count: number }\n ).count;\n\n const byTypeRows = this.db\n .prepare(\"SELECT type, COUNT(*) as count FROM memories GROUP BY type\")\n .all() as { type: string; count: number }[];\n const byType: Record<string, number> = {};\n for (const row of byTypeRows) {\n byType[row.type] = row.count;\n }\n\n const byScopeRows = this.db\n .prepare(\"SELECT scope, COUNT(*) as count FROM memories GROUP BY scope\")\n .all() as { scope: string; count: number }[];\n const byScope: Record<string, number> = {};\n for (const row of byScopeRows) {\n byScope[row.scope] = row.count;\n }\n\n return { total, byType, byScope };\n }\n\n // ─── Cleanup ─────────────────────────────────────────\n\n close(): void {\n this.db.close();\n }\n}\n\n// ─── Internal helpers ────────────────────────────────────\n\ninterface RawMemoryRow {\n id: string;\n type: string;\n scope: string;\n content: string;\n source: string;\n tags: string;\n created_at: string;\n last_accessed_at: string;\n access_count: number;\n expires_at: string | null;\n outcome: string | null;\n run_id: string | null;\n category: string | null;\n severity: string | null;\n supersedes: string | null;\n}\n\nfunction rowToEntry(row: RawMemoryRow): MemoryEntry {\n let tags: string[] = [];\n try {\n tags = JSON.parse(row.tags);\n } catch {\n tags = [];\n }\n\n return {\n id: row.id,\n type: row.type as MemoryEntry[\"type\"],\n scope: row.scope,\n content: row.content,\n source: row.source,\n tags,\n createdAt: row.created_at,\n lastAccessedAt: row.last_accessed_at,\n accessCount: row.access_count,\n expiresAt: row.expires_at ?? undefined,\n outcome: row.outcome ?? undefined,\n runId: row.run_id ?? undefined,\n category: row.category ?? undefined,\n severity: row.severity ?? undefined,\n supersedes: row.supersedes ?? undefined,\n };\n}\n","import { existsSync } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { WorkflowDefinition } from \"@/types\";\nimport { loadWorkflow } from \"@/workflows/loader\";\n\n/**\n * Registry for workflow definitions.\n * Loads built-in workflows from a directory and optional custom workflows.\n * Custom workflows with the same name override built-in ones.\n */\nexport class WorkflowRegistry {\n private readonly builtInDir: string;\n private readonly customDir: string | undefined;\n private readonly workflows = new Map<string, WorkflowDefinition>();\n\n constructor(builtInDir: string, customDir?: string) {\n this.builtInDir = builtInDir;\n this.customDir = customDir;\n }\n\n async load(): Promise<void> {\n // Load built-in workflows first\n await this.loadFromDir(this.builtInDir);\n\n // Custom workflows override built-in ones\n if (this.customDir) {\n await this.loadFromDir(this.customDir);\n }\n }\n\n get(name: string): WorkflowDefinition | undefined {\n return this.workflows.get(name);\n }\n\n list(): WorkflowDefinition[] {\n return [...this.workflows.values()];\n }\n\n has(name: string): boolean {\n return this.workflows.has(name);\n }\n\n private async loadFromDir(dir: string): Promise<void> {\n if (!existsSync(dir)) return;\n\n const files = await readdir(dir);\n for (const file of files) {\n if (!file.endsWith(\".yml\") && !file.endsWith(\".yaml\")) continue;\n const filePath = path.join(dir, file);\n const workflow = await loadWorkflow(filePath);\n this.workflows.set(workflow.name, workflow);\n }\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { parse } from \"yaml\";\nimport { z } from \"zod\";\nimport type { WorkflowDefinition, WorkflowGateDef, WorkflowStepDef } from \"@/types\";\n\n// ─── Zod Schemas ────────────────────────────────────────\n\nconst workflowStepDefSchema = z.object({\n type: z.literal(\"step\").optional().default(\"step\"),\n agent: z.string(),\n dependsOn: z.array(z.string()).optional(),\n prompt: z.string().optional(),\n sandbox: z.enum([\"writable\", \"readonly\"]).optional(),\n maxTurns: z.number().int().positive().optional(),\n mcpServers: z.array(z.string()).optional(),\n recovery: z\n .object({\n maxRetries: z.number().int().nonnegative().optional(),\n nonRetryable: z.array(z.string()).optional(),\n })\n .optional(),\n condition: z.string().optional(),\n});\n\nconst workflowGateDefSchema = z.object({\n type: z.literal(\"gate\"),\n dependsOn: z.array(z.string()).optional(),\n description: z.string(),\n timeout: z.string().optional(),\n autoApprove: z.boolean().optional(),\n});\n\nconst workflowHeaderSchema = z.object({\n name: z.string().min(1),\n description: z.string().optional(),\n steps: z.record(z.string(), z.unknown()),\n});\n\n// ─── Helpers ────────────────────────────────────────────\n\nfunction parseStepEntry(\n stepName: string,\n stepValue: unknown,\n): { step: WorkflowStepDef | WorkflowGateDef; errors: string[] } {\n const obj = stepValue as Record<string, unknown>;\n const schema = obj.type === \"gate\" ? workflowGateDefSchema : workflowStepDefSchema;\n const result = schema.safeParse(stepValue);\n\n if (result.success) {\n return { step: result.data as WorkflowStepDef | WorkflowGateDef, errors: [] };\n }\n return {\n step: stepValue as WorkflowStepDef,\n errors: result.error.issues.map(\n (i) => ` - steps.${stepName}.${i.path.join(\".\")}: ${i.message}`,\n ),\n };\n}\n\nfunction parseSteps(\n rawSteps: Record<string, unknown>,\n filePath: string,\n): Record<string, WorkflowStepDef | WorkflowGateDef> {\n if (Object.keys(rawSteps).length === 0) {\n throw new Error(\n `Invalid workflow definition in ${filePath}:\\n - steps: Workflow must have at least one step`,\n );\n }\n\n const steps: Record<string, WorkflowStepDef | WorkflowGateDef> = {};\n const errors: string[] = [];\n\n for (const [name, value] of Object.entries(rawSteps)) {\n const { step, errors: stepErrors } = parseStepEntry(name, value);\n if (stepErrors.length > 0) {\n errors.push(...stepErrors);\n } else {\n steps[name] = step;\n }\n }\n\n if (errors.length > 0) {\n throw new Error(`Invalid workflow definition in ${filePath}:\\n${errors.join(\"\\n\")}`);\n }\n\n return steps;\n}\n\n// ─── Loader ─────────────────────────────────────────────\n\nexport async function loadWorkflow(filePath: string): Promise<WorkflowDefinition> {\n const content = await readFile(filePath, \"utf-8\");\n const raw = parse(content) as unknown;\n\n const headerResult = workflowHeaderSchema.safeParse(raw);\n if (!headerResult.success) {\n const issues = headerResult.error.issues\n .map((i) => ` - ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid workflow definition in ${filePath}:\\n${issues}`);\n }\n\n const { name, description, steps: rawSteps } = headerResult.data;\n const steps = parseSteps(rawSteps, filePath);\n\n return { name, description, steps };\n}\n\nexport { workflowGateDefSchema, workflowStepDefSchema };\n","import { z } from \"zod\";\n\n// ─── Wake reason (why daemon woke from idle) ─────────────\n\nexport const wakeReasonSchema = z.enum([\"events\", \"timer\", \"active_runs\", \"forced\"]);\n\nexport type WakeReason = z.infer<typeof wakeReasonSchema>;\n\n// ─── Daemon state (persisted in state.json) ──────────────\n\nexport const supervisorDaemonStateSchema = z.object({\n pid: z.number(),\n sessionId: z.string(),\n port: z.number(),\n cwd: z.string(),\n startedAt: z.string(),\n lastHeartbeat: z.string().optional(),\n heartbeatCount: z.number().default(0),\n totalCostUsd: z.number().default(0),\n todayCostUsd: z.number().default(0),\n costResetDate: z.string().optional(),\n idleSkipCount: z.number().default(0),\n activeWorkSkipCount: z.number().default(0),\n status: z.enum([\"running\", \"draining\", \"stopped\"]).default(\"running\"),\n lastConsolidationHeartbeat: z.number().default(0),\n lastCompactionHeartbeat: z.number().default(0),\n lastConsolidationTimestamp: z.string().optional(),\n wakeReason: wakeReasonSchema.optional(),\n});\n\nexport type SupervisorDaemonState = z.infer<typeof supervisorDaemonStateSchema>;\n\n// ─── Incoming webhook event ──────────────────────────────\n\nexport const webhookIncomingEventSchema = z.object({\n id: z.string().optional(),\n source: z.string().optional(),\n event: z.string().optional(),\n payload: z.record(z.string(), z.unknown()).optional(),\n receivedAt: z.string(),\n processedAt: z.string().optional(),\n});\n\nexport type WebhookIncomingEvent = z.infer<typeof webhookIncomingEventSchema>;\n\n// ─── TUI / external inbox message ───────────────────────\n\nexport const inboxMessageSchema = z.object({\n id: z.string(),\n from: z.enum([\"tui\", \"api\", \"external\", \"agent\"]),\n text: z.string(),\n timestamp: z.string(),\n processedAt: z.string().optional(),\n});\n\nexport type InboxMessage = z.infer<typeof inboxMessageSchema>;\n\n// ─── Activity log entry ─────────────────────────────────\n\nexport const activityEntrySchema = z.object({\n id: z.string(),\n type: z.enum([\n \"heartbeat\",\n \"decision\",\n \"action\",\n \"error\",\n \"event\",\n \"message\",\n \"thinking\",\n \"plan\",\n \"dispatch\",\n \"tool_use\",\n ]),\n summary: z.string(),\n detail: z.unknown().optional(),\n timestamp: z.string(),\n});\n\nexport type ActivityEntry = z.infer<typeof activityEntrySchema>;\n\n// ─── Log buffer entry (written by neo log, read by heartbeat) ──\n\nexport const logBufferEntrySchema = z.object({\n id: z.string(),\n type: z.enum([\"progress\", \"action\", \"decision\", \"blocker\", \"milestone\", \"discovery\"]),\n message: z.string(),\n agent: z.string().optional(),\n runId: z.string().optional(),\n repo: z.string().optional(),\n target: z.enum([\"memory\", \"knowledge\", \"digest\"]),\n timestamp: z.string(),\n consolidatedAt: z.string().optional(),\n});\n\nexport type LogBufferEntry = z.infer<typeof logBufferEntrySchema>;\n\n// ─── Internal event kinds (timer-based, not external) ────\n\nexport const internalEventKindSchema = z.enum([\"consolidation_timer\", \"active_run_check\"]);\n\nexport type InternalEventKind = z.infer<typeof internalEventKindSchema>;\n\n// ─── Queued event (union of all event sources) ──────────\n\nexport type QueuedEvent =\n | { kind: \"webhook\"; data: WebhookIncomingEvent }\n | { kind: \"message\"; data: InboxMessage }\n | { kind: \"run_complete\"; runId: string; timestamp: string }\n | { kind: \"internal\"; eventKind: InternalEventKind; timestamp: string };\n","import { randomUUID } from \"node:crypto\";\nimport { appendFile, readFile, rename, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { ActivityEntry } from \"./schemas.js\";\n\nconst ACTIVITY_FILE = \"activity.jsonl\";\nconst MAX_SIZE_BYTES = 10 * 1024 * 1024; // 10MB rotation threshold\n\nexport class ActivityLog {\n readonly filePath: string;\n private readonly dir: string;\n\n constructor(dir: string) {\n this.dir = dir;\n this.filePath = path.join(dir, ACTIVITY_FILE);\n }\n\n /**\n * Append a structured entry to the activity log.\n * Rotates the file if it exceeds MAX_SIZE_BYTES.\n */\n async append(entry: ActivityEntry): Promise<void> {\n await this.checkRotation();\n const line = `${JSON.stringify(entry)}\\n`;\n await appendFile(this.filePath, line, \"utf-8\");\n }\n\n /**\n * Create and append a new entry with auto-generated id and timestamp.\n */\n async log(type: ActivityEntry[\"type\"], summary: string, detail?: unknown): Promise<void> {\n await this.append({\n id: randomUUID(),\n type,\n summary,\n detail,\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Read the last N entries from the activity log.\n */\n async tail(n: number): Promise<ActivityEntry[]> {\n let content: string;\n try {\n content = await readFile(this.filePath, \"utf-8\");\n } catch {\n return [];\n }\n\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n const lastLines = lines.slice(-n);\n\n const entries: ActivityEntry[] = [];\n for (const line of lastLines) {\n try {\n entries.push(JSON.parse(line) as ActivityEntry);\n } catch {\n // Skip malformed lines\n }\n }\n return entries;\n }\n\n private async checkRotation(): Promise<void> {\n try {\n const stats = await stat(this.filePath);\n if (stats.size > MAX_SIZE_BYTES) {\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const rotatedPath = path.join(this.dir, `activity-${timestamp}.jsonl`);\n await rename(this.filePath, rotatedPath);\n }\n } catch {\n // File doesn't exist yet — no rotation needed\n }\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport type { GlobalConfig } from \"@/config\";\nimport { getSupervisorDir } from \"@/paths\";\nimport { isProcessAlive } from \"@/shared/process\";\nimport { ActivityLog } from \"./activity-log.js\";\nimport { EventQueue } from \"./event-queue.js\";\nimport { HeartbeatLoop } from \"./heartbeat.js\";\nimport type { SupervisorDaemonState } from \"./schemas.js\";\nimport { WebhookServer } from \"./webhook-server.js\";\n\nexport interface SupervisorDaemonOptions {\n name: string;\n config: GlobalConfig;\n /** Path to bundled default SUPERVISOR.md (e.g. from @neotx/agents) */\n defaultInstructionsPath?: string | undefined;\n}\n\n/**\n * Orchestrates all supervisor components: webhook server, event queue,\n * heartbeat loop, memory, and activity logging.\n */\nexport class SupervisorDaemon {\n private readonly name: string;\n private readonly config: GlobalConfig;\n private readonly dir: string;\n private readonly defaultInstructionsPath: string | undefined;\n private webhookServer: WebhookServer | null = null;\n private eventQueue: EventQueue | null = null;\n private heartbeatLoop: HeartbeatLoop | null = null;\n private activityLog: ActivityLog | null = null;\n private sessionId = \"\";\n\n constructor(options: SupervisorDaemonOptions) {\n this.name = options.name;\n this.config = options.config;\n this.dir = getSupervisorDir(options.name);\n this.defaultInstructionsPath = options.defaultInstructionsPath;\n }\n\n async start(): Promise<void> {\n // Create supervisor directory\n await mkdir(this.dir, { recursive: true });\n\n // Check lockfile for duplicate daemons\n const lockPath = path.join(this.dir, \"daemon.lock\");\n if (existsSync(lockPath)) {\n const lockPid = await this.readLockPid(lockPath);\n if (lockPid && isProcessAlive(lockPid)) {\n throw new Error(\n `Supervisor \"${this.name}\" already running (PID ${lockPid}). Use --kill first.`,\n );\n }\n // Stale lock — clean up\n await rm(lockPath, { force: true });\n }\n\n // Write lockfile atomically\n const tempLock = `${lockPath}.${process.pid}`;\n await writeFile(tempLock, String(process.pid), \"utf-8\");\n const { rename } = await import(\"node:fs/promises\");\n await rename(tempLock, lockPath);\n\n // Recover session ID from previous state or generate new one\n const existingState = await this.readState();\n if (existingState?.sessionId && existingState.status !== \"stopped\") {\n this.sessionId = existingState.sessionId;\n } else {\n this.sessionId = randomUUID();\n }\n\n // Initialize activity log\n this.activityLog = new ActivityLog(this.dir);\n\n // Initialize event queue\n this.eventQueue = new EventQueue({\n maxEventsPerSec: this.config.supervisor.maxEventsPerSec,\n });\n\n // Replay unprocessed events from disk\n const inboxPath = path.join(this.dir, \"inbox.jsonl\");\n const eventsPath = path.join(this.dir, \"events.jsonl\");\n await this.eventQueue.replayUnprocessed(inboxPath, eventsPath);\n\n // Start file watching\n await this.eventQueue.startWatching(inboxPath, eventsPath);\n\n // Start webhook server\n this.webhookServer = new WebhookServer({\n port: this.config.supervisor.port,\n secret: this.config.supervisor.secret,\n eventsPath,\n onEvent: (event) => {\n this.eventQueue?.push({ kind: \"webhook\", data: event });\n\n // Convert session:complete/session:fail webhooks into run_complete events\n // so the heartbeat gets a structured signal that a run finished\n if (\n (event.event === \"session:complete\" || event.event === \"session:fail\") &&\n event.payload\n ) {\n const runId = typeof event.payload.runId === \"string\" ? event.payload.runId : undefined;\n if (runId) {\n this.eventQueue?.push({\n kind: \"run_complete\",\n runId,\n timestamp: event.receivedAt,\n });\n }\n }\n },\n getHealth: () => this.getHealthInfo(),\n });\n await this.webhookServer.start();\n\n // Write initial state\n await this.writeState({\n pid: process.pid,\n sessionId: this.sessionId,\n port: this.config.supervisor.port,\n cwd: homedir(),\n startedAt: new Date().toISOString(),\n lastHeartbeat: existingState?.lastHeartbeat,\n heartbeatCount: existingState?.heartbeatCount ?? 0,\n totalCostUsd: existingState?.totalCostUsd ?? 0,\n todayCostUsd: existingState?.todayCostUsd ?? 0,\n costResetDate: existingState?.costResetDate,\n idleSkipCount: existingState?.idleSkipCount ?? 0,\n activeWorkSkipCount: existingState?.activeWorkSkipCount ?? 0,\n status: \"running\",\n lastConsolidationHeartbeat: existingState?.lastConsolidationHeartbeat ?? 0,\n lastCompactionHeartbeat: existingState?.lastCompactionHeartbeat ?? 0,\n lastConsolidationTimestamp: existingState?.lastConsolidationTimestamp,\n });\n\n // Install signal handlers\n const shutdown = () => {\n // biome-ignore lint/suspicious/noConsole: Intentional daemon logging for signal handler errors\n this.stop().catch(console.error);\n };\n process.on(\"SIGTERM\", shutdown);\n process.on(\"SIGINT\", shutdown);\n\n await this.activityLog.log(\n \"event\",\n `Supervisor \"${this.name}\" started on port ${this.config.supervisor.port}`,\n );\n\n // Start heartbeat loop (blocks until stopped)\n const statePath = path.join(this.dir, \"state.json\");\n this.heartbeatLoop = new HeartbeatLoop({\n config: this.config,\n supervisorDir: this.dir,\n statePath,\n sessionId: this.sessionId,\n eventQueue: this.eventQueue,\n activityLog: this.activityLog,\n defaultInstructionsPath: this.defaultInstructionsPath,\n });\n\n await this.heartbeatLoop.start();\n }\n\n async stop(): Promise<void> {\n this.heartbeatLoop?.stop();\n this.eventQueue?.stopWatching();\n\n if (this.webhookServer) {\n await this.webhookServer.stop();\n }\n\n // Update state\n const state = await this.readState();\n if (state) {\n state.status = \"stopped\";\n await this.writeState(state);\n }\n\n // Remove lockfile\n const lockPath = path.join(this.dir, \"daemon.lock\");\n await rm(lockPath, { force: true });\n\n if (this.activityLog) {\n await this.activityLog.log(\"event\", `Supervisor \"${this.name}\" stopped`);\n }\n }\n\n private getHealthInfo(): Record<string, unknown> {\n return {\n status: \"ok\",\n name: this.name,\n pid: process.pid,\n uptime: process.uptime(),\n sessionId: this.sessionId,\n port: this.config.supervisor.port,\n };\n }\n\n private async readState(): Promise<SupervisorDaemonState | null> {\n const statePath = path.join(this.dir, \"state.json\");\n try {\n const raw = await readFile(statePath, \"utf-8\");\n return JSON.parse(raw) as SupervisorDaemonState;\n } catch {\n return null;\n }\n }\n\n private async writeState(state: SupervisorDaemonState): Promise<void> {\n const statePath = path.join(this.dir, \"state.json\");\n await writeFile(statePath, JSON.stringify(state, null, 2), \"utf-8\");\n }\n\n private async readLockPid(lockPath: string): Promise<number | null> {\n try {\n const raw = await readFile(lockPath, \"utf-8\");\n const pid = Number.parseInt(raw.trim(), 10);\n return Number.isNaN(pid) ? null : pid;\n } catch {\n return null;\n }\n }\n}\n","import { type FSWatcher, watch } from \"node:fs\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport type { InboxMessage, QueuedEvent, WebhookIncomingEvent } from \"./schemas.js\";\n\ninterface EventQueueOptions {\n maxEventsPerSec: number;\n}\n\nexport interface GroupedMessage {\n text: string;\n from: string;\n count: number;\n}\n\nexport interface GroupedEvents {\n messages: GroupedMessage[];\n webhooks: QueuedEvent[];\n runCompletions: QueuedEvent[];\n}\n\n/**\n * In-memory event queue with deduplication, rate limiting, and file watching.\n *\n * Accumulates events from 3 sources:\n * - Webhooks (pushed directly by WebhookServer)\n * - Inbox messages (watched from inbox.jsonl)\n * - Run completions (watched from runs directory)\n *\n * The daemon drains this queue at each heartbeat.\n */\nexport class EventQueue {\n private readonly queue: QueuedEvent[] = [];\n private readonly seenIds = new Set<string>();\n private readonly maxSeenIds = 1000;\n private readonly maxEventsPerSec: number;\n private eventCountThisSecond = 0;\n private currentSecond = 0;\n private watchers: FSWatcher[] = [];\n private fileOffsets = new Map<string, number>();\n\n /** Resolve function to wake up the heartbeat loop when an event arrives */\n private wakeUp: (() => void) | null = null;\n\n constructor(options: EventQueueOptions) {\n this.maxEventsPerSec = options.maxEventsPerSec;\n }\n\n /**\n * Push an event into the queue. Applies dedup and rate limiting.\n */\n push(event: QueuedEvent): boolean {\n // Deduplication by event ID\n const id = this.getEventId(event);\n if (id && this.seenIds.has(id)) return false;\n\n // Rate limiting\n const now = Math.floor(Date.now() / 1000);\n if (now !== this.currentSecond) {\n this.currentSecond = now;\n this.eventCountThisSecond = 0;\n }\n if (this.eventCountThisSecond >= this.maxEventsPerSec) return false;\n this.eventCountThisSecond++;\n\n // Track seen IDs (LRU-style: evict oldest when full)\n if (id) {\n this.seenIds.add(id);\n if (this.seenIds.size > this.maxSeenIds) {\n const first = this.seenIds.values().next().value;\n if (first) this.seenIds.delete(first);\n }\n }\n\n this.queue.push(event);\n this.wakeUp?.();\n return true;\n }\n\n /**\n * Drain all queued events and return them. Clears the queue.\n */\n drain(): QueuedEvent[] {\n const events = [...this.queue];\n this.queue.length = 0;\n return events;\n }\n\n /**\n * Drain and group events: deduplicates messages by content,\n * keeps webhooks and run completions separate.\n */\n drainAndGroup(): GroupedEvents {\n const events = this.drain();\n\n const messageMap = new Map<string, GroupedMessage>();\n const webhooks: QueuedEvent[] = [];\n const runCompletions: QueuedEvent[] = [];\n\n for (const event of events) {\n if (event.kind === \"message\") {\n const key = event.data.text.trim().toLowerCase();\n const existing = messageMap.get(key);\n if (existing) {\n existing.count++;\n } else {\n messageMap.set(key, { text: event.data.text, from: event.data.from, count: 1 });\n }\n } else if (event.kind === \"webhook\") {\n webhooks.push(event);\n } else {\n runCompletions.push(event);\n }\n }\n\n return {\n messages: [...messageMap.values()],\n webhooks,\n runCompletions,\n };\n }\n\n size(): number {\n return this.queue.length;\n }\n\n /**\n * Start watching inbox.jsonl and events.jsonl for new entries.\n * New lines are parsed and pushed into the queue.\n */\n async startWatching(inboxPath: string, eventsPath: string): Promise<void> {\n // Ensure files exist before watching — fs.watch() throws on missing files\n for (const p of [inboxPath, eventsPath]) {\n try {\n await writeFile(p, \"\", { flag: \"a\" });\n } catch (err) {\n // Non-critical: file creation may fail due to permissions or missing parent directory.\n // watchJsonlFile will handle this gracefully by skipping the watch.\n console.error(`[EventQueue] Failed to ensure file exists: ${p}`, err);\n }\n }\n this.watchJsonlFile(inboxPath, \"message\");\n this.watchJsonlFile(eventsPath, \"webhook\");\n }\n\n stopWatching(): void {\n for (const w of this.watchers) w.close();\n this.watchers = [];\n this.fileOffsets.clear();\n }\n\n /**\n * Replay unprocessed events from disk on startup.\n */\n async replayUnprocessed(inboxPath: string, eventsPath: string): Promise<void> {\n await this.replayFile(inboxPath, \"message\");\n await this.replayFile(eventsPath, \"webhook\");\n }\n\n /**\n * Returns a promise that resolves when a new event arrives or timeout is reached.\n */\n waitForEvent(timeoutMs: number): Promise<void> {\n if (this.queue.length > 0) return Promise.resolve();\n return new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n this.wakeUp = null;\n resolve();\n }, timeoutMs);\n\n this.wakeUp = () => {\n clearTimeout(timer);\n this.wakeUp = null;\n resolve();\n };\n });\n }\n\n /**\n * Interrupt any pending waitForEvent — used during shutdown.\n */\n interrupt(): void {\n this.wakeUp?.();\n }\n\n private getEventId(event: QueuedEvent): string | undefined {\n if (event.kind === \"webhook\") return event.data.id;\n if (event.kind === \"message\") return event.data.id;\n if (event.kind === \"run_complete\") return `run:${event.runId}`;\n return undefined;\n }\n\n private watchJsonlFile(filePath: string, kind: \"message\" | \"webhook\"): void {\n try {\n const watcher = watch(filePath, () => {\n this.readNewLines(filePath, kind).catch((err) => {\n // Non-critical: file may have been deleted or become unreadable between watch trigger and read\n console.error(`[EventQueue] Failed to read new lines from ${filePath}:`, err);\n });\n });\n this.watchers.push(watcher);\n } catch (err) {\n // Non-critical: file may not exist yet — watcher will be set up when file is created\n console.error(`[EventQueue] Cannot watch file (may not exist yet): ${filePath}`, err);\n }\n }\n\n private async readNewLines(filePath: string, kind: \"message\" | \"webhook\"): Promise<void> {\n let content: string;\n try {\n content = await readFile(filePath, \"utf-8\");\n } catch (_err) {\n // Non-critical: file may not exist or be temporarily unavailable during rotation\n // Silently return — the watcher will retry on next change event\n return;\n }\n\n const offset = this.fileOffsets.get(filePath) ?? 0;\n if (content.length <= offset) return;\n\n const newContent = content.slice(offset);\n this.fileOffsets.set(filePath, content.length);\n\n const lines = newContent.trim().split(\"\\n\").filter(Boolean);\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n if (parsed.processedAt) continue; // Already processed\n\n if (kind === \"webhook\") {\n this.push({ kind: \"webhook\", data: parsed as unknown as WebhookIncomingEvent });\n } else {\n this.push({ kind: \"message\", data: parsed as unknown as InboxMessage });\n }\n } catch (_err) {\n // Non-critical: skip malformed JSON lines (may be partial writes or corrupted entries)\n }\n }\n }\n\n private async replayFile(filePath: string, kind: \"message\" | \"webhook\"): Promise<void> {\n let content: string;\n try {\n content = await readFile(filePath, \"utf-8\");\n } catch (_err) {\n // Non-critical on replay: file may not exist yet on first startup\n // Events will be captured when file is created and watcher triggers\n return;\n }\n\n // Set offset so watcher doesn't re-read\n this.fileOffsets.set(filePath, content.length);\n\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n const unprocessed: string[] = [];\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n if (parsed.processedAt) continue;\n\n if (kind === \"webhook\") {\n this.push({ kind: \"webhook\", data: parsed as unknown as WebhookIncomingEvent });\n } else {\n this.push({ kind: \"message\", data: parsed as unknown as InboxMessage });\n }\n unprocessed.push(line);\n } catch (_err) {\n // Non-critical: skip malformed JSON lines during replay (may be partial writes)\n }\n }\n }\n\n /**\n * Mark events as processed by rewriting the source files.\n */\n async markProcessed(inboxPath: string, eventsPath: string, events: QueuedEvent[]): Promise<void> {\n const now = new Date().toISOString();\n\n for (const event of events) {\n if (event.kind === \"webhook\") {\n await this.markInFile(eventsPath, event.data.receivedAt, now);\n } else if (event.kind === \"message\") {\n await this.markInFile(inboxPath, event.data.timestamp, now);\n }\n }\n }\n\n private async markInFile(\n filePath: string,\n matchTimestamp: string,\n processedAt: string,\n ): Promise<void> {\n try {\n const content = await readFile(filePath, \"utf-8\");\n const lines = content.split(\"\\n\");\n let changed = false;\n\n const updated = lines.map((line) => {\n if (!line.trim()) return line;\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n if (\n (parsed.receivedAt === matchTimestamp || parsed.timestamp === matchTimestamp) &&\n !parsed.processedAt\n ) {\n parsed.processedAt = processedAt;\n changed = true;\n return JSON.stringify(parsed);\n }\n } catch (_err) {\n // Non-critical: keep malformed lines as-is (manual edits or corruption)\n }\n return line;\n });\n\n if (changed) {\n await writeFile(filePath, updated.join(\"\\n\"), \"utf-8\");\n this.fileOffsets.set(filePath, updated.join(\"\\n\").length);\n }\n } catch (err) {\n // Non-critical: marking as processed may fail but events are already handled.\n // Worst case: duplicate processing on restart (idempotent operations).\n console.error(`[EventQueue] Failed to mark events as processed in ${filePath}:`, err);\n }\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { readdir, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport type { GlobalConfig } from \"@/config\";\nimport { getDataDir, getRunsDir } from \"@/paths\";\nimport {\n isAssistantMessage,\n isInitMessage,\n isResultMessage,\n isToolResultMessage,\n isToolUseMessage,\n type SDKStreamMessage,\n} from \"@/sdk-types\";\nimport type { PersistedRun } from \"@/types\";\nimport type { ActivityLog } from \"./activity-log.js\";\nimport type { EventQueue } from \"./event-queue.js\";\nimport { compactLogBuffer, markConsolidated, readUnconsolidated } from \"./log-buffer.js\";\nimport type { MemoryEntry } from \"./memory/entry.js\";\nimport { MemoryStore } from \"./memory/store.js\";\nimport {\n buildCompactionPrompt,\n buildConsolidationPrompt,\n buildStandardPrompt,\n} from \"./prompt-builder.js\";\nimport type { LogBufferEntry, SupervisorDaemonState } from \"./schemas.js\";\n\n// ─── Default values for deprecated config fields ─────────\n// These maintain backward compatibility while allowing config removal.\n\n/** Max idle heartbeats to skip before forcing a heartbeat (no events, no active work) */\nconst DEFAULT_IDLE_SKIP_MAX = 20;\n\n/** Max heartbeats to skip when there's active work but no events */\nconst DEFAULT_ACTIVE_WORK_SKIP_MAX = 3;\n\n/** Consolidation runs every N heartbeats */\nconst DEFAULT_CONSOLIDATION_INTERVAL = 5;\n\n// ─── Consolidation logic ────────────────────────────────\n\n/**\n * Determine whether this heartbeat should be a consolidation cycle.\n * Consolidation runs every `consolidationInterval` heartbeats,\n * or earlier if there are pending unconsolidated entries (after at least 2 heartbeats).\n */\nexport function shouldConsolidate(\n heartbeatCount: number,\n lastConsolidationHeartbeat: number,\n consolidationInterval: number,\n hasPendingEntries: boolean,\n): boolean {\n const since = heartbeatCount - lastConsolidationHeartbeat;\n if (since >= consolidationInterval) return true;\n if (hasPendingEntries && since >= 2) return true;\n return false;\n}\n\n/**\n * Determine whether this heartbeat should run compaction.\n * Compaction is a deep cleanup pass that runs every ~50 heartbeats.\n */\nexport function shouldCompact(\n heartbeatCount: number,\n lastCompactionHeartbeat: number,\n compactionInterval = 50,\n): boolean {\n const since = heartbeatCount - lastCompactionHeartbeat;\n return since >= compactionInterval;\n}\n\n// ─── Helper types for runHeartbeat refactoring ───────────\n\ninterface BudgetCheckResult {\n todayCost: number;\n exceeded: boolean;\n}\n\ninterface SkipLogicResult {\n shouldSkip: boolean;\n resetCounters: boolean;\n}\n\ninterface HeartbeatModeResult {\n isConsolidation: boolean;\n isCompaction: boolean;\n unconsolidated: LogBufferEntry[];\n heartbeatCount: number;\n lastConsolidation: number;\n lastConsolidationTs: string | undefined;\n}\n\ninterface StateUpdateResult {\n stateUpdate: Partial<SupervisorDaemonState>;\n}\n\n// ─── HeartbeatLoop ───────────────────────────────────────\n\nexport interface HeartbeatLoopOptions {\n config: GlobalConfig;\n supervisorDir: string;\n statePath: string;\n sessionId: string;\n eventQueue: EventQueue;\n activityLog: ActivityLog;\n /** Path to bundled default SUPERVISOR.md (e.g. from @neotx/agents) */\n defaultInstructionsPath?: string | undefined;\n memoryDbPath?: string | undefined;\n}\n\n/**\n * The core autonomous loop. At each iteration:\n * 1. Drain events from the queue\n * 2. Read log buffer entries\n * 3. Determine standard vs consolidation mode\n * 4. Build the appropriate prompt\n * 5. Call sdk.query() for Claude to reason and act\n * 6. Mark entries consolidated and compact log buffer (consolidation only)\n * 7. Log activity\n * 8. Wait for the next event or idle timeout\n */\nexport class HeartbeatLoop {\n private stopping = false;\n private consecutiveFailures = 0;\n private activeAbort: AbortController | null = null;\n private readonly config: GlobalConfig;\n private readonly supervisorDir: string;\n private readonly statePath: string;\n private sessionId: string;\n private readonly eventQueue: EventQueue;\n private readonly activityLog: ActivityLog;\n\n private customInstructions: string | undefined;\n private readonly defaultInstructionsPath: string | undefined;\n private memoryStore: MemoryStore | null = null;\n private readonly memoryDbPath: string | undefined;\n\n constructor(options: HeartbeatLoopOptions) {\n this.config = options.config;\n this.supervisorDir = options.supervisorDir;\n this.statePath = options.statePath;\n this.sessionId = options.sessionId;\n this.eventQueue = options.eventQueue;\n this.activityLog = options.activityLog;\n this.defaultInstructionsPath = options.defaultInstructionsPath;\n this.memoryDbPath = options.memoryDbPath;\n }\n\n private getMemoryStore(): MemoryStore | null {\n if (!this.memoryStore && this.memoryDbPath) {\n try {\n this.memoryStore = new MemoryStore(this.memoryDbPath);\n } catch {\n // Memory store unavailable — continue without it\n }\n }\n return this.memoryStore;\n }\n\n async start(): Promise<void> {\n this.customInstructions = await this.loadInstructions();\n await this.activityLog.log(\"heartbeat\", \"Supervisor heartbeat loop started\");\n\n while (!this.stopping) {\n try {\n await this.runHeartbeat();\n this.consecutiveFailures = 0;\n } catch (error) {\n this.consecutiveFailures++;\n const msg = error instanceof Error ? error.message : String(error);\n await this.activityLog.log(\"error\", `Heartbeat failed: ${msg}`, { error: msg });\n\n // Circuit breaker: exponential backoff after consecutive failures\n if (this.consecutiveFailures >= this.config.supervisor.maxConsecutiveFailures) {\n const backoffMs = Math.min(\n this.config.supervisor.eventTimeoutMs *\n 2 ** (this.consecutiveFailures - this.config.supervisor.maxConsecutiveFailures),\n 15 * 60 * 1000, // max 15 minutes\n );\n await this.activityLog.log(\n \"error\",\n `Circuit breaker: backing off ${Math.round(backoffMs / 1000)}s after ${this.consecutiveFailures} failures`,\n );\n await this.sleep(backoffMs);\n continue;\n }\n }\n\n if (this.stopping) break;\n\n // Wait for next event or idle timeout\n await this.eventQueue.waitForEvent(this.config.supervisor.eventTimeoutMs);\n }\n\n await this.activityLog.log(\"heartbeat\", \"Supervisor heartbeat loop stopped\");\n }\n\n stop(): void {\n this.stopping = true;\n this.activeAbort?.abort(new Error(\"Supervisor shutting down\"));\n this.eventQueue.interrupt();\n }\n\n private async runHeartbeat(): Promise<void> {\n const startTime = Date.now();\n const heartbeatId = randomUUID();\n const state = await this.readState();\n const today = new Date().toISOString().slice(0, 10);\n\n // Check budget and return early if exceeded\n const budgetCheck = await this.checkBudgetExceeded(state, today);\n if (budgetCheck.exceeded) return;\n\n // Drain events and check for active work\n const grouped = this.eventQueue.drainAndGroup();\n const totalEventCount =\n grouped.messages.length + grouped.webhooks.length + grouped.runCompletions.length;\n const activeRuns = await this.getActiveRuns();\n\n // Handle skip logic for idle/active-work scenarios\n const skipResult = await this.handleSkipLogic({\n state,\n totalEventCount,\n activeRuns,\n });\n if (skipResult.shouldSkip) return;\n if (skipResult.resetCounters) {\n await this.updateState({ idleSkipCount: 0, activeWorkSkipCount: 0 });\n }\n\n // Determine heartbeat mode\n const modeResult = await this.determineHeartbeatMode(state);\n\n // Build prompt and log start\n const { prompt, modeLabel } = await this.buildHeartbeatModePrompt({\n grouped,\n todayCost: budgetCheck.todayCost,\n heartbeatCount: modeResult.heartbeatCount,\n unconsolidated: modeResult.unconsolidated,\n isCompaction: modeResult.isCompaction,\n isConsolidation: modeResult.isConsolidation,\n activeRuns,\n lastHeartbeat: state?.lastHeartbeat,\n lastConsolidationTimestamp: modeResult.lastConsolidationTs,\n });\n await this.activityLog.log(\n \"heartbeat\",\n `Heartbeat #${modeResult.heartbeatCount} starting (${modeLabel})`,\n {\n heartbeatId,\n eventCount: totalEventCount,\n messages: grouped.messages.length,\n webhooks: grouped.webhooks.length,\n runCompletions: grouped.runCompletions.length,\n isConsolidation: modeResult.isConsolidation,\n },\n );\n\n // Call SDK with timeout + shutdown abort\n const { costUsd, turnCount } = await this.callSdk(prompt, heartbeatId);\n\n // Post-response: mark entries consolidated and compact log buffer\n if (modeResult.isConsolidation) {\n const allIds = modeResult.unconsolidated.map((e) => e.id);\n if (allIds.length > 0) {\n await markConsolidated(this.supervisorDir, allIds);\n }\n await compactLogBuffer(this.supervisorDir);\n }\n\n // Build and apply state update\n const durationMs = Date.now() - startTime;\n const { stateUpdate } = this.buildStateUpdate({\n state,\n today,\n todayCost: budgetCheck.todayCost,\n costUsd,\n heartbeatCount: modeResult.heartbeatCount,\n isConsolidation: modeResult.isConsolidation,\n isCompaction: modeResult.isCompaction,\n });\n await this.updateState(stateUpdate);\n\n await this.activityLog.log(\n \"heartbeat\",\n `Heartbeat #${modeResult.heartbeatCount + 1} complete (${modeLabel})`,\n {\n heartbeatId,\n costUsd,\n durationMs,\n turnCount,\n isConsolidation: modeResult.isConsolidation,\n },\n );\n }\n\n /**\n * Check if supervisor daily budget is exceeded.\n */\n private async checkBudgetExceeded(\n state: SupervisorDaemonState | null,\n today: string,\n ): Promise<BudgetCheckResult> {\n const todayCost = state?.costResetDate === today ? (state.todayCostUsd ?? 0) : 0;\n\n if (todayCost >= this.config.supervisor.dailyCapUsd) {\n await this.activityLog.log(\n \"error\",\n `Supervisor daily budget exceeded ($${todayCost.toFixed(2)} / $${this.config.supervisor.dailyCapUsd}). Skipping heartbeat.`,\n );\n await this.sleep(this.config.supervisor.eventTimeoutMs);\n return { todayCost, exceeded: true };\n }\n\n return { todayCost, exceeded: false };\n }\n\n /**\n * Handle skip logic for idle and active-work scenarios.\n */\n private async handleSkipLogic(opts: {\n state: SupervisorDaemonState | null;\n totalEventCount: number;\n activeRuns: string[];\n }): Promise<SkipLogicResult> {\n const { state, totalEventCount, activeRuns } = opts;\n const idleSkipCount = state?.idleSkipCount ?? 0;\n const activeWorkSkipCount = state?.activeWorkSkipCount ?? 0;\n const hasActiveWork = activeRuns.length > 0;\n\n if (totalEventCount === 0) {\n if (hasActiveWork) {\n if (activeWorkSkipCount < DEFAULT_ACTIVE_WORK_SKIP_MAX) {\n await this.updateState({\n activeWorkSkipCount: activeWorkSkipCount + 1,\n idleSkipCount: 0,\n });\n await this.activityLog.log(\n \"heartbeat\",\n `Active-work skip #${activeWorkSkipCount + 1}/${DEFAULT_ACTIVE_WORK_SKIP_MAX} — ${activeRuns.length} runs active, no events`,\n );\n return { shouldSkip: true, resetCounters: false };\n }\n } else {\n if (idleSkipCount < DEFAULT_IDLE_SKIP_MAX) {\n await this.updateState({\n idleSkipCount: idleSkipCount + 1,\n activeWorkSkipCount: 0,\n });\n await this.activityLog.log(\"heartbeat\", `Idle skip #${idleSkipCount + 1} — no events`);\n return { shouldSkip: true, resetCounters: false };\n }\n }\n }\n\n const needsReset = idleSkipCount > 0 || activeWorkSkipCount > 0;\n return { shouldSkip: false, resetCounters: needsReset };\n }\n\n /**\n * Determine heartbeat mode: compaction > consolidation > standard.\n */\n private async determineHeartbeatMode(\n state: SupervisorDaemonState | null,\n ): Promise<HeartbeatModeResult> {\n const heartbeatCount = state?.heartbeatCount ?? 0;\n const lastConsolidation = state?.lastConsolidationHeartbeat ?? 0;\n const lastCompaction = state?.lastCompactionHeartbeat ?? 0;\n const lastConsolidationTs = state?.lastConsolidationTimestamp;\n const unconsolidated = await readUnconsolidated(this.supervisorDir);\n\n const hasNewEntriesSinceLastConsolidation = lastConsolidationTs\n ? unconsolidated.some((e) => e.timestamp > lastConsolidationTs)\n : unconsolidated.length > 0;\n\n const hasPendingEntries = unconsolidated.length > 0;\n const isCompaction = shouldCompact(heartbeatCount, lastCompaction);\n const wouldConsolidate = shouldConsolidate(\n heartbeatCount,\n lastConsolidation,\n DEFAULT_CONSOLIDATION_INTERVAL,\n hasPendingEntries,\n );\n const isConsolidation =\n isCompaction || (wouldConsolidate && hasNewEntriesSinceLastConsolidation);\n\n return {\n isConsolidation,\n isCompaction,\n unconsolidated,\n heartbeatCount,\n lastConsolidation,\n lastConsolidationTs,\n };\n }\n\n /**\n * Build the state update object after heartbeat completion.\n */\n private buildStateUpdate(opts: {\n state: SupervisorDaemonState | null;\n today: string;\n todayCost: number;\n costUsd: number;\n heartbeatCount: number;\n isConsolidation: boolean;\n isCompaction: boolean;\n }): StateUpdateResult {\n const stateUpdate: Partial<SupervisorDaemonState> = {\n sessionId: this.sessionId,\n lastHeartbeat: new Date().toISOString(),\n heartbeatCount: opts.heartbeatCount + 1,\n totalCostUsd: (opts.state?.totalCostUsd ?? 0) + opts.costUsd,\n todayCostUsd: opts.todayCost + opts.costUsd,\n costResetDate: opts.today,\n };\n\n if (opts.isConsolidation) {\n stateUpdate.lastConsolidationHeartbeat = opts.heartbeatCount + 1;\n stateUpdate.lastConsolidationTimestamp = new Date().toISOString();\n }\n\n if (opts.isCompaction) {\n stateUpdate.lastCompactionHeartbeat = opts.heartbeatCount + 1;\n }\n\n return { stateUpdate };\n }\n\n /**\n * Build the prompt for the current heartbeat mode.\n */\n private async buildHeartbeatModePrompt(opts: {\n grouped: ReturnType<EventQueue[\"drainAndGroup\"]>;\n todayCost: number;\n heartbeatCount: number;\n unconsolidated: LogBufferEntry[];\n isCompaction: boolean;\n isConsolidation: boolean;\n activeRuns: string[];\n lastHeartbeat: string | undefined;\n lastConsolidationTimestamp: string | undefined;\n }): Promise<{ prompt: string; modeLabel: string }> {\n const mcpServerNames = this.config.mcpServers ? Object.keys(this.config.mcpServers) : [];\n const store = this.getMemoryStore();\n const memories: MemoryEntry[] = store ? store.query({ limit: 40, sortBy: \"relevance\" }) : [];\n const recentActions = await this.activityLog.tail(20);\n const sharedOpts = {\n repos: this.config.repos,\n grouped: opts.grouped,\n budgetStatus: {\n todayUsd: opts.todayCost,\n capUsd: this.config.supervisor.dailyCapUsd,\n remainingPct:\n ((this.config.supervisor.dailyCapUsd - opts.todayCost) /\n this.config.supervisor.dailyCapUsd) *\n 100,\n },\n activeRuns: opts.activeRuns,\n heartbeatCount: opts.heartbeatCount,\n mcpServerNames,\n customInstructions: this.customInstructions,\n supervisorDir: this.supervisorDir,\n memories,\n recentActions,\n };\n\n if (opts.isCompaction) {\n return {\n prompt: buildCompactionPrompt({\n ...sharedOpts,\n lastConsolidationTimestamp: opts.lastConsolidationTimestamp,\n }),\n modeLabel: \"compaction\",\n };\n }\n\n if (opts.isConsolidation) {\n return {\n prompt: buildConsolidationPrompt({\n ...sharedOpts,\n lastConsolidationTimestamp: opts.lastConsolidationTimestamp,\n }),\n modeLabel: \"consolidation\",\n };\n }\n\n return {\n prompt: buildStandardPrompt(sharedOpts),\n modeLabel: \"standard\",\n };\n }\n\n /**\n * Call the Claude SDK and stream results.\n */\n private async callSdk(\n prompt: string,\n heartbeatId: string,\n ): Promise<{ output: string; costUsd: number; turnCount: number }> {\n const abortController = new AbortController();\n this.activeAbort = abortController;\n const timeout = setTimeout(() => {\n abortController.abort(new Error(\"Heartbeat timeout exceeded\"));\n }, this.config.supervisor.heartbeatTimeoutMs);\n\n let output = \"\";\n let costUsd = 0;\n let turnCount = 0;\n\n try {\n const sdk = await import(\"@anthropic-ai/claude-agent-sdk\");\n\n // Build allowed tools list — include MCP tool patterns for configured servers\n const allowedTools: string[] = [\"Bash\", \"Read\"];\n if (this.config.mcpServers) {\n for (const name of Object.keys(this.config.mcpServers)) {\n allowedTools.push(`mcp__${name}__*`);\n }\n }\n\n const queryOptions: Record<string, unknown> = {\n cwd: homedir(),\n maxTurns: 15,\n allowedTools,\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n mcpServers: this.config.mcpServers ?? {},\n };\n\n const stream = sdk.query({ prompt, options: queryOptions as never });\n\n for await (const message of stream) {\n if (abortController.signal.aborted) break;\n\n const msg = message as SDKStreamMessage;\n\n if (isInitMessage(msg)) {\n this.sessionId = msg.session_id;\n }\n\n if (isResultMessage(msg)) {\n output = msg.result ?? \"\";\n costUsd = msg.total_cost_usd ?? 0;\n turnCount = msg.num_turns ?? 0;\n }\n\n await this.logStreamMessage(msg, heartbeatId);\n }\n } finally {\n clearTimeout(timeout);\n this.activeAbort = null;\n }\n\n return { output, costUsd, turnCount };\n }\n\n private async readState(): Promise<SupervisorDaemonState | null> {\n try {\n const raw = await readFile(this.statePath, \"utf-8\");\n return JSON.parse(raw) as SupervisorDaemonState;\n } catch {\n return null;\n }\n }\n\n private async updateState(updates: Partial<SupervisorDaemonState>): Promise<void> {\n try {\n const raw = await readFile(this.statePath, \"utf-8\");\n const state = JSON.parse(raw) as SupervisorDaemonState;\n Object.assign(state, updates);\n await writeFile(this.statePath, JSON.stringify(state, null, 2), \"utf-8\");\n } catch {\n // Non-critical\n }\n }\n\n /** Read persisted run files and return summaries of active (running/paused) runs. */\n private async getActiveRuns(): Promise<string[]> {\n const runsDir = getRunsDir();\n if (!existsSync(runsDir)) return [];\n\n try {\n const entries = await readdir(runsDir, { withFileTypes: true });\n const active: string[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const subDir = path.join(runsDir, entry.name);\n const files = await readdir(subDir);\n\n for (const f of files) {\n if (!f.endsWith(\".json\")) continue;\n try {\n const raw = await readFile(path.join(subDir, f), \"utf-8\");\n const run = JSON.parse(raw) as PersistedRun;\n if (run.status === \"running\" || run.status === \"paused\") {\n active.push(\n `${run.runId} [${run.status}] ${run.workflow} on ${path.basename(run.repo)}`,\n );\n }\n } catch {\n // Corrupted or partial file — skip\n }\n }\n }\n\n return active;\n } catch {\n return [];\n }\n }\n\n /**\n * Load custom instructions from SUPERVISOR.md.\n * Resolution order:\n * 1. Explicit path via `supervisor.instructions` in config\n * 2. User default: ~/.neo/SUPERVISOR.md\n * 3. Bundled default from @neotx/agents (if path provided)\n */\n private async loadInstructions(): Promise<string | undefined> {\n const candidates: string[] = [];\n\n if (this.config.supervisor.instructions) {\n candidates.push(path.resolve(this.config.supervisor.instructions));\n }\n\n candidates.push(path.join(getDataDir(), \"SUPERVISOR.md\"));\n\n if (this.defaultInstructionsPath) {\n candidates.push(this.defaultInstructionsPath);\n }\n\n for (const filePath of candidates) {\n try {\n const content = await readFile(filePath, \"utf-8\");\n await this.activityLog.log(\"event\", `Loaded instructions from ${filePath}`);\n return content;\n } catch {\n // File not found — try next candidate\n }\n }\n\n return undefined;\n }\n\n /** Route a single SDK stream message to the appropriate log handler. */\n private async logStreamMessage(msg: SDKStreamMessage, heartbeatId: string): Promise<void> {\n if (isAssistantMessage(msg)) {\n await this.logContentBlocks(msg, heartbeatId);\n } else if (isToolUseMessage(msg)) {\n await this.logToolUse(msg, heartbeatId);\n } else if (isToolResultMessage(msg)) {\n await this.logToolResult(msg, heartbeatId);\n }\n }\n\n /** Log thinking and plan blocks from assistant content — no truncation. */\n private async logContentBlocks(msg: SDKStreamMessage, heartbeatId: string): Promise<void> {\n if (!isAssistantMessage(msg)) return;\n const content = msg.message?.content;\n if (!content) return;\n\n for (const block of content) {\n if (block.type === \"thinking\" && block.thinking) {\n await this.activityLog.log(\"thinking\", block.thinking, { heartbeatId });\n }\n if (block.type === \"text\" && block.text) {\n await this.activityLog.log(\"plan\", block.text, { heartbeatId });\n break; // Only log first text block per message\n }\n }\n }\n\n /** Log tool use events — distinguish MCP tools from built-in tools. */\n private async logToolUse(msg: SDKStreamMessage, heartbeatId: string): Promise<void> {\n if (!isToolUseMessage(msg)) return;\n const toolName = msg.tool;\n const isMcp = toolName.startsWith(\"mcp__\");\n await this.activityLog.log(\n isMcp ? \"tool_use\" : \"action\",\n isMcp ? toolName : `Tool use: ${toolName}`,\n { heartbeatId, tool: toolName, input: msg.input },\n );\n }\n\n /** Detect agent dispatches from bash tool results. */\n private async logToolResult(msg: SDKStreamMessage, heartbeatId: string): Promise<void> {\n if (!isToolResultMessage(msg)) return;\n const result = msg.result ?? \"\";\n const runMatch = /Run\\s+(\\S+)\\s+dispatched/i.exec(result);\n if (runMatch) {\n await this.activityLog.log(\"dispatch\", `Agent dispatched: ${runMatch[1]}`, {\n heartbeatId,\n runId: runMatch[1],\n });\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { appendFile, readFile, stat, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { LogBufferEntry } from \"./schemas.js\";\n\nconst LOG_BUFFER_FILE = \"log-buffer.jsonl\";\nconst MAX_FILE_BYTES = 1024 * 1024; // 1MB cap\nconst COMPACTION_AGE_MS = 24 * 60 * 60 * 1000; // 24h\nconst MAX_ENTRIES_PER_RUN = 5;\nconst MAX_DIGEST_ENTRIES = 30;\n\n// ─── Type markers for digest formatting ─────────────────\n\nconst TYPE_MARKERS: Record<string, string> = {\n milestone: \"★\",\n decision: \"◆\",\n blocker: \"⚠\",\n progress: \"·\",\n action: \"→\",\n discovery: \"◇\",\n};\n\n// ─── Core read/write ────────────────────────────────────\n\nfunction bufferPath(dir: string): string {\n return path.join(dir, LOG_BUFFER_FILE);\n}\n\nfunction parseLines(content: string): LogBufferEntry[] {\n const entries: LogBufferEntry[] = [];\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n for (const line of lines) {\n try {\n entries.push(JSON.parse(line) as LogBufferEntry);\n } catch {\n // Skip malformed lines\n }\n }\n return entries;\n}\n\n/**\n * Read all entries from log-buffer.jsonl.\n */\nexport async function readLogBuffer(dir: string): Promise<LogBufferEntry[]> {\n try {\n const content = await readFile(bufferPath(dir), \"utf-8\");\n return parseLines(content);\n } catch {\n return [];\n }\n}\n\n/**\n * Read entries with timestamp > since.\n */\nexport async function readLogBufferSince(dir: string, since: string): Promise<LogBufferEntry[]> {\n const entries = await readLogBuffer(dir);\n return entries.filter((e) => e.timestamp > since);\n}\n\n/**\n * Read entries where consolidatedAt is null/undefined.\n */\nexport async function readUnconsolidated(dir: string): Promise<LogBufferEntry[]> {\n const entries = await readLogBuffer(dir);\n return entries.filter((e) => !e.consolidatedAt);\n}\n\n/**\n * Set consolidatedAt on entries by id.\n * Rewrites the file with updated entries.\n */\nexport async function markConsolidated(dir: string, ids: string[]): Promise<void> {\n const filePath = bufferPath(dir);\n let content: string;\n try {\n content = await readFile(filePath, \"utf-8\");\n } catch {\n return;\n }\n\n const idSet = new Set(ids);\n const now = new Date().toISOString();\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n const updated: string[] = [];\n\n for (const line of lines) {\n try {\n const entry = JSON.parse(line) as LogBufferEntry;\n if (idSet.has(entry.id) && !entry.consolidatedAt) {\n entry.consolidatedAt = now;\n }\n updated.push(JSON.stringify(entry));\n } catch {\n updated.push(line);\n }\n }\n\n await writeFile(filePath, `${updated.join(\"\\n\")}\\n`, \"utf-8\");\n}\n\n/**\n * Remove entries with consolidatedAt older than 24h. Cap file at 1MB.\n */\nexport async function compactLogBuffer(dir: string): Promise<void> {\n const filePath = bufferPath(dir);\n let content: string;\n try {\n content = await readFile(filePath, \"utf-8\");\n } catch {\n return;\n }\n\n const now = Date.now();\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n const kept: string[] = [];\n\n for (const line of lines) {\n try {\n const entry = JSON.parse(line) as LogBufferEntry;\n if (entry.consolidatedAt) {\n const consolidatedTime = new Date(entry.consolidatedAt).getTime();\n if (now - consolidatedTime > COMPACTION_AGE_MS) {\n continue; // Drop old consolidated entries\n }\n }\n kept.push(JSON.stringify(entry));\n } catch {\n // Drop malformed lines during compaction\n }\n }\n\n // Cap at 1MB — drop oldest entries first\n let result = `${kept.join(\"\\n\")}\\n`;\n while (Buffer.byteLength(result, \"utf-8\") > MAX_FILE_BYTES && kept.length > 0) {\n kept.shift();\n result = `${kept.join(\"\\n\")}\\n`;\n }\n\n await writeFile(filePath, result, \"utf-8\");\n}\n\n// ─── Digest helpers ──────────────────────────────────────\n\nfunction groupEntriesByRunId(entries: LogBufferEntry[]): Map<string, LogBufferEntry[]> {\n const groups = new Map<string, LogBufferEntry[]>();\n for (const entry of entries) {\n const key = entry.runId ?? \"unassigned\";\n const group = groups.get(key);\n if (group) {\n group.push(entry);\n } else {\n groups.set(key, [entry]);\n }\n }\n return groups;\n}\n\nfunction dedupeAdjacentEntries(entries: LogBufferEntry[]): LogBufferEntry[] {\n const deduped: LogBufferEntry[] = [];\n for (const entry of entries) {\n const last = deduped[deduped.length - 1];\n if (last && last.message === entry.message) continue;\n deduped.push(entry);\n }\n return deduped;\n}\n\n/**\n * Build a human-readable digest from log buffer entries.\n * Groups by runId, sorts chronologically, adds type markers,\n * deduplicates adjacent identical messages, truncates output.\n */\nexport function buildAgentDigest(entries: LogBufferEntry[]): string {\n if (entries.length === 0) return \"\";\n\n const groups = groupEntriesByRunId(entries);\n const lines: string[] = [];\n let totalCount = 0;\n\n for (const [runId, group] of groups) {\n group.sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\n const deduped = dedupeAdjacentEntries(group);\n const limited = deduped.slice(0, MAX_ENTRIES_PER_RUN);\n\n const agentLabel = limited[0]?.agent ?? \"unknown\";\n lines.push(`[${runId}] (${agentLabel}):`);\n\n for (const entry of limited) {\n if (totalCount >= MAX_DIGEST_ENTRIES) break;\n const marker = TYPE_MARKERS[entry.type] ?? \"·\";\n lines.push(` ${marker} ${entry.message}`);\n totalCount++;\n }\n\n if (totalCount >= MAX_DIGEST_ENTRIES) {\n lines.push(\" ... (truncated)\");\n break;\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Append a single entry to the log buffer file.\n */\nexport async function appendLogBuffer(dir: string, entry: LogBufferEntry): Promise<void> {\n try {\n // Ensure directory exists (appendFile will create the file but not the dir)\n await appendFile(bufferPath(dir), `${JSON.stringify(entry)}\\n`, \"utf-8\");\n } catch {\n // Best-effort — don't crash the CLI if buffer write fails\n }\n}\n\n/**\n * Get file size of the log buffer (for monitoring).\n */\nexport async function getLogBufferSize(dir: string): Promise<number> {\n try {\n const stats = await stat(bufferPath(dir));\n return stats.size;\n } catch {\n return 0;\n }\n}\n","import type { RepoConfig } from \"@/config\";\nimport type { GroupedEvents } from \"./event-queue.js\";\nimport type { MemoryEntry } from \"./memory/entry.js\";\nimport type { ActivityEntry, QueuedEvent } from \"./schemas.js\";\n\n// ─── Shared options ─────────────────────────────────────\n\nexport interface PromptOptions {\n repos: RepoConfig[];\n grouped: GroupedEvents;\n budgetStatus: {\n todayUsd: number;\n capUsd: number;\n remainingPct: number;\n };\n activeRuns: string[];\n heartbeatCount: number;\n mcpServerNames: string[];\n customInstructions?: string | undefined;\n supervisorDir: string;\n memories: MemoryEntry[];\n recentActions: ActivityEntry[];\n}\n\nexport interface StandardPromptOptions extends PromptOptions {}\n\nexport interface ConsolidationPromptOptions extends PromptOptions {\n /** ISO timestamp of last consolidation — used to filter run history */\n lastConsolidationTimestamp?: string | undefined;\n}\n\n// ─── Role (concise identity + mindset) ──────────────────\n\nconst ROLE = `You are the neo autonomous supervisor. You orchestrate developer agents across repositories. You make decisions autonomously, act on events, and yield quickly.`;\n\n// ─── Commands reference ─────────────────────────────────\n\nconst COMMANDS = `### Dispatching agents\n\\`\\`\\`bash\nneo run <agent> --prompt \"...\" --repo <path> --branch <name> [--priority critical|high|medium|low] [--meta '<json>']\n\\`\\`\\`\n\n| Flag | Required | Description |\n|------|----------|-------------|\n| \\`--prompt\\` | always | Task description for the agent |\n| \\`--repo\\` | always | Target repository path |\n| \\`--branch\\` | always | Branch name for the isolated clone |\n| \\`--priority\\` | no | \\`critical\\`, \\`high\\`, \\`medium\\`, \\`low\\` |\n| \\`--meta\\` | recommended | JSON metadata for traceability and deduplication |\n\nAll agents require \\`--branch\\`. Each agent session runs in an isolated clone on that branch.\n\n### Monitoring & reading agent output\n\\`\\`\\`bash\nneo runs --short [--all] # check recent runs\nneo runs <runId> # full run details + agent output\nneo cost --short [--all] # check budget\nneo agents # list available agents\n\\`\\`\\`\n\n\\`neo runs <runId>\\` returns the agent's full output. Always read it after \\`architect\\` or \\`refiner\\` runs — their output contains the plan or decomposition you need to act on next.\n\n### Memory\n\\`\\`\\`bash\nneo memory write --type fact --scope /path \"Stable fact about repo\"\nneo memory write --type focus --expires 2h \"Current working context\"\nneo memory write --type procedure --scope /path \"How to do X\"\nneo memory forget <id>\nneo memory search \"keyword\"\nneo memory list --type fact\n\\`\\`\\`\n\n### Reporting\n\\`\\`\\`bash\nneo log <type> \"<message>\" # visible in TUI only\n\\`\\`\\``;\n\n// ─── Shared instruction blocks ──────────────────────────\n\nconst HEARTBEAT_RULES = `### Heartbeat lifecycle\n1. Process incoming events (messages, run completions)\n2. Follow up on pending work (CI checks, deferred dispatches) with \\`neo runs\\` or \\`gh pr checks\\`\n3. Make decisions and dispatch agents\n4. Update memory and log decisions\n5. Yield — each heartbeat should take seconds, not minutes\n\nAfter dispatching with \\`neo run\\`, note the runId in your focus and yield. Do NOT poll in a loop.\nCompletion events arrive at future heartbeats — react then.\nIf you deferred work (e.g. \"CI pending\"), you MUST check it at the next heartbeat.`;\n\nconst REPORTING_RULES = `### Reporting\n\\`neo log\\` is your ONLY visible output — the TUI shows these and nothing else.\n- \\`neo log decision \"...\"\\` — why you chose this route\n- \\`neo log action \"...\"\\` — what you dispatched/did\n- \\`neo log discovery \"...\"\\` — ephemeral observations\n- 1-3 sentences per log. Pack maximum info: ticket, agent, branch, runId, cost, PR#. No markdown.\n\nYour text output is NEVER shown to users.`;\n\nconst MEMORY_RULES = `### Memory — types and when to use each\n\n| Type | What | When | TTL |\n|------|------|------|-----|\n| \\`fact\\` | Stable truth that affects decisions | After discovering something that changes how you dispatch or review | Permanent (decays if unused) |\n| \\`procedure\\` | How-to recipe learned from failure | After the same issue occurs 3+ times | Permanent (decays if unused) |\n| \\`focus\\` | Structured working context | After every dispatch, deferral, or priority change | Expires (always set --expires) |\n| \\`feedback\\` | Recurring review pattern | After seeing the same reviewer complaint 3+ times | Permanent |\n| \\`episode\\` | Run outcome | Auto-created on run completion — do NOT write manually | Permanent |\n| \\`task\\` | Planned work item | After architect output or decomposition | Until done/abandoned |\n\n#### What to store\n- Architectural truths that affect future dispatch decisions (CI config, build requirements, tooling)\n- Procedures learned from repeated failures (3+ occurrences of the same issue)\n- Active working context in structured focus format (see below)\n\n#### What NOT to store\n- File counts, line numbers, or structural details derivable from code (\\`ls\\` or \\`cat package.json\\` can answer it)\n- Completed work details — once a PR is merged, forget the related facts unless they are reusable\n- Agent output details already available via \\`neo runs <id>\\`\n- Facts about repos where no work is currently planned\n\n#### Focus format (MANDATORY)\nFocus entries MUST use this structured format — no free-form paragraphs:\n\\`\\`\\`\nACTIVE: <runId> <agent> \"<task>\" branch:<name>\nPENDING: <taskId> \"<description>\" depends:<taskId>\nWAITING: <what> since:HB<N>\nPROCESSED: <runId> → <outcome> PR#<N>\n\\`\\`\\`\n\n\\`\\`\\`bash\n# Focus: structured working context (always set --expires)\nneo memory write --type focus --expires 2h \"ACTIVE: 5900a64a developer 'T1: schema+store' branch:feat/task-queue\nPENDING: T2 'CLI --outcome flag' depends:T1\nPENDING: T3+T4 'prompt injection' depends:T1\"\n\n# Facts: truths that change how you work (NOT trivia)\nneo memory write --type fact --scope /path/to/repo \"CI requires pnpm build before push — no auto-rebuild in pipeline\"\nneo memory write --type fact --scope /path/to/repo \"Biome enforces complexity max 20 — extract helpers for large functions\"\n\n# Procedures: recipes learned from failure (write after 3+ occurrences)\nneo memory write --type procedure --scope /path/to/repo \"Before re-dispatching after orphan failure, check if PR already merged with gh pr view\"\nneo memory write --type procedure --scope /path/to/repo \"Integration tests require DATABASE_URL env var — agent must set it\"\n\n# Feedback: recurring reviewer complaints\nneo memory write --type feedback --scope /path/to/repo --category input_validation \"Always validate user input at controller boundaries\"\n\n# Tasks: work queue items from architect/refiner output\nneo memory write --type task --scope /path/to/repo --severity high --category \"neo runs abc123\" \"T1: Implement auth middleware\"\nneo memory write --type task --scope /path/to/repo --severity medium --tags \"initiative:auth-v2,depends:mem_abc\" --category \"cat notes/plan-auth.md\" \"T2: Add JWT validation\"\n\n# Update task status as you work\nneo memory update <id> --outcome in_progress\nneo memory update <id> --outcome done\nneo memory update <id> --outcome blocked\nneo memory update <id> --outcome abandoned\n\n# Forget stale entries\nneo memory forget <id>\n\n# Search across all memories (semantic)\nneo memory search \"database setup\"\n\\`\\`\\`\n\n#### Work queue workflow (Tasks)\nAfter architect/refiner output, create tasks with \\`neo memory write --type task\\`:\n- Include \\`--category\\` with the command to retrieve context (\\`neo runs <id>\\` or \\`cat notes/<file>\\`)\n- Use \\`--tags depends:mem_<id>\\` for task dependencies\n- Use \\`--tags initiative:<name>\\` to group tasks across repos\n- Update status with \\`neo memory update <id> --outcome in_progress|done|blocked|abandoned\\`\n- The queue is shown at every heartbeat — you will not lose track\n\n#### Pattern escalation\nWhen you encounter the same failure or issue 3+ times, ALWAYS write a \\`procedure\\` memory so you handle it automatically next time. Do not re-discover the same problem repeatedly.\n\n#### Event deduplication\nAfter processing a run completion, record the runId as PROCESSED in your focus. If the same runId appears in future events, skip it — do not re-analyze.\n\n**Notes** (\\`notes/\\`, via Bash): use for detailed multi-page plans, analysis, and checklists that span multiple heartbeats. After creating or reading a plan, write a focus summary: \"Plan: <name> | Tasks: T1-T5 | Current: T1 | Next: T2 (depends T1) | Ref: cat notes/<file>\". Delete notes when done.`;\n\n// ─── Section builders ───────────────────────────────────\n\nfunction buildContextSections(opts: PromptOptions): string[] {\n const parts: string[] = [];\n\n if (opts.repos.length > 0) {\n const repoList = opts.repos.map((r) => `- ${r.path} (branch: ${r.defaultBranch})`).join(\"\\n\");\n parts.push(`Repositories:\\n${repoList}`);\n }\n\n if (opts.mcpServerNames.length > 0) {\n const mcpList = opts.mcpServerNames.map((n) => `- ${n}`).join(\"\\n\");\n parts.push(`Integrations (MCP):\\n${mcpList}`);\n }\n\n parts.push(\n `Budget: $${opts.budgetStatus.todayUsd.toFixed(2)} / $${opts.budgetStatus.capUsd.toFixed(2)} (${opts.budgetStatus.remainingPct.toFixed(0)}% remaining)`,\n );\n\n return parts;\n}\n\nfunction buildMemorySection(memories: MemoryEntry[], supervisorDir: string): string {\n const focusEntries = memories.filter((m) => m.type === \"focus\");\n const factEntries = memories.filter((m) => m.type === \"fact\");\n const procedureEntries = memories.filter((m) => m.type === \"procedure\");\n const feedbackEntries = memories.filter((m) => m.type === \"feedback\");\n\n const parts: string[] = [];\n\n // Focus (working context)\n if (focusEntries.length > 0) {\n const lines = focusEntries.map((m) => `- ${m.content}`).join(\"\\n\");\n parts.push(`<focus>\\n${lines}\\n</focus>`);\n } else {\n parts.push(\n \"<focus>\\n(empty — use neo memory write --type focus to set working context)\\n</focus>\",\n );\n }\n\n // Known facts — grouped by scope with staleness signal\n if (factEntries.length > 0) {\n const byScope = new Map<string, MemoryEntry[]>();\n for (const m of factEntries) {\n const scope = m.scope === \"global\" ? \"global\" : (m.scope.split(\"/\").pop() ?? m.scope);\n const group = byScope.get(scope) ?? [];\n group.push(m);\n byScope.set(scope, group);\n }\n\n const scopeSections: string[] = [];\n for (const [scope, entries] of byScope) {\n const oldestAccess = Math.min(\n ...entries.map((m) => Date.now() - new Date(m.lastAccessedAt).getTime()),\n );\n const daysAgo = Math.floor(oldestAccess / 86_400_000);\n const staleHint = daysAgo >= 5 ? ` (last accessed ${daysAgo}d ago)` : \"\";\n const lines = entries\n .map((m) => {\n const confidence = m.accessCount >= 3 ? \"\" : \" (unconfirmed)\";\n return ` - ${m.content}${confidence}`;\n })\n .join(\"\\n\");\n scopeSections.push(` [${scope}]${staleHint} (${entries.length})\\n${lines}`);\n }\n parts.push(`Known facts:\\n${scopeSections.join(\"\\n\")}`);\n }\n\n // Procedures\n if (procedureEntries.length > 0) {\n const lines = procedureEntries.map((m) => `- ${m.content}`).join(\"\\n\");\n parts.push(`Procedures:\\n${lines}`);\n }\n\n // Recurring feedback\n if (feedbackEntries.length > 0) {\n const lines = feedbackEntries\n .map((m) => `- [${m.category ?? \"general\"}] ${m.content}`)\n .join(\"\\n\");\n parts.push(`Recurring review issues:\\n${lines}`);\n }\n\n // Notes reminder\n parts.push(`For detailed plans and checklists, use notes:\n\\`\\`\\`bash\ncat > ${supervisorDir}/notes/plan-feature.md << 'EOF'\n<your detailed plan here>\nEOF\n\\`\\`\\``);\n\n return parts.join(\"\\n\\n\");\n}\n\n// ─── Work queue (tasks) ─────────────────────────────────\n\nconst DONE_OUTCOMES = new Set([\"done\", \"abandoned\"]);\nconst MAX_TASKS = 15;\n\ninterface TaskGroup {\n initiative: string | null;\n tasks: MemoryEntry[];\n}\n\nexport function buildWorkQueueSection(memories: MemoryEntry[]): string {\n // Filter task memories that are not done/abandoned\n const tasks = memories.filter((m) => m.type === \"task\" && !DONE_OUTCOMES.has(m.outcome ?? \"\"));\n\n if (tasks.length === 0) return \"\";\n\n // Count done tasks for the counter\n const doneCount = memories.filter(\n (m) => m.type === \"task\" && DONE_OUTCOMES.has(m.outcome ?? \"\"),\n ).length;\n\n // Group by initiative tag\n const groups: TaskGroup[] = [];\n const initiativeMap = new Map<string, MemoryEntry[]>();\n const noInitiative: MemoryEntry[] = [];\n\n for (const task of tasks) {\n const initiativeTag = task.tags.find((t) => t.startsWith(\"initiative:\"));\n if (initiativeTag) {\n const initiative = initiativeTag.slice(\"initiative:\".length);\n const group = initiativeMap.get(initiative) ?? [];\n group.push(task);\n initiativeMap.set(initiative, group);\n } else {\n noInitiative.push(task);\n }\n }\n\n // Build groups array\n for (const [initiative, taskList] of initiativeMap) {\n groups.push({ initiative, tasks: taskList });\n }\n if (noInitiative.length > 0) {\n groups.push({ initiative: null, tasks: noInitiative });\n }\n\n // Render tasks with cap\n const lines: string[] = [];\n let rendered = 0;\n const remaining = tasks.length;\n\n for (const group of groups) {\n if (rendered >= MAX_TASKS) break;\n\n // Add initiative header if multiple initiatives exist\n if (group.initiative && initiativeMap.size > 0) {\n lines.push(` [${group.initiative}]`);\n }\n\n for (const task of group.tasks) {\n if (rendered >= MAX_TASKS) break;\n\n const marker = formatTaskMarker(task.outcome);\n const severity = task.severity ? `[${task.severity}] ` : \"\";\n const scopeBasename = task.scope !== \"global\" ? ` (${getBasename(task.scope)})` : \"\";\n const runRef = task.runId ? ` [run ${task.runId.slice(0, 8)}]` : \"\";\n const categoryRef = task.category ? ` → ${task.category}` : \"\";\n\n lines.push(` ${marker} ${severity}${task.content}${scopeBasename}${runRef}${categoryRef}`);\n rendered++;\n }\n }\n\n // Add overflow notice if capped\n if (remaining > MAX_TASKS) {\n const overflow = remaining - MAX_TASKS;\n lines.push(` ... and ${overflow} more pending`);\n }\n\n const header = `Work queue (${remaining} remaining, ${doneCount} done):`;\n return `${header}\\n${lines.join(\"\\n\")}`;\n}\n\nfunction formatTaskMarker(outcome: string | undefined): string {\n switch (outcome) {\n case \"in_progress\":\n return \"[ACTIVE]\";\n case \"blocked\":\n return \"[BLOCKED]\";\n default:\n return \"○\";\n }\n}\n\nfunction getBasename(scopePath: string): string {\n const parts = scopePath.split(\"/\");\n return parts[parts.length - 1] || scopePath;\n}\n\n// ─── Recent actions ─────────────────────────────────────\n\nconst SIGNIFICANT_TYPES = new Set([\"decision\", \"action\", \"dispatch\", \"error\", \"plan\"]);\n\nfunction buildRecentActionsSection(entries: ActivityEntry[]): string {\n const significant = entries.filter((e) => SIGNIFICANT_TYPES.has(e.type));\n if (significant.length === 0) return \"\";\n\n const lines = significant.map((e) => {\n const ago = formatTimeAgo(Date.now() - new Date(e.timestamp).getTime());\n return `- [${e.type}] ${e.summary} (${ago})`;\n });\n\n return `Recent actions (your last heartbeats):\\n${lines.join(\"\\n\")}`;\n}\n\nfunction formatTimeAgo(ms: number): string {\n if (ms < 60_000) return \"just now\";\n const minutes = Math.floor(ms / 60_000);\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h${minutes % 60}m ago`;\n return `${Math.floor(hours / 24)}d ago`;\n}\n\n// ─── Events ─────────────────────────────────────────────\n\nfunction buildEventsSection(grouped: GroupedEvents): string {\n const { messages, webhooks, runCompletions } = grouped;\n const totalEvents = messages.length + webhooks.length + runCompletions.length;\n\n if (totalEvents === 0) {\n return \"No new events. Idle heartbeat — check on active runs if any, or wait.\";\n }\n\n const parts: string[] = [];\n for (const msg of messages) {\n const countSuffix = msg.count > 1 ? ` (x${msg.count})` : \"\";\n parts.push(`Message from ${msg.from}${countSuffix}: ${msg.text}`);\n }\n for (const evt of webhooks) {\n parts.push(formatEvent(evt));\n }\n for (const evt of runCompletions) {\n parts.push(formatEvent(evt));\n }\n return `${totalEvents} pending event(s):\\n${parts.join(\"\\n\\n\")}`;\n}\n\nfunction formatEvent(event: QueuedEvent): string {\n switch (event.kind) {\n case \"webhook\":\n return `Webhook [${event.data.source ?? \"unknown\"}] ${event.data.event ?? \"\"}\\n\\`\\`\\`json\\n${JSON.stringify(event.data.payload ?? {}, null, 2)}\\n\\`\\`\\``;\n case \"message\":\n return `Message from ${event.data.from}: ${event.data.text}`;\n case \"run_complete\":\n return `Run completed: ${event.runId} (check with \\`neo runs\\`)`;\n case \"internal\":\n return `Internal event: ${event.eventKind}`;\n }\n}\n\n// ─── Standard prompt (lightweight) ──────────────────────\n\n/**\n * Build the standard heartbeat prompt (4 out of 5 heartbeats).\n * Structure: <role> → <commands> → <context> → <instructions>\n */\nexport function buildStandardPrompt(opts: StandardPromptOptions): string {\n const sections: string[] = [];\n\n sections.push(`<role>\\n${ROLE}\\nHeartbeat #${opts.heartbeatCount}\\n</role>`);\n sections.push(`<commands>\\n${COMMANDS}\\n</commands>`);\n\n // Context\n const contextParts: string[] = [];\n contextParts.push(...buildContextSections(opts));\n\n if (opts.activeRuns.length > 0) {\n contextParts.push(`Active runs:\\n${opts.activeRuns.map((r) => `- ${r}`).join(\"\\n\")}`);\n }\n\n contextParts.push(buildMemorySection(opts.memories, opts.supervisorDir));\n\n const workQueue = buildWorkQueueSection(opts.memories);\n if (workQueue) {\n contextParts.push(workQueue);\n }\n\n const recentActions = buildRecentActionsSection(opts.recentActions);\n if (recentActions) {\n contextParts.push(recentActions);\n }\n\n contextParts.push(`Events:\\n${buildEventsSection(opts.grouped)}`);\n\n sections.push(`<context>\\n${contextParts.join(\"\\n\\n\")}\\n</context>`);\n\n // Instructions\n const instructionParts: string[] = [];\n instructionParts.push(HEARTBEAT_RULES);\n instructionParts.push(REPORTING_RULES);\n instructionParts.push(MEMORY_RULES);\n\n if (opts.customInstructions) {\n instructionParts.push(`### Custom instructions\\n${opts.customInstructions}`);\n }\n\n instructionParts.push(\n \"This is a standard heartbeat. Focus on processing events and dispatching work.\",\n );\n\n sections.push(`<instructions>\\n${instructionParts.join(\"\\n\\n\")}\\n</instructions>`);\n\n return sections.join(\"\\n\\n\");\n}\n\n// ─── Consolidation prompt ────────────────────────────────\n\n/**\n * Build the consolidation heartbeat prompt (1 out of 5 heartbeats).\n */\nexport function buildConsolidationPrompt(opts: ConsolidationPromptOptions): string {\n const sections: string[] = [];\n\n sections.push(`<role>\\n${ROLE}\\nHeartbeat #${opts.heartbeatCount} (CONSOLIDATION)\\n</role>`);\n sections.push(`<commands>\\n${COMMANDS}\\n</commands>`);\n\n // Context\n const contextParts: string[] = [];\n contextParts.push(...buildContextSections(opts));\n\n if (opts.activeRuns.length > 0) {\n contextParts.push(`Active runs:\\n${opts.activeRuns.map((r) => `- ${r}`).join(\"\\n\")}`);\n }\n\n contextParts.push(buildMemorySection(opts.memories, opts.supervisorDir));\n\n const workQueueConsolidation = buildWorkQueueSection(opts.memories);\n if (workQueueConsolidation) {\n contextParts.push(workQueueConsolidation);\n }\n\n const recentActions = buildRecentActionsSection(opts.recentActions);\n if (recentActions) {\n contextParts.push(recentActions);\n }\n\n contextParts.push(`Events:\\n${buildEventsSection(opts.grouped)}`);\n\n sections.push(`<context>\\n${contextParts.join(\"\\n\\n\")}\\n</context>`);\n\n // Instructions\n const instructionParts: string[] = [];\n instructionParts.push(HEARTBEAT_RULES);\n instructionParts.push(REPORTING_RULES);\n instructionParts.push(MEMORY_RULES);\n\n if (opts.customInstructions) {\n instructionParts.push(`### Custom instructions\\n${opts.customInstructions}`);\n }\n\n instructionParts.push(\n `### Consolidation\nThis is a CONSOLIDATION heartbeat.\n\n**Idle guard**: if there are NO active runs AND no new events since last consolidation, log \"idle, no changes\" and yield immediately. Do NOT re-validate facts you already reviewed.\n\nIf there IS active work, your job:\n\n1. **Review memory** — check facts and procedures for accuracy. Remove outdated entries. Resolve contradictions (keep newer). Remove facts about completed work (merged PRs, finished initiatives).\n2. **Update focus** — rewrite focus using the MANDATORY structured format (ACTIVE/PENDING/WAITING/PROCESSED). Remove resolved items. Add new context.\n3. **Pattern escalation** — if agents hit the same issue 3+ times (check recent actions), write a \\`procedure\\` to prevent recurrence.\n4. **Prune completed work** — if a PR is merged or an initiative is done, forget related facts that are no longer actionable. Keep only reusable architectural truths.\n\n\\`\\`\\`bash\nneo memory write --type procedure --scope /repo \"Before re-dispatching after orphan, check gh pr view first\"\nneo memory write --type focus --expires 4h \"ACTIVE: abc123 developer 'T3: prompt injection' branch:feat/task-queue\nPROCESSED: 5900a64a → PR#70 APPROVED\"\nneo memory forget <stale-id>\n\\`\\`\\``,\n );\n\n sections.push(`<instructions>\\n${instructionParts.join(\"\\n\\n\")}\\n</instructions>`);\n\n return sections.join(\"\\n\\n\");\n}\n\n// ─── Compaction prompt ──────────────────────────────────\n\n/**\n * Build the compaction heartbeat prompt (every ~50 heartbeats).\n */\nexport function buildCompactionPrompt(opts: ConsolidationPromptOptions): string {\n const sections: string[] = [];\n\n sections.push(`<role>\\n${ROLE}\\nHeartbeat #${opts.heartbeatCount} (COMPACTION)\\n</role>`);\n sections.push(`<commands>\\n${COMMANDS}\\n</commands>`);\n\n // Context — memory for cleanup review\n const contextParts: string[] = [];\n contextParts.push(...buildContextSections(opts));\n contextParts.push(buildMemorySection(opts.memories, opts.supervisorDir));\n\n const workQueueCompaction = buildWorkQueueSection(opts.memories);\n if (workQueueCompaction) {\n contextParts.push(workQueueCompaction);\n }\n\n sections.push(`<context>\\n${contextParts.join(\"\\n\\n\")}\\n</context>`);\n\n // Instructions\n const instructionParts: string[] = [];\n instructionParts.push(HEARTBEAT_RULES);\n instructionParts.push(REPORTING_RULES);\n instructionParts.push(MEMORY_RULES);\n\n if (opts.customInstructions) {\n instructionParts.push(`### Custom instructions\\n${opts.customInstructions}`);\n }\n\n instructionParts.push(`### Compaction\nThis is a COMPACTION heartbeat. Deep-clean your ENTIRE memory.\n\n1. **Remove stale facts** — facts >7 days old with no recent reinforcement. Check the \"(last accessed Xd ago)\" hints in the facts section.\n2. **Remove completed-work facts** — if all PRs for a repo initiative are merged/closed, forget related facts. Keep only reusable architectural truths (build system, CI config, tooling).\n3. **Remove trivial facts** — file counts, line numbers, structural details that \\`ls\\` or \\`cat package.json\\` can answer. These waste context.\n4. **Merge duplicates** — combine similar facts within the same scope into one.\n5. **Clean up focus** — forget resolved items, rewrite remaining in structured format.\n6. **Delete completed notes** from notes/ directory.\n7. **Stay under 15 facts per scope** — prioritize facts that affect dispatch decisions.\n\nFlag contradictions: if two facts contradict, keep the newer one.\n\n\\`\\`\\`bash\nneo memory list --type fact\nneo memory forget <stale-id>\n\\`\\`\\``);\n\n sections.push(`<instructions>\\n${instructionParts.join(\"\\n\\n\")}\\n</instructions>`);\n\n return sections.join(\"\\n\\n\");\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { appendFile } from \"node:fs/promises\";\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\nimport type { WebhookIncomingEvent } from \"./schemas.js\";\n\nconst MAX_BODY_SIZE = 1024 * 1024; // 1MB\n\ninterface WebhookServerOptions {\n port: number;\n secret?: string | undefined;\n eventsPath: string;\n onEvent: (event: WebhookIncomingEvent) => void;\n getHealth: () => Record<string, unknown>;\n}\n\n/**\n * Minimal HTTP server for receiving incoming webhooks.\n *\n * Routes:\n * POST /webhook — receive any JSON payload, persist to disk, push to queue\n * GET /health — liveness check with daemon status\n *\n * Uses raw http.createServer — zero external dependencies.\n */\nexport class WebhookServer {\n private server: Server | null = null;\n private readonly port: number;\n private readonly secret: string | undefined;\n private readonly eventsPath: string;\n private readonly onEvent: (event: WebhookIncomingEvent) => void;\n private readonly getHealth: () => Record<string, unknown>;\n\n constructor(options: WebhookServerOptions) {\n this.port = options.port;\n this.secret = options.secret;\n this.eventsPath = options.eventsPath;\n this.onEvent = options.onEvent;\n this.getHealth = options.getHealth;\n }\n\n async start(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.server = createServer((req, res) => {\n this.handleRequest(req, res).catch((err) => {\n this.sendJson(res, 500, { error: \"Internal server error\", detail: String(err) });\n });\n });\n\n this.server.on(\"error\", reject);\n\n this.server.listen(this.port, () => {\n resolve();\n });\n });\n }\n\n async stop(): Promise<void> {\n return new Promise<void>((resolve) => {\n if (!this.server) {\n resolve();\n return;\n }\n this.server.close(() => resolve());\n });\n }\n\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = req.url ?? \"/\";\n\n if (req.method === \"GET\" && url === \"/health\") {\n this.sendJson(res, 200, this.getHealth());\n return;\n }\n\n if (req.method === \"POST\" && url === \"/webhook\") {\n await this.handleWebhook(req, res);\n return;\n }\n\n this.sendJson(res, 404, { error: \"Not found\" });\n }\n\n private async handleWebhook(req: IncomingMessage, res: ServerResponse): Promise<void> {\n // Read body first (needed for both parsing and HMAC verification)\n const body = await this.readBody(req);\n if (body === null) {\n this.sendJson(res, 413, { error: \"Payload too large (max 1MB)\" });\n return;\n }\n\n // Validate HMAC signature if secret is configured\n if (this.secret) {\n const signature = req.headers[\"x-neo-signature\"] as string | undefined;\n if (!signature) {\n this.sendJson(res, 401, { error: \"Missing X-Neo-Signature header\" });\n return;\n }\n\n const expected = createHmac(\"sha256\", this.secret).update(body).digest(\"hex\");\n const expectedBuf = Buffer.from(expected, \"utf-8\");\n const actualBuf = Buffer.from(signature, \"utf-8\");\n if (expectedBuf.length !== actualBuf.length || !timingSafeEqual(expectedBuf, actualBuf)) {\n this.sendJson(res, 403, { error: \"Invalid signature\" });\n return;\n }\n }\n\n // Parse JSON\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(body) as Record<string, unknown>;\n } catch {\n this.sendJson(res, 400, { error: \"Invalid JSON\" });\n return;\n }\n\n const event: WebhookIncomingEvent = {\n id: typeof parsed.id === \"string\" ? parsed.id : undefined,\n source: typeof parsed.source === \"string\" ? parsed.source : undefined,\n event: typeof parsed.event === \"string\" ? parsed.event : undefined,\n payload: (parsed.payload as Record<string, unknown> | undefined) ?? parsed,\n receivedAt: new Date().toISOString(),\n };\n\n // Disk-first: persist before pushing to memory\n await appendFile(this.eventsPath, `${JSON.stringify(event)}\\n`, \"utf-8\");\n\n // Push to in-memory queue\n this.onEvent(event);\n\n this.sendJson(res, 200, { ok: true, id: event.id });\n }\n\n private readBody(req: IncomingMessage): Promise<string | null> {\n return new Promise((resolve) => {\n const chunks: Buffer[] = [];\n let size = 0;\n\n req.on(\"data\", (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY_SIZE) {\n resolve(null);\n req.destroy();\n return;\n }\n chunks.push(chunk);\n });\n\n req.on(\"end\", () => {\n resolve(Buffer.concat(chunks).toString(\"utf-8\"));\n });\n\n req.on(\"error\", () => resolve(null));\n });\n }\n\n private sendJson(res: ServerResponse, status: number, data: unknown): void {\n res.writeHead(status, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(data));\n }\n}\n","export const VERSION = \"0.1.0\";\n\n// ─── Orchestrator (public API) ──────────────────────────\n\nexport { loadAgentFile } from \"@/agents/loader\";\nexport { AgentRegistry } from \"@/agents/registry\";\nexport { resolveAgent } from \"@/agents/resolver\";\nexport {\n agentConfigSchema,\n agentModelSchema,\n agentSandboxSchema,\n agentToolEntrySchema,\n agentToolSchema,\n} from \"@/agents/schema\";\nexport type {\n SemaphoreCallbacks,\n SemaphoreConfig,\n} from \"@/concurrency/semaphore\";\n// ─── Concurrency ────────────────────────────────────────\nexport { Semaphore } from \"@/concurrency/semaphore\";\nexport type {\n GlobalConfig,\n McpServerConfig,\n NeoConfig,\n RepoConfig,\n RepoConfigInput,\n} from \"@/config\";\nexport {\n addRepoToGlobalConfig,\n globalConfigSchema,\n listReposFromGlobalConfig,\n loadConfig,\n loadGlobalConfig,\n mcpServerConfigSchema,\n neoConfigSchema,\n removeRepoFromGlobalConfig,\n repoConfigSchema,\n} from \"@/config\";\n// ─── Cost ──────────────────────────────────────────────\nexport { CostJournal } from \"@/cost/journal\";\nexport { NeoEventEmitter } from \"@/events\";\n// ─── Events ────────────────────────────────────────────\nexport { EventJournal } from \"@/events/journal\";\nexport { matchesFilter, WebhookDispatcher } from \"@/events/webhook\";\nexport type { SessionCloneInfo } from \"@/isolation/clone\";\n// ─── Isolation ──────────────────────────────────────────\nexport {\n createSessionClone,\n listSessionClones,\n removeSessionClone,\n} from \"@/isolation/clone\";\nexport {\n createBranch,\n deleteBranch,\n fetchRemote,\n getBranchName,\n getCurrentBranch,\n pushBranch,\n pushSessionBranch,\n} from \"@/isolation/git\";\nexport type { SandboxConfig } from \"@/isolation/sandbox\";\nexport { buildSandboxConfig } from \"@/isolation/sandbox\";\nexport type { AuditLogMiddleware } from \"@/middleware/audit-log\";\n// ─── Middleware ─────────────────────────────────────────\nexport { auditLog } from \"@/middleware/audit-log\";\nexport { budgetGuard } from \"@/middleware/budget-guard\";\nexport type { MiddlewareChain, SDKHooks } from \"@/middleware/chain\";\nexport { buildMiddlewareChain, buildSDKHooks } from \"@/middleware/chain\";\nexport type { LoopDetectionMiddleware } from \"@/middleware/loop-detection\";\nexport { loopDetection } from \"@/middleware/loop-detection\";\nexport type { OrchestratorOptions } from \"@/orchestrator\";\nexport { Orchestrator } from \"@/orchestrator\";\n// ─── Paths ─────────────────────────────────────────────\nexport {\n getDataDir,\n getJournalsDir,\n getRepoRunsDir,\n getRunDispatchPath,\n getRunLogPath,\n getRunsDir,\n getSupervisorActivityPath,\n getSupervisorDir,\n getSupervisorEventsPath,\n getSupervisorInboxPath,\n getSupervisorLockPath,\n getSupervisorStatePath,\n getSupervisorsDir,\n toRepoSlug,\n} from \"@/paths\";\nexport type { ParsedOutput } from \"@/runner/output-parser\";\n// ─── Runner ────────────────────────────────────────────\nexport { parseOutput } from \"@/runner/output-parser\";\nexport type { RecoveryOptions } from \"@/runner/recovery\";\nexport { runWithRecovery } from \"@/runner/recovery\";\nexport type {\n SessionEvent,\n SessionOptions,\n SessionResult,\n} from \"@/runner/session\";\nexport { runSession, SessionError } from \"@/runner/session\";\nexport type {\n SessionExecutionConfig,\n SessionExecutionDeps,\n SessionExecutionInput,\n SessionExecutionResult,\n} from \"@/runner/session-executor\";\nexport {\n buildFullPrompt,\n buildGitStrategyInstructions,\n buildReportingInstructions,\n loadRepoInstructions,\n SessionExecutor,\n} from \"@/runner/session-executor\";\n// ─── Process utilities ─────────────────────────────────\nexport { isProcessAlive } from \"@/shared/process\";\nexport type { SupervisorState } from \"@/supervisor\";\n// ─── Supervisor (legacy) ──────────────────────────────\nexport { supervisorStateSchema } from \"@/supervisor\";\nexport type {\n ActivityEntry,\n HeartbeatLoopOptions,\n InboxMessage,\n QueuedEvent,\n SupervisorDaemonOptions,\n SupervisorDaemonState,\n WebhookIncomingEvent,\n} from \"@/supervisor/index\";\n// ─── Supervisor (daemon) ──────────────────────────────\nexport {\n ActivityLog,\n activityEntrySchema,\n appendLogBuffer,\n EventQueue,\n HeartbeatLoop,\n inboxMessageSchema,\n SupervisorDaemon,\n supervisorDaemonStateSchema,\n WebhookServer,\n webhookIncomingEventSchema,\n} from \"@/supervisor/index\";\nexport type {\n Embedder,\n MemoryEntry,\n MemoryQuery,\n MemoryStats,\n MemoryType,\n MemoryWriteInput,\n} from \"@/supervisor/memory/index\";\n// ─── Memory ───────────────────────────────────────────\nexport { LocalEmbedder, MemoryStore } from \"@/supervisor/memory/index\";\nexport * from \"@/types\";\n// ─── Workflows ─────────────────────────────────────────\nexport { loadWorkflow, workflowGateDefSchema, workflowStepDefSchema } from \"@/workflows/loader\";\nexport { WorkflowRegistry } from \"@/workflows/registry\";\n"],"mappings":"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","names":["path","path","resolve","readFile","path","parseYaml","z","path","z","parseYaml","readFile","path","readFile","path","mkdir","readFile","appendFile","appendFile","resolve","existsSync","mkdir","readdir","execFile","resolve","promisify","execFileAsync","GIT_TIMEOUT","resolve","appendFile","mkdir","path","ensureDir","randomUUID","existsSync","mkdir","readFile","path","existsSync","mkdir","readdir","readFile","writeFile","path","mkdir","path","writeFile","existsSync","readdir","readFile","readFile","path","resolve","path","readFile","z","randomUUID","existsSync","path","limit","existsSync","readdir","path","readFile","z","existsSync","readdir","path","path","resolve","mkdir","randomUUID","strategy","existsSync","readdir","readFile","z","randomUUID","appendFile","readFile","path","randomUUID","existsSync","mkdir","readFile","rm","writeFile","homedir","path","readFile","writeFile","resolve","randomUUID","existsSync","readdir","readFile","writeFile","homedir","path","appendFile","readFile","stat","writeFile","path","path","readFile","readFile","writeFile","appendFile","randomUUID","homedir","readFile","writeFile","existsSync","readdir","path","resolve","createHmac","appendFile","resolve","mkdir","path","existsSync","rm","writeFile","rename","randomUUID","homedir","readFile"]}