@neotx/core 0.1.0-alpha.11 → 0.1.0-alpha.13

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/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 /** Skip orphan recovery on start — workers should set this to true to avoid false orphan detection on concurrent launches. */\n skipOrphanRecovery?: boolean | 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 private readonly skipOrphanRecovery: boolean;\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 this.skipOrphanRecovery = options.skipOrphanRecovery ?? false;\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 if (!this.skipOrphanRecovery) {\n await this.recoverOrphanedRuns();\n }\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 pid: process.pid,\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 pid: process.pid,\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/** Grace period before a run without PID can be considered orphaned (ms). */\nconst ORPHAN_GRACE_PERIOD_MS = 30_000;\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\n // Never mark our own process's runs as orphaned\n if (run.pid && run.pid === process.pid) return null;\n\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 // Don't mark recently created runs as orphaned — the worker process\n // may not have written its PID yet (race condition on concurrent launches)\n const ageMs = Date.now() - new Date(run.createdAt).getTime();\n if (ageMs < ORPHAN_GRACE_PERIOD_MS) 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 (error: unknown) {\n // EPERM means the process exists but we lack permission to signal it\n if (error instanceof Error && \"code\" in error && error.code === \"EPERM\") {\n return true;\n }\n // ESRCH means the process does not exist\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 buildIdlePrompt,\n buildStandardPrompt,\n isIdleHeartbeat,\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 if (isIdleHeartbeat(sharedOpts)) {\n return {\n prompt: buildIdlePrompt(sharedOpts),\n modeLabel: \"idle\",\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 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 (identity + behavioral contract) ──────────────\n\nconst ROLE = `You are the neo autonomous supervisor — a stateless dispatch controller.\n\nYou receive state (events, memory, work queue) and produce actions (tool calls).\n\n<behavioral-contract>\n- Your ONLY visible output is \\`neo log\\` commands. The TUI shows these and nothing else.\n- Your text output is NEVER shown to anyone — every token of text is wasted cost.\n- Produce tool calls, not explanations. Do not narrate your reasoning.\n- You NEVER modify code — that is the agents' job.\n</behavioral-contract>`;\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\\` | **always** | JSON with \\`\"label\"\\` for identification + \\`\"ticketId\"\\`, \\`\"stage\"\\`, etc. |\n\nAll agents require \\`--branch\\`. Each agent session runs in an isolated clone on that branch.\nAlways include \\`--meta '{\"label\":\"T1-auth-middleware\",\"ticketId\":\"YC-42\",\"stage\":\"develop\"}'\\` so you can identify runs later.\n\n### Monitoring & reading agent output\n\\`\\`\\`bash\nneo runs --short # check recent runs\nneo runs --short --status running # check active runs are alive\nneo runs <runId> # full run details + agent output (MUST READ on completion)\nneo cost --short [--all] # check budget\n\\`\\`\\`\n\n\\`neo runs <runId>\\` returns the agent's full output. **ALWAYS read it when a run completes** — it contains structured JSON (PR URLs, issues, plans, milestones) that you need to decide next steps.\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 write --type task --scope /path --severity high --category \"neo runs <id>\" \"Task description\"\nneo memory update <id> --outcome in_progress|done|blocked|abandoned\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\nconst COMMANDS_COMPACT = `### Commands (reference)\n\\`neo run <agent> --prompt \"...\" --repo <path> --branch <name> --meta '{\"label\":\"T1-auth\",...}'\\`\n\\`neo runs [--short | <runId>]\\` · \\`neo runs --short --status running\\` · \\`neo cost --short\\`\n\\`neo memory write|update|forget|search|list\\` · \\`neo log <type> \"<msg>\"\\`\nALWAYS read run output on completion: \\`neo runs <runId>\\` — it contains the agent's structured result.`;\n\n// ─── Shared instruction blocks ──────────────────────────\n\nconst HEARTBEAT_RULES = `### Heartbeat lifecycle\n\n<decision-tree>\n1. DEDUP FIRST — check focus for PROCESSED entries. Skip any runId already processed.\n2. MONITOR RUNS — \\`neo runs --short\\` to check active run status. If a run completed since last HB, read its output with \\`neo runs <runId>\\` BEFORE doing anything else.\n3. PENDING TASKS? — dispatch the next eligible task from work queue. Do not re-plan.\n4. EVENTS? — process run completions, messages, webhooks. Parse agent JSON output.\n5. FOLLOW-UPS? — check CI (\\`gh pr checks\\`), deferred dispatches.\n6. DISPATCH — route work to agents. Mark tasks \\`in_progress\\`, add ACTIVE to focus.\n7. YIELD — log your decisions and yield. Do not poll. Completions arrive at future heartbeats.\n</decision-tree>\n\n<run-monitoring>\nRuns are your agents in the field. You MUST actively track them:\n- **On dispatch**: include a label in \\`--meta\\` for identification: \\`--meta '{\"label\":\"T6-csv-export\",\"ticketId\":\"YC-42\",...}'\\`\n- **On completion**: ALWAYS run \\`neo runs <runId>\\` to read the full output. Parse structured JSON (PR URLs, issues, plans). This is NOT optional — you cannot decide next steps without reading the output.\n- **On failure**: read the output to understand why. Decide: retry (blocked), abandon, or escalate.\n- **Active runs**: check \\`neo runs --short --status running\\` to verify your runs are still alive. If a run disappeared, investigate.\n</run-monitoring>\n\n<orchestration>\nWhen managing a multi-task initiative (architect decomposition, feature with milestones):\n\n**Before dispatching a task:**\n1. Run the task's \\`--category\\` command to retrieve context (architect plan, previous run output)\n2. Write a detailed \\`--prompt\\` with: task description, acceptance criteria, files to modify, and context from previous tasks in the initiative\n3. Include results from completed sibling tasks if relevant (e.g. \"T5 added date filtering in fetchAllFstRecords — now integrate it into CSV export\")\n\n**After a run completes:**\n1. \\`neo runs <runId>\\` — read the FULL output, not just status\n2. Extract: PR URL/number, files changed, test results, any issues\n3. Verify the output matches the task's acceptance criteria\n4. If the agent opened a PR: dispatch \\`reviewer\\` in parallel with CI (do not wait for CI)\n5. Update the task outcome and log the result with concrete details (PR#, branch, what was done)\n\n**Cross-task context:**\n- Each task in an initiative builds on previous ones. When dispatching T6, tell the agent what T1-T5 produced (PR numbers, branches merged, APIs added)\n- Store key outputs as facts if they affect future tasks: \"T5 added dateRange param to fetchAllFstRecords (PR#20 merged)\"\n- Use notes for initiative-level plans: \\`cat notes/plan-<initiative>.md\\` — update as tasks complete\n</orchestration>\n\n<rules>\n- Work queue IS your plan. Never re-plan existing tasks.\n- Maximize parallelism: dispatch independent tasks in the same heartbeat.\n- After dispatch: update focus, yield immediately. Do NOT wait for results.\n- Deferred work (CI pending): MUST check at next heartbeat.\n</rules>`;\n\nconst REPORTING_RULES = `### Reporting\n\n\\`neo log\\` is your ONLY visible output. Use telegraphic format.\n\n<log-format>\nneo log decision \"<ticket> → <action> | <1-line reason>\"\nneo log action \"<agent> <repo>:<branch> run:<runId> | <context>\"\nneo log discovery \"<what> in <where>\"\n</log-format>\n\n<examples>\n<example type=\"good\">\nneo log decision \"YC-42 → developer | clear spec, complexity 3\"\nneo log action \"developer standards:feat/YC-42-auth run:5900a64a | task T1\"\nneo log discovery \"CI requires node 20 in api-service\"\n</example>\n<example type=\"bad\">\nneo log plan \"Good! Now let me check the status and update things accordingly.\"\nneo log decision \"Heartbeat #309: Idle cycle - no action required. All 4 repositories stable.\"\nneo log action \"I've dispatched a developer agent to work on the authentication feature.\"\n</example>\n</examples>`;\n\nconst MEMORY_RULES_CORE = `### Memory\n\n<memory-types>\n| Type | Store when | TTL |\n|------|-----------|-----|\n| \\`fact\\` | Stable truth affecting dispatch decisions | Permanent (decays) |\n| \\`procedure\\` | Same failure 3+ times | Permanent |\n| \\`focus\\` | After every dispatch/deferral | --expires required |\n| \\`task\\` | Any planned work (tickets, decompositions, follow-ups) | Until done/abandoned |\n| \\`feedback\\` | Same review complaint 3+ times | Permanent |\n</memory-types>\n\n<memory-rules>\n- Focus MUST use structured format: ACTIVE/PENDING/WAITING/PROCESSED lines only.\n- NEVER store: file counts, line numbers, completed work details, data available via \\`neo runs <id>\\`.\n- After PR merge: forget related facts unless they are reusable architectural truths.\n- Pattern escalation: same failure 3+ times → write a \\`procedure\\`.\n- Every memory that references external context MUST include a retrieval command (in \\`--category\\` for tasks, in content for facts/procedures). You are stateless — if you can't retrieve it later, don't store it.\n</memory-rules>\n\n<task-workflow>\nTasks are your work queue. The work queue section above shows them with markers (\\`○\\` pending, \\`[ACTIVE]\\` in_progress, \\`[BLOCKED]\\` blocked).\n\nCreate a task for any planned work: incoming tickets, architect decompositions, refiner sub-tickets, follow-up actions, CI fixes.\n- \\`--severity critical|high|medium|low\\` — dispatch highest severity first\n- \\`--tags \"initiative:<name>\"\\` — groups related tasks (shown as [initiative] headers in queue)\n- \\`--tags \"depends:mem_<id>\"\\` — task cannot start until dependency is done\n- \\`--category\\` — **MANDATORY** — the command to retrieve context for this task (shown as \\`→ <command>\\` in queue)\n\n**Context retrieval rule**: every task and relevant memory MUST include a way for you to access its source context at a future heartbeat. You are stateless — without this, you lose the context.\n- Agent output: \\`--category \"neo runs <runId>\"\\`\n- Note/plan: \\`--category \"cat notes/plan-feature.md\"\\`\n- Notion ticket: \\`--category \"API-retrieve-a-page <notionPageId>\"\\`\n- Architect decomposition: \\`--category \"neo runs <architectRunId>\"\\` (contains milestones + tasks)\n\nLifecycle: create → \\`neo memory update <id> --outcome in_progress\\` (on dispatch) → \\`done\\` (on success) / \\`blocked\\` (on failure, will retry) / \\`abandoned\\` (terminal, won't retry)\n\nDispatch rule: pick the highest-severity task with no unmet dependencies. Dispatch independent tasks in parallel. Before dispatching, run the \\`--category\\` command to retrieve task context.\n</task-workflow>\n\n<focus-format>\nACTIVE: <runId> <agent> \"<task>\" branch:<name>\nPENDING: <taskId> \"<description>\" depends:<taskId>\nWAITING: <what> since:HB<N>\nPROCESSED: <runId> → <outcome> PR#<N>\n</focus-format>\n\n**Notes** (\\`notes/\\`, via Bash): use for detailed multi-page plans that span multiple heartbeats. After creating a plan, write a focus summary with \\`--category \"cat notes/<file>\"\\`. Delete notes when done.`;\n\nconst MEMORY_RULES_EXAMPLES = `<memory-commands>\nneo memory write --type focus --expires 2h \"ACTIVE: 5900a64a developer 'T1' branch:feat/x\"\nneo memory write --type fact --scope /repo \"CI requires pnpm build — discovered in run abc123\"\nneo memory write --type procedure --scope /repo \"Check gh pr view before re-dispatch\"\nneo memory write --type task --scope /repo --severity high --category \"neo runs abc123\" --tags \"initiative:auth-v2,depends:mem_xyz\" \"T1: Auth middleware\"\nneo memory update <id> --outcome in_progress|done|blocked|abandoned\nneo memory forget <id>\n</memory-commands>`;\n\n// ─── Section builders ───────────────────────────────────\n\nfunction getCommandsSection(heartbeatCount: number): string {\n return heartbeatCount <= 3 ? COMMANDS : COMMANDS_COMPACT;\n}\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 const tasks = memories.filter((m) => m.type === \"task\" && !DONE_OUTCOMES.has(m.outcome ?? \"\"));\n const doneCount = countDoneTasks(memories);\n\n if (tasks.length === 0) {\n if (doneCount > 0) {\n return `Work queue (0 remaining, ${doneCount} done) — all tasks complete. Pick up new work or wait for events.`;\n }\n return \"\";\n }\n\n const groups = groupTasksByInitiative(tasks);\n const lines = renderTaskGroups(groups);\n\n if (tasks.length > MAX_TASKS) {\n lines.push(` ... and ${tasks.length - MAX_TASKS} more pending`);\n }\n\n const header = `Work queue (${tasks.length} remaining, ${doneCount} done) — dispatch the next eligible task:`;\n return `${header}\\n${lines.join(\"\\n\")}`;\n}\n\nfunction countDoneTasks(memories: MemoryEntry[]): number {\n return memories.filter((m) => m.type === \"task\" && DONE_OUTCOMES.has(m.outcome ?? \"\")).length;\n}\n\nfunction groupTasksByInitiative(tasks: MemoryEntry[]): TaskGroup[] {\n const initiativeMap = new Map<string, MemoryEntry[]>();\n const noInitiative: MemoryEntry[] = [];\n\n for (const task of tasks) {\n const tag = task.tags.find((t) => t.startsWith(\"initiative:\"));\n if (tag) {\n const key = tag.slice(\"initiative:\".length);\n const group = initiativeMap.get(key) ?? [];\n group.push(task);\n initiativeMap.set(key, group);\n } else {\n noInitiative.push(task);\n }\n }\n\n const groups: TaskGroup[] = [];\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 return groups;\n}\n\nfunction renderTaskGroups(groups: TaskGroup[]): string[] {\n const lines: string[] = [];\n let rendered = 0;\n\n for (const group of groups) {\n if (rendered >= MAX_TASKS) break;\n if (group.initiative && groups.length > 1) {\n lines.push(` [${group.initiative}]`);\n }\n for (const task of group.tasks) {\n if (rendered >= MAX_TASKS) break;\n lines.push(` ${formatTaskLine(task)}`);\n rendered++;\n }\n }\n\n return lines;\n}\n\nfunction formatTaskLine(task: MemoryEntry): string {\n const marker = formatTaskMarker(task.outcome);\n const severity = task.severity ? `[${task.severity}] ` : \"\";\n const scope = task.scope !== \"global\" ? ` (${getBasename(task.scope)})` : \"\";\n const run = task.runId ? ` [run ${task.runId.slice(0, 8)}]` : \"\";\n const cat = task.category ? ` → ${task.category}` : \"\";\n return `${marker} ${severity}${task.content}${scope}${run}${cat}`;\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\"]);\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.\";\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// ─── Idle prompt (minimal — no events, no runs, no tasks) ─\n\n/**\n * Check if this heartbeat has nothing to do.\n */\nexport function isIdleHeartbeat(opts: PromptOptions): boolean {\n const { messages, webhooks, runCompletions } = opts.grouped;\n const totalEvents = messages.length + webhooks.length + runCompletions.length;\n const hasWork = buildWorkQueueSection(opts.memories) !== \"\";\n return totalEvents === 0 && opts.activeRuns.length === 0 && !hasWork;\n}\n\n/**\n * Build a minimal idle prompt (~50 tokens).\n * Used when there are no events, no active runs, and no pending tasks.\n */\nexport function buildIdlePrompt(opts: StandardPromptOptions): string {\n return `<role>\n${ROLE}\nHeartbeat #${opts.heartbeatCount}\n</role>\n\n<context>\nNo events. No active runs. No pending tasks.\nBudget: $${opts.budgetStatus.todayUsd.toFixed(2)} / $${opts.budgetStatus.capUsd.toFixed(2)} (${opts.budgetStatus.remainingPct.toFixed(0)}% remaining)\n</context>\n\n<directive>\nNothing to do. Run \\`neo log discovery \"idle\"\\` and yield. Do not produce any other output.\n</directive>`;\n}\n\n// ─── Standard prompt ────────────────────────────────────\n\n/**\n * Build the standard heartbeat prompt (4 out of 5 heartbeats).\n * Structure: <role> → <context> (data top) → <reference> → <instructions> (rules bottom)\n */\nexport function buildStandardPrompt(opts: StandardPromptOptions): string {\n const sections: string[] = [];\n\n // Role — identity + behavioral contract\n sections.push(`<role>\\n${ROLE}\\nHeartbeat #${opts.heartbeatCount}\\n</role>`);\n\n // Context — data first (Anthropic best practice: data top, instructions bottom)\n const contextParts: string[] = [];\n\n const workQueue = buildWorkQueueSection(opts.memories);\n if (workQueue) {\n contextParts.push(workQueue);\n }\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(...buildContextSections(opts));\n contextParts.push(buildMemorySection(opts.memories, opts.supervisorDir));\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 // Reference — commands (compact after first few heartbeats)\n sections.push(`<reference>\\n${getCommandsSection(opts.heartbeatCount)}\\n</reference>`);\n\n // Instructions — rules last\n const instructionParts: string[] = [];\n instructionParts.push(HEARTBEAT_RULES);\n instructionParts.push(REPORTING_RULES);\n instructionParts.push(MEMORY_RULES_CORE);\n\n if (opts.customInstructions) {\n instructionParts.push(`### Custom instructions\\n${opts.customInstructions}`);\n }\n\n const { messages, webhooks, runCompletions } = opts.grouped;\n const hasEvents = messages.length + webhooks.length + runCompletions.length > 0;\n instructionParts.push(\n hasEvents\n ? \"Process events, dispatch eligible work, yield. Each heartbeat costs ~$0.10 — be efficient.\"\n : \"No events. If pending work exists, dispatch it. Otherwise yield immediately.\",\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\n // Context — data first\n const contextParts: string[] = [];\n\n const workQueueConsolidation = buildWorkQueueSection(opts.memories);\n if (workQueueConsolidation) {\n contextParts.push(workQueueConsolidation);\n }\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(...buildContextSections(opts));\n contextParts.push(buildMemorySection(opts.memories, opts.supervisorDir));\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 // Reference\n sections.push(`<reference>\\n${getCommandsSection(opts.heartbeatCount)}\\n</reference>`);\n\n // Instructions\n const instructionParts: string[] = [];\n instructionParts.push(HEARTBEAT_RULES);\n instructionParts.push(REPORTING_RULES);\n instructionParts.push(MEMORY_RULES_CORE);\n instructionParts.push(MEMORY_RULES_EXAMPLES);\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.\n5. **Prune done tasks** — forget tasks with outcome \\`done\\` or \\`abandoned\\` older than 7 days.`,\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\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 // Reference\n sections.push(`<reference>\\n${getCommandsSection(opts.heartbeatCount)}\\n</reference>`);\n\n // Instructions\n const instructionParts: string[] = [];\n instructionParts.push(HEARTBEAT_RULES);\n instructionParts.push(REPORTING_RULES);\n instructionParts.push(MEMORY_RULES_CORE);\n instructionParts.push(MEMORY_RULES_EXAMPLES);\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. **Prune done tasks** — forget tasks with outcome \\`done\\` or \\`abandoned\\` older than 7 days.\n7. **Delete completed notes** from notes/ directory.\n8. **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"]}
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 /** Skip orphan recovery on start — workers should set this to true to avoid false orphan detection on concurrent launches. */\n skipOrphanRecovery?: boolean | 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 private readonly skipOrphanRecovery: boolean;\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 this.skipOrphanRecovery = options.skipOrphanRecovery ?? false;\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 if (!this.skipOrphanRecovery) {\n await this.recoverOrphanedRuns();\n }\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 pid: process.pid,\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 pid: process.pid,\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/** Grace period before a run without PID can be considered orphaned (ms). */\nconst ORPHAN_GRACE_PERIOD_MS = 30_000;\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\n // Never mark our own process's runs as orphaned\n if (run.pid && run.pid === process.pid) return null;\n\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 // Don't mark recently created runs as orphaned — the worker process\n // may not have written its PID yet (race condition on concurrent launches)\n const ageMs = Date.now() - new Date(run.createdAt).getTime();\n if (ageMs < ORPHAN_GRACE_PERIOD_MS) 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 (error: unknown) {\n // EPERM means the process exists but we lack permission to signal it\n if (error instanceof Error && \"code\" in error && error.code === \"EPERM\") {\n return true;\n }\n // ESRCH means the process does not exist\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 buildIdlePrompt,\n buildStandardPrompt,\n isIdleHeartbeat,\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 if (isIdleHeartbeat(sharedOpts)) {\n return {\n prompt: buildIdlePrompt(sharedOpts),\n modeLabel: \"idle\",\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 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 (identity + behavioral contract) ──────────────\n\nconst ROLE = `You are the neo autonomous supervisor — a stateless dispatch controller.\n\nYou receive state (events, memory, work queue), produce actions (tool calls) and monitor the execution of your agents.\n\n<behavioral-contract>\n- Your ONLY visible output is \\`neo log\\` commands. The TUI shows these and nothing else.\n- Your text output is NEVER shown to anyone — every token of text is wasted cost.\n- Produce tool calls, not explanations. Do not narrate your reasoning.\n- You NEVER modify code — that is the agents' job.\n- You can read code in the available repos (path in \\`neo repos\\` command)\n</behavioral-contract>`;\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\\` | **always** | JSON with \\`\"label\"\\` for identification + \\`\"ticketId\"\\`, \\`\"stage\"\\`, etc. |\n\nAll agents require \\`--branch\\`. Each agent session runs in an isolated clone on that branch.\nAlways include \\`--meta '{\"label\":\"T1-auth-middleware\",\"ticketId\":\"YC-42\",\"stage\":\"develop\"}'\\` so you can identify runs later.\n\n### Monitoring & reading agent output\n\\`\\`\\`bash\nneo runs --short # check recent runs\nneo runs --short --status running # check active runs are alive\nneo runs <runId> # full run details + agent output (MUST READ on completion)\nneo cost --short [--all] # check budget\n\\`\\`\\`\n\n\\`neo runs <runId>\\` returns the agent's full output. **ALWAYS read it when a run completes** — it contains structured JSON (PR URLs, issues, plans, milestones) that you need to decide next steps.\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 write --type task --scope /path --severity high --category \"neo runs <id>\" \"Task description\"\nneo memory update <id> --outcome in_progress|done|blocked|abandoned\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\nconst COMMANDS_COMPACT = `### Commands (reference)\n\\`neo run <agent> --prompt \"...\" --repo <path> --branch <name> --meta '{\"label\":\"T1-auth\",...}'\\`\n\\`neo runs [--short | <runId>]\\` · \\`neo runs --short --status running\\` · \\`neo cost --short\\`\n\\`neo memory write|update|forget|search|list\\` · \\`neo log <type> \"<msg>\"\\`\nALWAYS read run output on completion: \\`neo runs <runId>\\` — it contains the agent's structured result.`;\n\n// ─── Shared instruction blocks ──────────────────────────\n\nconst HEARTBEAT_RULES = `### Heartbeat lifecycle\n\n<decision-tree>\n1. DEDUP FIRST — check focus for PROCESSED entries. Skip any runId already processed.\n2. MONITOR RUNS — \\`neo runs --short\\` to check active run status. If a run completed since last HB, read its output with \\`neo runs <runId>\\` BEFORE doing anything else.\n3. PENDING TASKS? — dispatch the next eligible task from work queue. Do not re-plan.\n4. EVENTS? — process run completions, messages, webhooks. Parse agent JSON output.\n5. FOLLOW-UPS? — check CI (\\`gh pr checks\\`), deferred dispatches.\n6. DISPATCH — route work to agents. Mark tasks \\`in_progress\\`, add ACTIVE to focus.\n7. YIELD — log your decisions and yield. Do not poll. Completions arrive at future heartbeats.\n</decision-tree>\n\n<run-monitoring>\nRuns are your agents in the field. You MUST actively track them:\n- **On dispatch**: include a label in \\`--meta\\` for identification: \\`--meta '{\"label\":\"T6-csv-export\",\"ticketId\":\"YC-42\",...}'\\`\n- **On completion**: ALWAYS run \\`neo runs <runId>\\` to read the full output. Parse structured JSON (PR URLs, issues, plans). This is NOT optional — you cannot decide next steps without reading the output.\n- **On failure**: read the output to understand why. Decide: retry (blocked), abandon, or escalate.\n- **Active runs**: check \\`neo runs --short --status running\\` to verify your runs are still alive. If a run disappeared, investigate.\n</run-monitoring>\n\n<orchestration>\nWhen managing a multi-task initiative (architect decomposition, feature with milestones):\n\n**Branch strategy:**\n- Use ONE branch per initiative: \\`feat/YC-2670-kanban-improvements\\` — all tasks in the initiative push commits to this same branch\n- Each agent inherits the previous task's work without needing merges\n- The first task creates the branch. Subsequent tasks reuse it with the same \\`--branch\\` flag\n- Open the PR after the first task completes. Later tasks push additional commits to the same PR\n- Tasks within an initiative MUST be dispatched sequentially (not in parallel) since they share a branch\n- Independent initiatives CAN run in parallel on different branches\n\n**Before dispatching a task:**\n1. Run the task's \\`--category\\` command to retrieve context (architect plan, previous run output)\n2. Write a detailed \\`--prompt\\` with: task description, acceptance criteria, files to modify, and context from previous tasks in the initiative\n3. Include results from completed sibling tasks: what was built, which files were changed, which APIs were added\n4. Always pass the same \\`--branch\\` as previous tasks in the initiative\n\n**After a run completes:**\n1. \\`neo runs <runId>\\` — read the FULL output, not just status\n2. Extract: PR URL/number, files changed, test results, any issues\n3. Verify the output matches the task's acceptance criteria\n4. If the agent opened a PR: dispatch \\`reviewer\\` in parallel with CI (do not wait for CI)\n5. Update the task outcome and log the result with concrete details (PR#, branch, what was done)\n6. Update the initiative note with the completed milestone\n\n**Cross-task context:**\n- Each task builds on previous ones. When dispatching T6, tell the agent what T1-T5 produced (commits, APIs added, files changed)\n- Store key outputs as facts if they affect future tasks: \"T5 added dateRange param to fetchAllFstRecords\"\n- Use notes for initiative-level plans: \\`cat notes/plan-<initiative>.md\\` — update as tasks complete\n</orchestration>\n\n<rules>\n- Work queue IS your plan. Never re-plan existing tasks.\n- Maximize parallelism: dispatch independent tasks in the same heartbeat.\n- After dispatch: update focus, yield immediately. Do NOT wait for results.\n- Deferred work (CI pending): MUST check at next heartbeat.\n</rules>`;\n\nconst REPORTING_RULES = `### Reporting\n\n\\`neo log\\` is your ONLY visible output. Use telegraphic format.\n\n<log-format>\nneo log decision \"<ticket> → <action> | <1-line reason>\"\nneo log action \"<agent> <repo>:<branch> run:<runId> | <context>\"\nneo log discovery \"<what> in <where>\"\n</log-format>\n\n<examples>\n<example type=\"good\">\nneo log decision \"YC-42 → developer | clear spec, complexity 3\"\nneo log action \"developer standards:feat/YC-42-auth run:5900a64a | task T1\"\nneo log discovery \"CI requires node 20 in api-service\"\n</example>\n<example type=\"bad\">\nneo log plan \"Good! Now let me check the status and update things accordingly.\"\nneo log decision \"Heartbeat #309: Idle cycle - no action required. All 4 repositories stable.\"\nneo log action \"I've dispatched a developer agent to work on the authentication feature.\"\n</example>\n</examples>`;\n\nconst MEMORY_RULES_CORE = `### Memory\n\n<memory-types>\n| Type | Store when | TTL |\n|------|-----------|-----|\n| \\`fact\\` | Stable truth affecting dispatch decisions | Permanent (decays) |\n| \\`procedure\\` | Same failure 3+ times | Permanent |\n| \\`focus\\` | After every dispatch/deferral | --expires required |\n| \\`task\\` | Any planned work (tickets, decompositions, follow-ups) | Until done/abandoned |\n| \\`feedback\\` | Same review complaint 3+ times | Permanent |\n</memory-types>\n\n<memory-rules>\n- Focus MUST use structured format: ACTIVE/PENDING/WAITING/PROCESSED lines only.\n- NEVER store: file counts, line numbers, completed work details, data available via \\`neo runs <id>\\`.\n- After PR merge: forget related facts unless they are reusable architectural truths.\n- Pattern escalation: same failure 3+ times → write a \\`procedure\\`.\n- Every memory that references external context MUST include a retrieval command (in \\`--category\\` for tasks, in content for facts/procedures). You are stateless — if you can't retrieve it later, don't store it.\n</memory-rules>\n\n<task-workflow>\nTasks are your work queue. The work queue section above shows them with markers (\\`○\\` pending, \\`[ACTIVE]\\` in_progress, \\`[BLOCKED]\\` blocked).\n\nCreate a task for any planned work: incoming tickets, architect decompositions, refiner sub-tickets, follow-up actions, CI fixes.\n- \\`--severity critical|high|medium|low\\` — dispatch highest severity first\n- \\`--tags \"initiative:<name>\"\\` — groups related tasks (shown as [initiative] headers in queue)\n- \\`--tags \"depends:mem_<id>\"\\` — task cannot start until dependency is done\n- \\`--category\\` — **MANDATORY** — the command to retrieve context for this task (shown as \\`→ <command>\\` in queue)\n\n**Context retrieval rule**: every task and relevant memory MUST include a way for you to access its source context at a future heartbeat. You are stateless — without this, you lose the context.\n- Agent output: \\`--category \"neo runs <runId>\"\\`\n- Note/plan: \\`--category \"cat notes/plan-feature.md\"\\`\n- Notion ticket: \\`--category \"API-retrieve-a-page <notionPageId>\"\\`\n- Architect decomposition: \\`--category \"neo runs <architectRunId>\"\\` (contains milestones + tasks)\n\nLifecycle: create → \\`neo memory update <id> --outcome in_progress\\` (on dispatch) → \\`done\\` (on success) / \\`blocked\\` (on failure, will retry) / \\`abandoned\\` (terminal, won't retry)\n\nDispatch rule: pick the highest-severity task with no unmet dependencies. Dispatch independent tasks in parallel. Before dispatching, run the \\`--category\\` command to retrieve task context.\n</task-workflow>\n\n<focus-format>\nACTIVE: <runId> <agent> \"<task>\" branch:<name>\nPENDING: <taskId> \"<description>\" depends:<taskId>\nWAITING: <what> since:HB<N>\nPROCESSED: <runId> → <outcome> PR#<N>\n</focus-format>\n\n<notes>\n\nYou have a notes/ directory for rich markdown documents that persist across heartbeats.\n\nWhen to use notes:\n- Architect decompositions: save the full plan with milestones, tasks, acceptance criteria, dependency graph\n- Initiative tracking: progress log with completed/pending tasks, PRs merged, blockers\n- Complex debugging: accumulate findings across multiple heartbeats\n- Review checklists: aggregate reviewer feedback across fix/review cycles\n\nHow to use:\n- Write: \\`cat > notes/plan-YC-2670-kanban.md << 'EOF' ... EOF\\` — include milestones checklist, acceptance criteria, file paths\n- Read: \\`cat notes/plan-YC-2670-kanban.md\\` — retrieve full context at any heartbeat\n- Link to tasks: \\`neo memory write --type task --category \"cat notes/plan-YC-2670-kanban.md\" \"M3: UI\"\\`\n- Update: check off completed milestones, add PR numbers, note blockers after each task completes\n- Cleanup: \\`rm notes/plan-*.md\\` when the initiative is done\n\nUse notes for every initiative with 3+ tasks. They are your project management tool.\n</notes>`;\n\nconst MEMORY_RULES_EXAMPLES = `<memory-examples>\nneo memory write --type focus --expires 2h \"ACTIVE: 5900a64a developer 'T1' branch:feat/x (cat notes/plan-YC-2670-kanban.md)\"\nneo memory write --type fact --scope /repo \"CI requires pnpm build — discovered in run 2g589f34a5a\"\nneo memory write --type procedure --scope /repo \"Check gh pr view before re-dispatch\"\nneo memory write --type procedure --scope /repo \"Always run pnpm lint before push\"\nneo memory write --type procedure --scope /repo/backend \"User want to dispatch reviewer agent without waiting for CI\"\nneo memory write --type task --scope /repo --severity high --category \"neo runs 2g589f34a5a\" --tags \"initiative:auth-v2,depends:mem_xyz\" \"T1: Auth middleware\"\nneo memory update <id> --outcome in_progress|done|blocked|abandoned\nneo memory forget <id>\n</memory-examples>`;\n\n// ─── Section builders ───────────────────────────────────\n\nfunction getCommandsSection(heartbeatCount: number): string {\n return heartbeatCount <= 3 ? COMMANDS : COMMANDS_COMPACT;\n}\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 const tasks = memories.filter((m) => m.type === \"task\" && !DONE_OUTCOMES.has(m.outcome ?? \"\"));\n const doneCount = countDoneTasks(memories);\n\n if (tasks.length === 0) {\n if (doneCount > 0) {\n return `Work queue (0 remaining, ${doneCount} done) — all tasks complete. Pick up new work or wait for events.`;\n }\n return \"\";\n }\n\n const groups = groupTasksByInitiative(tasks);\n const lines = renderTaskGroups(groups);\n\n if (tasks.length > MAX_TASKS) {\n lines.push(` ... and ${tasks.length - MAX_TASKS} more pending`);\n }\n\n const header = `Work queue (${tasks.length} remaining, ${doneCount} done) — dispatch the next eligible task:`;\n return `${header}\\n${lines.join(\"\\n\")}`;\n}\n\nfunction countDoneTasks(memories: MemoryEntry[]): number {\n return memories.filter((m) => m.type === \"task\" && DONE_OUTCOMES.has(m.outcome ?? \"\")).length;\n}\n\nfunction groupTasksByInitiative(tasks: MemoryEntry[]): TaskGroup[] {\n const initiativeMap = new Map<string, MemoryEntry[]>();\n const noInitiative: MemoryEntry[] = [];\n\n for (const task of tasks) {\n const tag = task.tags.find((t) => t.startsWith(\"initiative:\"));\n if (tag) {\n const key = tag.slice(\"initiative:\".length);\n const group = initiativeMap.get(key) ?? [];\n group.push(task);\n initiativeMap.set(key, group);\n } else {\n noInitiative.push(task);\n }\n }\n\n const groups: TaskGroup[] = [];\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 return groups;\n}\n\nfunction renderTaskGroups(groups: TaskGroup[]): string[] {\n const lines: string[] = [];\n let rendered = 0;\n\n for (const group of groups) {\n if (rendered >= MAX_TASKS) break;\n if (group.initiative && groups.length > 1) {\n lines.push(` [${group.initiative}]`);\n }\n for (const task of group.tasks) {\n if (rendered >= MAX_TASKS) break;\n lines.push(` ${formatTaskLine(task)}`);\n rendered++;\n }\n }\n\n return lines;\n}\n\nfunction formatTaskLine(task: MemoryEntry): string {\n const marker = formatTaskMarker(task.outcome);\n const severity = task.severity ? `[${task.severity}] ` : \"\";\n const scope = task.scope !== \"global\" ? ` (${getBasename(task.scope)})` : \"\";\n const run = task.runId ? ` [run ${task.runId.slice(0, 8)}]` : \"\";\n const cat = task.category ? ` → ${task.category}` : \"\";\n return `${marker} ${severity}${task.content}${scope}${run}${cat}`;\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\"]);\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.\";\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// ─── Idle prompt (minimal — no events, no runs, no tasks) ─\n\n/**\n * Check if this heartbeat has nothing to do.\n */\nexport function isIdleHeartbeat(opts: PromptOptions): boolean {\n const { messages, webhooks, runCompletions } = opts.grouped;\n const totalEvents = messages.length + webhooks.length + runCompletions.length;\n const hasWork = buildWorkQueueSection(opts.memories) !== \"\";\n return totalEvents === 0 && opts.activeRuns.length === 0 && !hasWork;\n}\n\n/**\n * Build a minimal idle prompt (~50 tokens).\n * Used when there are no events, no active runs, and no pending tasks.\n */\nexport function buildIdlePrompt(opts: StandardPromptOptions): string {\n return `<role>\n${ROLE}\nHeartbeat #${opts.heartbeatCount}\n</role>\n\n<context>\nNo events. No active runs. No pending tasks.\nBudget: $${opts.budgetStatus.todayUsd.toFixed(2)} / $${opts.budgetStatus.capUsd.toFixed(2)} (${opts.budgetStatus.remainingPct.toFixed(0)}% remaining)\n</context>\n\n<directive>\nNothing to do. Run \\`neo log discovery \"idle\"\\` and yield. Do not produce any other output.\n</directive>`;\n}\n\n// ─── Standard prompt ────────────────────────────────────\n\n/**\n * Build the standard heartbeat prompt (4 out of 5 heartbeats).\n * Structure: <role> → <context> (data top) → <reference> → <instructions> (rules bottom)\n */\nexport function buildStandardPrompt(opts: StandardPromptOptions): string {\n const sections: string[] = [];\n\n // Role — identity + behavioral contract\n sections.push(`<role>\\n${ROLE}\\nHeartbeat #${opts.heartbeatCount}\\n</role>`);\n\n // Context — data first (Anthropic best practice: data top, instructions bottom)\n const contextParts: string[] = [];\n\n const workQueue = buildWorkQueueSection(opts.memories);\n if (workQueue) {\n contextParts.push(workQueue);\n }\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(...buildContextSections(opts));\n contextParts.push(buildMemorySection(opts.memories, opts.supervisorDir));\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 // Reference — commands (compact after first few heartbeats)\n sections.push(`<reference>\\n${getCommandsSection(opts.heartbeatCount)}\\n</reference>`);\n\n // Instructions — rules last\n const instructionParts: string[] = [];\n instructionParts.push(HEARTBEAT_RULES);\n instructionParts.push(REPORTING_RULES);\n instructionParts.push(MEMORY_RULES_CORE);\n\n if (opts.customInstructions) {\n instructionParts.push(`### Custom instructions\\n${opts.customInstructions}`);\n }\n\n const { messages, webhooks, runCompletions } = opts.grouped;\n const hasEvents = messages.length + webhooks.length + runCompletions.length > 0;\n instructionParts.push(\n hasEvents\n ? \"Process events, dispatch eligible work, yield. Each heartbeat costs ~$0.10 — be efficient.\"\n : \"No events. If pending work exists, dispatch it. Otherwise yield immediately.\",\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\n // Context — data first\n const contextParts: string[] = [];\n\n const workQueueConsolidation = buildWorkQueueSection(opts.memories);\n if (workQueueConsolidation) {\n contextParts.push(workQueueConsolidation);\n }\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(...buildContextSections(opts));\n contextParts.push(buildMemorySection(opts.memories, opts.supervisorDir));\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 // Reference\n sections.push(`<reference>\\n${getCommandsSection(opts.heartbeatCount)}\\n</reference>`);\n\n // Instructions\n const instructionParts: string[] = [];\n instructionParts.push(HEARTBEAT_RULES);\n instructionParts.push(REPORTING_RULES);\n instructionParts.push(MEMORY_RULES_CORE);\n instructionParts.push(MEMORY_RULES_EXAMPLES);\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.\n5. **Prune done tasks** — forget tasks with outcome \\`done\\` or \\`abandoned\\` older than 7 days.`,\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\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 // Reference\n sections.push(`<reference>\\n${getCommandsSection(opts.heartbeatCount)}\\n</reference>`);\n\n // Instructions\n const instructionParts: string[] = [];\n instructionParts.push(HEARTBEAT_RULES);\n instructionParts.push(REPORTING_RULES);\n instructionParts.push(MEMORY_RULES_CORE);\n instructionParts.push(MEMORY_RULES_EXAMPLES);\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. **Prune done tasks** — forget tasks with outcome \\`done\\` or \\`abandoned\\` older than 7 days.\n7. **Delete completed notes** from notes/ directory.\n8. **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"]}